zrocclaw 0.0.13 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zrocclaw",
3
- "version": "0.0.13",
3
+ "version": "0.0.14",
4
4
  "description": "个人专属浏览器AI助手命令行工具",
5
5
  "keywords": [
6
6
  "zrocclaw",
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-46XX2E7T.mjs
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 configFilePath = import_path2.default.join(configDir, "model.json");
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
- try {
179
- await import_promises.default.access(configFilePath);
180
- const data = await import_promises.default.readFile(configFilePath, "utf-8");
181
- res.json(JSON.parse(data));
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
- await import_promises.default.mkdir(configDir, { recursive: true });
199
- let currentConfig = {};
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
- const data = await import_promises.default.readFile(configFilePath, "utf-8");
202
- currentConfig = JSON.parse(data);
203
- } catch (error) {
204
- if (error.code !== "ENOENT") {
205
- throw error;
329
+ await import_promises.default.access(workspaceSkillsPath);
330
+ } catch (e) {
331
+ if (e.code === "ENOENT") {
332
+ await writeSkillsConfig([]);
333
+ return res.json([]);
206
334
  }
207
335
  }
208
- const newConfig = { ...currentConfig, ...req.body };
209
- await import_promises.default.writeFile(configFilePath, JSON.stringify(newConfig, null, 2), "utf-8");
210
- res.json(newConfig);
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]);
211
388
  } catch (error) {
212
- console.error("\u4FEE\u6539\u6A21\u578B\u5931\u8D25:", error);
213
- res.status(500).json({ error: "\u4FEE\u6539\u6A21\u578B\u5931\u8D25" });
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" });
437
+ }
438
+ throw e;
439
+ }
440
+ } catch (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-OSSFB5D4.mjs
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");
@@ -632,9 +861,10 @@ var listFilesTool = (0, import_tools2.tool)(
632
861
  }
633
862
  );
634
863
  var extractPageStateTool = (0, import_tools3.tool)(
635
- async () => {
864
+ async (input) => {
865
+ const includeText = input?.includeText ?? false;
636
866
  const p = await playwrightManager.getPage();
637
- const elementsMetadata = await p.evaluate(() => {
867
+ const evaluateResult = await p.evaluate((includeTextArg) => {
638
868
  document.querySelectorAll(".ai-label-container").forEach((el) => el.remove());
639
869
  document.querySelectorAll("[idu-mark-id]").forEach((el) => el.removeAttribute("idu-mark-id"));
640
870
  const selectors = [
@@ -696,18 +926,48 @@ var extractPageStateTool = (0, import_tools3.tool)(
696
926
  });
697
927
  }
698
928
  });
699
- return metadata;
700
- });
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);
701
957
  const title = await p.title();
702
958
  return {
703
959
  url: p.url(),
704
960
  title,
705
- elements: elementsMetadata
961
+ elements: evaluateResult.metadata,
962
+ ...includeText && evaluateResult.viewportText ? { text: evaluateResult.viewportText } : {}
706
963
  };
707
964
  },
708
965
  {
709
966
  name: "extract_page_state",
710
- 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
+ })
711
971
  }
712
972
  );
713
973
  var executePlaywrightActionsTool = (0, import_tools3.tool)(
@@ -771,9 +1031,9 @@ var PLAYWRIGHT_PROMPT = `
771
1031
 
772
1032
  2. **extract_page_state**:
773
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
774
- * **\u8F93\u5165**: \u65E0\u3002
775
- * **\u8F93\u51FA**: \u5305\u542B\u9875\u9762 URL\u3001Title \u4EE5\u53CA\u5E26\u6709 ID \u6807\u8BB0\u7684\u53EF\u4EA4\u4E92\u5143\u7D20\u5217\u8868\u3002
776
- * **\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**
777
1037
 
778
1038
  ### Utility
779
1039
  3. **get_current_time**:
@@ -800,9 +1060,13 @@ var PLAYWRIGHT_PROMPT = `
800
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
801
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
802
1062
 
803
- 2. **skills/ (\u6280\u80FD\u76EE\u5F55)**:
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)**:
804
1068
  * \u4F4D\u4E8E \`skills/\` \u6587\u4EF6\u5939\u4E0B\u3002
805
- * **\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
806
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
807
1071
 
808
1072
  ## Workflow (Standard Operating Procedure)
@@ -1102,9 +1366,9 @@ var streamInvoke = async function* (query, thread_id, modelConfig) {
1102
1366
  // src/routes/chat.ts
1103
1367
  var import_promises2 = __toESM(require("fs/promises"));
1104
1368
  var import_path3 = __toESM(require("path"));
1105
- var import_crypto = __toESM(require("crypto"));
1369
+ var import_crypto2 = __toESM(require("crypto"));
1106
1370
  var configDir2 = getConfigPath();
1107
- var configFilePath2 = import_path3.default.join(configDir2, "model.json");
1371
+ var configFilePath = import_path3.default.join(configDir2, "model.json");
1108
1372
  var router2 = (0, import_express2.Router)();
1109
1373
  router2.get("/", (req, res) => {
1110
1374
  res.json({ status: "OK" });
@@ -1116,7 +1380,7 @@ router2.post("/stream", async (req, res) => {
1116
1380
  if (!query || !thread_id) {
1117
1381
  return res.status(400).json({ error: "Missing query or thread_id in request body" });
1118
1382
  }
1119
- const configContent = await import_promises2.default.readFile(configFilePath2, "utf-8");
1383
+ const configContent = await import_promises2.default.readFile(configFilePath, "utf-8");
1120
1384
  const config = JSON.parse(configContent);
1121
1385
  const modelConfig = config.defaultModel;
1122
1386
  if (!modelConfig) {
@@ -1143,7 +1407,7 @@ router2.get("/session", (req, res) => {
1143
1407
  const isNew = req.query.new === "true";
1144
1408
  let sessionId = session_default.getSessionId();
1145
1409
  if (!sessionId || isNew) {
1146
- sessionId = import_crypto.default.randomUUID();
1410
+ sessionId = import_crypto2.default.randomUUID();
1147
1411
  session_default.setSessionId(sessionId);
1148
1412
  }
1149
1413
  res.json({ sessionId });