@dai_ming/plugin-deliverables 1.1.5 → 1.1.6
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 +2 -2
- package/deliverables.dev.config.json +1 -2
- package/deliverables.prod.config.json +1 -2
- package/deliverables.staging.config.json +1 -2
- package/index.js +90 -25
- package/openclaw-plugin.json +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -47,9 +47,9 @@ deliverables__upload_deliverable
|
|
|
47
47
|
配置字段:
|
|
48
48
|
|
|
49
49
|
- `kbBaseUrl` — 知识库 API 内部地址(Pod 内通信)
|
|
50
|
-
- `kbPublicUrl` — 用户可见的预览链接地址
|
|
51
50
|
|
|
52
|
-
环境变量 `KNOWLEDGE_DB_URL`
|
|
51
|
+
环境变量 `KNOWLEDGE_DB_URL` 可覆盖配置文件值。`KNOWLEDGE_DB_API_KEY` 仅通过环境变量配置(默认 `kb-agent-key-2025`)。
|
|
52
|
+
IM 交付物链接信任校验使用固定前缀规则:`https://uniclaw-ai-kb`、`http://knowledge-db` 或 `http://localhost`。
|
|
53
53
|
|
|
54
54
|
## 发布
|
|
55
55
|
|
package/index.js
CHANGED
|
@@ -54,7 +54,7 @@ const AUTO_UPLOAD_MAX_FILES = 8;
|
|
|
54
54
|
const AUTO_UPLOAD_MAX_BYTES = 200 * 1024 * 1024;
|
|
55
55
|
const AUTO_UPLOAD_SCAN_MAX_ENTRIES = 4000;
|
|
56
56
|
const AUTO_UPLOAD_SCAN_DEPTH = 5;
|
|
57
|
-
const DELIVERABLE_KB_PATH_RE = /\/documents\/content
|
|
57
|
+
const DELIVERABLE_KB_PATH_RE = /\/documents\/(?:content|preview)(?:\/|$)/u;
|
|
58
58
|
const DELIVERABLE_LINK_PREFIX_RE =
|
|
59
59
|
/^\s*(?:[-*+]\s+)?(?:预览链接|下载链接|文件列表|项目入口|在线预览|在线体验|目录链接)\s*[::]/u;
|
|
60
60
|
const DELIVERABLE_LINK_LABEL_RE =
|
|
@@ -715,11 +715,6 @@ function kbBaseURL() {
|
|
|
715
715
|
return (process.env.KNOWLEDGE_DB_URL || cfg.kbBaseUrl || DEFAULT_KB_BASE_URL).replace(/\/$/, "");
|
|
716
716
|
}
|
|
717
717
|
|
|
718
|
-
function kbPublicURL() {
|
|
719
|
-
const cfg = loadDeliverableConfig();
|
|
720
|
-
return (process.env.KNOWLEDGE_DB_PUBLIC_URL || cfg.kbPublicUrl || process.env.KNOWLEDGE_DB_URL || cfg.kbBaseUrl || DEFAULT_KB_BASE_URL).replace(/\/$/, "");
|
|
721
|
-
}
|
|
722
|
-
|
|
723
718
|
function kbApiKey() {
|
|
724
719
|
return process.env.KNOWLEDGE_DB_API_KEY || DEFAULT_KB_API_KEY;
|
|
725
720
|
}
|
|
@@ -732,25 +727,77 @@ function kbUploadPath(groupId, groupName) {
|
|
|
732
727
|
return "/" + gname + "/raw";
|
|
733
728
|
}
|
|
734
729
|
|
|
735
|
-
function
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
+ "&group_id=" + encodeURIComponent(trimString(groupId) || DEFAULT_GROUP_ID)
|
|
739
|
-
+ "&id=" + encodeURIComponent(String(documentId));
|
|
730
|
+
function kbUploadItems(response) {
|
|
731
|
+
const data = (response && response.data) || response || {};
|
|
732
|
+
return Array.isArray(data.items) ? data.items : [];
|
|
740
733
|
}
|
|
741
734
|
|
|
742
|
-
function
|
|
735
|
+
function kbFirstSuccessfulUploadItem(response) {
|
|
736
|
+
const items = kbUploadItems(response);
|
|
737
|
+
if (items.length === 0) {
|
|
738
|
+
return null;
|
|
739
|
+
}
|
|
740
|
+
return items.find((item) => item && !item.error && item.document) || items[0] || null;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
function kbExtractDocument(response) {
|
|
744
|
+
const item = kbFirstSuccessfulUploadItem(response);
|
|
745
|
+
if (item && item.document && typeof item.document === "object" && !Array.isArray(item.document)) {
|
|
746
|
+
return item.document;
|
|
747
|
+
}
|
|
743
748
|
const data = (response && response.data) || response || {};
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
return items[0].document.id;
|
|
749
|
+
if (data.document && typeof data.document === "object" && !Array.isArray(data.document)) {
|
|
750
|
+
return data.document;
|
|
747
751
|
}
|
|
752
|
+
return data && typeof data === "object" && !Array.isArray(data) ? data : {};
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
function kbExtractDocumentId(response) {
|
|
756
|
+
const document = kbExtractDocument(response);
|
|
757
|
+
if (document.id !== undefined) {
|
|
758
|
+
return document.id;
|
|
759
|
+
}
|
|
760
|
+
const data = (response && response.data) || response || {};
|
|
748
761
|
if (data.id !== undefined) {
|
|
749
762
|
return data.id;
|
|
750
763
|
}
|
|
751
764
|
return null;
|
|
752
765
|
}
|
|
753
766
|
|
|
767
|
+
function extractURLField(obj, keys) {
|
|
768
|
+
if (!obj || typeof obj !== "object" || Array.isArray(obj)) {
|
|
769
|
+
return "";
|
|
770
|
+
}
|
|
771
|
+
for (const key of keys) {
|
|
772
|
+
const value = obj[key];
|
|
773
|
+
if (isString(value) && value.trim()) {
|
|
774
|
+
return value.trim();
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
return "";
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
function kbExtractReturnedLinks(response) {
|
|
781
|
+
const item = kbFirstSuccessfulUploadItem(response) || {};
|
|
782
|
+
const document = kbExtractDocument(response);
|
|
783
|
+
return {
|
|
784
|
+
downloadURL:
|
|
785
|
+
extractURLField(document, ["download_url", "downloadURL"]) ||
|
|
786
|
+
extractURLField(item, ["download_url", "downloadURL"]),
|
|
787
|
+
previewURL:
|
|
788
|
+
extractURLField(document, ["preview_url", "previewURL"]) ||
|
|
789
|
+
extractURLField(item, ["preview_url", "previewURL"]),
|
|
790
|
+
};
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
function requireKBReturnedLink(response) {
|
|
794
|
+
const links = kbExtractReturnedLinks(response);
|
|
795
|
+
if (!links.previewURL && !links.downloadURL) {
|
|
796
|
+
throw new Error("kb upload response missing preview_url/download_url");
|
|
797
|
+
}
|
|
798
|
+
return links;
|
|
799
|
+
}
|
|
800
|
+
|
|
754
801
|
function buildFileBuffersFromBody(body, isDirectory) {
|
|
755
802
|
if (isDirectory && Array.isArray(body.files)) {
|
|
756
803
|
return body.files.map((file) => ({
|
|
@@ -1185,8 +1232,9 @@ async function uploadDeliverable(args) {
|
|
|
1185
1232
|
};
|
|
1186
1233
|
const response = await kbMultipartUpload(fileBuffers, fields);
|
|
1187
1234
|
const documentId = kbExtractDocumentId(response);
|
|
1188
|
-
const
|
|
1189
|
-
const
|
|
1235
|
+
const links = requireKBReturnedLink(response);
|
|
1236
|
+
const previewURL = links.previewURL || links.downloadURL;
|
|
1237
|
+
const downloadURL = links.downloadURL || previewURL;
|
|
1190
1238
|
const replyMarkdown = buildReplyMarkdown({
|
|
1191
1239
|
previewURL,
|
|
1192
1240
|
downloadURL,
|
|
@@ -1255,12 +1303,14 @@ async function uploadCandidate(candidate, body) {
|
|
|
1255
1303
|
path: uploadPath,
|
|
1256
1304
|
});
|
|
1257
1305
|
const documentId = kbExtractDocumentId(response);
|
|
1258
|
-
const
|
|
1306
|
+
const links = requireKBReturnedLink(response);
|
|
1307
|
+
const previewURL = links.previewURL || links.downloadURL;
|
|
1308
|
+
const downloadURL = links.downloadURL || previewURL;
|
|
1259
1309
|
const result = {
|
|
1260
1310
|
fileName,
|
|
1261
1311
|
document_id: documentId,
|
|
1262
1312
|
previewURL,
|
|
1263
|
-
downloadURL
|
|
1313
|
+
downloadURL,
|
|
1264
1314
|
};
|
|
1265
1315
|
cache.set(cacheKey, { result, createdAt: Date.now() });
|
|
1266
1316
|
return result;
|
|
@@ -1755,8 +1805,6 @@ function extractDeliverableURL(line) {
|
|
|
1755
1805
|
function configuredKBHosts() {
|
|
1756
1806
|
const cfg = loadDeliverableConfig();
|
|
1757
1807
|
const values = [
|
|
1758
|
-
process.env.KNOWLEDGE_DB_PUBLIC_URL,
|
|
1759
|
-
cfg.kbPublicUrl,
|
|
1760
1808
|
process.env.KNOWLEDGE_DB_URL,
|
|
1761
1809
|
cfg.kbBaseUrl,
|
|
1762
1810
|
DEFAULT_KB_BASE_URL,
|
|
@@ -1777,6 +1825,15 @@ function configuredKBHosts() {
|
|
|
1777
1825
|
return hosts;
|
|
1778
1826
|
}
|
|
1779
1827
|
|
|
1828
|
+
function isTrustedDeliverableURLPrefix(rawURL) {
|
|
1829
|
+
const normalized = String(rawURL || "").trim().toLowerCase();
|
|
1830
|
+
return (
|
|
1831
|
+
normalized.startsWith("https://uniclaw-ai-kb") ||
|
|
1832
|
+
normalized.startsWith("http://knowledge-db") ||
|
|
1833
|
+
normalized.startsWith("http://localhost")
|
|
1834
|
+
);
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1780
1837
|
function isTrustedDeliverableURL(rawURL) {
|
|
1781
1838
|
if (!isString(rawURL) || !rawURL.trim()) {
|
|
1782
1839
|
return false;
|
|
@@ -1790,6 +1847,9 @@ function isTrustedDeliverableURL(rawURL) {
|
|
|
1790
1847
|
if (!DELIVERABLE_KB_PATH_RE.test(parsed.pathname)) {
|
|
1791
1848
|
return false;
|
|
1792
1849
|
}
|
|
1850
|
+
if (isTrustedDeliverableURLPrefix(rawURL)) {
|
|
1851
|
+
return true;
|
|
1852
|
+
}
|
|
1793
1853
|
const hosts = configuredKBHosts();
|
|
1794
1854
|
const host = parsed.host.toLowerCase();
|
|
1795
1855
|
const hostname = parsed.hostname.toLowerCase();
|
|
@@ -1922,7 +1982,11 @@ function extractDeliverableIdentity(rawURL) {
|
|
|
1922
1982
|
return "";
|
|
1923
1983
|
}
|
|
1924
1984
|
const docId = parsed.searchParams.get("id");
|
|
1925
|
-
|
|
1985
|
+
if (docId) {
|
|
1986
|
+
return String(docId);
|
|
1987
|
+
}
|
|
1988
|
+
const match = parsed.pathname.match(/\/documents\/(?:content|preview)\/([^/]+)/u);
|
|
1989
|
+
return match && match[1] ? decodeURIComponent(match[1]) : "";
|
|
1926
1990
|
}
|
|
1927
1991
|
|
|
1928
1992
|
function selectPalzFileURL(linkItems) {
|
|
@@ -1939,8 +2003,8 @@ function selectPalzFileURL(linkItems) {
|
|
|
1939
2003
|
if (identities.size !== 1) {
|
|
1940
2004
|
return "";
|
|
1941
2005
|
}
|
|
1942
|
-
const
|
|
1943
|
-
return (
|
|
2006
|
+
const preview = linkItems.find((item) => /预览链接/u.test(String((item && item.line) || "")));
|
|
2007
|
+
return (preview && preview.url) || linkItems[0].url || "";
|
|
1944
2008
|
}
|
|
1945
2009
|
|
|
1946
2010
|
function cloneBody(body, content, suffix) {
|
|
@@ -2217,10 +2281,11 @@ plugin.__test = {
|
|
|
2217
2281
|
isOSSLikeURL,
|
|
2218
2282
|
isTrustedDeliverableURL,
|
|
2219
2283
|
kbExtractDocumentId,
|
|
2284
|
+
kbExtractReturnedLinks,
|
|
2220
2285
|
kbMultipartUpload,
|
|
2221
|
-
kbPreviewURL,
|
|
2222
2286
|
kbUploadPath,
|
|
2223
2287
|
loadDeliverableConfig,
|
|
2288
|
+
requireKBReturnedLink,
|
|
2224
2289
|
selectPalzFileURL,
|
|
2225
2290
|
splitDeliverableMessage,
|
|
2226
2291
|
};
|
package/openclaw-plugin.json
CHANGED
package/openclaw.plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "plugin-deliverables",
|
|
3
3
|
"name": "Deliverables",
|
|
4
4
|
"description": "Deliverables runtime guard for upload-first file delivery with Palz split-send diagnostics.",
|
|
5
|
-
"version": "1.1.
|
|
5
|
+
"version": "1.1.6",
|
|
6
6
|
"skills": ["./skills"],
|
|
7
7
|
"configSchema": {
|
|
8
8
|
"type": "object",
|
package/package.json
CHANGED