zrocclaw 0.0.12 → 0.0.14
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 +8 -0
- package/package.json +1 -1
- package/server/server.js +333 -53
- package/server/static/assets/{Chat-I4ZIdxyC.js → Chat-4RxQRwRb.js} +3 -3
- package/server/static/assets/Config-BT-iqhcX.js +1 -0
- package/server/static/assets/{Welcome-DPYUQXhQ.js → Welcome-CGBkelb3.js} +1 -1
- package/server/static/assets/index-B3xx8wNP.js +2 -0
- package/server/static/assets/index-CnpxtwAn.css +2 -0
- package/server/static/assets/runtime-core.esm-bundler-soWVaCX3.js +1 -0
- package/server/static/index.html +3 -3
- package/server/static/assets/Config-BnWzqU3z.js +0 -1
- package/server/static/assets/index-B4HOtFAZ.css +0 -2
- package/server/static/assets/index-emQuqO8G.js +0 -2
- package/server/static/assets/runtime-core.esm-bundler-DEKlsnJd.js +0 -1
package/README.md
CHANGED
|
@@ -6,6 +6,14 @@ ZrocClaw 官方命令行工具,用于快速启动和管理你的专属浏览
|
|
|
6
6
|
|
|
7
7
|
本工具提供了简易的命令,底层依赖 `pm2` 来守护后台进程,帮助你一键启动、停止、或更新 ZrocClaw 服务。
|
|
8
8
|
|
|
9
|
+
## 前置条件
|
|
10
|
+
|
|
11
|
+
在安装 CLI 工具前,请确保您的系统满足以下要求:
|
|
12
|
+
|
|
13
|
+
- **Node.js**: 版本需 **>= 22.0.0**。
|
|
14
|
+
- **包管理器**: `npm` 或 `pnpm`。
|
|
15
|
+
- **浏览器**: 需本地安装 **Google Chrome** 或 Chromium 浏览器(以支持 ZrocClaw 后台的浏览器自动化操作)。
|
|
16
|
+
|
|
9
17
|
## 安装
|
|
10
18
|
|
|
11
19
|
推荐进行全局安装,以便在任何终端路径下均可执行:
|
package/package.json
CHANGED
package/server/server.js
CHANGED
|
@@ -30,7 +30,7 @@ var import_helmet = __toESM(require("helmet"));
|
|
|
30
30
|
// src/routes/config.ts
|
|
31
31
|
var import_express = require("express");
|
|
32
32
|
|
|
33
|
-
// ../../packages/core/dist/chunk-
|
|
33
|
+
// ../../packages/core/dist/chunk-5YB6N3QX.mjs
|
|
34
34
|
var os = __toESM(require("os"), 1);
|
|
35
35
|
var path = __toESM(require("path"), 1);
|
|
36
36
|
var fs = __toESM(require("fs"), 1);
|
|
@@ -79,6 +79,10 @@ function getHistoryPath(subPath) {
|
|
|
79
79
|
const historyPath = path.join(getConfigPath(), "history");
|
|
80
80
|
return resolveAndEnsurePath(historyPath, subPath);
|
|
81
81
|
}
|
|
82
|
+
function getSkillsPath(subPath) {
|
|
83
|
+
const skillsPath = path.join(getWorkspacePath(), "skills");
|
|
84
|
+
return resolveAndEnsurePath(skillsPath, subPath);
|
|
85
|
+
}
|
|
82
86
|
var SessionModel = class _SessionModel {
|
|
83
87
|
static instance;
|
|
84
88
|
filePath;
|
|
@@ -167,27 +171,37 @@ var session_default = sessionModel;
|
|
|
167
171
|
// src/routes/config.ts
|
|
168
172
|
var import_promises = __toESM(require("fs/promises"));
|
|
169
173
|
var import_path2 = __toESM(require("path"));
|
|
174
|
+
var import_crypto = __toESM(require("crypto"));
|
|
170
175
|
var router = (0, import_express.Router)();
|
|
171
176
|
router.get("/", (req, res) => {
|
|
172
177
|
res.json({ configPath: getConfigPath() });
|
|
173
178
|
});
|
|
174
179
|
var configDir = getConfigPath();
|
|
175
|
-
var
|
|
180
|
+
var configModelPath = import_path2.default.join(configDir, "model.json");
|
|
181
|
+
async function readModelConfig() {
|
|
182
|
+
try {
|
|
183
|
+
await import_promises.default.access(configModelPath);
|
|
184
|
+
const data = await import_promises.default.readFile(configModelPath, "utf-8");
|
|
185
|
+
return JSON.parse(data);
|
|
186
|
+
} catch (error) {
|
|
187
|
+
if (error.code === "ENOENT") {
|
|
188
|
+
return {};
|
|
189
|
+
}
|
|
190
|
+
throw error;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
async function writeModelConfig(config) {
|
|
194
|
+
await import_promises.default.mkdir(configDir, { recursive: true });
|
|
195
|
+
await import_promises.default.writeFile(configModelPath, JSON.stringify(config, null, 2), "utf-8");
|
|
196
|
+
}
|
|
176
197
|
router.get("/model", async (req, res) => {
|
|
177
198
|
try {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
res.json(
|
|
182
|
-
} catch (error) {
|
|
183
|
-
if (error.code === "ENOENT") {
|
|
184
|
-
await import_promises.default.mkdir(configDir, { recursive: true });
|
|
185
|
-
await import_promises.default.writeFile(configFilePath, "{}", "utf-8");
|
|
186
|
-
res.json({});
|
|
187
|
-
} else {
|
|
188
|
-
throw error;
|
|
189
|
-
}
|
|
199
|
+
const config = await readModelConfig();
|
|
200
|
+
if (Object.keys(config).length === 0) {
|
|
201
|
+
await writeModelConfig({});
|
|
202
|
+
return res.json({});
|
|
190
203
|
}
|
|
204
|
+
res.json(config);
|
|
191
205
|
} catch (error) {
|
|
192
206
|
console.error("\u83B7\u53D6\u6A21\u578B\u5931\u8D25:", error);
|
|
193
207
|
res.status(500).json({ error: "\u83B7\u53D6\u6A21\u578B\u5931\u8D25" });
|
|
@@ -195,22 +209,237 @@ router.get("/model", async (req, res) => {
|
|
|
195
209
|
});
|
|
196
210
|
router.post("/model", async (req, res) => {
|
|
197
211
|
try {
|
|
198
|
-
|
|
199
|
-
|
|
212
|
+
const { modelName, provider, apiKey, baseURL } = req.body;
|
|
213
|
+
const newModel = {
|
|
214
|
+
id: import_crypto.default.randomUUID(),
|
|
215
|
+
modelName,
|
|
216
|
+
provider,
|
|
217
|
+
apiKey,
|
|
218
|
+
baseURL
|
|
219
|
+
};
|
|
220
|
+
const config = await readModelConfig();
|
|
221
|
+
if (!Array.isArray(config.models)) {
|
|
222
|
+
config.models = [];
|
|
223
|
+
}
|
|
224
|
+
config.models.unshift(newModel);
|
|
225
|
+
if (!config.defaultModel) {
|
|
226
|
+
config.defaultModel = newModel;
|
|
227
|
+
}
|
|
228
|
+
await writeModelConfig(config);
|
|
229
|
+
res.json(newModel);
|
|
230
|
+
} catch (error) {
|
|
231
|
+
console.error("\u65B0\u589E\u6A21\u578B\u5931\u8D25:", error);
|
|
232
|
+
res.status(500).json({ error: "\u65B0\u589E\u6A21\u578B\u5931\u8D25" });
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
router.post("/model/edit", async (req, res) => {
|
|
236
|
+
try {
|
|
237
|
+
const modelData = req.body;
|
|
238
|
+
if (!modelData || !modelData.id) {
|
|
239
|
+
return res.status(400).json({ error: "\u7F3A\u5C11\u6A21\u578BID" });
|
|
240
|
+
}
|
|
241
|
+
const config = await readModelConfig();
|
|
242
|
+
if (!Array.isArray(config.models)) {
|
|
243
|
+
config.models = [];
|
|
244
|
+
}
|
|
245
|
+
const index = config.models.findIndex((m) => m.id === modelData.id);
|
|
246
|
+
if (index === -1) {
|
|
247
|
+
return res.status(404).json({ error: "\u6A21\u578B\u4E0D\u5B58\u5728" });
|
|
248
|
+
}
|
|
249
|
+
config.models[index] = { ...config.models[index], ...modelData };
|
|
250
|
+
if (config.defaultModel && config.defaultModel.id === modelData.id) {
|
|
251
|
+
config.defaultModel = config.models[index];
|
|
252
|
+
}
|
|
253
|
+
await writeModelConfig(config);
|
|
254
|
+
res.json(config.models[index]);
|
|
255
|
+
} catch (error) {
|
|
256
|
+
console.error("\u7F16\u8F91\u6A21\u578B\u5931\u8D25:", error);
|
|
257
|
+
res.status(500).json({ error: "\u7F16\u8F91\u6A21\u578B\u5931\u8D25" });
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
router.post("/model/delete", async (req, res) => {
|
|
261
|
+
try {
|
|
262
|
+
const { id } = req.body;
|
|
263
|
+
if (!id) {
|
|
264
|
+
return res.status(400).json({ error: "\u7F3A\u5C11\u6A21\u578BID" });
|
|
265
|
+
}
|
|
266
|
+
const config = await readModelConfig();
|
|
267
|
+
if (!Array.isArray(config.models)) {
|
|
268
|
+
config.models = [];
|
|
269
|
+
}
|
|
270
|
+
const initialLength = config.models.length;
|
|
271
|
+
config.models = config.models.filter((m) => m.id !== id);
|
|
272
|
+
if (config.models.length === initialLength) {
|
|
273
|
+
return res.status(404).json({ error: "\u6A21\u578B\u4E0D\u5B58\u5728" });
|
|
274
|
+
}
|
|
275
|
+
if (config.defaultModel && config.defaultModel.id === id) {
|
|
276
|
+
config.defaultModel = config.models.length > 0 ? config.models[0] : null;
|
|
277
|
+
}
|
|
278
|
+
await writeModelConfig(config);
|
|
279
|
+
res.json({ success: true, message: "\u5220\u9664\u6210\u529F" });
|
|
280
|
+
} catch (error) {
|
|
281
|
+
console.error("\u5220\u9664\u6A21\u578B\u5931\u8D25:", error);
|
|
282
|
+
res.status(500).json({ error: "\u5220\u9664\u6A21\u578B\u5931\u8D25" });
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
router.post("/model/default", async (req, res) => {
|
|
286
|
+
try {
|
|
287
|
+
const { id } = req.body;
|
|
288
|
+
if (!id) {
|
|
289
|
+
return res.status(400).json({ error: "\u7F3A\u5C11\u6A21\u578BID" });
|
|
290
|
+
}
|
|
291
|
+
const config = await readModelConfig();
|
|
292
|
+
if (!Array.isArray(config.models)) {
|
|
293
|
+
config.models = [];
|
|
294
|
+
}
|
|
295
|
+
const model = config.models.find((m) => m.id === id);
|
|
296
|
+
if (!model) {
|
|
297
|
+
return res.status(404).json({ error: "\u6A21\u578B\u4E0D\u5B58\u5728" });
|
|
298
|
+
}
|
|
299
|
+
config.defaultModel = model;
|
|
300
|
+
await writeModelConfig(config);
|
|
301
|
+
res.json({ success: true, defaultModel: config.defaultModel });
|
|
302
|
+
} catch (error) {
|
|
303
|
+
console.error("\u8BBE\u7F6E\u9ED8\u8BA4\u6A21\u578B\u5931\u8D25:", error);
|
|
304
|
+
res.status(500).json({ error: "\u8BBE\u7F6E\u9ED8\u8BA4\u6A21\u578B\u5931\u8D25" });
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
var workspaceDir = getWorkspacePath();
|
|
308
|
+
var workspaceSkillsPath = import_path2.default.join(workspaceDir, "SKILLS.json");
|
|
309
|
+
var skillsDir = getSkillsPath();
|
|
310
|
+
async function readSkillsConfig() {
|
|
311
|
+
try {
|
|
312
|
+
await import_promises.default.access(workspaceSkillsPath);
|
|
313
|
+
const data = await import_promises.default.readFile(workspaceSkillsPath, "utf-8");
|
|
314
|
+
return JSON.parse(data);
|
|
315
|
+
} catch (error) {
|
|
316
|
+
if (error.code === "ENOENT") {
|
|
317
|
+
return [];
|
|
318
|
+
}
|
|
319
|
+
throw error;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
async function writeSkillsConfig(config) {
|
|
323
|
+
await import_promises.default.mkdir(workspaceDir, { recursive: true });
|
|
324
|
+
await import_promises.default.writeFile(workspaceSkillsPath, JSON.stringify(config, null, 2), "utf-8");
|
|
325
|
+
}
|
|
326
|
+
router.get("/skills", async (req, res) => {
|
|
327
|
+
try {
|
|
200
328
|
try {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
329
|
+
await import_promises.default.access(workspaceSkillsPath);
|
|
330
|
+
} catch (e) {
|
|
331
|
+
if (e.code === "ENOENT") {
|
|
332
|
+
await writeSkillsConfig([]);
|
|
333
|
+
return res.json([]);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
const config = await readSkillsConfig();
|
|
337
|
+
res.json(config);
|
|
338
|
+
} catch (error) {
|
|
339
|
+
console.error("\u83B7\u53D6\u6280\u80FD\u5217\u8868\u5931\u8D25:", error);
|
|
340
|
+
res.status(500).json({ error: "\u83B7\u53D6\u6280\u80FD\u5217\u8868\u5931\u8D25" });
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
router.post("/skills", async (req, res) => {
|
|
344
|
+
try {
|
|
345
|
+
const { name, summary, content } = req.body;
|
|
346
|
+
const id = import_crypto.default.randomUUID();
|
|
347
|
+
const newSkill = {
|
|
348
|
+
id,
|
|
349
|
+
name,
|
|
350
|
+
summary,
|
|
351
|
+
path: `./skills/${id}.md`
|
|
352
|
+
};
|
|
353
|
+
const skills = await readSkillsConfig();
|
|
354
|
+
if (!Array.isArray(skills)) {
|
|
355
|
+
throw new Error("skills.json \u683C\u5F0F\u9519\u8BEF");
|
|
356
|
+
}
|
|
357
|
+
skills.unshift(newSkill);
|
|
358
|
+
await writeSkillsConfig(skills);
|
|
359
|
+
await import_promises.default.mkdir(skillsDir, { recursive: true });
|
|
360
|
+
const mdPath = import_path2.default.join(skillsDir, `${id}.md`);
|
|
361
|
+
await import_promises.default.writeFile(mdPath, content || "", "utf-8");
|
|
362
|
+
res.json(newSkill);
|
|
363
|
+
} catch (error) {
|
|
364
|
+
console.error("\u65B0\u589E\u6280\u80FD\u5931\u8D25:", error);
|
|
365
|
+
res.status(500).json({ error: "\u65B0\u589E\u6280\u80FD\u5931\u8D25" });
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
router.post("/skills/edit", async (req, res) => {
|
|
369
|
+
try {
|
|
370
|
+
const { id, name, summary, content } = req.body;
|
|
371
|
+
if (!id) {
|
|
372
|
+
return res.status(400).json({ error: "\u7F3A\u5C11\u6280\u80FDID" });
|
|
373
|
+
}
|
|
374
|
+
const skills = await readSkillsConfig();
|
|
375
|
+
if (!Array.isArray(skills)) {
|
|
376
|
+
throw new Error("skills.json \u683C\u5F0F\u9519\u8BEF");
|
|
377
|
+
}
|
|
378
|
+
const index = skills.findIndex((s) => s.id === id);
|
|
379
|
+
if (index === -1) {
|
|
380
|
+
return res.status(404).json({ error: "\u6280\u80FD\u4E0D\u5B58\u5728" });
|
|
381
|
+
}
|
|
382
|
+
skills[index] = { ...skills[index], name, summary };
|
|
383
|
+
await writeSkillsConfig(skills);
|
|
384
|
+
await import_promises.default.mkdir(skillsDir, { recursive: true });
|
|
385
|
+
const mdPath = import_path2.default.join(skillsDir, `${id}.md`);
|
|
386
|
+
await import_promises.default.writeFile(mdPath, content || "", "utf-8");
|
|
387
|
+
res.json(skills[index]);
|
|
388
|
+
} catch (error) {
|
|
389
|
+
console.error("\u7F16\u8F91\u6280\u80FD\u5931\u8D25:", error);
|
|
390
|
+
res.status(500).json({ error: "\u7F16\u8F91\u6280\u80FD\u5931\u8D25" });
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
router.post("/skills/delete", async (req, res) => {
|
|
394
|
+
try {
|
|
395
|
+
const { id } = req.body;
|
|
396
|
+
if (!id) {
|
|
397
|
+
return res.status(400).json({ error: "\u7F3A\u5C11\u6280\u80FDID" });
|
|
398
|
+
}
|
|
399
|
+
let skills = await readSkillsConfig();
|
|
400
|
+
if (!Array.isArray(skills)) {
|
|
401
|
+
throw new Error("skills.json \u683C\u5F0F\u9519\u8BEF");
|
|
402
|
+
}
|
|
403
|
+
const initialLength = skills.length;
|
|
404
|
+
skills = skills.filter((s) => s.id !== id);
|
|
405
|
+
if (skills.length === initialLength) {
|
|
406
|
+
return res.status(404).json({ error: "\u6280\u80FD\u4E0D\u5B58\u5728" });
|
|
407
|
+
}
|
|
408
|
+
await writeSkillsConfig(skills);
|
|
409
|
+
const mdPath = import_path2.default.join(skillsDir, `${id}.md`);
|
|
410
|
+
try {
|
|
411
|
+
await import_promises.default.unlink(mdPath);
|
|
412
|
+
} catch (e) {
|
|
413
|
+
if (e.code !== "ENOENT") {
|
|
414
|
+
console.error("\u5220\u9664\u6280\u80FD\u6587\u4EF6\u5931\u8D25:", e);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
res.json({ success: true, message: "\u5220\u9664\u6210\u529F" });
|
|
418
|
+
} catch (error) {
|
|
419
|
+
console.error("\u5220\u9664\u6280\u80FD\u5931\u8D25:", error);
|
|
420
|
+
res.status(500).json({ error: "\u5220\u9664\u6280\u80FD\u5931\u8D25" });
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
router.post("/skills/detail", async (req, res) => {
|
|
424
|
+
try {
|
|
425
|
+
const { id } = req.body;
|
|
426
|
+
if (!id) {
|
|
427
|
+
return res.status(400).json({ error: "\u7F3A\u5C11\u6280\u80FDID" });
|
|
428
|
+
}
|
|
429
|
+
const mdPath = import_path2.default.join(skillsDir, `${id}.md`);
|
|
430
|
+
try {
|
|
431
|
+
await import_promises.default.access(mdPath);
|
|
432
|
+
const content = await import_promises.default.readFile(mdPath, "utf-8");
|
|
433
|
+
res.json({ content });
|
|
434
|
+
} catch (e) {
|
|
435
|
+
if (e.code === "ENOENT") {
|
|
436
|
+
return res.status(404).json({ error: "\u6280\u80FD\u6587\u4EF6\u4E0D\u5B58\u5728" });
|
|
206
437
|
}
|
|
438
|
+
throw e;
|
|
207
439
|
}
|
|
208
|
-
const newConfig = { ...currentConfig, ...req.body };
|
|
209
|
-
await import_promises.default.writeFile(configFilePath, JSON.stringify(newConfig, null, 2), "utf-8");
|
|
210
|
-
res.json(newConfig);
|
|
211
440
|
} catch (error) {
|
|
212
|
-
console.error("\
|
|
213
|
-
res.status(500).json({ error: "\
|
|
441
|
+
console.error("\u83B7\u53D6\u6280\u80FD\u8BE6\u60C5\u5931\u8D25:", error);
|
|
442
|
+
res.status(500).json({ error: "\u83B7\u53D6\u6280\u80FD\u8BE6\u60C5\u5931\u8D25" });
|
|
214
443
|
}
|
|
215
444
|
});
|
|
216
445
|
var config_default = router;
|
|
@@ -377,7 +606,7 @@ var PlaywrightExecutor = class {
|
|
|
377
606
|
}
|
|
378
607
|
};
|
|
379
608
|
|
|
380
|
-
// ../../packages/core/dist/chunk-
|
|
609
|
+
// ../../packages/core/dist/chunk-PEGXHECU.mjs
|
|
381
610
|
var import_openai = require("@langchain/openai");
|
|
382
611
|
var import_langchain = require("langchain");
|
|
383
612
|
var import_messages = require("@langchain/core/messages");
|
|
@@ -515,14 +744,28 @@ var readFileTool = (0, import_tools2.tool)(
|
|
|
515
744
|
}
|
|
516
745
|
);
|
|
517
746
|
var writeFileTool = (0, import_tools2.tool)(
|
|
518
|
-
async ({ filePath, content }) => {
|
|
747
|
+
async ({ filePath, content, startLine, endLine }) => {
|
|
519
748
|
const targetPath = resolveSafePath(filePath);
|
|
520
749
|
try {
|
|
521
750
|
const stat2 = await fs4.stat(targetPath);
|
|
522
751
|
if (!stat2.isFile()) {
|
|
523
752
|
throw new Error("\u76EE\u6807\u8DEF\u5F84\u4E0D\u662F\u6587\u4EF6");
|
|
524
753
|
}
|
|
525
|
-
|
|
754
|
+
if (startLine !== void 0) {
|
|
755
|
+
const fileContent = await fs4.readFile(targetPath, "utf-8");
|
|
756
|
+
const lines = fileContent.split("\n");
|
|
757
|
+
const startIdx = Math.max(0, startLine - 1);
|
|
758
|
+
let deleteCount = 1;
|
|
759
|
+
if (endLine !== void 0) {
|
|
760
|
+
const endIdx = endLine - 1;
|
|
761
|
+
deleteCount = Math.max(0, endIdx - startIdx + 1);
|
|
762
|
+
}
|
|
763
|
+
const contentLines = content.split("\n");
|
|
764
|
+
lines.splice(startIdx, deleteCount, ...contentLines);
|
|
765
|
+
await fs4.writeFile(targetPath, lines.join("\n"), { encoding: "utf-8" });
|
|
766
|
+
} else {
|
|
767
|
+
await fs4.writeFile(targetPath, content || "", { encoding: "utf-8" });
|
|
768
|
+
}
|
|
526
769
|
return JSON.stringify({
|
|
527
770
|
success: true,
|
|
528
771
|
operation: "write_file",
|
|
@@ -539,10 +782,12 @@ var writeFileTool = (0, import_tools2.tool)(
|
|
|
539
782
|
},
|
|
540
783
|
{
|
|
541
784
|
name: "write_file",
|
|
542
|
-
description: "\u5728\u5DE5\u4F5C\u76EE\u5F55\u5185\
|
|
785
|
+
description: "\u5728\u5DE5\u4F5C\u76EE\u5F55\u5185\u5199\u5165\u5DF2\u6709\u6587\u4EF6\u3002\u53EF\u4EE5\u5168\u91CF\u8986\u76D6\uFF0C\u4E5F\u53EF\u4EE5\u6307\u5B9A\u884C\u53F7\u8FDB\u884C\u5C40\u90E8\u66FF\u6362/\u63D2\u5165\u4EE5\u8282\u7701 token\u3002\u6CE8\u610F\uFF1AfilePath\u5FC5\u987B\u662F\u76F8\u5BF9\u5DE5\u4F5C\u76EE\u5F55\u7684\u8DEF\u5F84\u3002",
|
|
543
786
|
schema: z2.object({
|
|
544
787
|
filePath: z2.string().describe("\u76F8\u5BF9\u5DE5\u4F5C\u76EE\u5F55\u7684\u6587\u4EF6\u8DEF\u5F84"),
|
|
545
|
-
content: z2.string().describe("\u8981\u5199\u5165\u7684\u6587\u4EF6\u5185\u5BB9")
|
|
788
|
+
content: z2.string().describe("\u8981\u5199\u5165\u6216\u63D2\u5165\u7684\u6587\u4EF6\u5185\u5BB9"),
|
|
789
|
+
startLine: z2.number().optional().describe("\u8D77\u59CB\u884C\u53F7\uFF08\u4ECE1\u5F00\u59CB\uFF09\u3002\u5982\u679C\u63D0\u4F9B\u6B64\u53C2\u6570\uFF0C\u5219\u5728\u6307\u5B9A\u884C\u8FDB\u884C\u5C40\u90E8\u66FF\u6362\u6216\u63D2\u5165\u3002\u5982\u679C\u672A\u63D0\u4F9B\uFF0C\u5219\u5168\u91CF\u8986\u76D6\u6587\u4EF6\u3002"),
|
|
790
|
+
endLine: z2.number().optional().describe("\u7ED3\u675F\u884C\u53F7\uFF08\u4ECE1\u5F00\u59CB\uFF0C\u5305\u542B\u8BE5\u884C\uFF09\u3002\u5982\u679C\u63D0\u4F9B\u6B64\u53C2\u6570\uFF0C\u5C06\u628A\u4ECE startLine \u5230 endLine \u7684\u5185\u5BB9\u66FF\u6362\u4E3A\u65B0 content\uFF1B\u5982\u679C\u4EC5\u63D0\u4F9B startLine\uFF0C\u5219\u4EC5\u66FF\u6362\u8BE5\u884C\uFF1B\u5982\u679C\u8981\u5728\u67D0\u884C\u524D\u5355\u7EAF\u63D2\u5165\u800C\u4E0D\u5220\u9664\u539F\u5185\u5BB9\uFF0C\u53EF\u5C06 endLine \u8BBE\u4E3A startLine - 1\u3002")
|
|
546
791
|
})
|
|
547
792
|
}
|
|
548
793
|
);
|
|
@@ -616,9 +861,10 @@ var listFilesTool = (0, import_tools2.tool)(
|
|
|
616
861
|
}
|
|
617
862
|
);
|
|
618
863
|
var extractPageStateTool = (0, import_tools3.tool)(
|
|
619
|
-
async () => {
|
|
864
|
+
async (input) => {
|
|
865
|
+
const includeText = input?.includeText ?? false;
|
|
620
866
|
const p = await playwrightManager.getPage();
|
|
621
|
-
const
|
|
867
|
+
const evaluateResult = await p.evaluate((includeTextArg) => {
|
|
622
868
|
document.querySelectorAll(".ai-label-container").forEach((el) => el.remove());
|
|
623
869
|
document.querySelectorAll("[idu-mark-id]").forEach((el) => el.removeAttribute("idu-mark-id"));
|
|
624
870
|
const selectors = [
|
|
@@ -680,18 +926,48 @@ var extractPageStateTool = (0, import_tools3.tool)(
|
|
|
680
926
|
});
|
|
681
927
|
}
|
|
682
928
|
});
|
|
683
|
-
|
|
684
|
-
|
|
929
|
+
let viewportText = void 0;
|
|
930
|
+
if (includeTextArg) {
|
|
931
|
+
const walker = document.createTreeWalker(
|
|
932
|
+
document.body,
|
|
933
|
+
NodeFilter.SHOW_TEXT,
|
|
934
|
+
null
|
|
935
|
+
);
|
|
936
|
+
let node;
|
|
937
|
+
const textParts = [];
|
|
938
|
+
while (node = walker.nextNode()) {
|
|
939
|
+
const parent = node.parentElement;
|
|
940
|
+
const text = node.nodeValue?.trim();
|
|
941
|
+
if (parent && text) {
|
|
942
|
+
const tagName = parent.tagName.toLowerCase();
|
|
943
|
+
if (tagName !== "script" && tagName !== "style" && tagName !== "noscript") {
|
|
944
|
+
if (isVisible(parent)) {
|
|
945
|
+
const rect = parent.getBoundingClientRect();
|
|
946
|
+
if (isInViewport(rect)) {
|
|
947
|
+
textParts.push(text);
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
viewportText = Array.from(new Set(textParts)).join("\n");
|
|
954
|
+
}
|
|
955
|
+
return { metadata, viewportText };
|
|
956
|
+
}, includeText);
|
|
685
957
|
const title = await p.title();
|
|
686
958
|
return {
|
|
687
959
|
url: p.url(),
|
|
688
960
|
title,
|
|
689
|
-
elements:
|
|
961
|
+
elements: evaluateResult.metadata,
|
|
962
|
+
...includeText && evaluateResult.viewportText ? { text: evaluateResult.viewportText } : {}
|
|
690
963
|
};
|
|
691
964
|
},
|
|
692
965
|
{
|
|
693
966
|
name: "extract_page_state",
|
|
694
|
-
description: "\u6293\u53D6\u5F53\u524D\u9875\u9762\u7684\u5173\u952E\u4EA4\u4E92\u5143\u7D20\uFF0C\u5E76\u8F93\u51FA\u5E26\u7F16\u53F7\u7684\u5143\u7D20\u6458\u8981\u4E0E\u4E0A\u4E0B\u6587\u6458\u8981"
|
|
967
|
+
description: "\u6293\u53D6\u5F53\u524D\u9875\u9762\u7684\u5173\u952E\u4EA4\u4E92\u5143\u7D20\uFF0C\u5E76\u8F93\u51FA\u5E26\u7F16\u53F7\u7684\u5143\u7D20\u6458\u8981\u4E0E\u4E0A\u4E0B\u6587\u6458\u8981\u3002\u53EF\u901A\u8FC7 includeText \u53C2\u6570\u989D\u5916\u83B7\u53D6\u89C6\u53E3\u5185\u7684\u7EAF\u6587\u672C\u4FE1\u606F\u3002",
|
|
968
|
+
schema: z3.object({
|
|
969
|
+
includeText: z3.boolean().optional().default(false).describe("\u662F\u5426\u83B7\u53D6\u5F53\u524D\u89C6\u53E3\u5185\u7684\u7EAF\u6587\u672C\u4FE1\u606F")
|
|
970
|
+
})
|
|
695
971
|
}
|
|
696
972
|
);
|
|
697
973
|
var executePlaywrightActionsTool = (0, import_tools3.tool)(
|
|
@@ -755,9 +1031,9 @@ var PLAYWRIGHT_PROMPT = `
|
|
|
755
1031
|
|
|
756
1032
|
2. **extract_page_state**:
|
|
757
1033
|
* **\u7528\u9014**: \u83B7\u53D6\u5F53\u524D\u9875\u9762\u4E0A\u4E0B\u6587\u6458\u8981\uFF0C\u5E76\u5728\u9875\u9762\u4E0A\u6807\u8BB0\u53EF\u4EA4\u4E92\u5143\u7D20\uFF08Set-of-Mark\uFF09\u3002
|
|
758
|
-
* **\u8F93\u5165**: \
|
|
759
|
-
* **\u8F93\u51FA**: \u5305\u542B\u9875\u9762 URL\u3001Title \u4EE5\u53CA\u5E26\u6709 ID \u6807\u8BB0\u7684\u53EF\u4EA4\u4E92\u5143\u7D20\u5217\u8868\u3002
|
|
760
|
-
* **\u4F55\u65F6\u4F7F\u7528**: \u5728\u9700\u8981\u7406\u89E3\u9875\u9762\u7ED3\u6784\u6216\u7CBE\u786E\u5B9A\u4F4D\u5143\u7D20\u65F6\u4F7F\u7528\u3002\u8FD4\u56DE\u7684\u5143\u7D20 ID \u53EF\u7528\u4E8E\u751F\u6210\u7CBE\u786E\u7684 CSS \u9009\u62E9\u5668\uFF08\u5982 \`[idu-mark-id="123"]\`\uFF09\u3002
|
|
1034
|
+
* **\u8F93\u5165**: \u53EF\u9009\u53C2\u6570 \`includeText\` (\u5E03\u5C14\u503C)\uFF0C\u7528\u4E8E\u989D\u5916\u83B7\u53D6\u5F53\u524D\u89C6\u53E3\u5185\u7684\u7EAF\u6587\u672C\u4FE1\u606F\u3002
|
|
1035
|
+
* **\u8F93\u51FA**: \u5305\u542B\u9875\u9762 URL\u3001Title \u4EE5\u53CA\u5E26\u6709 ID \u6807\u8BB0\u7684\u53EF\u4EA4\u4E92\u5143\u7D20\u5217\u8868\uFF08\u5F00\u542F \`includeText\` \u65F6\u8FD8\u4F1A\u5305\u542B\u89C6\u53E3\u5185\u7684\u7EAF\u6587\u672C\u4FE1\u606F\uFF09\u3002
|
|
1036
|
+
* **\u4F55\u65F6\u4F7F\u7528**: \u5728\u9700\u8981\u7406\u89E3\u9875\u9762\u7ED3\u6784\u6216\u7CBE\u786E\u5B9A\u4F4D\u5143\u7D20\u65F6\u4F7F\u7528\u3002\u8FD4\u56DE\u7684\u5143\u7D20 ID \u53EF\u7528\u4E8E\u751F\u6210\u7CBE\u786E\u7684 CSS \u9009\u62E9\u5668\uFF08\u5982 \`[idu-mark-id="123"]\`\uFF09\u3002**\u6CE8\u610F\uFF1A\u4E00\u822C\u7EAF\u64CD\u4F5C\u9875\u9762\u65F6\u4E0D\u9700\u8981\u6253\u5F00 \`includeText\` \u5F00\u5173\uFF0C\u4EE5\u514D\u6D6A\u8D39\u5B9D\u8D35\u7684 Token\u3002\u53EA\u6709\u5728\u786E\u5B9E\u9700\u8981\u83B7\u53D6\u9875\u9762\u66F4\u591A\u6587\u672C\u4FE1\u606F\u8FDB\u884C\u5185\u5BB9\u7406\u89E3\u65F6\uFF0C\u624D\u5C06 \`includeText\` \u8BBE\u4E3A true\u3002**
|
|
761
1037
|
|
|
762
1038
|
### Utility
|
|
763
1039
|
3. **get_current_time**:
|
|
@@ -765,14 +1041,14 @@ var PLAYWRIGHT_PROMPT = `
|
|
|
765
1041
|
* **\u8F93\u5165**: \u53EF\u9009\u683C\u5F0F\u5316\u5B57\u7B26\u4E32\u548C\u65F6\u533A\u3002
|
|
766
1042
|
|
|
767
1043
|
### File System & Memory
|
|
768
|
-
\u4F60\u62E5\u6709\u5BF9\u5DE5\u4F5C\u76EE\u5F55
|
|
1044
|
+
\u4F60\u62E5\u6709\u5BF9\u5DE5\u4F5C\u76EE\u5F55\uFF08\u6216\u6587\u4EF6\u64CD\u4F5C\u5DE5\u5177\u6307\u5B9A\u7684\u6839\u76EE\u5F55\uFF09\u7684\u6587\u4EF6\u64CD\u4F5C\u6743\u9650\u3002
|
|
769
1045
|
|
|
770
|
-
4.
|
|
771
|
-
* \`
|
|
772
|
-
* \`
|
|
773
|
-
* \`
|
|
774
|
-
* \`
|
|
775
|
-
* \`
|
|
1046
|
+
4. **\u6587\u4EF6\u64CD\u4F5C\u5DE5\u5177\u7EC4**: \u63D0\u4F9B\u4E86\u4E00\u7EC4\u539F\u5B50\u5316\u7684\u6587\u4EF6\u64CD\u4F5C\u5DE5\u5177\uFF1A
|
|
1047
|
+
* \`create_file_or_directory\`: \u5728\u5DE5\u4F5C\u76EE\u5F55\u5185\u65B0\u5EFA\u6587\u4EF6\u6216\u76EE\u5F55\u3002
|
|
1048
|
+
* \`read_file\`: \u5728\u5DE5\u4F5C\u76EE\u5F55\u5185\u8BFB\u53D6\u5DF2\u6709\u6587\u4EF6\u5185\u5BB9\u3002
|
|
1049
|
+
* \`write_file\`: \u5728\u5DE5\u4F5C\u76EE\u5F55\u5185\u5199\u5165\u5DF2\u6709\u6587\u4EF6\u3002\u652F\u6301\u5168\u91CF\u8986\u76D6\uFF0C\u4E5F\u652F\u6301\u901A\u8FC7\u6307\u5B9A\u884C\u53F7 (startLine / endLine) \u8FDB\u884C\u5C40\u90E8\u66FF\u6362\u6216\u63D2\u5165\u4EE5\u8282\u7701 token\u3002
|
|
1050
|
+
* \`delete_file_or_directory\`: \u5728\u5DE5\u4F5C\u76EE\u5F55\u5185\u5220\u9664\u6587\u4EF6\u6216\u76EE\u5F55\u3002
|
|
1051
|
+
* \`list_files\`: \u5217\u51FA\u5DE5\u4F5C\u76EE\u5F55\u5185\u7684\u76EE\u5F55\u5185\u5BB9\u3002
|
|
776
1052
|
|
|
777
1053
|
## Long-term Memory & Skills
|
|
778
1054
|
|
|
@@ -784,9 +1060,13 @@ var PLAYWRIGHT_PROMPT = `
|
|
|
784
1060
|
* **\u8BFB\u53D6**: \u7CFB\u7EDF\u4F1A\u5728\u6BCF\u6B21\u5BF9\u8BDD\u5F00\u59CB\u65F6\u8BFB\u53D6\u6B64\u6587\u4EF6\uFF08\u6216\u4F60\u53EF\u4EE5\u4E3B\u52A8\u8BFB\u53D6\uFF09\uFF0C\u8BF7\u9075\u5FAA\u5176\u4E2D\u7684\u6307\u793A\u3002
|
|
785
1061
|
* **\u5199\u5165**: \u5F53\u7528\u6237\u901A\u8FC7\u6307\u4EE4\u544A\u77E5\u65B0\u7684\u4E60\u60EF\u3001\u89C4\u5B9A\uFF0C\u6216\u4F60\u5B66\u4F1A\u4E86\u65B0\u6280\u80FD\u65F6\uFF0C\u8BF7\u52A1\u5FC5\u66F4\u65B0\u6B64\u6587\u4EF6\u3002
|
|
786
1062
|
|
|
787
|
-
2. **
|
|
1063
|
+
2. **SKILLS.json (\u7528\u6237\u914D\u7F6E\u6280\u80FD\u5217\u8868)**:
|
|
1064
|
+
* \u4F4D\u4E8E\u6839\u76EE\u5F55\u4E0B\u7684 \`SKILLS.json\` \u6587\u4EF6\u5B58\u653E\u7528\u6237\u624B\u52A8\u914D\u7F6E\u7684\u6280\u80FD\u5217\u8868\u3002
|
|
1065
|
+
* \u4F60\u53EF\u4EE5\u901A\u8FC7\u8BFB\u53D6\u8BE5\u6587\u4EF6\u83B7\u53D6\u6280\u80FD\u5217\u8868\uFF08\u5305\u542B ID\u3001\u540D\u79F0\u3001\u6458\u8981\u548C\u8DEF\u5F84\uFF09\u3002
|
|
1066
|
+
|
|
1067
|
+
3. **skills/ (\u6280\u80FD\u76EE\u5F55)**:
|
|
788
1068
|
* \u4F4D\u4E8E \`skills/\` \u6587\u4EF6\u5939\u4E0B\u3002
|
|
789
|
-
* **\u7528\u9014**: \u5B58\u653E\u5177\u4F53\u7684\u6280\u80FD\u6587\u6863\u6216\u590D\u6742\u4EFB\u52A1\u7684\u64CD\u4F5C\u6307\u5357\u3002
|
|
1069
|
+
* **\u7528\u9014**: \u5B58\u653E\u5177\u4F53\u7684\u6280\u80FD\u6587\u6863\u6216\u590D\u6742\u4EFB\u52A1\u7684\u64CD\u4F5C\u6307\u5357\u3002\u4F60\u53EF\u4EE5\u6839\u636E \`SKILLS.json\` \u4E2D\u7684 ID\uFF0C\u8BFB\u53D6\u5BF9\u5E94 \`skills/\${id}.md\` \u62FF\u5230\u6280\u80FD\u7684\u6B63\u6587\u5185\u5BB9\u3002
|
|
790
1070
|
* **\u7EF4\u62A4**: \u5F53\u4F60\u4E60\u5F97\u4E00\u4E2A\u65B0\u7684\u590D\u6742\u64CD\u4F5C\u6D41\u7A0B\u65F6\uFF0C\u5E94\u5C06\u5176\u8BE6\u7EC6\u6B65\u9AA4\u6574\u7406\u4E3A\u4E00\u4E2A Markdown \u6587\u4EF6\u4FDD\u5B58\u5728 \`skills/\` \u76EE\u5F55\u4E0B\uFF0C\u5E76\u5728 \`AGENTS.md\` \u4E2D\u6DFB\u52A0\u8BE5\u6280\u80FD\u7684\u6458\u8981\u548C\u94FE\u63A5\u3002
|
|
791
1071
|
|
|
792
1072
|
## Workflow (Standard Operating Procedure)
|
|
@@ -1086,9 +1366,9 @@ var streamInvoke = async function* (query, thread_id, modelConfig) {
|
|
|
1086
1366
|
// src/routes/chat.ts
|
|
1087
1367
|
var import_promises2 = __toESM(require("fs/promises"));
|
|
1088
1368
|
var import_path3 = __toESM(require("path"));
|
|
1089
|
-
var
|
|
1369
|
+
var import_crypto2 = __toESM(require("crypto"));
|
|
1090
1370
|
var configDir2 = getConfigPath();
|
|
1091
|
-
var
|
|
1371
|
+
var configFilePath = import_path3.default.join(configDir2, "model.json");
|
|
1092
1372
|
var router2 = (0, import_express2.Router)();
|
|
1093
1373
|
router2.get("/", (req, res) => {
|
|
1094
1374
|
res.json({ status: "OK" });
|
|
@@ -1100,7 +1380,7 @@ router2.post("/stream", async (req, res) => {
|
|
|
1100
1380
|
if (!query || !thread_id) {
|
|
1101
1381
|
return res.status(400).json({ error: "Missing query or thread_id in request body" });
|
|
1102
1382
|
}
|
|
1103
|
-
const configContent = await import_promises2.default.readFile(
|
|
1383
|
+
const configContent = await import_promises2.default.readFile(configFilePath, "utf-8");
|
|
1104
1384
|
const config = JSON.parse(configContent);
|
|
1105
1385
|
const modelConfig = config.defaultModel;
|
|
1106
1386
|
if (!modelConfig) {
|
|
@@ -1127,7 +1407,7 @@ router2.get("/session", (req, res) => {
|
|
|
1127
1407
|
const isNew = req.query.new === "true";
|
|
1128
1408
|
let sessionId = session_default.getSessionId();
|
|
1129
1409
|
if (!sessionId || isNew) {
|
|
1130
|
-
sessionId =
|
|
1410
|
+
sessionId = import_crypto2.default.randomUUID();
|
|
1131
1411
|
session_default.setSessionId(sessionId);
|
|
1132
1412
|
}
|
|
1133
1413
|
res.json({ sessionId });
|