duclaw-cli 1.9.13 → 1.9.15
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/dist/bundle.js +380 -144
- package/dist/main.js +1 -1
- package/dist/worker-main.js +1 -1
- package/package.json +1 -1
package/dist/bundle.js
CHANGED
|
@@ -30242,7 +30242,7 @@ function printHelp() {
|
|
|
30242
30242
|
`);
|
|
30243
30243
|
}
|
|
30244
30244
|
function printVersion() {
|
|
30245
|
-
console.log(`duclaw-cli v${true ? "1.9.
|
|
30245
|
+
console.log(`duclaw-cli v${true ? "1.9.15" : "unknown"}`);
|
|
30246
30246
|
}
|
|
30247
30247
|
function getDuclawTemplate() {
|
|
30248
30248
|
return {
|
|
@@ -32288,9 +32288,9 @@ var NodeFsHandler = class {
|
|
|
32288
32288
|
if (this.fsw.closed) {
|
|
32289
32289
|
return;
|
|
32290
32290
|
}
|
|
32291
|
-
const
|
|
32291
|
+
const dirname8 = sp.dirname(file);
|
|
32292
32292
|
const basename4 = sp.basename(file);
|
|
32293
|
-
const parent = this.fsw._getWatchedDir(
|
|
32293
|
+
const parent = this.fsw._getWatchedDir(dirname8);
|
|
32294
32294
|
let prevStats = stats;
|
|
32295
32295
|
if (parent.has(basename4))
|
|
32296
32296
|
return;
|
|
@@ -32317,7 +32317,7 @@ var NodeFsHandler = class {
|
|
|
32317
32317
|
prevStats = newStats2;
|
|
32318
32318
|
}
|
|
32319
32319
|
} catch (error) {
|
|
32320
|
-
this.fsw._remove(
|
|
32320
|
+
this.fsw._remove(dirname8, basename4);
|
|
32321
32321
|
}
|
|
32322
32322
|
} else if (parent.has(basename4)) {
|
|
32323
32323
|
const at = newStats.atimeMs;
|
|
@@ -33279,8 +33279,8 @@ var chokidar_default = { watch, FSWatcher };
|
|
|
33279
33279
|
var import_node_cron = __toESM(require_node_cron());
|
|
33280
33280
|
|
|
33281
33281
|
// src/agent/createAgent.ts
|
|
33282
|
-
var
|
|
33283
|
-
var
|
|
33282
|
+
var import_node_crypto16 = require("node:crypto");
|
|
33283
|
+
var import_node_fs8 = require("node:fs");
|
|
33284
33284
|
|
|
33285
33285
|
// src/background/BackgroundManager.ts
|
|
33286
33286
|
var import_child_process = require("child_process");
|
|
@@ -41627,6 +41627,183 @@ async function parseResponseJson(response) {
|
|
|
41627
41627
|
}
|
|
41628
41628
|
}
|
|
41629
41629
|
|
|
41630
|
+
// src/attachments/attachmentContext.ts
|
|
41631
|
+
var import_node_crypto4 = require("node:crypto");
|
|
41632
|
+
var import_node_fs3 = require("node:fs");
|
|
41633
|
+
var import_node_path12 = require("node:path");
|
|
41634
|
+
var MAX_ATTACHMENT_RECORDS = 100;
|
|
41635
|
+
var RECENT_ATTACHMENT_LIMIT = 5;
|
|
41636
|
+
function makeAttachmentId(input) {
|
|
41637
|
+
const raw2 = [
|
|
41638
|
+
input.userId,
|
|
41639
|
+
input.platform,
|
|
41640
|
+
input.messageId,
|
|
41641
|
+
input.resourceKey,
|
|
41642
|
+
input.kind
|
|
41643
|
+
].join(":");
|
|
41644
|
+
const digest = (0, import_node_crypto4.createHash)("sha256").update(raw2).digest("hex").slice(0, 16);
|
|
41645
|
+
return `att_${input.kind === "image" ? "img" : "file"}_${digest}`;
|
|
41646
|
+
}
|
|
41647
|
+
function indexPath(userId) {
|
|
41648
|
+
return (0, import_node_path12.join)(getDuclawWorkspaceDir(), userId, "attachments", "index.json");
|
|
41649
|
+
}
|
|
41650
|
+
function readIndex(userId) {
|
|
41651
|
+
const filePath = indexPath(userId);
|
|
41652
|
+
if (!(0, import_node_fs3.existsSync)(filePath)) return [];
|
|
41653
|
+
try {
|
|
41654
|
+
const parsed = JSON.parse((0, import_node_fs3.readFileSync)(filePath, "utf8"));
|
|
41655
|
+
return Array.isArray(parsed) ? parsed.filter(isAttachmentRecord) : [];
|
|
41656
|
+
} catch (error) {
|
|
41657
|
+
console.warn(`[attachments] failed to read attachment index: ${error.message}`);
|
|
41658
|
+
return [];
|
|
41659
|
+
}
|
|
41660
|
+
}
|
|
41661
|
+
function writeIndex(userId, records) {
|
|
41662
|
+
const filePath = indexPath(userId);
|
|
41663
|
+
(0, import_node_fs3.mkdirSync)((0, import_node_path12.dirname)(filePath), { recursive: true });
|
|
41664
|
+
(0, import_node_fs3.writeFileSync)(filePath, JSON.stringify(records.slice(0, MAX_ATTACHMENT_RECORDS), null, 2));
|
|
41665
|
+
}
|
|
41666
|
+
function isAttachmentRecord(value) {
|
|
41667
|
+
const record = value;
|
|
41668
|
+
return Boolean(record) && typeof record.id === "string" && (record.kind === "image" || record.kind === "file") && typeof record.userId === "string" && typeof record.pathOrUrl === "string";
|
|
41669
|
+
}
|
|
41670
|
+
function stringValue2(value) {
|
|
41671
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
41672
|
+
}
|
|
41673
|
+
function attachmentKind(value) {
|
|
41674
|
+
const type = stringValue2(value.type);
|
|
41675
|
+
const mimeType = stringValue2(value.mimeType);
|
|
41676
|
+
const name = stringValue2(value.name) ?? stringValue2(value.path) ?? stringValue2(value.url) ?? "";
|
|
41677
|
+
if (type === "image" || mimeType?.startsWith("image/") || /\.(png|jpe?g|gif|webp)$/i.test(name)) {
|
|
41678
|
+
return "image";
|
|
41679
|
+
}
|
|
41680
|
+
return "file";
|
|
41681
|
+
}
|
|
41682
|
+
function xmlEscape(value) {
|
|
41683
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
41684
|
+
}
|
|
41685
|
+
function upsertAttachments(userId, records) {
|
|
41686
|
+
if (records.length === 0) return;
|
|
41687
|
+
const existing = readIndex(userId);
|
|
41688
|
+
const byId = /* @__PURE__ */ new Map();
|
|
41689
|
+
for (const record of [...records, ...existing]) {
|
|
41690
|
+
if (!byId.has(record.id)) byId.set(record.id, record);
|
|
41691
|
+
}
|
|
41692
|
+
writeIndex(userId, Array.from(byId.values()).sort((a, b) => b.receivedAt.localeCompare(a.receivedAt)));
|
|
41693
|
+
}
|
|
41694
|
+
function listRecentAttachments(userId, limit = RECENT_ATTACHMENT_LIMIT) {
|
|
41695
|
+
return readIndex(userId).sort((a, b) => b.receivedAt.localeCompare(a.receivedAt)).slice(0, limit);
|
|
41696
|
+
}
|
|
41697
|
+
function resolveAttachmentPathOrUrl(userId, attachmentId) {
|
|
41698
|
+
return readIndex(userId).find((record) => record.id === attachmentId)?.pathOrUrl;
|
|
41699
|
+
}
|
|
41700
|
+
function collectAttachmentsFromRequest(request) {
|
|
41701
|
+
const metadata = request.metadata ?? {};
|
|
41702
|
+
const platform = request.platform || "unknown";
|
|
41703
|
+
const messageId = request.requestId;
|
|
41704
|
+
const receivedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
41705
|
+
const records = [];
|
|
41706
|
+
const seen = /* @__PURE__ */ new Set();
|
|
41707
|
+
const addRecord = (input) => {
|
|
41708
|
+
if (!input.pathOrUrl) return;
|
|
41709
|
+
const id = makeAttachmentId({
|
|
41710
|
+
userId: request.userId,
|
|
41711
|
+
platform,
|
|
41712
|
+
messageId,
|
|
41713
|
+
resourceKey: input.resourceKey,
|
|
41714
|
+
kind: input.kind
|
|
41715
|
+
});
|
|
41716
|
+
if (seen.has(id)) return;
|
|
41717
|
+
seen.add(id);
|
|
41718
|
+
records.push({
|
|
41719
|
+
id,
|
|
41720
|
+
kind: input.kind,
|
|
41721
|
+
platform,
|
|
41722
|
+
userId: request.userId,
|
|
41723
|
+
messageId,
|
|
41724
|
+
resourceKey: input.resourceKey,
|
|
41725
|
+
pathOrUrl: input.pathOrUrl,
|
|
41726
|
+
name: input.name,
|
|
41727
|
+
mimeType: input.mimeType,
|
|
41728
|
+
source: input.source,
|
|
41729
|
+
receivedAt
|
|
41730
|
+
});
|
|
41731
|
+
};
|
|
41732
|
+
const imageUrl = stringValue2(metadata.imageUrl);
|
|
41733
|
+
const imageKey = stringValue2(metadata.imageKey);
|
|
41734
|
+
if (imageUrl && imageKey) {
|
|
41735
|
+
addRecord({
|
|
41736
|
+
kind: "image",
|
|
41737
|
+
resourceKey: imageKey,
|
|
41738
|
+
pathOrUrl: imageUrl,
|
|
41739
|
+
source: `${platform}_metadata`
|
|
41740
|
+
});
|
|
41741
|
+
}
|
|
41742
|
+
const fileUrl = stringValue2(metadata.fileUrl);
|
|
41743
|
+
const fileName = stringValue2(metadata.fileName);
|
|
41744
|
+
if (fileUrl && fileName) {
|
|
41745
|
+
addRecord({
|
|
41746
|
+
kind: "file",
|
|
41747
|
+
resourceKey: fileName,
|
|
41748
|
+
pathOrUrl: fileUrl,
|
|
41749
|
+
name: fileName,
|
|
41750
|
+
source: `${platform}_metadata`
|
|
41751
|
+
});
|
|
41752
|
+
}
|
|
41753
|
+
const attachments = Array.isArray(metadata.attachments) ? metadata.attachments : [];
|
|
41754
|
+
for (const attachment of attachments) {
|
|
41755
|
+
const resourceKey = stringValue2(attachment.id) ?? stringValue2(attachment.name);
|
|
41756
|
+
const pathOrUrl = stringValue2(attachment.url) ?? stringValue2(attachment.path);
|
|
41757
|
+
if (!resourceKey || !pathOrUrl) continue;
|
|
41758
|
+
addRecord({
|
|
41759
|
+
kind: attachmentKind(attachment),
|
|
41760
|
+
resourceKey,
|
|
41761
|
+
pathOrUrl,
|
|
41762
|
+
name: stringValue2(attachment.name),
|
|
41763
|
+
mimeType: stringValue2(attachment.mimeType),
|
|
41764
|
+
source: `${platform}_attachment`
|
|
41765
|
+
});
|
|
41766
|
+
}
|
|
41767
|
+
return records;
|
|
41768
|
+
}
|
|
41769
|
+
function buildAttachmentContextXml(records) {
|
|
41770
|
+
if (records.length === 0) return "";
|
|
41771
|
+
const lines = [
|
|
41772
|
+
`<recent-attachments>`,
|
|
41773
|
+
` <system-note>Use attachment_id when referring to these attachments. Do not invent or reproduce long URLs; tools can resolve the real file source from attachment_id.</system-note>`
|
|
41774
|
+
];
|
|
41775
|
+
for (const record of records) {
|
|
41776
|
+
lines.push(` <${record.kind} id="${xmlEscape(record.id)}">`);
|
|
41777
|
+
lines.push(` <source>${xmlEscape(record.source ?? record.platform)}</source>`);
|
|
41778
|
+
lines.push(` <message_id>${xmlEscape(record.messageId)}</message_id>`);
|
|
41779
|
+
lines.push(` <resource_key>${xmlEscape(record.resourceKey)}</resource_key>`);
|
|
41780
|
+
if (record.name) lines.push(` <name>${xmlEscape(record.name)}</name>`);
|
|
41781
|
+
if (record.mimeType) lines.push(` <mime_type>${xmlEscape(record.mimeType)}</mime_type>`);
|
|
41782
|
+
lines.push(` <received_at>${xmlEscape(record.receivedAt)}</received_at>`);
|
|
41783
|
+
lines.push(` </${record.kind}>`);
|
|
41784
|
+
}
|
|
41785
|
+
lines.push(`</recent-attachments>`);
|
|
41786
|
+
return lines.join("\n");
|
|
41787
|
+
}
|
|
41788
|
+
function attachRecentAttachmentContext(request, content) {
|
|
41789
|
+
const current = collectAttachmentsFromRequest(request);
|
|
41790
|
+
if (current.length > 0) {
|
|
41791
|
+
upsertAttachments(request.userId, current);
|
|
41792
|
+
request.metadata = {
|
|
41793
|
+
...request.metadata ?? {},
|
|
41794
|
+
attachmentIds: current.map((record) => record.id),
|
|
41795
|
+
attachmentId: current[0]?.id
|
|
41796
|
+
};
|
|
41797
|
+
}
|
|
41798
|
+
const context = buildAttachmentContextXml(listRecentAttachments(request.userId));
|
|
41799
|
+
if (!context) return content;
|
|
41800
|
+
return `${content}
|
|
41801
|
+
|
|
41802
|
+
<system-reminder>
|
|
41803
|
+
${context}
|
|
41804
|
+
</system-reminder>`;
|
|
41805
|
+
}
|
|
41806
|
+
|
|
41630
41807
|
// src/tools/tools/ImageUnderstand.ts
|
|
41631
41808
|
var guessMediaTypeFromData = (base64Data) => {
|
|
41632
41809
|
if (base64Data.startsWith("/9j/")) return "image/jpeg";
|
|
@@ -41646,6 +41823,7 @@ var controlPlaneBaseUrl = () => {
|
|
|
41646
41823
|
return process.env.DUCLAW_CONTROL_PLANE_BASE_URL?.replace(/\/$/, "");
|
|
41647
41824
|
};
|
|
41648
41825
|
var USER_IMAGE_REUPLOAD_MESSAGE = `\u8FD9\u5F20\u56FE\u7247\u6682\u65F6\u65E0\u6CD5\u6309\u56FE\u7247\u683C\u5F0F\u89E3\u6790\u3002\u8BF7\u91CD\u65B0\u53D1\u9001 JPG/PNG/WebP \u56FE\u7247\uFF0C\u6216\u8005\u5728\u624B\u673A\u4E0A\u622A\u56FE\u540E\u518D\u53D1\u4E00\u6B21\u3002`;
|
|
41826
|
+
var USER_IMAGE_UNDERSTAND_CREDIT_EXHAUSTED_MESSAGE = `Credit \u4F59\u989D\u4E0D\u8DB3\uFF0C\u65E0\u6CD5\u5B8C\u6210\u672C\u6B21\u56FE\u7247\u7406\u89E3\u3002\u8BF7\u5148\u5145\u503C\u6216\u4F7F\u7528\u6FC0\u6D3B\u7801\u589E\u52A0 Credit\u3002`;
|
|
41649
41827
|
var normalizeRuntimeAttachmentUrl = (input) => {
|
|
41650
41828
|
return input.replace("/api/mobile/attachments/", "/internal/runtime/mobile/attachments/");
|
|
41651
41829
|
};
|
|
@@ -41722,6 +41900,10 @@ var imageUnderstand = {
|
|
|
41722
41900
|
type: `string`,
|
|
41723
41901
|
description: `\u56FE\u7247\u7684\u8BBF\u95EEurl\u6216base64\u7F16\u7801\u5185\u5BB9\u3002\u5F53\u7528\u6237\u76F4\u63A5\u53D1\u9001\u56FE\u7247\u65F6\u6B64\u53C2\u6570\u53EF\u7701\u7565,\u5DE5\u5177\u4F1A\u81EA\u52A8\u4ECE\u4E0A\u4E0B\u6587\u83B7\u53D6\u56FE\u7247\u3002`
|
|
41724
41902
|
},
|
|
41903
|
+
attachment_id: {
|
|
41904
|
+
type: `string`,
|
|
41905
|
+
description: `\u6700\u8FD1\u9644\u4EF6\u4E0A\u4E0B\u6587\u4E2D\u7684\u77ED\u9644\u4EF6 ID\uFF0C\u4F8B\u5982 att_img_xxx\u3002\u4F18\u5148\u4F7F\u7528\u5B83\u5F15\u7528\u5386\u53F2\u56FE\u7247\uFF0C\u4E0D\u8981\u624B\u5199\u957F URL\u3002`
|
|
41906
|
+
},
|
|
41725
41907
|
prompt: {
|
|
41726
41908
|
type: `string`,
|
|
41727
41909
|
description: `prompt\u5B57\u6BB5\u7528\u6765\u63CF\u8FF0\u6587\u5B57\u6307\u4EE4,\u4F8B\u5982"\u63CF\u8FF0\u56FE\u7247\u5185\u5BB9"`
|
|
@@ -41730,7 +41912,8 @@ var imageUnderstand = {
|
|
|
41730
41912
|
required: [`prompt`]
|
|
41731
41913
|
},
|
|
41732
41914
|
async execute(input, userRequest) {
|
|
41733
|
-
const
|
|
41915
|
+
const attachmentId = typeof input.attachment_id === "string" ? input.attachment_id.trim() : "";
|
|
41916
|
+
const imageSource = userRequest?.metadata?.imageUrl || (attachmentId && userRequest?.userId ? resolveAttachmentPathOrUrl(userRequest.userId, attachmentId) : void 0) || input.image_url;
|
|
41734
41917
|
if (!imageSource) {
|
|
41735
41918
|
throw new Error(`[ImageUnderstand] \u672A\u63D0\u4F9B\u56FE\u7247: \u8BF7\u4F20\u5165 image_url \u53C2\u6570\u6216\u901A\u8FC7\u6D88\u606F\u53D1\u9001\u56FE\u7247`);
|
|
41736
41919
|
}
|
|
@@ -41776,6 +41959,15 @@ var imageUnderstand = {
|
|
|
41776
41959
|
providerResponseId: response.providerResponseId,
|
|
41777
41960
|
authStyle,
|
|
41778
41961
|
userRequest
|
|
41962
|
+
}).catch((error) => {
|
|
41963
|
+
if (error instanceof ImageUnderstandMeteringError && (error.meteringStatus === "credit_exhausted" || error.statusCode === 402)) {
|
|
41964
|
+
throw new UserRecoverableToolError(
|
|
41965
|
+
"credit_exhausted",
|
|
41966
|
+
USER_IMAGE_UNDERSTAND_CREDIT_EXHAUSTED_MESSAGE,
|
|
41967
|
+
error.message
|
|
41968
|
+
);
|
|
41969
|
+
}
|
|
41970
|
+
throw error;
|
|
41779
41971
|
});
|
|
41780
41972
|
return resultText;
|
|
41781
41973
|
}
|
|
@@ -41783,7 +41975,7 @@ var imageUnderstand = {
|
|
|
41783
41975
|
|
|
41784
41976
|
// src/tools/tools/ImageGenerate.ts
|
|
41785
41977
|
var import_promises12 = require("node:fs/promises");
|
|
41786
|
-
var
|
|
41978
|
+
var import_node_path13 = __toESM(require("node:path"));
|
|
41787
41979
|
var DEFAULT_BASE_URL = "https://direct.shanyiapi.com";
|
|
41788
41980
|
var DEFAULT_MODEL = "gpt-image-2";
|
|
41789
41981
|
var RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([403, 429, 500, 502, 503, 504, 524]);
|
|
@@ -41810,7 +42002,7 @@ function extensionFromContentType(contentType) {
|
|
|
41810
42002
|
}
|
|
41811
42003
|
function extensionFromUrl(url) {
|
|
41812
42004
|
try {
|
|
41813
|
-
const ext =
|
|
42005
|
+
const ext = import_node_path13.default.extname(new URL(url).pathname).toLowerCase();
|
|
41814
42006
|
if ([".png", ".jpg", ".jpeg", ".webp", ".gif"].includes(ext)) return ext;
|
|
41815
42007
|
} catch {
|
|
41816
42008
|
return "";
|
|
@@ -41943,7 +42135,7 @@ var imageGenerate = {
|
|
|
41943
42135
|
requestId: generated.requestId
|
|
41944
42136
|
}, null, 2);
|
|
41945
42137
|
}
|
|
41946
|
-
const outDir =
|
|
42138
|
+
const outDir = import_node_path13.default.join(getEffectiveCwd(userRequest), "imagegen");
|
|
41947
42139
|
await (0, import_promises12.mkdir)(outDir, { recursive: true });
|
|
41948
42140
|
const stem = sanitizeName(String(input.filenameStem || prompt));
|
|
41949
42141
|
const savedFiles = [];
|
|
@@ -41952,7 +42144,7 @@ var imageGenerate = {
|
|
|
41952
42144
|
const image = item.url ? await downloadImage(item.url, timeoutMs) : item.b64_json ? decodeBase64Image(item.b64_json) : null;
|
|
41953
42145
|
if (!image) continue;
|
|
41954
42146
|
const fileName = `${stem}-${index + 1}${image.extension}`;
|
|
41955
|
-
const filePath =
|
|
42147
|
+
const filePath = import_node_path13.default.join(outDir, fileName);
|
|
41956
42148
|
await (0, import_promises12.writeFile)(filePath, image.buffer);
|
|
41957
42149
|
savedFiles.push({ filePath, fileName });
|
|
41958
42150
|
}
|
|
@@ -42397,10 +42589,10 @@ var goalDelete = {
|
|
|
42397
42589
|
};
|
|
42398
42590
|
|
|
42399
42591
|
// src/tools/tools/department/DepartmentCreate.ts
|
|
42400
|
-
var
|
|
42592
|
+
var import_node_crypto9 = require("node:crypto");
|
|
42401
42593
|
|
|
42402
42594
|
// src/department/mailbox/mailbox.ts
|
|
42403
|
-
var
|
|
42595
|
+
var import_node_crypto8 = require("node:crypto");
|
|
42404
42596
|
|
|
42405
42597
|
// src/agent/interruptRegistry.ts
|
|
42406
42598
|
var registry = /* @__PURE__ */ new Map();
|
|
@@ -42451,7 +42643,7 @@ var drainInterrupts = (userId) => {
|
|
|
42451
42643
|
};
|
|
42452
42644
|
|
|
42453
42645
|
// src/agent/events.ts
|
|
42454
|
-
var
|
|
42646
|
+
var import_node_crypto5 = require("node:crypto");
|
|
42455
42647
|
var rowToEvent = (row) => ({
|
|
42456
42648
|
id: row.id,
|
|
42457
42649
|
userId: row.userId,
|
|
@@ -42468,7 +42660,7 @@ var rowToEvent = (row) => ({
|
|
|
42468
42660
|
var recordAgentEvent = (input) => {
|
|
42469
42661
|
const db3 = createSqliteDB();
|
|
42470
42662
|
const now = Date.now();
|
|
42471
|
-
const id = `evt_${(0,
|
|
42663
|
+
const id = `evt_${(0, import_node_crypto5.randomUUID)().slice(0, 12)}`;
|
|
42472
42664
|
const payloadJson = JSON.stringify(input.payload);
|
|
42473
42665
|
db3.prepare(`
|
|
42474
42666
|
INSERT INTO agent_events (
|
|
@@ -42599,7 +42791,7 @@ ${ceoFollowupInstruction}
|
|
|
42599
42791
|
};
|
|
42600
42792
|
|
|
42601
42793
|
// src/department/mailbox/events.ts
|
|
42602
|
-
var
|
|
42794
|
+
var import_node_crypto6 = require("node:crypto");
|
|
42603
42795
|
var parseDetail = (detailJson) => {
|
|
42604
42796
|
if (!detailJson) return void 0;
|
|
42605
42797
|
try {
|
|
@@ -42640,7 +42832,7 @@ var mapMailboxEventRow = (row) => {
|
|
|
42640
42832
|
var recordMailboxEvent = (input) => {
|
|
42641
42833
|
const db3 = createSqliteDB();
|
|
42642
42834
|
const event = {
|
|
42643
|
-
id: (0,
|
|
42835
|
+
id: (0, import_node_crypto6.randomUUID)().slice(0, 12),
|
|
42644
42836
|
messageId: input.messageId,
|
|
42645
42837
|
mailboxId: input.mailboxId,
|
|
42646
42838
|
actorMailboxId: input.actorMailboxId,
|
|
@@ -42924,7 +43116,7 @@ var deleteDepartmentMemberById = (departmentName, memberId) => {
|
|
|
42924
43116
|
};
|
|
42925
43117
|
|
|
42926
43118
|
// src/department/mailbox/ceoFollowup.ts
|
|
42927
|
-
var
|
|
43119
|
+
var import_node_crypto7 = require("node:crypto");
|
|
42928
43120
|
var rowToFollowup = (row) => ({
|
|
42929
43121
|
id: row.id,
|
|
42930
43122
|
sourceMessageId: row.sourceMessageId,
|
|
@@ -42971,7 +43163,7 @@ var enqueueCeoFollowupFromMailbox = (message) => {
|
|
|
42971
43163
|
if (!message.originUserId || !message.originPlatform) return null;
|
|
42972
43164
|
const db3 = createSqliteDB();
|
|
42973
43165
|
const now = Date.now();
|
|
42974
|
-
const id = `cfu_${(0,
|
|
43166
|
+
const id = `cfu_${(0, import_node_crypto7.randomUUID)().slice(0, 12)}`;
|
|
42975
43167
|
db3.prepare(`
|
|
42976
43168
|
INSERT INTO ceo_followups (
|
|
42977
43169
|
id,
|
|
@@ -43301,7 +43493,7 @@ var recordMailboxReceivedAgentEvent = (msg) => {
|
|
|
43301
43493
|
};
|
|
43302
43494
|
var sendMessage2 = (fromMailboxId, toMailboxId, content, options) => {
|
|
43303
43495
|
const db3 = createSqliteDB();
|
|
43304
|
-
const id = (0,
|
|
43496
|
+
const id = (0, import_node_crypto8.randomUUID)().slice(0, 8);
|
|
43305
43497
|
const threadId = options?.threadId || id;
|
|
43306
43498
|
const workItemContext = resolveWorkItemContext(fromMailboxId, toMailboxId, id, options);
|
|
43307
43499
|
const stmt = db3.prepare(`insert into mailbox (
|
|
@@ -43444,7 +43636,7 @@ var departmentCreate = {
|
|
|
43444
43636
|
return `[departmentCreate] \u4E0D\u5B58\u5728 id=${sourceGoalId} \u7684\u76EE\u6807`;
|
|
43445
43637
|
}
|
|
43446
43638
|
let departmentDefinition = {
|
|
43447
|
-
id: (0,
|
|
43639
|
+
id: (0, import_node_crypto9.randomUUID)().slice(0, 8),
|
|
43448
43640
|
name,
|
|
43449
43641
|
charter,
|
|
43450
43642
|
sourceGoalId,
|
|
@@ -43711,7 +43903,7 @@ var departmentList = {
|
|
|
43711
43903
|
};
|
|
43712
43904
|
|
|
43713
43905
|
// src/tools/tools/department/DepartmentMemberCreate.ts
|
|
43714
|
-
var
|
|
43906
|
+
var import_node_crypto10 = require("node:crypto");
|
|
43715
43907
|
var DESCRIPTION25 = `
|
|
43716
43908
|
\u521B\u5EFA\u90E8\u95E8\u6210\u5458\u3002
|
|
43717
43909
|
|
|
@@ -43777,7 +43969,7 @@ var departmentMemberCreate = {
|
|
|
43777
43969
|
}
|
|
43778
43970
|
}
|
|
43779
43971
|
let departmentMember = {
|
|
43780
|
-
id: (0,
|
|
43972
|
+
id: (0, import_node_crypto10.randomUUID)().slice(0, 8),
|
|
43781
43973
|
name,
|
|
43782
43974
|
departmentId: department.id,
|
|
43783
43975
|
mailBoxId: getMailBoxId(department.name, name),
|
|
@@ -43967,13 +44159,13 @@ ${replies}`;
|
|
|
43967
44159
|
};
|
|
43968
44160
|
|
|
43969
44161
|
// src/department/learning.ts
|
|
43970
|
-
var
|
|
43971
|
-
var
|
|
43972
|
-
var
|
|
44162
|
+
var import_node_fs5 = require("node:fs");
|
|
44163
|
+
var import_node_path15 = __toESM(require("node:path"));
|
|
44164
|
+
var import_node_crypto11 = require("node:crypto");
|
|
43973
44165
|
|
|
43974
44166
|
// src/skill/SkillValidator.ts
|
|
43975
|
-
var
|
|
43976
|
-
var
|
|
44167
|
+
var import_node_fs4 = require("node:fs");
|
|
44168
|
+
var import_node_path14 = __toESM(require("node:path"));
|
|
43977
44169
|
var SKILL_NAME_PATTERN = /^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$/;
|
|
43978
44170
|
var REQUIRED_SECTIONS = [
|
|
43979
44171
|
/(^|\n)##\s+(when to use|何时使用|trigger|triggers)\b/i,
|
|
@@ -43999,9 +44191,9 @@ var assertSafeSkillTarget = (rootDir, skillName) => {
|
|
|
43999
44191
|
if (!isValidSkillName(skillName)) {
|
|
44000
44192
|
throw new Error(`Invalid skill name "${skillName}". Use lowercase letters, digits, and single hyphens only.`);
|
|
44001
44193
|
}
|
|
44002
|
-
const root =
|
|
44003
|
-
const target =
|
|
44004
|
-
if (target !==
|
|
44194
|
+
const root = import_node_path14.default.resolve(rootDir);
|
|
44195
|
+
const target = import_node_path14.default.resolve(root, skillName);
|
|
44196
|
+
if (target !== import_node_path14.default.join(root, skillName) || !target.startsWith(root + import_node_path14.default.sep)) {
|
|
44005
44197
|
throw new Error(`Invalid skill install target for "${skillName}".`);
|
|
44006
44198
|
}
|
|
44007
44199
|
return target;
|
|
@@ -44074,14 +44266,14 @@ var validateSkillDocument = (input) => {
|
|
|
44074
44266
|
}
|
|
44075
44267
|
}
|
|
44076
44268
|
if (input.baseDir) {
|
|
44077
|
-
const normalizedBase =
|
|
44269
|
+
const normalizedBase = import_node_path14.default.resolve(input.baseDir);
|
|
44078
44270
|
for (const match2 of parsed.body.matchAll(/\]\(([^)]+)\)/g)) {
|
|
44079
44271
|
const href = match2[1].trim();
|
|
44080
44272
|
if (!href || /^[a-z][a-z0-9+.-]*:/i.test(href) || href.startsWith(`#`)) continue;
|
|
44081
|
-
const target =
|
|
44082
|
-
if (!target.startsWith(normalizedBase +
|
|
44273
|
+
const target = import_node_path14.default.resolve(normalizedBase, href.split(`#`)[0]);
|
|
44274
|
+
if (!target.startsWith(normalizedBase + import_node_path14.default.sep) && target !== normalizedBase) {
|
|
44083
44275
|
addError(errors, `unsafe_reference`, `Relative link "${href}" escapes the skill directory.`);
|
|
44084
|
-
} else if (!(0,
|
|
44276
|
+
} else if (!(0, import_node_fs4.existsSync)(target)) {
|
|
44085
44277
|
addError(errors, `missing_reference`, `Relative link "${href}" does not exist in the skill directory.`);
|
|
44086
44278
|
}
|
|
44087
44279
|
}
|
|
@@ -44098,9 +44290,9 @@ var mergeIssues = (target, source) => {
|
|
|
44098
44290
|
target.warnings.push(...source.warnings);
|
|
44099
44291
|
};
|
|
44100
44292
|
var validateScriptsDirectory = (skillDir, warnings) => {
|
|
44101
|
-
const scriptsDir =
|
|
44102
|
-
if (!(0,
|
|
44103
|
-
const entries = (0,
|
|
44293
|
+
const scriptsDir = import_node_path14.default.join(skillDir, `scripts`);
|
|
44294
|
+
if (!(0, import_node_fs4.existsSync)(scriptsDir)) return;
|
|
44295
|
+
const entries = (0, import_node_fs4.readdirSync)(scriptsDir, { withFileTypes: true }).filter((entry) => entry.isFile());
|
|
44104
44296
|
if (entries.length === 0) {
|
|
44105
44297
|
addWarning(warnings, `empty_scripts_dir`, `scripts/ exists but contains no files.`);
|
|
44106
44298
|
}
|
|
@@ -44108,19 +44300,19 @@ var validateScriptsDirectory = (skillDir, warnings) => {
|
|
|
44108
44300
|
var validateSkillDirectory = (skillDir, options = {}) => {
|
|
44109
44301
|
const errors = [];
|
|
44110
44302
|
const warnings = [];
|
|
44111
|
-
const normalizedSkillDir =
|
|
44112
|
-
const skillMdPath =
|
|
44113
|
-
if (!(0,
|
|
44303
|
+
const normalizedSkillDir = import_node_path14.default.resolve(skillDir);
|
|
44304
|
+
const skillMdPath = import_node_path14.default.join(normalizedSkillDir, `SKILL.md`);
|
|
44305
|
+
if (!(0, import_node_fs4.existsSync)(normalizedSkillDir) || !(0, import_node_fs4.statSync)(normalizedSkillDir).isDirectory()) {
|
|
44114
44306
|
addError(errors, `missing_skill_dir`, `Skill directory does not exist: ${normalizedSkillDir}`);
|
|
44115
44307
|
return { ok: false, errors, warnings, skillDir: normalizedSkillDir, skillMdPath };
|
|
44116
44308
|
}
|
|
44117
|
-
if (!(0,
|
|
44309
|
+
if (!(0, import_node_fs4.existsSync)(skillMdPath) || !(0, import_node_fs4.statSync)(skillMdPath).isFile()) {
|
|
44118
44310
|
addError(errors, `missing_skill_md`, `Skill directory must contain SKILL.md.`);
|
|
44119
44311
|
return { ok: false, errors, warnings, skillDir: normalizedSkillDir, skillMdPath };
|
|
44120
44312
|
}
|
|
44121
|
-
const raw2 = (0,
|
|
44313
|
+
const raw2 = (0, import_node_fs4.readFileSync)(skillMdPath, `utf-8`);
|
|
44122
44314
|
const documentResult = validateSkillDocument({
|
|
44123
|
-
skillName: options.expectedName ??
|
|
44315
|
+
skillName: options.expectedName ?? import_node_path14.default.basename(normalizedSkillDir),
|
|
44124
44316
|
skillMd: raw2,
|
|
44125
44317
|
baseDir: normalizedSkillDir
|
|
44126
44318
|
});
|
|
@@ -44172,26 +44364,26 @@ var formatSkillValidationIssues = (result) => {
|
|
|
44172
44364
|
};
|
|
44173
44365
|
|
|
44174
44366
|
// src/department/learning.ts
|
|
44175
|
-
var ensureDir = (dir) => (0,
|
|
44367
|
+
var ensureDir = (dir) => (0, import_node_fs5.mkdirSync)(dir, { recursive: true });
|
|
44176
44368
|
var readJsonArray = (filePath) => {
|
|
44177
|
-
if (!(0,
|
|
44178
|
-
return JSON.parse((0,
|
|
44369
|
+
if (!(0, import_node_fs5.existsSync)(filePath)) return [];
|
|
44370
|
+
return JSON.parse((0, import_node_fs5.readFileSync)(filePath, "utf-8"));
|
|
44179
44371
|
};
|
|
44180
44372
|
var writeJsonArray = (filePath, records) => {
|
|
44181
|
-
ensureDir(
|
|
44182
|
-
(0,
|
|
44373
|
+
ensureDir(import_node_path15.default.dirname(filePath));
|
|
44374
|
+
(0, import_node_fs5.writeFileSync)(filePath, JSON.stringify(records, null, " "), "utf-8");
|
|
44183
44375
|
};
|
|
44184
44376
|
var departmentMemoryPath = (departmentName) => {
|
|
44185
|
-
return
|
|
44377
|
+
return import_node_path15.default.join(getDepartmentWorkSpaceDir(departmentName), "department-memory.json");
|
|
44186
44378
|
};
|
|
44187
44379
|
var departmentSkillPath = (departmentName) => {
|
|
44188
|
-
return
|
|
44380
|
+
return import_node_path15.default.join(getDepartmentWorkSpaceDir(departmentName), "department-skills.json");
|
|
44189
44381
|
};
|
|
44190
44382
|
var departmentSkillDir = (departmentName, skillName) => {
|
|
44191
|
-
return assertSafeSkillTarget(
|
|
44383
|
+
return assertSafeSkillTarget(import_node_path15.default.join(getDepartmentWorkSpaceDir(departmentName), "skills"), skillName);
|
|
44192
44384
|
};
|
|
44193
44385
|
var proposalsPath = () => {
|
|
44194
|
-
return
|
|
44386
|
+
return import_node_path15.default.join(getDepartmentBaseDir(), "department-proposals.json");
|
|
44195
44387
|
};
|
|
44196
44388
|
var getDepartmentNameForHead = (request) => {
|
|
44197
44389
|
const mailboxId = request?.departmentAgentId;
|
|
@@ -44207,7 +44399,7 @@ var listDepartmentMemories = (departmentName) => {
|
|
|
44207
44399
|
var createDepartmentMemory = (departmentName, input) => {
|
|
44208
44400
|
const now = Date.now();
|
|
44209
44401
|
const memory = {
|
|
44210
|
-
id: (0,
|
|
44402
|
+
id: (0, import_node_crypto11.randomUUID)().slice(0, 8),
|
|
44211
44403
|
departmentName,
|
|
44212
44404
|
title: input.title,
|
|
44213
44405
|
content: input.content,
|
|
@@ -44258,7 +44450,7 @@ ${formatSkillValidationIssues(validation)}`);
|
|
|
44258
44450
|
}
|
|
44259
44451
|
const now = Date.now();
|
|
44260
44452
|
const skill = {
|
|
44261
|
-
id: (0,
|
|
44453
|
+
id: (0, import_node_crypto11.randomUUID)().slice(0, 8),
|
|
44262
44454
|
departmentName,
|
|
44263
44455
|
skillName: input.skillName,
|
|
44264
44456
|
description: input.description,
|
|
@@ -44289,7 +44481,7 @@ var keepDepartmentSkill = (departmentName, id) => {
|
|
|
44289
44481
|
${formatSkillValidationIssues(validation)}`);
|
|
44290
44482
|
}
|
|
44291
44483
|
ensureDir(skillDir);
|
|
44292
|
-
(0,
|
|
44484
|
+
(0, import_node_fs5.writeFileSync)(import_node_path15.default.join(skillDir, "SKILL.md"), records[idx].skillMd, "utf-8");
|
|
44293
44485
|
const smokeTest = smokeTestSkillDirectory(skillDir, { expectedName: records[idx].skillName });
|
|
44294
44486
|
if (!smokeTest.ok) {
|
|
44295
44487
|
throw new Error(`[departmentSkill] Skill smoke test \u5931\u8D25\uFF1A
|
|
@@ -44310,7 +44502,7 @@ var createDepartmentProposal = (input) => {
|
|
|
44310
44502
|
const records = readJsonArray(proposalsPath());
|
|
44311
44503
|
const proposal = {
|
|
44312
44504
|
...input,
|
|
44313
|
-
id: (0,
|
|
44505
|
+
id: (0, import_node_crypto11.randomUUID)().slice(0, 8),
|
|
44314
44506
|
status: "pending",
|
|
44315
44507
|
createdAt: Date.now()
|
|
44316
44508
|
};
|
|
@@ -44669,8 +44861,8 @@ var mailboxFollowup = {
|
|
|
44669
44861
|
|
|
44670
44862
|
// src/tools/tools/Bash.ts
|
|
44671
44863
|
var import_node_child_process = require("node:child_process");
|
|
44672
|
-
var
|
|
44673
|
-
var
|
|
44864
|
+
var import_node_crypto12 = require("node:crypto");
|
|
44865
|
+
var import_node_fs6 = require("node:fs");
|
|
44674
44866
|
var DESCRIPTION30 = `\u5728\u7CFB\u7EDF shell \u4E2D\u6267\u884C\u547D\u4EE4\u3002
|
|
44675
44867
|
|
|
44676
44868
|
\u7528\u9014\uFF1A
|
|
@@ -44710,7 +44902,7 @@ var sessions = /* @__PURE__ */ new Map();
|
|
|
44710
44902
|
function findExecutableShell2() {
|
|
44711
44903
|
for (const shell of SHELL_CANDIDATES2) {
|
|
44712
44904
|
try {
|
|
44713
|
-
(0,
|
|
44905
|
+
(0, import_node_fs6.accessSync)(shell, import_node_fs6.constants.X_OK);
|
|
44714
44906
|
return shell;
|
|
44715
44907
|
} catch {
|
|
44716
44908
|
}
|
|
@@ -44719,11 +44911,11 @@ function findExecutableShell2() {
|
|
|
44719
44911
|
}
|
|
44720
44912
|
function validateCwd(cwd) {
|
|
44721
44913
|
try {
|
|
44722
|
-
const stat11 = (0,
|
|
44914
|
+
const stat11 = (0, import_node_fs6.statSync)(cwd);
|
|
44723
44915
|
if (!stat11.isDirectory()) {
|
|
44724
44916
|
return `[bash] \u9519\u8BEF: cwd \u4E0D\u662F\u76EE\u5F55: ${cwd}`;
|
|
44725
44917
|
}
|
|
44726
|
-
(0,
|
|
44918
|
+
(0, import_node_fs6.accessSync)(cwd, import_node_fs6.constants.R_OK | import_node_fs6.constants.X_OK);
|
|
44727
44919
|
return null;
|
|
44728
44920
|
} catch (err) {
|
|
44729
44921
|
const code = err.code;
|
|
@@ -44966,7 +45158,7 @@ var bashTool = {
|
|
|
44966
45158
|
stdio: ["pipe", "pipe", "pipe"],
|
|
44967
45159
|
detached: process.platform !== "win32"
|
|
44968
45160
|
});
|
|
44969
|
-
const id = (0,
|
|
45161
|
+
const id = (0, import_node_crypto12.randomUUID)().slice(0, 8);
|
|
44970
45162
|
const session = {
|
|
44971
45163
|
id,
|
|
44972
45164
|
command,
|
|
@@ -45184,12 +45376,11 @@ var createSaasCreditToolHookPlugin = () => ({
|
|
|
45184
45376
|
toolCallId: ctx.toolCallId,
|
|
45185
45377
|
requestId: ctx.userRequest?.requestId ?? null,
|
|
45186
45378
|
occurredAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
45187
|
-
|
|
45188
|
-
|
|
45189
|
-
|
|
45190
|
-
|
|
45191
|
-
|
|
45192
|
-
}
|
|
45379
|
+
meterType: usage.meterType,
|
|
45380
|
+
provider: usage.provider,
|
|
45381
|
+
unit: usage.unit,
|
|
45382
|
+
quantity: usage.quantity,
|
|
45383
|
+
metadata: usage.metadata
|
|
45193
45384
|
})
|
|
45194
45385
|
});
|
|
45195
45386
|
const body = await parseJson2(response);
|
|
@@ -45197,7 +45388,7 @@ var createSaasCreditToolHookPlugin = () => ({
|
|
|
45197
45388
|
if (response.status === 402 || status === "credit_exhausted") {
|
|
45198
45389
|
throw new UserRecoverableToolError(
|
|
45199
45390
|
"credit_exhausted",
|
|
45200
|
-
|
|
45391
|
+
usage.userMessage,
|
|
45201
45392
|
`[saas-credit] ${ctx.toolName} credit exhausted`
|
|
45202
45393
|
);
|
|
45203
45394
|
}
|
|
@@ -45207,14 +45398,27 @@ var createSaasCreditToolHookPlugin = () => ({
|
|
|
45207
45398
|
}
|
|
45208
45399
|
});
|
|
45209
45400
|
function meteredToolUsage(ctx) {
|
|
45210
|
-
if (ctx.toolName
|
|
45211
|
-
|
|
45212
|
-
|
|
45213
|
-
|
|
45214
|
-
|
|
45215
|
-
|
|
45216
|
-
|
|
45217
|
-
|
|
45401
|
+
if (ctx.toolName === "websearch") {
|
|
45402
|
+
if (isWebSearchErrorResult(ctx.resultText)) return null;
|
|
45403
|
+
return {
|
|
45404
|
+
meterType: "web.content_retrieval",
|
|
45405
|
+
provider: "exa",
|
|
45406
|
+
unit: "content",
|
|
45407
|
+
quantity: normalizeNumResults(ctx.input.numResults),
|
|
45408
|
+
userMessage: "Credit \u4F59\u989D\u4E0D\u8DB3\uFF0C\u65E0\u6CD5\u5B8C\u6210\u672C\u6B21\u7F51\u9875\u641C\u7D22\u3002\u8BF7\u5148\u5145\u503C\u6216\u4F7F\u7528\u6FC0\u6D3B\u7801\u589E\u52A0 Credit\u3002",
|
|
45409
|
+
metadata: {
|
|
45410
|
+
platform: ctx.userRequest?.platform ?? null,
|
|
45411
|
+
departmentAgentId: ctx.userRequest?.departmentAgentId ?? null,
|
|
45412
|
+
input: sanitizedWebSearchInput(ctx.input)
|
|
45413
|
+
}
|
|
45414
|
+
};
|
|
45415
|
+
}
|
|
45416
|
+
if (ctx.toolName === "image_generate") {
|
|
45417
|
+
const usage = imageGenerateUsage(ctx);
|
|
45418
|
+
if (!usage) return null;
|
|
45419
|
+
return usage;
|
|
45420
|
+
}
|
|
45421
|
+
return null;
|
|
45218
45422
|
}
|
|
45219
45423
|
function normalizeNumResults(value) {
|
|
45220
45424
|
if (typeof value !== "number" || !Number.isFinite(value)) return DEFAULT_WEB_SEARCH_NUM_RESULTS;
|
|
@@ -45233,6 +45437,37 @@ function sanitizedWebSearchInput(input) {
|
|
|
45233
45437
|
contextMaxCharacters: typeof input.contextMaxCharacters === "number" ? input.contextMaxCharacters : null
|
|
45234
45438
|
};
|
|
45235
45439
|
}
|
|
45440
|
+
function imageGenerateUsage(ctx) {
|
|
45441
|
+
const result = parseResultJson(ctx.resultText);
|
|
45442
|
+
if (!result || result.ok !== true) return null;
|
|
45443
|
+
const savedFiles = Array.isArray(result.savedFiles) ? result.savedFiles : [];
|
|
45444
|
+
const quantity = savedFiles.length > 0 ? savedFiles.length : 1;
|
|
45445
|
+
return {
|
|
45446
|
+
meterType: "image.generate",
|
|
45447
|
+
provider: "shanyi",
|
|
45448
|
+
unit: "image",
|
|
45449
|
+
quantity,
|
|
45450
|
+
userMessage: "Credit \u4F59\u989D\u4E0D\u8DB3\uFF0C\u65E0\u6CD5\u751F\u6210\u56FE\u7247\u3002\u751F\u6210\u56FE\u7247\u6BCF\u5F20\u9700\u8981 20 Credit\uFF08\u7EA6 0.2 \u5143\uFF09\uFF0C\u8BF7\u5148\u5145\u503C\u6216\u4F7F\u7528\u6FC0\u6D3B\u7801\u589E\u52A0 Credit\u3002",
|
|
45451
|
+
metadata: {
|
|
45452
|
+
platform: ctx.userRequest?.platform ?? null,
|
|
45453
|
+
departmentAgentId: ctx.userRequest?.departmentAgentId ?? null,
|
|
45454
|
+
model: typeof result.model === "string" ? result.model : null,
|
|
45455
|
+
size: typeof result.size === "string" ? result.size : null,
|
|
45456
|
+
resolution: typeof result.resolution === "string" ? result.resolution : null,
|
|
45457
|
+
requestId: typeof result.requestId === "string" ? result.requestId : null,
|
|
45458
|
+
prompt: typeof ctx.input.prompt === "string" ? ctx.input.prompt.slice(0, 500) : null
|
|
45459
|
+
}
|
|
45460
|
+
};
|
|
45461
|
+
}
|
|
45462
|
+
function parseResultJson(value) {
|
|
45463
|
+
if (!value) return null;
|
|
45464
|
+
try {
|
|
45465
|
+
const parsed = JSON.parse(value);
|
|
45466
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
45467
|
+
} catch {
|
|
45468
|
+
return null;
|
|
45469
|
+
}
|
|
45470
|
+
}
|
|
45236
45471
|
async function parseJson2(response) {
|
|
45237
45472
|
try {
|
|
45238
45473
|
return await response.json();
|
|
@@ -45733,10 +45968,10 @@ var readDreamHistoryLimit = () => {
|
|
|
45733
45968
|
};
|
|
45734
45969
|
|
|
45735
45970
|
// src/skillForge/SkillForgeEngine.ts
|
|
45736
|
-
var
|
|
45971
|
+
var import_node_fs7 = require("node:fs");
|
|
45737
45972
|
var import_node_os2 = require("node:os");
|
|
45738
|
-
var
|
|
45739
|
-
var
|
|
45973
|
+
var import_node_path16 = require("node:path");
|
|
45974
|
+
var import_node_crypto13 = require("node:crypto");
|
|
45740
45975
|
var SkillForgeEngine = class {
|
|
45741
45976
|
proposalStorage;
|
|
45742
45977
|
draftRoot;
|
|
@@ -45744,8 +45979,8 @@ var SkillForgeEngine = class {
|
|
|
45744
45979
|
constructor(deps) {
|
|
45745
45980
|
this.proposalStorage = deps.proposalStorage;
|
|
45746
45981
|
const opt = deps.options ?? {};
|
|
45747
|
-
this.draftRoot = opt.draftRoot ?? (0,
|
|
45748
|
-
this.skillsInstallDir = opt.skillsInstallDir ?? (0,
|
|
45982
|
+
this.draftRoot = opt.draftRoot ?? (0, import_node_path16.join)((0, import_node_os2.homedir)(), ".duclaw", "skill-proposals");
|
|
45983
|
+
this.skillsInstallDir = opt.skillsInstallDir ?? (0, import_node_path16.join)((0, import_node_os2.homedir)(), ".agents", "skills");
|
|
45749
45984
|
}
|
|
45750
45985
|
// ---------- 公开方法 ----------
|
|
45751
45986
|
/**
|
|
@@ -45770,14 +46005,14 @@ ${formatSkillValidationIssues(validation)}`);
|
|
|
45770
46005
|
if (pending.some((p) => p.skillName === skillName)) {
|
|
45771
46006
|
return null;
|
|
45772
46007
|
}
|
|
45773
|
-
const id = (0,
|
|
45774
|
-
const draftDir = (0,
|
|
45775
|
-
(0,
|
|
45776
|
-
(0,
|
|
46008
|
+
const id = (0, import_node_crypto13.randomBytes)(4).toString("hex");
|
|
46009
|
+
const draftDir = (0, import_node_path16.join)(this.draftRoot, userId, id);
|
|
46010
|
+
(0, import_node_fs7.mkdirSync)(draftDir, { recursive: true });
|
|
46011
|
+
(0, import_node_fs7.writeFileSync)((0, import_node_path16.join)(draftDir, "SKILL.md"), skillMd, "utf-8");
|
|
45777
46012
|
const directoryValidation = validateSkillDirectory(draftDir, { expectedName: skillName });
|
|
45778
46013
|
if (!directoryValidation.ok) {
|
|
45779
46014
|
try {
|
|
45780
|
-
(0,
|
|
46015
|
+
(0, import_node_fs7.rmSync)(draftDir, { recursive: true, force: true });
|
|
45781
46016
|
} catch {
|
|
45782
46017
|
}
|
|
45783
46018
|
throw new Error(`[skillForge] Skill \u76EE\u5F55\u6821\u9A8C\u5931\u8D25\uFF1A
|
|
@@ -45812,26 +46047,26 @@ ${formatSkillValidationIssues(validation)}`);
|
|
|
45812
46047
|
}
|
|
45813
46048
|
const target = assertSafeSkillTarget(this.skillsInstallDir, proposal.skillName);
|
|
45814
46049
|
let installedTarget = target;
|
|
45815
|
-
if ((0,
|
|
46050
|
+
if ((0, import_node_fs7.existsSync)(target)) {
|
|
45816
46051
|
const alt = target + "-" + proposalId;
|
|
45817
|
-
(0,
|
|
45818
|
-
(0,
|
|
46052
|
+
(0, import_node_fs7.mkdirSync)(alt, { recursive: true });
|
|
46053
|
+
(0, import_node_fs7.cpSync)(proposal.draftDir, alt, { recursive: true });
|
|
45819
46054
|
installedTarget = alt;
|
|
45820
46055
|
} else {
|
|
45821
|
-
(0,
|
|
45822
|
-
(0,
|
|
46056
|
+
(0, import_node_fs7.mkdirSync)(target, { recursive: true });
|
|
46057
|
+
(0, import_node_fs7.cpSync)(proposal.draftDir, target, { recursive: true });
|
|
45823
46058
|
}
|
|
45824
46059
|
const smokeTest = smokeTestSkillDirectory(installedTarget, { expectedName: proposal.skillName });
|
|
45825
46060
|
if (!smokeTest.ok) {
|
|
45826
46061
|
try {
|
|
45827
|
-
(0,
|
|
46062
|
+
(0, import_node_fs7.rmSync)(installedTarget, { recursive: true, force: true });
|
|
45828
46063
|
} catch {
|
|
45829
46064
|
}
|
|
45830
46065
|
throw new Error(`[skillForge] Skill smoke test \u5931\u8D25\uFF0C\u5DF2\u56DE\u6EDA\u843D\u5730\u76EE\u5F55\uFF1A
|
|
45831
46066
|
${formatSkillValidationIssues(smokeTest)}`);
|
|
45832
46067
|
}
|
|
45833
46068
|
try {
|
|
45834
|
-
(0,
|
|
46069
|
+
(0, import_node_fs7.rmSync)(proposal.draftDir, { recursive: true, force: true });
|
|
45835
46070
|
} catch {
|
|
45836
46071
|
}
|
|
45837
46072
|
await this.removeProposal(userId, proposalId);
|
|
@@ -45843,7 +46078,7 @@ ${formatSkillValidationIssues(smokeTest)}`);
|
|
|
45843
46078
|
const proposal = list.find((p) => p.id === proposalId);
|
|
45844
46079
|
if (!proposal) return null;
|
|
45845
46080
|
try {
|
|
45846
|
-
(0,
|
|
46081
|
+
(0, import_node_fs7.rmSync)(proposal.draftDir, { recursive: true, force: true });
|
|
45847
46082
|
} catch {
|
|
45848
46083
|
}
|
|
45849
46084
|
await this.removeProposal(userId, proposalId);
|
|
@@ -46052,7 +46287,7 @@ var skillForgeDrop = (engine) => ({
|
|
|
46052
46287
|
});
|
|
46053
46288
|
|
|
46054
46289
|
// src/memory/MemoryEngine.ts
|
|
46055
|
-
var
|
|
46290
|
+
var import_node_crypto14 = require("node:crypto");
|
|
46056
46291
|
var MemoryEngine = class {
|
|
46057
46292
|
storage;
|
|
46058
46293
|
recallIndexStorage;
|
|
@@ -46080,7 +46315,7 @@ var MemoryEngine = class {
|
|
|
46080
46315
|
}
|
|
46081
46316
|
const now = Date.now();
|
|
46082
46317
|
const memory = {
|
|
46083
|
-
id: (0,
|
|
46318
|
+
id: (0, import_node_crypto14.randomBytes)(4).toString("hex"),
|
|
46084
46319
|
userId,
|
|
46085
46320
|
title,
|
|
46086
46321
|
content,
|
|
@@ -46732,13 +46967,13 @@ var COMPANY_VALUES_PROMPT = `<\u516C\u53F8\u5171\u540C\u4FE1\u5FF5>
|
|
|
46732
46967
|
</\u516C\u53F8\u5171\u540C\u4FE1\u5FF5>`;
|
|
46733
46968
|
|
|
46734
46969
|
// src/agent/outboundDedup.ts
|
|
46735
|
-
var
|
|
46970
|
+
var import_node_crypto15 = require("node:crypto");
|
|
46736
46971
|
var DEFAULT_WINDOW_MS = 15e3;
|
|
46737
46972
|
var recentSends = /* @__PURE__ */ new Map();
|
|
46738
46973
|
var lastSweepAt = 0;
|
|
46739
46974
|
var normalize3 = (text2) => text2.replace(/\s+/g, " ").trim();
|
|
46740
46975
|
var keyFor = (userId, normalized) => {
|
|
46741
|
-
const hash = (0,
|
|
46976
|
+
const hash = (0, import_node_crypto15.createHash)("sha1").update(normalized).digest("hex");
|
|
46742
46977
|
return `${userId}::${hash}`;
|
|
46743
46978
|
};
|
|
46744
46979
|
var sweep = (now, windowMs) => {
|
|
@@ -46786,12 +47021,12 @@ var isAbortError2 = (error) => {
|
|
|
46786
47021
|
return error.name === "AbortError" || error.message.includes("aborted") || error.message.includes("AbortError");
|
|
46787
47022
|
};
|
|
46788
47023
|
var llmRequestIdForTurn = (request, messages, system, tools) => {
|
|
46789
|
-
const hash = (0,
|
|
47024
|
+
const hash = (0, import_node_crypto16.createHash)("sha256").update(request.requestId).update("\0").update(system).update("\0").update(JSON.stringify(messages)).update("\0").update(JSON.stringify(tools.map((tool) => tool.name).sort())).digest("hex").slice(0, 40);
|
|
46790
47025
|
return `dreq_${hash}`;
|
|
46791
47026
|
};
|
|
46792
47027
|
var getDefaultAgentConfig = (tools, systemPrompt) => {
|
|
46793
47028
|
loadEnv();
|
|
46794
|
-
(0,
|
|
47029
|
+
(0, import_node_fs8.mkdirSync)(DEFAULT_WORKSPACE_PATH, { recursive: true });
|
|
46795
47030
|
let system = ``;
|
|
46796
47031
|
if (!systemPrompt) {
|
|
46797
47032
|
system = `
|
|
@@ -47024,7 +47259,8 @@ var createAgent = (config2 = getDefaultAgentConfig()) => {
|
|
|
47024
47259
|
if (config2.workspacePath && !request.defaultWorkDir) {
|
|
47025
47260
|
request.defaultWorkDir = config2.workspacePath;
|
|
47026
47261
|
}
|
|
47027
|
-
const { userId,
|
|
47262
|
+
const { userId, job } = request;
|
|
47263
|
+
const content = attachRecentAttachmentContext(request, request.content);
|
|
47028
47264
|
const internalOnly = request.metadata?.internalOnly === true;
|
|
47029
47265
|
const injectedEventIds = /* @__PURE__ */ new Set();
|
|
47030
47266
|
const interruptQueuedEventIds = /* @__PURE__ */ new Set();
|
|
@@ -51866,7 +52102,7 @@ var cors = (options) => {
|
|
|
51866
52102
|
|
|
51867
52103
|
// src/server/index.ts
|
|
51868
52104
|
var import_promises14 = require("node:fs/promises");
|
|
51869
|
-
var
|
|
52105
|
+
var import_node_path20 = __toESM(require("node:path"));
|
|
51870
52106
|
|
|
51871
52107
|
// src/git/worktree.ts
|
|
51872
52108
|
var import_child_process2 = require("child_process");
|
|
@@ -53211,8 +53447,8 @@ mailboxRoutes.get("/mailbox/summary", (c) => {
|
|
|
53211
53447
|
|
|
53212
53448
|
// src/server/routes/memory.ts
|
|
53213
53449
|
var import_redis4 = __toESM(require_dist2());
|
|
53214
|
-
var
|
|
53215
|
-
var
|
|
53450
|
+
var import_node_fs9 = require("node:fs");
|
|
53451
|
+
var import_node_path17 = __toESM(require("node:path"));
|
|
53216
53452
|
var memoryEngineSingleton = null;
|
|
53217
53453
|
var dreamStorageSingleton = null;
|
|
53218
53454
|
var dreamHistoryStorageSingleton = null;
|
|
@@ -53312,12 +53548,12 @@ var addPlausibleUserId = (set, userId) => {
|
|
|
53312
53548
|
if (normalized && isPlausibleUserId(normalized)) set.add(normalized);
|
|
53313
53549
|
};
|
|
53314
53550
|
var readJsonFilesFromDir = (dir) => {
|
|
53315
|
-
if (!(0,
|
|
53551
|
+
if (!(0, import_node_fs9.existsSync)(dir)) return [];
|
|
53316
53552
|
const result = [];
|
|
53317
|
-
for (const file of (0,
|
|
53553
|
+
for (const file of (0, import_node_fs9.readdirSync)(dir)) {
|
|
53318
53554
|
if (!file.endsWith(".json")) continue;
|
|
53319
53555
|
try {
|
|
53320
|
-
result.push(JSON.parse((0,
|
|
53556
|
+
result.push(JSON.parse((0, import_node_fs9.readFileSync)(import_node_path17.default.join(dir, file), "utf-8")));
|
|
53321
53557
|
} catch (err) {
|
|
53322
53558
|
console.warn(`[memoryRoutes] \u8DF3\u8FC7\u65E0\u6CD5\u89E3\u6790\u7684\u672C\u5730\u4E0A\u4E0B\u6587\u6587\u4EF6 ${file}: ${err.message}`);
|
|
53323
53559
|
}
|
|
@@ -53325,13 +53561,13 @@ var readJsonFilesFromDir = (dir) => {
|
|
|
53325
53561
|
return result;
|
|
53326
53562
|
};
|
|
53327
53563
|
var extractFileBackedStorageKeysForTest = (dataDir) => {
|
|
53328
|
-
const kvRoot =
|
|
53329
|
-
if (!(0,
|
|
53564
|
+
const kvRoot = import_node_path17.default.join(dataDir, "kv");
|
|
53565
|
+
if (!(0, import_node_fs9.existsSync)(kvRoot)) return [];
|
|
53330
53566
|
const keys = [];
|
|
53331
|
-
for (const prefixDir of (0,
|
|
53332
|
-
const absolutePrefixDir =
|
|
53333
|
-
if (!(0,
|
|
53334
|
-
for (const file of (0,
|
|
53567
|
+
for (const prefixDir of (0, import_node_fs9.readdirSync)(kvRoot)) {
|
|
53568
|
+
const absolutePrefixDir = import_node_path17.default.join(kvRoot, prefixDir);
|
|
53569
|
+
if (!(0, import_node_fs9.existsSync)(absolutePrefixDir)) continue;
|
|
53570
|
+
for (const file of (0, import_node_fs9.readdirSync)(absolutePrefixDir)) {
|
|
53335
53571
|
if (!file.endsWith(".json")) continue;
|
|
53336
53572
|
try {
|
|
53337
53573
|
const logicalKey = Buffer.from(file.replace(/\.json$/, ""), "base64url").toString("utf8");
|
|
@@ -53349,12 +53585,12 @@ var collectLocalConversationUserIds = () => {
|
|
|
53349
53585
|
};
|
|
53350
53586
|
var extractLocalConversationUserIdsForTest = (homeDir) => {
|
|
53351
53587
|
const userIds = /* @__PURE__ */ new Set();
|
|
53352
|
-
for (const context of readJsonFilesFromDir(
|
|
53588
|
+
for (const context of readJsonFilesFromDir(import_node_path17.default.join(homeDir, "goal-context"))) {
|
|
53353
53589
|
addPlausibleUserId(userIds, context.threadId);
|
|
53354
53590
|
addPlausibleUserId(userIds, context.originUserId);
|
|
53355
53591
|
if (context.goalId) addPlausibleUserId(userIds, `kanban:goal:${context.goalId}`);
|
|
53356
53592
|
}
|
|
53357
|
-
for (const goal of readJsonFilesFromDir(
|
|
53593
|
+
for (const goal of readJsonFilesFromDir(import_node_path17.default.join(homeDir, "tasks"))) {
|
|
53358
53594
|
if (goal.id) addPlausibleUserId(userIds, `kanban:goal:${goal.id}`);
|
|
53359
53595
|
}
|
|
53360
53596
|
return userIds;
|
|
@@ -53771,7 +54007,7 @@ ${item.dreamContent}` : item.dreamContent).join("\n\n");
|
|
|
53771
54007
|
});
|
|
53772
54008
|
|
|
53773
54009
|
// src/server/routes/tools.ts
|
|
53774
|
-
var
|
|
54010
|
+
var import_node_path18 = __toESM(require("node:path"));
|
|
53775
54011
|
var toolRoutes = new Hono2();
|
|
53776
54012
|
var listActiveDepartmentSkills = () => {
|
|
53777
54013
|
return listDepartments().flatMap(
|
|
@@ -53782,7 +54018,7 @@ var listActiveDepartmentSkills = () => {
|
|
|
53782
54018
|
scope: "department",
|
|
53783
54019
|
departmentName: department.name,
|
|
53784
54020
|
detail: () => {
|
|
53785
|
-
const skillDir =
|
|
54021
|
+
const skillDir = import_node_path18.default.join(getDepartmentWorkSpaceDir(department.name), "skills", skill.skillName);
|
|
53786
54022
|
return `Base directory for this skill: ${skillDir}
|
|
53787
54023
|
|
|
53788
54024
|
${skill.skillMd}`;
|
|
@@ -53871,7 +54107,7 @@ var systemRoutes = new Hono2();
|
|
|
53871
54107
|
var startTime = Date.now();
|
|
53872
54108
|
systemRoutes.get("/system/info", (c) => {
|
|
53873
54109
|
return c.json({
|
|
53874
|
-
version: true ? "1.9.
|
|
54110
|
+
version: true ? "1.9.15" : "unknown",
|
|
53875
54111
|
uptime: Math.floor((Date.now() - startTime) / 1e3),
|
|
53876
54112
|
env: process.env.NODE_ENV || "development",
|
|
53877
54113
|
nodeVersion: process.version
|
|
@@ -53879,9 +54115,9 @@ systemRoutes.get("/system/info", (c) => {
|
|
|
53879
54115
|
});
|
|
53880
54116
|
|
|
53881
54117
|
// src/server/routes/mobile.ts
|
|
53882
|
-
var
|
|
54118
|
+
var import_node_crypto17 = require("node:crypto");
|
|
53883
54119
|
var import_promises13 = require("node:fs/promises");
|
|
53884
|
-
var
|
|
54120
|
+
var import_node_path19 = __toESM(require("node:path"));
|
|
53885
54121
|
var mobileRoutes = new Hono2();
|
|
53886
54122
|
var resolveMobileUserId = (body, headerUserId) => {
|
|
53887
54123
|
return body.userId?.trim() || headerUserId?.trim() || "ios:local-user";
|
|
@@ -53923,12 +54159,12 @@ ${goal.tasks.map((task) => `- [${task.status}] ${task.subject}`).join("\n")}` :
|
|
|
53923
54159
|
return lines.join("\n");
|
|
53924
54160
|
};
|
|
53925
54161
|
var sanitizeFileName = (fileName) => {
|
|
53926
|
-
const cleaned =
|
|
54162
|
+
const cleaned = import_node_path19.default.basename(fileName).replace(/[^\w.\-()\u4e00-\u9fa5 ]+/g, "_").trim();
|
|
53927
54163
|
return cleaned || `attachment-${Date.now()}`;
|
|
53928
54164
|
};
|
|
53929
54165
|
var inferAttachmentType2 = (mimeType = "", fileName = "") => {
|
|
53930
54166
|
if (mimeType.startsWith("image/")) return "image";
|
|
53931
|
-
const ext =
|
|
54167
|
+
const ext = import_node_path19.default.extname(fileName).toLowerCase();
|
|
53932
54168
|
if ([".png", ".jpg", ".jpeg", ".gif", ".webp"].includes(ext)) return "image";
|
|
53933
54169
|
return "file";
|
|
53934
54170
|
};
|
|
@@ -53983,11 +54219,11 @@ mobileRoutes.post("/mobile/attachments", async (c) => {
|
|
|
53983
54219
|
const fileName = sanitizeFileName(body.fileName || `attachment-${Date.now()}`);
|
|
53984
54220
|
const mimeType = body.mimeType || "application/octet-stream";
|
|
53985
54221
|
const type = inferAttachmentType2(mimeType, fileName);
|
|
53986
|
-
const attachmentId = (0,
|
|
54222
|
+
const attachmentId = (0, import_node_crypto17.randomUUID)();
|
|
53987
54223
|
const buffer = Buffer.from(dataBase64, "base64");
|
|
53988
|
-
const dir =
|
|
54224
|
+
const dir = import_node_path19.default.join(getDuclawWorkspaceDir(), mobileUserId, "mobile", type === "image" ? "images" : "files");
|
|
53989
54225
|
await (0, import_promises13.mkdir)(dir, { recursive: true });
|
|
53990
|
-
const localPath =
|
|
54226
|
+
const localPath = import_node_path19.default.join(dir, `${attachmentId}-${fileName}`);
|
|
53991
54227
|
await (0, import_promises13.writeFile)(localPath, buffer);
|
|
53992
54228
|
const attachment = saveMobileAttachment({
|
|
53993
54229
|
id: attachmentId,
|
|
@@ -54015,7 +54251,7 @@ mobileRoutes.post("/mobile/messages", async (c) => {
|
|
|
54015
54251
|
}
|
|
54016
54252
|
const mobileUserId = resolveMobileUserId(body, c.req.header("x-user-id"));
|
|
54017
54253
|
const threadId = resolveThreadId(body.goalId, mobileUserId);
|
|
54018
|
-
const requestId = body.clientMessageId?.trim() || (0,
|
|
54254
|
+
const requestId = body.clientMessageId?.trim() || (0, import_node_crypto17.randomUUID)();
|
|
54019
54255
|
const agentText = body.contextText?.trim() || text2;
|
|
54020
54256
|
const attachmentContent = buildContentWithAttachments(agentText, attachments);
|
|
54021
54257
|
const content = buildGoalPrompt(body.goalId, attachmentContent.content);
|
|
@@ -54206,7 +54442,7 @@ function createServer() {
|
|
|
54206
54442
|
app.route("/api", mobileRoutes);
|
|
54207
54443
|
app.use("/*", serveStatic({ root: webDistRoot }));
|
|
54208
54444
|
app.get("/*", async (c) => {
|
|
54209
|
-
const indexHtml = await (0, import_promises14.readFile)(
|
|
54445
|
+
const indexHtml = await (0, import_promises14.readFile)(import_node_path20.default.join(webDistRoot, "index.html"), "utf8");
|
|
54210
54446
|
const tenantId = c.req.header("x-tenant-id");
|
|
54211
54447
|
const assetBase = tenantId ? `/t/${tenantId}` : "";
|
|
54212
54448
|
const html = indexHtml.replaceAll('"./', `"${assetBase}/`);
|
|
@@ -54233,10 +54469,10 @@ function shouldStartCoreChannelGateways(env = process.env) {
|
|
|
54233
54469
|
}
|
|
54234
54470
|
|
|
54235
54471
|
// src/runtime/saasAssets.ts
|
|
54236
|
-
var
|
|
54472
|
+
var import_node_fs10 = require("node:fs");
|
|
54237
54473
|
var import_promises15 = require("node:fs/promises");
|
|
54238
54474
|
var import_node_os3 = require("node:os");
|
|
54239
|
-
var
|
|
54475
|
+
var import_node_path21 = __toESM(require("node:path"));
|
|
54240
54476
|
var MAX_CONTEXT_ASSETS = Number(process.env.DUCLAW_SAAS_ASSET_CONTEXT_LIMIT ?? 1e3);
|
|
54241
54477
|
var MAX_SKILL_ASSETS = Number(process.env.DUCLAW_SAAS_ASSET_SKILL_LIMIT ?? 200);
|
|
54242
54478
|
async function restoreSaasRuntimeAssets(reason) {
|
|
@@ -54266,8 +54502,8 @@ async function restoreSaasRuntimeAssets(reason) {
|
|
|
54266
54502
|
async function restoreContextAsset(context, overwrite) {
|
|
54267
54503
|
const target = contextPathForSourceKey(context.sourceKey);
|
|
54268
54504
|
if (!target) return false;
|
|
54269
|
-
if (!overwrite && (0,
|
|
54270
|
-
await (0, import_promises15.mkdir)(
|
|
54505
|
+
if (!overwrite && (0, import_node_fs10.existsSync)(target)) return false;
|
|
54506
|
+
await (0, import_promises15.mkdir)(import_node_path21.default.dirname(target), { recursive: true });
|
|
54271
54507
|
await (0, import_promises15.writeFile)(target, JSON.stringify(context.payload), "utf8");
|
|
54272
54508
|
return true;
|
|
54273
54509
|
}
|
|
@@ -54275,8 +54511,8 @@ async function restoreSkillAsset(skill, overwrite) {
|
|
|
54275
54511
|
if (!skill.skillMd) return false;
|
|
54276
54512
|
const target = safeSkillTargetPath(skill.sourcePath, skill.skillName);
|
|
54277
54513
|
if (!target) return false;
|
|
54278
|
-
if (!overwrite && (0,
|
|
54279
|
-
await (0, import_promises15.mkdir)(
|
|
54514
|
+
if (!overwrite && (0, import_node_fs10.existsSync)(target)) return false;
|
|
54515
|
+
await (0, import_promises15.mkdir)(import_node_path21.default.dirname(target), { recursive: true });
|
|
54280
54516
|
await (0, import_promises15.writeFile)(target, skill.skillMd, "utf8");
|
|
54281
54517
|
return true;
|
|
54282
54518
|
}
|
|
@@ -54309,30 +54545,30 @@ function runtimeAssetClient() {
|
|
|
54309
54545
|
function contextPathForSourceKey(sourceKey) {
|
|
54310
54546
|
if (sourceKey.startsWith("agent:")) {
|
|
54311
54547
|
const logicalKey = sourceKey.slice("agent:".length);
|
|
54312
|
-
return
|
|
54548
|
+
return import_node_path21.default.join(getDuclawDataDir(), "kv", "agent", `${Buffer.from(logicalKey).toString("base64url")}.json`);
|
|
54313
54549
|
}
|
|
54314
54550
|
if (sourceKey.startsWith("goal-context:")) {
|
|
54315
|
-
return
|
|
54551
|
+
return import_node_path21.default.join(getDuclawHomeDir(), "goal-context", `${sourceKey.slice("goal-context:".length)}.json`);
|
|
54316
54552
|
}
|
|
54317
54553
|
if (sourceKey.startsWith("tasks:")) {
|
|
54318
|
-
return
|
|
54554
|
+
return import_node_path21.default.join(getDuclawHomeDir(), "tasks", `${sourceKey.slice("tasks:".length)}.json`);
|
|
54319
54555
|
}
|
|
54320
54556
|
return null;
|
|
54321
54557
|
}
|
|
54322
54558
|
function safeSkillTargetPath(sourcePath, skillName) {
|
|
54323
|
-
const allowedRoots = skillRoots().map((root) =>
|
|
54324
|
-
const normalized =
|
|
54325
|
-
if (allowedRoots.some((root) => normalized ===
|
|
54559
|
+
const allowedRoots = skillRoots().map((root) => import_node_path21.default.resolve(root));
|
|
54560
|
+
const normalized = import_node_path21.default.resolve(sourcePath);
|
|
54561
|
+
if (allowedRoots.some((root) => normalized === import_node_path21.default.join(root, import_node_path21.default.basename(import_node_path21.default.dirname(normalized)), "SKILL.md"))) {
|
|
54326
54562
|
return normalized;
|
|
54327
54563
|
}
|
|
54328
54564
|
const safeName = skillName.replace(/[^a-zA-Z0-9._-]/g, "-").slice(0, 120) || "imported-skill";
|
|
54329
|
-
return
|
|
54565
|
+
return import_node_path21.default.join("/home/user/app/skills", safeName, "SKILL.md");
|
|
54330
54566
|
}
|
|
54331
54567
|
function skillRoots() {
|
|
54332
54568
|
return [
|
|
54333
54569
|
"/home/user/app/skills",
|
|
54334
|
-
|
|
54335
|
-
|
|
54570
|
+
import_node_path21.default.join(getDuclawHomeDir(), "skills"),
|
|
54571
|
+
import_node_path21.default.join((0, import_node_os3.homedir)(), ".agents", "skills")
|
|
54336
54572
|
];
|
|
54337
54573
|
}
|
|
54338
54574
|
|