@workclaw/openclaw-workclaw 1.0.16 → 1.0.18
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 +21 -1
- package/index.ts +210 -210
- package/openclaw.plugin.json +1 -0
- package/package.json +12 -5
- package/setup-entry.ts +6 -0
- package/skills/openclaw-workclaw-cron/SKILL.md +45 -28
- package/src/accounts.ts +62 -37
- package/src/api/accounts-api.ts +88 -89
- package/src/api/prompts-api.ts +70 -77
- package/src/api/session-api.ts +99 -108
- package/src/api/skills-api.ts +35 -37
- package/src/api/workspace.ts +27 -29
- package/src/channel.ts +200 -202
- package/src/config-schema.ts +9 -9
- package/src/connection/workclaw-client.ts +554 -567
- package/src/gateway/agent-handlers.ts +392 -426
- package/src/gateway/config-writer.ts +228 -243
- package/src/gateway/message-context.ts +534 -362
- package/src/gateway/message-dispatcher.ts +529 -489
- package/src/gateway/reconnect.ts +217 -113
- package/src/gateway/skills-handler.ts +408 -472
- package/src/gateway/skills-list-handler.ts +9 -9
- package/src/gateway/tools-list-handler.ts +70 -72
- package/src/gateway/workclaw-gateway.ts +328 -486
- package/src/media/upload.ts +83 -94
- package/src/outbound/index.ts +57 -55
- package/src/outbound/workclaw-sender.ts +134 -133
- package/src/runtime.ts +291 -194
- package/src/send.ts +1 -1
- package/src/tools/openclaw-workclaw-cron/api/index.ts +6 -6
- package/src/tools/openclaw-workclaw-cron/src/add/params.ts +20 -19
- package/src/tools/openclaw-workclaw-cron/src/add/sync.ts +2 -2
- package/src/tools/openclaw-workclaw-cron/src/disable/params.ts +1 -1
- package/src/tools/openclaw-workclaw-cron/src/disable/sync.ts +3 -3
- package/src/tools/openclaw-workclaw-cron/src/enable/params.ts +1 -1
- package/src/tools/openclaw-workclaw-cron/src/enable/sync.ts +3 -3
- package/src/tools/openclaw-workclaw-cron/src/notify/sync.ts +2 -2
- package/src/tools/openclaw-workclaw-cron/src/remove/params.ts +1 -1
- package/src/tools/openclaw-workclaw-cron/src/remove/sync.ts +3 -3
- package/src/tools/openclaw-workclaw-cron/src/update/params.ts +195 -197
- package/src/tools/openclaw-workclaw-cron/src/update/sync.ts +4 -4
- package/src/tools/openclaw-workclaw-system/src/get/index.ts +2 -2
- package/src/tools/openclaw-workclaw-system/src/token/index.ts +4 -4
- package/src/types.ts +38 -40
- package/src/utils/content.ts +16 -21
- package/tests/accounts.test.ts +285 -0
- package/tests/message-context.test.ts +313 -0
- package/tests/reconnect.test.ts +257 -0
- package/tests/workclaw-client.test.ts +112 -0
- package/tsconfig.json +8 -5
- package/vitest.config.ts +8 -0
|
@@ -1,133 +1,134 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { OpenclawWorkclawFullAccountConfig } from '../types.js'
|
|
1
|
+
import type { WorkclawFullAccountConfig } from "../types.js";
|
|
3
2
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} from
|
|
9
|
-
import {
|
|
3
|
+
sendWorkclawMessage,
|
|
4
|
+
sendWorkclawReplyMessage as sendWorkclawReplyToMessage,
|
|
5
|
+
resolveWorkclawMessage,
|
|
6
|
+
type WorkclawConnectionConfig,
|
|
7
|
+
} from "../connection/workclaw-client.js";
|
|
8
|
+
import { getWorkclawLogger } from "../runtime.js";
|
|
10
9
|
|
|
11
10
|
export interface WorkClawSenderParams {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
11
|
+
cacheKey: string;
|
|
12
|
+
to: string;
|
|
13
|
+
text: string;
|
|
14
|
+
mediaUrl?: string;
|
|
15
|
+
replyToMessageId?: string;
|
|
16
|
+
openConversationId?: string;
|
|
17
|
+
agentId?: string | number;
|
|
18
|
+
config: WorkclawFullAccountConfig;
|
|
19
|
+
/**
|
|
20
|
+
* 消息类型:
|
|
21
|
+
* - "reply": 回复消息(用户触发)
|
|
22
|
+
* - "push": 主动推送(定时任务触发)
|
|
23
|
+
*/
|
|
24
|
+
messageType?: "reply" | "push";
|
|
25
|
+
msgType?: string;
|
|
26
|
+
last?: boolean;
|
|
28
27
|
}
|
|
29
28
|
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
|
|
30
|
+
export async function sendWorkclawOutboundMessage(
|
|
31
|
+
params: WorkClawSenderParams,
|
|
32
32
|
): Promise<{ messageId: string }> {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (!msgType) {
|
|
59
|
-
({ msgType, content } = resolveOpenclawWorkclawMessage(content, mediaUrl))
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// msgType 转换为 "1"(文本)或其他类型码
|
|
63
|
-
const messageTypeCode = msgType === 'text' ? '1' : msgType
|
|
64
|
-
|
|
65
|
-
// 构建 OpenclawWorkclawConnectionConfig(短名格式,用于 connection 模块)
|
|
66
|
-
const workclawConfig: OpenclawWorkclawConnectionConfig = {
|
|
67
|
-
baseUrl: config.baseUrl ?? '',
|
|
68
|
-
appKey: config.appKey ?? '',
|
|
69
|
-
appSecret: config.appSecret ?? '',
|
|
70
|
-
localIp: config.localIp,
|
|
71
|
-
allowInsecureTls: config.allowInsecureTls,
|
|
72
|
-
requestTimeout: config.requestTimeout,
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// 解析 userId 作为 receiveId(优先使用配置中保存的原始 userId)
|
|
76
|
-
// 配置中的 userId 是原始值(可能为负数),to 是绝对值(OpenClaw 要求)
|
|
77
|
-
const receiveId = config.userId ?? to
|
|
78
|
-
|
|
79
|
-
// 从配置中读取 endpoint,支持自定义
|
|
80
|
-
const replyEndpoint = config.replyEndpoint || '/open-apis/im/v1/messages/{messageId}/reply'
|
|
81
|
-
const pushEndpoint = config.pushEndpoint || '/open-apis/im/v1/messages'
|
|
82
|
-
|
|
83
|
-
if (messageType === 'reply') {
|
|
84
|
-
// 回复消息需要 replyToMessageId
|
|
85
|
-
if (!replyToMessageId) {
|
|
86
|
-
throw new Error('replyToMessageId is required for reply message')
|
|
33
|
+
const {
|
|
34
|
+
cacheKey,
|
|
35
|
+
to,
|
|
36
|
+
mediaUrl,
|
|
37
|
+
replyToMessageId,
|
|
38
|
+
openConversationId,
|
|
39
|
+
agentId,
|
|
40
|
+
config,
|
|
41
|
+
messageType = "reply",
|
|
42
|
+
last,
|
|
43
|
+
} = params;
|
|
44
|
+
|
|
45
|
+
let msgType = params.msgType;
|
|
46
|
+
let content = params.text;
|
|
47
|
+
|
|
48
|
+
// 优先级: 传入参数 > 配置
|
|
49
|
+
const resolvedAgentId = agentId ?? config.agentId;
|
|
50
|
+
|
|
51
|
+
if (resolvedAgentId === undefined || resolvedAgentId === null || String(resolvedAgentId).trim() === "") {
|
|
52
|
+
throw new Error(
|
|
53
|
+
"agentId is required for sending messages. " +
|
|
54
|
+
"Please create an account via cloud platform command or configure accounts in openclaw.json"
|
|
55
|
+
);
|
|
87
56
|
}
|
|
88
57
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
//
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
//
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
58
|
+
|
|
59
|
+
if (!msgType) {
|
|
60
|
+
({ msgType, content } = resolveWorkclawMessage(content, mediaUrl));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
// msgType 转换为 "1"(文本)或其他类型码
|
|
65
|
+
const messageTypeCode = msgType === "text" ? "1" : msgType;
|
|
66
|
+
|
|
67
|
+
// 构建 WorkclawConnectionConfig(短名格式,用于 connection 模块)
|
|
68
|
+
const workclawConfig: WorkclawConnectionConfig = {
|
|
69
|
+
baseUrl: config.baseUrl ?? "",
|
|
70
|
+
appKey: config.appKey ?? "",
|
|
71
|
+
appSecret: config.appSecret ?? "",
|
|
72
|
+
localIp: config.localIp,
|
|
73
|
+
allowInsecureTls: config.allowInsecureTls,
|
|
74
|
+
requestTimeout: config.requestTimeout,
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// 解析 userId 作为 receiveId(优先使用配置中保存的原始 userId)
|
|
78
|
+
// 配置中的 userId 是原始值(可能为负数),to 是绝对值(OpenClaw 要求)
|
|
79
|
+
const receiveId = config.userId ?? to;
|
|
80
|
+
|
|
81
|
+
// 从配置中读取 endpoint,支持自定义
|
|
82
|
+
const replyEndpoint = config.replyEndpoint || "/open-apis/im/v1/messages/{messageId}/reply";
|
|
83
|
+
const pushEndpoint = config.pushEndpoint || "/open-apis/im/v1/messages";
|
|
84
|
+
|
|
85
|
+
if (messageType === "reply") {
|
|
86
|
+
// 回复消息需要 replyToMessageId
|
|
87
|
+
if (!replyToMessageId) {
|
|
88
|
+
throw new Error("replyToMessageId is required for reply message");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// 优先使用传入的 openConversationId,其次使用配置中持久化的
|
|
92
|
+
const resolvedOpenConversationId = openConversationId ?? config.openConversationId;
|
|
93
|
+
getWorkclawLogger().info(`Sending reply message to messageId: ${replyToMessageId}, openConversationId: ${resolvedOpenConversationId}`);
|
|
94
|
+
|
|
95
|
+
const msgId = await sendWorkclawReplyToMessage({
|
|
96
|
+
cacheKey,
|
|
97
|
+
config: workclawConfig,
|
|
98
|
+
agentId: resolvedAgentId,
|
|
99
|
+
receiveId,
|
|
100
|
+
msgType: messageTypeCode,
|
|
101
|
+
content,
|
|
102
|
+
messageId: replyToMessageId,
|
|
103
|
+
openConversationId: resolvedOpenConversationId,
|
|
104
|
+
endpoint: replyEndpoint.replace("{messageId}", String(replyToMessageId)),
|
|
105
|
+
last,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
return { messageId: msgId };
|
|
109
|
+
} else {
|
|
110
|
+
// 主动推送消息
|
|
111
|
+
getWorkclawLogger().info(` Sending proactive message`);
|
|
112
|
+
|
|
113
|
+
// 优先使用传入的 openConversationId,其次使用配置中持久化的
|
|
114
|
+
const resolvedOpenConversationId = openConversationId ?? config.openConversationId;
|
|
115
|
+
getWorkclawLogger().info(` Resolved openConversationId: ${resolvedOpenConversationId}`);
|
|
116
|
+
getWorkclawLogger().info(` Config openConversationId: ${config.openConversationId}`);
|
|
117
|
+
|
|
118
|
+
const msgId = await sendWorkclawMessage({
|
|
119
|
+
cacheKey,
|
|
120
|
+
config: workclawConfig,
|
|
121
|
+
agentId: resolvedAgentId,
|
|
122
|
+
receiveId,
|
|
123
|
+
msgType: messageTypeCode,
|
|
124
|
+
content,
|
|
125
|
+
openConversationId: resolvedOpenConversationId,
|
|
126
|
+
endpoint: pushEndpoint,
|
|
127
|
+
last,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
return { messageId: msgId };
|
|
131
|
+
}
|
|
131
132
|
}
|
|
132
133
|
|
|
133
134
|
/**
|
|
@@ -135,23 +136,23 @@ export async function sendOpenclawWorkclawOutboundMessage(
|
|
|
135
136
|
* POST /im/v1/messages
|
|
136
137
|
*/
|
|
137
138
|
export async function sendWorkClawPushMessage(
|
|
138
|
-
|
|
139
|
+
params: Omit<WorkClawSenderParams, "messageType">,
|
|
139
140
|
): Promise<{ messageId: string }> {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
141
|
+
return sendWorkclawOutboundMessage({
|
|
142
|
+
...params,
|
|
143
|
+
messageType: "push",
|
|
144
|
+
});
|
|
144
145
|
}
|
|
145
146
|
|
|
146
147
|
/**
|
|
147
148
|
* 发送回复消息(用户触发)
|
|
148
149
|
* POST /im/v1/messages/{messageId}/reply
|
|
149
150
|
*/
|
|
150
|
-
export async function
|
|
151
|
-
|
|
151
|
+
export async function sendWorkclawReplyMessage(
|
|
152
|
+
params: Omit<WorkClawSenderParams, "messageType">,
|
|
152
153
|
): Promise<{ messageId: string }> {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
154
|
+
return sendWorkclawOutboundMessage({
|
|
155
|
+
...params,
|
|
156
|
+
messageType: "reply",
|
|
157
|
+
});
|
|
157
158
|
}
|