@dcrays/dcgchat-test 0.1.9

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/tool.ts ADDED
@@ -0,0 +1,65 @@
1
+
2
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
3
+ import { getWsConnection } from "./connection.js";
4
+ import { logDcgchat } from "./log.js";
5
+
6
+ let msgParams = {} as {
7
+ userId: number;
8
+ token: string
9
+ sessionId: string
10
+ messageId: string
11
+ }
12
+ export function setMsgParams(params: any) {
13
+ msgParams = params;
14
+ }
15
+
16
+ export function getMsgParams() {
17
+ return msgParams;
18
+ }
19
+
20
+ export function monitoringToolMessage(api: OpenClawPluginApi) {
21
+ api.on("after_tool_call", (event, payload) => {
22
+ const ws = getWsConnection()
23
+ const params = getMsgParams();
24
+ //
25
+ if (ws?.readyState === WebSocket.OPEN && params?.sessionId) {
26
+ ws.send(JSON.stringify({
27
+ messageType: "openclaw_bot_chat",
28
+ _userId: params?.userId,
29
+ source: "client",
30
+ content: {
31
+ bot_token: params?.token,
32
+ response: 'all_finished',
33
+ session_id:params?.sessionId,
34
+ message_id: params?.messageId || Date.now().toString()
35
+ },
36
+ }));
37
+ ws.send(JSON.stringify({
38
+ messageType: "openclaw_bot_chat",
39
+ _userId: params?.userId,
40
+ source: "client",
41
+ content: {
42
+ bot_token: params?.token,
43
+ response: JSON.stringify({
44
+ type: 'tool_call',
45
+ ...event
46
+ }),
47
+ session_id:params?.sessionId,
48
+ message_id: params?.messageId || Date.now().toString()
49
+ },
50
+ }));
51
+ ws.send(JSON.stringify({
52
+ messageType: "openclaw_bot_chat",
53
+ _userId: params?.userId,
54
+ source: "client",
55
+ content: {
56
+ bot_token: params?.token,
57
+ response: 'all_finished',
58
+ session_id:params?.sessionId,
59
+ message_id: params?.messageId || Date.now().toString()
60
+ },
61
+ }));
62
+ logDcgchat.info(`dcgchat: tool message to ${params?.sessionId}, ${JSON.stringify(event)}`);
63
+ }
64
+ });
65
+ }
package/src/types.ts ADDED
@@ -0,0 +1,103 @@
1
+ /**
2
+ * 插件配置(channels.dcgchat 下的字段)
3
+ */
4
+ export type DcgchatConfig = {
5
+ enabled?: boolean;
6
+ /** 后端 WebSocket 地址,例如 ws://localhost:8080/openclaw/ws */
7
+ wsUrl?: string;
8
+ /** 连接认证 token */
9
+ botToken?: string;
10
+ /** 用户标识 */
11
+ userId?: string;
12
+ domainId?: string;
13
+ appId?: string;
14
+ };
15
+
16
+ export type ResolvedDcgchatAccount = {
17
+ accountId: string;
18
+ enabled: boolean;
19
+ configured: boolean;
20
+ wsUrl: string;
21
+ botToken: string;
22
+ userId: string;
23
+ domainId?: string;
24
+ appId?: string;
25
+ };
26
+
27
+ /**
28
+ * 下行消息:后端 → OpenClaw(用户发的消息)
29
+ */
30
+ // export type InboundMessage = {
31
+ // type: "message";
32
+ // userId: string;
33
+ // text: string;
34
+ // };
35
+ export type InboundMessage = {
36
+ messageType: string; // "openclaw_bot_chat",
37
+ _userId: number;
38
+ source: string; // 'server',
39
+ // content: string;
40
+ content: {
41
+ bot_token: string;
42
+ session_id: string;
43
+ message_id: string;
44
+ text: string;
45
+ file_urls?: string[];
46
+ };
47
+ };
48
+
49
+ // {"_userId":40,"content":"{\"bot_token\":\"sk_b7f8a3e1c5d24e6f8a1b3c4d5e6f7a8b\",\"session_id\":\"1\",\"message_id\":\"1\",\"text\":\"你好\"}","messageType":"openclaw_bot_chat","msgId":398599,"source":"server","title":"OPENCLAW机器人对话"}
50
+
51
+ /**
52
+ * 上行消息:OpenClaw → 后端(Agent 回复)
53
+ */
54
+ // export type OutboundReply = {
55
+ // type: "reply";
56
+ // userId: string;
57
+ // text: string;
58
+ // };
59
+
60
+ export type OutboundReply = {
61
+ messageType: string; // "openclaw_bot_chat",
62
+ _userId: number; // 100
63
+ source: string; // 'client',
64
+ // content: string;
65
+ content: {
66
+ bot_token: string; // ""
67
+ session_id: string; // ""
68
+ message_id: string; // ""
69
+ response: string; // ""
70
+ state: string; // final, chunk
71
+ };
72
+ };
73
+
74
+ export interface IResponse<T = unknown> {
75
+ /** 响应状态码 */
76
+ code?: number | string;
77
+ /** 响应数据 */
78
+ data?: T;
79
+ /** 响应消息 */
80
+ message?: string;
81
+ }
82
+
83
+ export interface IStsToken {
84
+ bucket: string;
85
+ endPoint: string;
86
+ expiration: string;
87
+ ossFileKey: string;
88
+ policy: string;
89
+ region: string;
90
+ signature: string;
91
+ sourceFileName: string;
92
+ stsEndPoint: string;
93
+ tempAccessKeyId: string;
94
+ tempAccessKeySecret: string;
95
+ tempSecurityToken: string;
96
+ uploadDir: string;
97
+ protocol: string;
98
+ }
99
+
100
+ export interface IStsTokenReq {
101
+ sourceFileName: string
102
+ isPrivate: number
103
+ }
@@ -0,0 +1,97 @@
1
+ /**
2
+ * userToken 缓存管理模块
3
+ * 负责维护 botToken -> userToken 的映射关系,支持自动过期
4
+ */
5
+
6
+ // userToken 缓存配置
7
+ const TOKEN_CACHE_DURATION = 60 * 60 * 1000; // 1小时
8
+
9
+ type TokenCacheEntry = {
10
+ token: string;
11
+ expiresAt: number;
12
+ };
13
+
14
+ // 内存缓存:botToken -> { token, expiresAt }
15
+ const tokenCache = new Map<string, TokenCacheEntry>();
16
+
17
+ /**
18
+ * 设置 userToken 缓存
19
+ * @param botToken 机器人 token
20
+ * @param userToken 用户 token
21
+ */
22
+ export function setUserTokenCache(botToken: string, userToken: string): void {
23
+ const expiresAt = Date.now() + TOKEN_CACHE_DURATION;
24
+ tokenCache.set(botToken, { token: userToken, expiresAt });
25
+ console.log(
26
+ `[token-cache] cached userToken for botToken=${botToken.slice(0, 10)}..., expires at ${new Date(expiresAt).toISOString()}`,
27
+ );
28
+ }
29
+
30
+ /**
31
+ * 获取 userToken 缓存(自动检查过期)
32
+ * @param botToken 机器人 token
33
+ * @returns userToken 或 null(未找到或已过期)
34
+ */
35
+ export function getUserTokenCache(botToken: string): string | null {
36
+ const entry = tokenCache.get(botToken);
37
+ if (!entry) {
38
+ console.log(`[token-cache] no cache found for botToken=${botToken.slice(0, 10)}...`);
39
+ return null;
40
+ }
41
+
42
+ // 检查是否过期
43
+ if (Date.now() >= entry.expiresAt) {
44
+ console.log(`[token-cache] cache expired for botToken=${botToken.slice(0, 10)}..., removing`);
45
+ tokenCache.delete(botToken);
46
+ return null;
47
+ }
48
+
49
+ console.log(
50
+ `[token-cache] cache hit for botToken=${botToken.slice(0, 10)}..., valid until ${new Date(entry.expiresAt).toISOString()}`,
51
+ );
52
+ return entry.token;
53
+ }
54
+
55
+ /**
56
+ * 清除指定 botToken 的缓存
57
+ * @param botToken 机器人 token
58
+ */
59
+ export function clearUserTokenCache(botToken: string): void {
60
+ tokenCache.delete(botToken);
61
+ console.log(`[token-cache] cleared cache for botToken=${botToken.slice(0, 10)}...`);
62
+ }
63
+
64
+ /**
65
+ * 清除所有缓存
66
+ */
67
+ export function clearAllUserTokenCache(): void {
68
+ tokenCache.clear();
69
+ console.log(`[token-cache] cleared all token cache`);
70
+ }
71
+
72
+ /**
73
+ * 获取缓存统计信息(用于调试)
74
+ */
75
+ export function getTokenCacheStats(): {
76
+ total: number;
77
+ valid: number;
78
+ expired: number;
79
+ } {
80
+ const now = Date.now();
81
+ let valid = 0;
82
+ let expired = 0;
83
+
84
+ for (const entry of tokenCache.values()) {
85
+ if (now < entry.expiresAt) {
86
+ valid++;
87
+ } else {
88
+ expired++;
89
+ }
90
+ }
91
+
92
+ return {
93
+ total: tokenCache.size,
94
+ valid,
95
+ expired,
96
+ };
97
+ }