@dai_ming/plugin-deliverables 1.1.8 → 1.2.0
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/index.js +109 -27
- package/openclaw-plugin.json +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -880,6 +880,7 @@ function kbMultipartUpload(fileBuffers, fields, pathsArray) {
|
|
|
880
880
|
"X-API-Key": kbApiKey(),
|
|
881
881
|
"Content-Length": body.length,
|
|
882
882
|
},
|
|
883
|
+
timeout: 10000,
|
|
883
884
|
},
|
|
884
885
|
(res) => {
|
|
885
886
|
const chunks = [];
|
|
@@ -905,6 +906,9 @@ function kbMultipartUpload(fileBuffers, fields, pathsArray) {
|
|
|
905
906
|
});
|
|
906
907
|
},
|
|
907
908
|
);
|
|
909
|
+
req.on("timeout", () => {
|
|
910
|
+
req.destroy(new Error("kb upload timeout after 10s"));
|
|
911
|
+
});
|
|
908
912
|
req.on("error", reject);
|
|
909
913
|
req.write(body);
|
|
910
914
|
req.end();
|
|
@@ -1802,6 +1806,30 @@ function extractDeliverableURL(line) {
|
|
|
1802
1806
|
return "";
|
|
1803
1807
|
}
|
|
1804
1808
|
|
|
1809
|
+
function extractAllDeliverableURLs(line) {
|
|
1810
|
+
const text = String(line || "").trim();
|
|
1811
|
+
if (!text) {
|
|
1812
|
+
return [];
|
|
1813
|
+
}
|
|
1814
|
+
const urls = [];
|
|
1815
|
+
const seen = new Set();
|
|
1816
|
+
const markdownLinks = text.matchAll(/\((https?:\/\/[^)\s]+)\)/giu);
|
|
1817
|
+
for (const m of markdownLinks) {
|
|
1818
|
+
const url = m[1].trim();
|
|
1819
|
+
if (url && !seen.has(url)) {
|
|
1820
|
+
seen.add(url);
|
|
1821
|
+
urls.push(url);
|
|
1822
|
+
}
|
|
1823
|
+
}
|
|
1824
|
+
if (urls.length === 0) {
|
|
1825
|
+
const rawLink = text.match(/https?:\/\/\S+/iu);
|
|
1826
|
+
if (rawLink && rawLink[0]) {
|
|
1827
|
+
urls.push(rawLink[0].trim());
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
return urls;
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1805
1833
|
function configuredKBHosts() {
|
|
1806
1834
|
const cfg = loadDeliverableConfig();
|
|
1807
1835
|
const values = [
|
|
@@ -1943,10 +1971,12 @@ function splitDeliverableMessage(text) {
|
|
|
1943
1971
|
const normalizedLine = stripBulletPrefix(line).trim();
|
|
1944
1972
|
if (normalizedLine) {
|
|
1945
1973
|
linkLines.push(normalizedLine);
|
|
1946
|
-
const
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1974
|
+
const urls = extractAllDeliverableURLs(normalizedLine);
|
|
1975
|
+
for (const url of urls) {
|
|
1976
|
+
if (isTrustedDeliverableURL(url)) {
|
|
1977
|
+
linkUrls.push(url);
|
|
1978
|
+
linkItems.push({ line: normalizedLine, url });
|
|
1979
|
+
}
|
|
1950
1980
|
}
|
|
1951
1981
|
}
|
|
1952
1982
|
}
|
|
@@ -1965,6 +1995,7 @@ function splitDeliverableMessage(text) {
|
|
|
1965
1995
|
linkItems,
|
|
1966
1996
|
primaryLinkUrl: linkUrls.length > 0 ? linkUrls[0] : "",
|
|
1967
1997
|
fileLinkUrl: selectPalzFileURL(linkItems),
|
|
1998
|
+
deduplicatedItems: deduplicateLinkItems(linkItems),
|
|
1968
1999
|
};
|
|
1969
2000
|
}
|
|
1970
2001
|
|
|
@@ -2007,6 +2038,31 @@ function selectPalzFileURL(linkItems) {
|
|
|
2007
2038
|
return (preview && preview.url) || linkItems[0].url || "";
|
|
2008
2039
|
}
|
|
2009
2040
|
|
|
2041
|
+
function deduplicateLinkItems(linkItems) {
|
|
2042
|
+
if (!Array.isArray(linkItems) || linkItems.length === 0) {
|
|
2043
|
+
return { fileItems: [], textItems: [] };
|
|
2044
|
+
}
|
|
2045
|
+
const byIdentity = new Map();
|
|
2046
|
+
const textItems = [];
|
|
2047
|
+
for (const item of linkItems) {
|
|
2048
|
+
const identity = extractDeliverableIdentity(item && item.url);
|
|
2049
|
+
if (!identity) {
|
|
2050
|
+
textItems.push(item);
|
|
2051
|
+
continue;
|
|
2052
|
+
}
|
|
2053
|
+
const existing = byIdentity.get(identity);
|
|
2054
|
+
if (!existing) {
|
|
2055
|
+
byIdentity.set(identity, item);
|
|
2056
|
+
} else if (/\/documents\/preview\//u.test(String(item.url || ""))) {
|
|
2057
|
+
byIdentity.set(identity, item);
|
|
2058
|
+
}
|
|
2059
|
+
}
|
|
2060
|
+
return {
|
|
2061
|
+
fileItems: Array.from(byIdentity.values()),
|
|
2062
|
+
textItems,
|
|
2063
|
+
};
|
|
2064
|
+
}
|
|
2065
|
+
|
|
2010
2066
|
function cloneBody(body, content, suffix) {
|
|
2011
2067
|
const next = {};
|
|
2012
2068
|
Object.keys(body).forEach((key) => {
|
|
@@ -2063,6 +2119,7 @@ function shouldSplitPalzPayload(body) {
|
|
|
2063
2119
|
links: split.links,
|
|
2064
2120
|
primaryLinkUrl: split.primaryLinkUrl,
|
|
2065
2121
|
fileLinkUrl: split.fileLinkUrl,
|
|
2122
|
+
deduplicatedItems: split.deduplicatedItems,
|
|
2066
2123
|
};
|
|
2067
2124
|
}
|
|
2068
2125
|
return split;
|
|
@@ -2157,16 +2214,15 @@ function installPalzFetchPatch(api) {
|
|
|
2157
2214
|
return originalFetch(input, init);
|
|
2158
2215
|
}
|
|
2159
2216
|
|
|
2217
|
+
const dedup = split.deduplicatedItems || { fileItems: [], textItems: [] };
|
|
2218
|
+
const hasFileItems = dedup.fileItems.length > 0;
|
|
2219
|
+
const hasTextItems = dedup.textItems.length > 0;
|
|
2220
|
+
|
|
2160
2221
|
const summaryBody = cloneBody(parsed, split.summary, "__summary");
|
|
2161
|
-
const fileLinkUrl = split.fileLinkUrl || "";
|
|
2162
|
-
const linksBody = fileLinkUrl
|
|
2163
|
-
? cloneBodyAsFileLink(parsed, fileLinkUrl, "__links")
|
|
2164
|
-
: cloneBody(parsed, split.links, "__links");
|
|
2165
2222
|
const summaryBodyStr = JSON.stringify(summaryBody);
|
|
2166
|
-
const linksBodyStr = JSON.stringify(linksBody);
|
|
2167
2223
|
|
|
2168
2224
|
api.logger.info?.(
|
|
2169
|
-
`[plugin-deliverables] split deliverable reply injected by plugin-deliverables target=${String(parsed.conversation_id || "")} summaryMsgId=${String(summaryBody.msg_id || "")}
|
|
2225
|
+
`[plugin-deliverables] split deliverable reply injected by plugin-deliverables target=${String(parsed.conversation_id || "")} summaryMsgId=${String(summaryBody.msg_id || "")} fileLinks=${dedup.fileItems.length} textLinks=${dedup.textItems.length}`,
|
|
2170
2226
|
);
|
|
2171
2227
|
api.logger.info?.(
|
|
2172
2228
|
`[plugin-deliverables] palz summary request body_length=${summaryBodyStr.length}\n request_body=${summaryBodyStr}`,
|
|
@@ -2176,28 +2232,54 @@ function installPalzFetchPatch(api) {
|
|
|
2176
2232
|
const summaryInit = Object.assign({}, baseInit, {
|
|
2177
2233
|
body: summaryBodyStr,
|
|
2178
2234
|
});
|
|
2179
|
-
const linksInit = Object.assign({}, baseInit, {
|
|
2180
|
-
body: linksBodyStr,
|
|
2181
|
-
});
|
|
2182
2235
|
|
|
2183
|
-
const
|
|
2184
|
-
const
|
|
2236
|
+
const summaryResponse = await originalFetch(input, summaryInit);
|
|
2237
|
+
const summaryResponseText = await readResponseText(summaryResponse);
|
|
2185
2238
|
api.logger.info?.(
|
|
2186
|
-
`[plugin-deliverables] palz summary response status=${
|
|
2239
|
+
`[plugin-deliverables] palz summary response status=${summaryResponse ? summaryResponse.status : "unknown"} ok=${Boolean(summaryResponse && summaryResponse.ok)}\n response_body=${previewText(summaryResponseText)}`,
|
|
2187
2240
|
);
|
|
2188
|
-
if (!
|
|
2189
|
-
return
|
|
2241
|
+
if (!summaryResponse || !summaryResponse.ok) {
|
|
2242
|
+
return summaryResponse;
|
|
2190
2243
|
}
|
|
2191
2244
|
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
)
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2245
|
+
let lastResponse = summaryResponse;
|
|
2246
|
+
|
|
2247
|
+
for (let idx = 0; idx < dedup.fileItems.length; idx += 1) {
|
|
2248
|
+
const item = dedup.fileItems[idx];
|
|
2249
|
+
const fileBody = cloneBodyAsFileLink(parsed, item.url, `__links_${idx}`);
|
|
2250
|
+
const fileBodyStr = JSON.stringify(fileBody);
|
|
2251
|
+
api.logger.info?.(
|
|
2252
|
+
`[plugin-deliverables] palz file_url request [${idx}] body_length=${fileBodyStr.length} url=${item.url}\n request_body=${fileBodyStr}`,
|
|
2253
|
+
);
|
|
2254
|
+
const fileInit = Object.assign({}, baseInit, { body: fileBodyStr });
|
|
2255
|
+
const fileResponse = await originalFetch(input, fileInit);
|
|
2256
|
+
const fileResponseText = await readResponseText(fileResponse);
|
|
2257
|
+
api.logger.info?.(
|
|
2258
|
+
`[plugin-deliverables] palz file_url response [${idx}] status=${fileResponse ? fileResponse.status : "unknown"} ok=${Boolean(fileResponse && fileResponse.ok)}\n response_body=${previewText(fileResponseText)}`,
|
|
2259
|
+
);
|
|
2260
|
+
if (!fileResponse || !fileResponse.ok) {
|
|
2261
|
+
return fileResponse;
|
|
2262
|
+
}
|
|
2263
|
+
lastResponse = fileResponse;
|
|
2264
|
+
}
|
|
2265
|
+
|
|
2266
|
+
if (hasTextItems) {
|
|
2267
|
+
const textContent = dedup.textItems.map((item) => item.line).join("\n");
|
|
2268
|
+
const textBody = cloneBody(parsed, textContent, "__links_text");
|
|
2269
|
+
const textBodyStr = JSON.stringify(textBody);
|
|
2270
|
+
api.logger.info?.(
|
|
2271
|
+
`[plugin-deliverables] palz text links request body_length=${textBodyStr.length}\n request_body=${textBodyStr}`,
|
|
2272
|
+
);
|
|
2273
|
+
const textInit = Object.assign({}, baseInit, { body: textBodyStr });
|
|
2274
|
+
const textResponse = await originalFetch(input, textInit);
|
|
2275
|
+
const textResponseText = await readResponseText(textResponse);
|
|
2276
|
+
api.logger.info?.(
|
|
2277
|
+
`[plugin-deliverables] palz text links response status=${textResponse ? textResponse.status : "unknown"} ok=${Boolean(textResponse && textResponse.ok)}\n response_body=${previewText(textResponseText)}`,
|
|
2278
|
+
);
|
|
2279
|
+
lastResponse = textResponse;
|
|
2280
|
+
}
|
|
2281
|
+
|
|
2282
|
+
return lastResponse;
|
|
2201
2283
|
};
|
|
2202
2284
|
|
|
2203
2285
|
globalThis.fetch = patchedFetch;
|
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.
|
|
5
|
+
"version": "1.2.0",
|
|
6
6
|
"skills": ["./skills"],
|
|
7
7
|
"configSchema": {
|
|
8
8
|
"type": "object",
|
package/package.json
CHANGED