@workclaw/openclaw-workclaw 1.0.18 → 1.0.20
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 +30 -11
- package/dist/api.d.ts +3 -0
- package/dist/api.js +3 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +264 -0
- package/dist/setup-entry.d.ts +2 -0
- package/dist/setup-entry.js +12 -0
- package/dist/src/accounts.d.ts +66 -0
- package/dist/src/accounts.js +279 -0
- package/dist/src/api/accounts-api.d.ts +2 -0
- package/dist/src/api/accounts-api.js +130 -0
- package/dist/src/api/prompts-api.d.ts +2 -0
- package/dist/src/api/prompts-api.js +103 -0
- package/dist/src/api/session-api.d.ts +2 -0
- package/dist/src/api/session-api.js +207 -0
- package/dist/src/api/skills-api.d.ts +2 -0
- package/dist/src/api/skills-api.js +64 -0
- package/dist/src/api/workspace.d.ts +3 -0
- package/dist/src/api/workspace.js +30 -0
- package/dist/src/channel.d.ts +11 -0
- package/{src/channel.ts → dist/src/channel.js} +199 -225
- package/dist/src/config-schema.d.ts +93 -0
- package/dist/src/config-schema.js +56 -0
- package/dist/src/connection/workclaw-client.d.ts +147 -0
- package/dist/src/connection/workclaw-client.js +351 -0
- package/dist/src/gateway/agent-handlers.d.ts +12 -0
- package/{src/gateway/agent-handlers.ts → dist/src/gateway/agent-handlers.js} +372 -462
- package/dist/src/gateway/config-writer.d.ts +71 -0
- package/dist/src/gateway/config-writer.js +302 -0
- package/dist/src/gateway/cron-tasks-handler.d.ts +19 -0
- package/dist/src/gateway/cron-tasks-handler.js +188 -0
- package/dist/src/gateway/message-context.d.ts +80 -0
- package/{src/gateway/message-context.ts → dist/src/gateway/message-context.js} +509 -594
- package/dist/src/gateway/message-dispatcher.d.ts +18 -0
- package/dist/src/gateway/message-dispatcher.js +572 -0
- package/dist/src/gateway/reconnect.d.ts +27 -0
- package/{src/gateway/reconnect.ts → dist/src/gateway/reconnect.js} +210 -253
- package/dist/src/gateway/skills-handler.d.ts +29 -0
- package/dist/src/gateway/skills-handler.js +615 -0
- package/dist/src/gateway/skills-list-handler.d.ts +27 -0
- package/dist/src/gateway/skills-list-handler.js +233 -0
- package/dist/src/gateway/tools-list-handler.d.ts +30 -0
- package/dist/src/gateway/tools-list-handler.js +101 -0
- package/dist/src/gateway/workclaw-gateway.d.ts +14 -0
- package/dist/src/gateway/workclaw-gateway.js +237 -0
- package/dist/src/media/upload.d.ts +13 -0
- package/dist/src/media/upload.js +125 -0
- package/dist/src/outbound/index.d.ts +36 -0
- package/dist/src/outbound/index.js +123 -0
- package/dist/src/outbound/workclaw-sender.d.ts +36 -0
- package/{src/outbound/workclaw-sender.ts → dist/src/outbound/workclaw-sender.js} +95 -158
- package/dist/src/runtime.d.ts +116 -0
- package/dist/src/runtime.js +374 -0
- package/dist/src/secret-contract-api.d.ts +4 -0
- package/dist/src/secret-contract-api.js +4 -0
- package/{src/send.ts → dist/src/send.d.ts} +1 -1
- package/dist/src/send.js +1 -0
- package/dist/src/setup-api.d.ts +3 -0
- package/dist/src/setup-api.js +3 -0
- package/dist/src/setup-core.d.ts +3 -0
- package/dist/src/setup-core.js +13 -0
- package/dist/src/setup-surface.d.ts +7 -0
- package/dist/src/setup-surface.js +363 -0
- package/dist/src/tools/openclaw-workclaw-cron/api/index.d.ts +93 -0
- package/dist/src/tools/openclaw-workclaw-cron/api/index.js +209 -0
- package/dist/src/tools/openclaw-workclaw-cron/index.d.ts +10 -0
- package/{src/tools/openclaw-workclaw-cron/index.ts → dist/src/tools/openclaw-workclaw-cron/index.js} +33 -39
- package/dist/src/tools/openclaw-workclaw-cron/src/add/params.d.ts +16 -0
- package/dist/src/tools/openclaw-workclaw-cron/src/add/params.js +152 -0
- package/dist/src/tools/openclaw-workclaw-cron/src/add/sync.d.ts +18 -0
- package/dist/src/tools/openclaw-workclaw-cron/src/add/sync.js +162 -0
- package/dist/src/tools/openclaw-workclaw-cron/src/disable/params.d.ts +14 -0
- package/dist/src/tools/openclaw-workclaw-cron/src/disable/params.js +80 -0
- package/dist/src/tools/openclaw-workclaw-cron/src/disable/sync.d.ts +14 -0
- package/dist/src/tools/openclaw-workclaw-cron/src/disable/sync.js +107 -0
- package/dist/src/tools/openclaw-workclaw-cron/src/enable/params.d.ts +14 -0
- package/dist/src/tools/openclaw-workclaw-cron/src/enable/params.js +80 -0
- package/dist/src/tools/openclaw-workclaw-cron/src/enable/sync.d.ts +14 -0
- package/dist/src/tools/openclaw-workclaw-cron/src/enable/sync.js +107 -0
- package/dist/src/tools/openclaw-workclaw-cron/src/notify/sync.d.ts +17 -0
- package/dist/src/tools/openclaw-workclaw-cron/src/notify/sync.js +127 -0
- package/dist/src/tools/openclaw-workclaw-cron/src/remove/params.d.ts +14 -0
- package/dist/src/tools/openclaw-workclaw-cron/src/remove/params.js +87 -0
- package/dist/src/tools/openclaw-workclaw-cron/src/remove/sync.d.ts +14 -0
- package/dist/src/tools/openclaw-workclaw-cron/src/remove/sync.js +107 -0
- package/dist/src/tools/openclaw-workclaw-cron/src/update/params.d.ts +17 -0
- package/dist/src/tools/openclaw-workclaw-cron/src/update/params.js +164 -0
- package/dist/src/tools/openclaw-workclaw-cron/src/update/sync.d.ts +18 -0
- package/dist/src/tools/openclaw-workclaw-cron/src/update/sync.js +135 -0
- package/dist/src/tools/openclaw-workclaw-cron/types/index.d.ts +52 -0
- package/dist/src/tools/openclaw-workclaw-cron/types/index.js +4 -0
- package/dist/src/tools/openclaw-workclaw-cron/utils/index.d.ts +40 -0
- package/dist/src/tools/openclaw-workclaw-cron/utils/index.js +122 -0
- package/dist/src/tools/openclaw-workclaw-system/index.d.ts +10 -0
- package/{src/tools/openclaw-workclaw-system/index.ts → dist/src/tools/openclaw-workclaw-system/index.js} +15 -17
- package/dist/src/tools/openclaw-workclaw-system/src/get/index.d.ts +8 -0
- package/dist/src/tools/openclaw-workclaw-system/src/get/index.js +64 -0
- package/dist/src/tools/openclaw-workclaw-system/src/token/index.d.ts +8 -0
- package/dist/src/tools/openclaw-workclaw-system/src/token/index.js +78 -0
- package/{src/types.ts → dist/src/types.d.ts} +39 -58
- package/dist/src/types.js +1 -0
- package/dist/src/utils/content.d.ts +15 -0
- package/{src/utils/content.ts → dist/src/utils/content.js} +38 -35
- package/package.json +13 -9
- package/index.ts +0 -302
- package/setup-entry.ts +0 -6
- package/src/accounts.ts +0 -312
- package/src/api/accounts-api.ts +0 -156
- package/src/api/prompts-api.ts +0 -116
- package/src/api/session-api.ts +0 -238
- package/src/api/skills-api.ts +0 -72
- package/src/api/workspace.ts +0 -41
- package/src/config-schema.ts +0 -110
- package/src/connection/workclaw-client.ts +0 -643
- package/src/gateway/config-writer.ts +0 -296
- package/src/gateway/message-dispatcher.ts +0 -641
- package/src/gateway/skills-handler.ts +0 -741
- package/src/gateway/skills-list-handler.ts +0 -332
- package/src/gateway/tools-list-handler.ts +0 -160
- package/src/gateway/workclaw-gateway.ts +0 -367
- package/src/media/upload.ts +0 -157
- package/src/outbound/index.ts +0 -185
- package/src/runtime.ts +0 -497
- package/src/tools/openclaw-workclaw-cron/api/index.ts +0 -326
- package/src/tools/openclaw-workclaw-cron/src/add/params.ts +0 -177
- package/src/tools/openclaw-workclaw-cron/src/add/sync.ts +0 -188
- package/src/tools/openclaw-workclaw-cron/src/disable/params.ts +0 -100
- package/src/tools/openclaw-workclaw-cron/src/disable/sync.ts +0 -127
- package/src/tools/openclaw-workclaw-cron/src/enable/params.ts +0 -100
- package/src/tools/openclaw-workclaw-cron/src/enable/sync.ts +0 -127
- package/src/tools/openclaw-workclaw-cron/src/notify/sync.ts +0 -148
- package/src/tools/openclaw-workclaw-cron/src/remove/params.ts +0 -109
- package/src/tools/openclaw-workclaw-cron/src/remove/sync.ts +0 -127
- package/src/tools/openclaw-workclaw-cron/src/update/params.ts +0 -195
- package/src/tools/openclaw-workclaw-cron/src/update/sync.ts +0 -161
- package/src/tools/openclaw-workclaw-cron/types/index.ts +0 -55
- package/src/tools/openclaw-workclaw-cron/utils/index.ts +0 -141
- package/src/tools/openclaw-workclaw-system/src/get/index.ts +0 -77
- package/src/tools/openclaw-workclaw-system/src/token/index.ts +0 -93
- package/tests/accounts.test.ts +0 -285
- package/tests/message-context.test.ts +0 -313
- package/tests/reconnect.test.ts +0 -257
- package/tests/workclaw-client.test.ts +0 -112
- package/tsconfig.json +0 -14
- package/vitest.config.ts +0 -8
|
@@ -1,245 +1,204 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent Handlers - handle AGENT_CREATED, AGENT_UPDATED, AGENT_DELETED events
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
)
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
//
|
|
167
|
-
if (
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if (
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
//
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
if (existsSync(src)) {
|
|
203
|
-
await copyFile(src, dest);
|
|
204
|
-
log?.info?.(`Workspace: Copied ${file} to ${workspaceDir}`);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
// 2. 生成 IDENTITY.md(使用后端推送的智能体信息)
|
|
210
|
-
const identityContent = buildIdentityContent(accountData);
|
|
211
|
-
const identityPath = join(workspaceDir, "IDENTITY.md");
|
|
212
|
-
await writeFile(identityPath, identityContent, "utf-8");
|
|
213
|
-
log?.info?.(`Workspace: Created IDENTITY.md in ${workspaceDir}`);
|
|
214
|
-
|
|
215
|
-
// 3. 生成 SOUL.md(使用后端推送的智能体信息)
|
|
216
|
-
const soulContent = buildSoulContent(accountData);
|
|
217
|
-
const soulPath = join(workspaceDir, "SOUL.md");
|
|
218
|
-
await writeFile(soulPath, soulContent, "utf-8");
|
|
219
|
-
log?.info?.(`Workspace: Created SOUL.md in ${workspaceDir}`);
|
|
220
|
-
|
|
221
|
-
log?.info?.(`Workspace: Successfully initialized workspace for agent ${agentId}`);
|
|
222
|
-
} catch (err) {
|
|
223
|
-
log?.error?.(`Workspace: Failed to initialize workspace: ${String(err)}`);
|
|
224
|
-
// 不抛出错误,不影响主流程
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* 构建 IDENTITY.md 内容
|
|
230
|
-
*/
|
|
231
|
-
function buildIdentityContent(accountData: {
|
|
232
|
-
nickName?: string;
|
|
233
|
-
name?: string;
|
|
234
|
-
tip?: string;
|
|
235
|
-
characterSettings?: string;
|
|
236
|
-
job?: string;
|
|
237
|
-
city?: string;
|
|
238
|
-
}): string {
|
|
239
|
-
const agentName = accountData.nickName || accountData.name || "智小途";
|
|
240
|
-
const tip = accountData.tip || "";
|
|
241
|
-
const characterSettings = accountData.characterSettings || "";
|
|
242
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Agent Handlers - handle AGENT_CREATED, AGENT_UPDATED, AGENT_DELETED events
|
|
3
|
+
*/
|
|
4
|
+
import { resolveAccountByUserIdAndAgentId, allocateWorkerAccountId, refreshAccountCache } from "../accounts.js";
|
|
5
|
+
import { writeConfigFile } from "./config-writer.js";
|
|
6
|
+
import { stopWorkclawGateway } from "./workclaw-gateway.js";
|
|
7
|
+
import { homedir } from "os";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
import { writeFile, copyFile, mkdir } from "fs/promises";
|
|
10
|
+
import { execSync } from "child_process";
|
|
11
|
+
import { existsSync } from "fs";
|
|
12
|
+
/** 修复目录所有权(仅非 Windows 环境) */
|
|
13
|
+
function fixOwner(dir) {
|
|
14
|
+
if (process.platform === 'win32')
|
|
15
|
+
return;
|
|
16
|
+
try {
|
|
17
|
+
execSync(`chown -R node:node "${dir}"`, { stdio: 'ignore' });
|
|
18
|
+
}
|
|
19
|
+
catch { }
|
|
20
|
+
}
|
|
21
|
+
async function createSubAgentForAccount(agentId, userId, accountData, cfg, log) {
|
|
22
|
+
try {
|
|
23
|
+
const channels = cfg?.channels ?? {};
|
|
24
|
+
const openclawWorkclaw = channels['openclaw-workclaw'] ?? {};
|
|
25
|
+
const accounts = openclawWorkclaw.accounts ?? {};
|
|
26
|
+
const accountCount = Object.keys(accounts).length;
|
|
27
|
+
const subAgentId = `workclaw-${agentId}`;
|
|
28
|
+
const existingAgents = cfg?.agents?.list ?? [];
|
|
29
|
+
const existingBindings = cfg?.bindings ?? [];
|
|
30
|
+
const agentExists = existingAgents.some((a) => a.id === subAgentId);
|
|
31
|
+
if (!agentExists) {
|
|
32
|
+
const newAgentsList = [...existingAgents];
|
|
33
|
+
const subAgent = {
|
|
34
|
+
id: subAgentId,
|
|
35
|
+
default: false,
|
|
36
|
+
name: accountData.nickName || `智小途 - Agent ${agentId}`,
|
|
37
|
+
workspace: `~/.openclaw/workspace-workclaw/${agentId}`,
|
|
38
|
+
agentDir: `~/.openclaw/agents/workclaw-${agentId}/agent`,
|
|
39
|
+
tools: { allow: ["*"] },
|
|
40
|
+
};
|
|
41
|
+
newAgentsList.push(subAgent);
|
|
42
|
+
if (accountCount === 0) {
|
|
43
|
+
const defaultAgent = {
|
|
44
|
+
id: "default",
|
|
45
|
+
default: true,
|
|
46
|
+
name: "Default Agent",
|
|
47
|
+
workspace: "default",
|
|
48
|
+
tools: { allow: ["*"] },
|
|
49
|
+
};
|
|
50
|
+
newAgentsList.push(defaultAgent);
|
|
51
|
+
log?.info?.(`SubAgent: Created default agent with default workspace`);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
log?.info?.(`SubAgent: Using existing default agent`);
|
|
55
|
+
}
|
|
56
|
+
const bindingAccountId = resolveAccountByUserIdAndAgentId(cfg, String(userId), String(agentId));
|
|
57
|
+
const newBinding = {
|
|
58
|
+
agentId: subAgentId,
|
|
59
|
+
match: {
|
|
60
|
+
channel: "openclaw-workclaw",
|
|
61
|
+
accountId: bindingAccountId ?? "*",
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
const newBindings = [...existingBindings, newBinding];
|
|
65
|
+
log?.info?.(`SubAgent: Created binding for agentId: ${subAgentId}, accountId: ${bindingAccountId ?? "*"}`);
|
|
66
|
+
return {
|
|
67
|
+
agents: {
|
|
68
|
+
list: newAgentsList,
|
|
69
|
+
defaults: cfg?.agents?.defaults ?? {},
|
|
70
|
+
},
|
|
71
|
+
bindings: newBindings,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
const newAgents = {
|
|
76
|
+
list: [...existingAgents],
|
|
77
|
+
defaults: cfg?.agents?.defaults ?? {},
|
|
78
|
+
};
|
|
79
|
+
const bindingExists = existingBindings.some((b) => b?.agentId === subAgentId);
|
|
80
|
+
let newBindings = [...existingBindings];
|
|
81
|
+
if (!bindingExists) {
|
|
82
|
+
const bindingAccountId = resolveAccountByUserIdAndAgentId(cfg, String(userId), String(agentId));
|
|
83
|
+
newBindings.push({
|
|
84
|
+
agentId: subAgentId,
|
|
85
|
+
match: {
|
|
86
|
+
channel: "openclaw-workclaw",
|
|
87
|
+
accountId: bindingAccountId ?? "*",
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
log?.info?.(`SubAgent: Created binding for agentId: ${subAgentId}, accountId: ${bindingAccountId ?? "*"}`);
|
|
91
|
+
}
|
|
92
|
+
log?.info?.(`SubAgent: Created sub-agent: ${subAgentId} with workspace: workclaw-${agentId} (account #${accountCount + 1})`);
|
|
93
|
+
return {
|
|
94
|
+
agents: newAgents,
|
|
95
|
+
bindings: newBindings,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
log?.error?.(`SubAgent: Failed to create sub-agent: ${String(err)}`);
|
|
101
|
+
return {};
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* 初始化智能体 workspace 目录
|
|
106
|
+
* 复制 AGENTS.md、TOOLS.md、USER.md,并生成 IDENTITY.md、SOUL.md
|
|
107
|
+
*/
|
|
108
|
+
async function initializeAgentWorkspace(agentId, accountData, log) {
|
|
109
|
+
try {
|
|
110
|
+
const agentIdStr = String(agentId);
|
|
111
|
+
const home = homedir().trim();
|
|
112
|
+
const workspaceDir = join(home, ".openclaw", "workspace-workclaw", agentIdStr);
|
|
113
|
+
const mainWorkspaceDir = join(home, ".openclaw", "workspace");
|
|
114
|
+
const openclawDir = join(home, ".openclaw");
|
|
115
|
+
// 确保 .openclaw 目录存在
|
|
116
|
+
if (!existsSync(openclawDir)) {
|
|
117
|
+
try {
|
|
118
|
+
await mkdir(openclawDir, { recursive: true, mode: 0o755 });
|
|
119
|
+
log?.info?.(`Workspace: Created directory ${openclawDir}`);
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
if (err.code === 'EACCES' || err.code === 'EPERM') {
|
|
123
|
+
log?.warn?.(`Workspace: Permission denied creating ${openclawDir}, attempting with 777`);
|
|
124
|
+
await mkdir(openclawDir, { recursive: true, mode: 0o777 });
|
|
125
|
+
}
|
|
126
|
+
else
|
|
127
|
+
throw err;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// 修复权限(目录可能已存在但权限不对)
|
|
131
|
+
fixOwner(openclawDir);
|
|
132
|
+
// 确保 workspace 目录存在
|
|
133
|
+
if (!existsSync(workspaceDir)) {
|
|
134
|
+
try {
|
|
135
|
+
await mkdir(workspaceDir, { recursive: true, mode: 0o755 });
|
|
136
|
+
log?.info?.(`Workspace: Created directory ${workspaceDir}`);
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
if (err.code === 'EACCES' || err.code === 'EPERM') {
|
|
140
|
+
log?.warn?.(`Workspace: Permission denied creating ${workspaceDir}, attempting with 777`);
|
|
141
|
+
await mkdir(workspaceDir, { recursive: true, mode: 0o777 });
|
|
142
|
+
}
|
|
143
|
+
else
|
|
144
|
+
throw err;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// 修复权限(目录可能已存在但权限不对)
|
|
148
|
+
fixOwner(workspaceDir);
|
|
149
|
+
// 确保 main workspace 目录存在(用于复制模板文件)
|
|
150
|
+
if (!existsSync(mainWorkspaceDir)) {
|
|
151
|
+
try {
|
|
152
|
+
await mkdir(mainWorkspaceDir, { recursive: true, mode: 0o755 });
|
|
153
|
+
log?.info?.(`Workspace: Created directory ${mainWorkspaceDir}`);
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
if (err.code === 'EACCES' || err.code === 'EPERM') {
|
|
157
|
+
log?.warn?.(`Workspace: Permission denied creating ${mainWorkspaceDir}, attempting with 777`);
|
|
158
|
+
await mkdir(mainWorkspaceDir, { recursive: true, mode: 0o777 });
|
|
159
|
+
}
|
|
160
|
+
else
|
|
161
|
+
throw err;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// 修复权限(目录可能已存在但权限不对)
|
|
165
|
+
fixOwner(mainWorkspaceDir);
|
|
166
|
+
// 1. 复制 AGENTS.md、TOOLS.md、USER.md(从 main workspace)
|
|
167
|
+
if (existsSync(mainWorkspaceDir)) {
|
|
168
|
+
const filesToCopy = ["AGENTS.md", "TOOLS.md", "USER.md"];
|
|
169
|
+
for (const file of filesToCopy) {
|
|
170
|
+
const src = join(mainWorkspaceDir, file);
|
|
171
|
+
const dest = join(workspaceDir, file);
|
|
172
|
+
if (existsSync(src)) {
|
|
173
|
+
await copyFile(src, dest);
|
|
174
|
+
log?.info?.(`Workspace: Copied ${file} to ${workspaceDir}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
// 2. 生成 IDENTITY.md(使用后端推送的智能体信息)
|
|
179
|
+
const identityContent = buildIdentityContent(accountData);
|
|
180
|
+
const identityPath = join(workspaceDir, "IDENTITY.md");
|
|
181
|
+
await writeFile(identityPath, identityContent, "utf-8");
|
|
182
|
+
log?.info?.(`Workspace: Created IDENTITY.md in ${workspaceDir}`);
|
|
183
|
+
// 3. 生成 SOUL.md(使用后端推送的智能体信息)
|
|
184
|
+
const soulContent = buildSoulContent(accountData);
|
|
185
|
+
const soulPath = join(workspaceDir, "SOUL.md");
|
|
186
|
+
await writeFile(soulPath, soulContent, "utf-8");
|
|
187
|
+
log?.info?.(`Workspace: Created SOUL.md in ${workspaceDir}`);
|
|
188
|
+
log?.info?.(`Workspace: Successfully initialized workspace for agent ${agentId}`);
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
log?.error?.(`Workspace: Failed to initialize workspace: ${String(err)}`);
|
|
192
|
+
// 不抛出错误,不影响主流程
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* 构建 IDENTITY.md 内容
|
|
197
|
+
*/
|
|
198
|
+
function buildIdentityContent(accountData) {
|
|
199
|
+
const agentName = accountData.nickName || accountData.name || "智小途";
|
|
200
|
+
const tip = accountData.tip || "";
|
|
201
|
+
const characterSettings = accountData.characterSettings || "";
|
|
243
202
|
return `# IDENTITY.md - Who Am I?
|
|
244
203
|
|
|
245
204
|
_Fill this in during your first conversation. Make it yours._
|
|
@@ -258,40 +217,30 @@ Notes:
|
|
|
258
217
|
|
|
259
218
|
- Save this file at the workspace root as \`IDENTITY.md\`.
|
|
260
219
|
- For avatars, use a workspace-relative path like \`avatars/openclaw.png\`.
|
|
261
|
-
${tip ? `\n---\n${tip}` : ""}`;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
const
|
|
285
|
-
const city = accountData.city || "";
|
|
286
|
-
|
|
287
|
-
const features: string[] = [];
|
|
288
|
-
if (personFeatures) features.push(personFeatures);
|
|
289
|
-
if (workFeatures) features.push(workFeatures);
|
|
290
|
-
if (learningFeatures) features.push(learningFeatures);
|
|
291
|
-
if (socializeFeatures) features.push(socializeFeatures);
|
|
292
|
-
|
|
293
|
-
const featuresText = features.length > 0 ? `\n${features.map(f => `- ${f}`).join("\n")}` : "";
|
|
294
|
-
|
|
220
|
+
${tip ? `\n---\n${tip}` : ""}`;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* 构建 SOUL.md 内容
|
|
224
|
+
*/
|
|
225
|
+
function buildSoulContent(accountData) {
|
|
226
|
+
const agentName = accountData.nickName || accountData.name || "智小途";
|
|
227
|
+
const introduction = accountData.introduction || "";
|
|
228
|
+
const personFeatures = accountData.personFeatures || "";
|
|
229
|
+
const workFeatures = accountData.workFeatures || "";
|
|
230
|
+
const learningFeatures = accountData.learningFeatures || "";
|
|
231
|
+
const socializeFeatures = accountData.socializeFeatures || "";
|
|
232
|
+
const job = accountData.job || "";
|
|
233
|
+
const city = accountData.city || "";
|
|
234
|
+
const features = [];
|
|
235
|
+
if (personFeatures)
|
|
236
|
+
features.push(personFeatures);
|
|
237
|
+
if (workFeatures)
|
|
238
|
+
features.push(workFeatures);
|
|
239
|
+
if (learningFeatures)
|
|
240
|
+
features.push(learningFeatures);
|
|
241
|
+
if (socializeFeatures)
|
|
242
|
+
features.push(socializeFeatures);
|
|
243
|
+
const featuresText = features.length > 0 ? `\n${features.map(f => `- ${f}`).join("\n")}` : "";
|
|
295
244
|
return `# SOUL.md - Who You Are
|
|
296
245
|
|
|
297
246
|
_You're not a chatbot. You're becoming someone._
|
|
@@ -335,189 +284,150 @@ ${city ? `\n**城市:** ${city}` : ""}
|
|
|
335
284
|
|
|
336
285
|
---
|
|
337
286
|
|
|
338
|
-
_This file is yours to evolve. As you learn who you are, update it._`;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
const
|
|
425
|
-
const
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
log?.info?.(`AgentDeleted: Deleting account for agent ${agentId}, userId: ${userId}`);
|
|
488
|
-
|
|
489
|
-
const accountKey = resolveAccountByUserIdAndAgentId(cfg, String(userId), String(agentId));
|
|
490
|
-
|
|
491
|
-
const channels = cfg.channels || {};
|
|
492
|
-
const openclawWorkclaw = channels['openclaw-workclaw'] || {};
|
|
493
|
-
const accounts = openclawWorkclaw.accounts || {};
|
|
494
|
-
|
|
495
|
-
if (!accountKey || !accounts[accountKey]) {
|
|
496
|
-
log?.warn?.(`AgentDeleted: Account not found for (userId=${userId}, agentId=${agentId})`);
|
|
497
|
-
return;
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
const wsStrategy = (accounts[accountKey] as any)?.wsConnectionStrategy || "per-account";
|
|
501
|
-
stopWorkclawGateway(accountKey, wsStrategy);
|
|
502
|
-
log?.info?.(`AgentDeleted: Gateway stopped for account: ${accountKey}`);
|
|
503
|
-
|
|
504
|
-
delete accounts[accountKey];
|
|
505
|
-
|
|
506
|
-
const newConfig = {
|
|
507
|
-
...cfg,
|
|
508
|
-
channels: {
|
|
509
|
-
...channels,
|
|
510
|
-
'openclaw-workclaw': {
|
|
511
|
-
...openclawWorkclaw,
|
|
512
|
-
accounts,
|
|
513
|
-
},
|
|
514
|
-
},
|
|
515
|
-
};
|
|
516
|
-
|
|
517
|
-
await writeConfigFile(newConfig, cfg, log);
|
|
518
|
-
refreshAccountCache(cfg);
|
|
519
|
-
log?.info?.(`AgentDeleted: Account ${accountKey} deleted successfully`);
|
|
520
|
-
} catch (err) {
|
|
521
|
-
log?.error?.(`AgentDeleted: Failed to delete account: ${String(err)}`);
|
|
522
|
-
}
|
|
523
|
-
}
|
|
287
|
+
_This file is yours to evolve. As you learn who you are, update it._`;
|
|
288
|
+
}
|
|
289
|
+
export async function handleAgentCreated(accountData, cfg, log) {
|
|
290
|
+
try {
|
|
291
|
+
const agentId = accountData.agentId;
|
|
292
|
+
const userId = accountData.userId;
|
|
293
|
+
if (!agentId) {
|
|
294
|
+
log?.error?.(`AgentCreated: Missing agentId`);
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
log?.info?.(`AgentCreated: Creating account for agent ${agentId}, userId: ${userId}`);
|
|
298
|
+
const channels = cfg.channels || {};
|
|
299
|
+
const openclawWorkclaw = channels['openclaw-workclaw'] || {};
|
|
300
|
+
const accounts = { ...openclawWorkclaw.accounts };
|
|
301
|
+
let accountKey = resolveAccountByUserIdAndAgentId(cfg, String(userId), String(agentId));
|
|
302
|
+
if (accountKey) {
|
|
303
|
+
log?.info?.(`AgentCreated: Account ${accountKey} already exists, updating...`);
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
accountKey = allocateWorkerAccountId(cfg, String(userId), String(agentId));
|
|
307
|
+
log?.info?.(`AgentCreated: Allocated workspace account: ${accountKey} for (userId=${userId}, agentId=${agentId})`);
|
|
308
|
+
}
|
|
309
|
+
accounts[accountKey] = {
|
|
310
|
+
...accounts[accountKey],
|
|
311
|
+
enabled: true,
|
|
312
|
+
agentId: agentId,
|
|
313
|
+
};
|
|
314
|
+
const subAgentConfig = await createSubAgentForAccount(agentId, userId, accountData, cfg, log);
|
|
315
|
+
const newConfig = {
|
|
316
|
+
...cfg,
|
|
317
|
+
channels: {
|
|
318
|
+
...channels,
|
|
319
|
+
'openclaw-workclaw': {
|
|
320
|
+
...openclawWorkclaw,
|
|
321
|
+
accounts,
|
|
322
|
+
},
|
|
323
|
+
},
|
|
324
|
+
...subAgentConfig,
|
|
325
|
+
};
|
|
326
|
+
await writeConfigFile(newConfig, cfg, log);
|
|
327
|
+
refreshAccountCache(cfg);
|
|
328
|
+
log?.info?.(`AgentCreated: Account ${accountKey} created successfully`);
|
|
329
|
+
// 初始化 workspace 目录(复制/生成 AGENTS.md、TOOLS.md、USER.md、IDENTITY.md、SOUL.md)
|
|
330
|
+
await initializeAgentWorkspace(agentId, accountData, log);
|
|
331
|
+
}
|
|
332
|
+
catch (err) {
|
|
333
|
+
log?.error?.(`AgentCreated: Failed to create account: ${String(err)}`);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
export async function handleAgentUpdated(accountData, cfg, log) {
|
|
337
|
+
try {
|
|
338
|
+
const agentId = accountData.agentId;
|
|
339
|
+
const userId = accountData.userId;
|
|
340
|
+
if (!agentId) {
|
|
341
|
+
log?.error?.(`AgentUpdated: Missing agentId`);
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
log?.info?.(`AgentUpdated: Updating account for agent ${agentId}, userId: ${userId}`);
|
|
345
|
+
const accountKey = resolveAccountByUserIdAndAgentId(cfg, String(userId), String(agentId));
|
|
346
|
+
const channels = cfg.channels || {};
|
|
347
|
+
const openclawWorkclaw = channels['openclaw-workclaw'] || {};
|
|
348
|
+
const accounts = openclawWorkclaw.accounts || {};
|
|
349
|
+
if (!accountKey || !accounts[accountKey]) {
|
|
350
|
+
log?.warn?.(`AgentUpdated: Account not found (userId=${userId}, agentId=${agentId}), delegating to handleAgentCreated...`);
|
|
351
|
+
await handleAgentCreated(accountData, cfg, log);
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
accounts[accountKey] = {
|
|
355
|
+
...accounts[accountKey],
|
|
356
|
+
nickName: accountData.nickName,
|
|
357
|
+
phone: accountData.phone,
|
|
358
|
+
status: accountData.status,
|
|
359
|
+
introduction: accountData.introduction,
|
|
360
|
+
};
|
|
361
|
+
const newConfig = {
|
|
362
|
+
...cfg,
|
|
363
|
+
channels: {
|
|
364
|
+
...channels,
|
|
365
|
+
'openclaw-workclaw': {
|
|
366
|
+
...openclawWorkclaw,
|
|
367
|
+
accounts,
|
|
368
|
+
},
|
|
369
|
+
},
|
|
370
|
+
};
|
|
371
|
+
// 更新 agents.list 中对应 agent 的 name
|
|
372
|
+
const subAgentId = `workclaw-${agentId}`;
|
|
373
|
+
const agentsList = cfg?.agents?.list ?? [];
|
|
374
|
+
const agentIndex = agentsList.findIndex((a) => a.id === subAgentId);
|
|
375
|
+
if (agentIndex >= 0 && accountData.nickName) {
|
|
376
|
+
agentsList[agentIndex] = {
|
|
377
|
+
...agentsList[agentIndex],
|
|
378
|
+
name: accountData.nickName,
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
const finalConfig = {
|
|
382
|
+
...newConfig,
|
|
383
|
+
agents: {
|
|
384
|
+
...cfg?.agents,
|
|
385
|
+
list: agentsList,
|
|
386
|
+
},
|
|
387
|
+
};
|
|
388
|
+
await writeConfigFile(finalConfig, cfg, log);
|
|
389
|
+
refreshAccountCache(cfg);
|
|
390
|
+
log?.info?.(`AgentUpdated: Account ${accountKey} updated successfully`);
|
|
391
|
+
}
|
|
392
|
+
catch (err) {
|
|
393
|
+
log?.error?.(`AgentUpdated: Failed to update account: ${String(err)}`);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
export async function handleAgentDeleted(accountData, cfg, log) {
|
|
397
|
+
try {
|
|
398
|
+
const agentId = accountData.agentId;
|
|
399
|
+
const userId = accountData.userId;
|
|
400
|
+
if (!agentId) {
|
|
401
|
+
log?.error?.(`AgentDeleted: Missing agentId`);
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
log?.info?.(`AgentDeleted: Deleting account for agent ${agentId}, userId: ${userId}`);
|
|
405
|
+
const accountKey = resolveAccountByUserIdAndAgentId(cfg, String(userId), String(agentId));
|
|
406
|
+
const channels = cfg.channels || {};
|
|
407
|
+
const openclawWorkclaw = channels['openclaw-workclaw'] || {};
|
|
408
|
+
const accounts = openclawWorkclaw.accounts || {};
|
|
409
|
+
if (!accountKey || !accounts[accountKey]) {
|
|
410
|
+
log?.warn?.(`AgentDeleted: Account not found for (userId=${userId}, agentId=${agentId})`);
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
stopWorkclawGateway(accountKey);
|
|
414
|
+
log?.info?.(`AgentDeleted: Gateway stopped for account: ${accountKey}`);
|
|
415
|
+
delete accounts[accountKey];
|
|
416
|
+
const newConfig = {
|
|
417
|
+
...cfg,
|
|
418
|
+
channels: {
|
|
419
|
+
...channels,
|
|
420
|
+
'openclaw-workclaw': {
|
|
421
|
+
...openclawWorkclaw,
|
|
422
|
+
accounts,
|
|
423
|
+
},
|
|
424
|
+
},
|
|
425
|
+
};
|
|
426
|
+
await writeConfigFile(newConfig, cfg, log);
|
|
427
|
+
refreshAccountCache(cfg);
|
|
428
|
+
log?.info?.(`AgentDeleted: Account ${accountKey} deleted successfully`);
|
|
429
|
+
}
|
|
430
|
+
catch (err) {
|
|
431
|
+
log?.error?.(`AgentDeleted: Failed to delete account: ${String(err)}`);
|
|
432
|
+
}
|
|
433
|
+
}
|