@rebon/cli-linux-x64 0.17.2 → 0.18.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/bin/compose-runtime/package.json +17 -0
- package/bin/compose-runtime/payload/compose/credentials-runtime.js +38 -0
- package/bin/compose-runtime/payload/compose/llm-runtime.js +330 -0
- package/bin/compose-runtime/payload/compose/loop-assembly.js +149 -0
- package/bin/compose-runtime/payload/compose/serve-dispatch.js +82 -0
- package/bin/compose-runtime/payload/compose/shims/dsh-anonymous-user-id.js +10 -0
- package/bin/compose-runtime/payload/compose/shims/dsh-credentials.js +13 -0
- package/bin/compose-runtime/payload/compose/shims/dsh-launch-environment.js +21 -0
- package/bin/compose-runtime/payload/compose/shims/dsh-llm.js +313 -0
- package/bin/compose-runtime/payload/compose/shims/dsh-settings.js +43 -0
- package/bin/compose-runtime/payload/compose/shims/dsh-tools.js +20 -0
- package/bin/compose-runtime/payload/compose/shims/dsh-web.js +10 -0
- package/bin/compose-runtime/payload/compose/shims/llm-adapter.js +32 -0
- package/bin/compose-runtime/payload/compose/shims/zod-lite.js +49 -0
- package/bin/compose-runtime/payload/compose/systemprompt-runtime.js +74 -0
- package/bin/compose-runtime/payload/compose/tools-runtime.js +228 -0
- package/bin/compose-runtime/payload/compose/web-runtime.js +204 -0
- package/bin/compose-runtime/payload/vendor/cordis/index.js +1530 -0
- package/bin/compose-runtime/payload/vendor/cosmokit/LICENSE +21 -0
- package/bin/compose-runtime/payload/vendor/cosmokit/index.mjs +357 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-agent +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-agent-loop +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-llm-core +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-llm-deepseek +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-logger-console +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-scope +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-session +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-system-prompt +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-timeout +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-timer +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-tool-todo +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-tool-web +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-tools-schema +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-web-search-exa +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/agent-loop.js +1193 -0
- package/bin/compose-runtime/payload/vendor/dsh/agent.js +714 -0
- package/bin/compose-runtime/payload/vendor/dsh/llm-core.js +269 -0
- package/bin/compose-runtime/payload/vendor/dsh/llm-deepseek.js +672 -0
- package/bin/compose-runtime/payload/vendor/dsh/logger-console.js +83 -0
- package/bin/compose-runtime/payload/vendor/dsh/scope.js +287 -0
- package/bin/compose-runtime/payload/vendor/dsh/session.js +1668 -0
- package/bin/compose-runtime/payload/vendor/dsh/system-prompt.js +309 -0
- package/bin/compose-runtime/payload/vendor/dsh/timeout.js +100 -0
- package/bin/compose-runtime/payload/vendor/dsh/timer.js +128 -0
- package/bin/compose-runtime/payload/vendor/dsh/tool-todo.js +143 -0
- package/bin/compose-runtime/payload/vendor/dsh/tool-web.js +1527 -0
- package/bin/compose-runtime/payload/vendor/dsh/tools-schema.js +849 -0
- package/bin/compose-runtime/payload/vendor/dsh/web-search-exa.js +122 -0
- package/bin/compose-runtime/payload/vendor/eventsource-parser/LICENSE +21 -0
- package/bin/compose-runtime/payload/vendor/eventsource-parser/index.js +177 -0
- package/bin/compose-runtime/payload/vendor/eventsource-parser/stream.js +48 -0
- package/bin/compose-runtime/payload/vendor/schemastery/index.mjs +656 -0
- package/bin/compose-runtime/payload-manifests.json +48 -0
- package/bin/compose-runtime/src/bridge.mjs +142 -0
- package/bin/compose-runtime/src/credentials-runtime.mjs +50 -0
- package/bin/compose-runtime/src/eventsource-stream.mjs +48 -0
- package/bin/compose-runtime/src/index.mjs +7 -0
- package/bin/compose-runtime/src/llm-runtime.mjs +326 -0
- package/bin/compose-runtime/src/loader.mjs +78 -0
- package/bin/compose-runtime/src/loop-assembly.mjs +237 -0
- package/bin/compose-runtime/src/payload.mjs +49 -0
- package/bin/compose-runtime/src/plugin.mjs +59 -0
- package/bin/compose-runtime/src/realm.mjs +223 -0
- package/bin/compose-runtime/src/registry.mjs +191 -0
- package/bin/compose-runtime/src/resolve.mjs +115 -0
- package/bin/compose-runtime/src/systemprompt-runtime.mjs +67 -0
- package/bin/compose-runtime/src/tools-runtime.mjs +239 -0
- package/bin/compose-runtime/src/web-runtime.mjs +209 -0
- package/bin/plugin-host/package.json +11 -0
- package/bin/plugin-host/src/bridge.mjs +64 -0
- package/bin/plugin-host/src/cli.mjs +105 -0
- package/bin/plugin-host/src/framing.mjs +113 -0
- package/bin/plugin-host/src/host.mjs +624 -0
- package/bin/plugin-host/src/json.mjs +196 -0
- package/bin/plugin-host/src/lifecycle.mjs +114 -0
- package/bin/plugin-host/src/loader.mjs +142 -0
- package/bin/plugin-host/src/methods.mjs +256 -0
- package/bin/plugin-host/src/protocol.mjs +129 -0
- package/bin/plugin-host/src/sdk.mjs +7 -0
- package/bin/rebon +0 -0
- package/bin/rebon-boa-helper +0 -0
- package/package.json +4 -1
|
@@ -0,0 +1,1527 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
8
|
+
try {
|
|
9
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
10
|
+
} catch (e) {
|
|
11
|
+
throw mod = 0, e;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
var __copyProps = (to, from, except, desc) => {
|
|
15
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
16
|
+
for (let key of __getOwnPropNames(from))
|
|
17
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
18
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
23
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
24
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
25
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
26
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
27
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
28
|
+
mod
|
|
29
|
+
));
|
|
30
|
+
|
|
31
|
+
// node_modules/.pnpm/@joplin+turndown-plugin-gfm@1.0.67/node_modules/@joplin/turndown-plugin-gfm/lib/turndown-plugin-gfm.cjs.js
|
|
32
|
+
var require_turndown_plugin_gfm_cjs = __commonJS({
|
|
33
|
+
"node_modules/.pnpm/@joplin+turndown-plugin-gfm@1.0.67/node_modules/@joplin/turndown-plugin-gfm/lib/turndown-plugin-gfm.cjs.js"(exports) {
|
|
34
|
+
"use strict";
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
var highlightRegExp = /highlight-(?:text|source)-([a-z0-9]+)/;
|
|
37
|
+
function highlightedCodeBlock(turndownService) {
|
|
38
|
+
turndownService.addRule("highlightedCodeBlock", {
|
|
39
|
+
filter: function(node) {
|
|
40
|
+
var firstChild = node.firstChild;
|
|
41
|
+
return node.nodeName === "DIV" && highlightRegExp.test(node.className) && firstChild && firstChild.nodeName === "PRE";
|
|
42
|
+
},
|
|
43
|
+
replacement: function(content, node, options) {
|
|
44
|
+
var className = node.className || "";
|
|
45
|
+
var language = (className.match(highlightRegExp) || [null, ""])[1];
|
|
46
|
+
return "\n\n" + options.fence + language + "\n" + node.firstChild.textContent + "\n" + options.fence + "\n\n";
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function strikethrough(turndownService) {
|
|
51
|
+
turndownService.addRule("strikethrough", {
|
|
52
|
+
filter: ["del", "s", "strike"],
|
|
53
|
+
replacement: function(content) {
|
|
54
|
+
return "~~" + content + "~~";
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
var indexOf = Array.prototype.indexOf;
|
|
59
|
+
var every = Array.prototype.every;
|
|
60
|
+
var rules2 = {};
|
|
61
|
+
var alignMap = { left: ":---", right: "---:", center: ":---:" };
|
|
62
|
+
var isCodeBlock_ = null;
|
|
63
|
+
var options_ = null;
|
|
64
|
+
var tableShouldBeSkippedCache_ = /* @__PURE__ */ new WeakMap();
|
|
65
|
+
function getAlignment(node) {
|
|
66
|
+
return node ? (node.getAttribute("align") || node.style.textAlign || "").toLowerCase() : "";
|
|
67
|
+
}
|
|
68
|
+
function getBorder(alignment) {
|
|
69
|
+
return alignment ? alignMap[alignment] : "---";
|
|
70
|
+
}
|
|
71
|
+
function getColumnAlignment(table, columnIndex) {
|
|
72
|
+
var votes = {
|
|
73
|
+
left: 0,
|
|
74
|
+
right: 0,
|
|
75
|
+
center: 0,
|
|
76
|
+
"": 0
|
|
77
|
+
};
|
|
78
|
+
var align = "";
|
|
79
|
+
for (var i = 0; i < table.rows.length; ++i) {
|
|
80
|
+
var row = table.rows[i];
|
|
81
|
+
if (columnIndex < row.childNodes.length) {
|
|
82
|
+
var cellAlignment = getAlignment(row.childNodes[columnIndex]);
|
|
83
|
+
++votes[cellAlignment];
|
|
84
|
+
if (votes[cellAlignment] > votes[align]) {
|
|
85
|
+
align = cellAlignment;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return align;
|
|
90
|
+
}
|
|
91
|
+
rules2.tableCell = {
|
|
92
|
+
filter: ["th", "td"],
|
|
93
|
+
replacement: function(content, node) {
|
|
94
|
+
if (tableShouldBeSkipped(nodeParentTable(node))) return content;
|
|
95
|
+
return cell(content, node);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
rules2.tableRow = {
|
|
99
|
+
filter: "tr",
|
|
100
|
+
replacement: function(content, node) {
|
|
101
|
+
const parentTable = nodeParentTable(node);
|
|
102
|
+
if (tableShouldBeSkipped(parentTable)) return content;
|
|
103
|
+
var borderCells = "";
|
|
104
|
+
if (isHeadingRow(node)) {
|
|
105
|
+
const colCount = tableColCount(parentTable);
|
|
106
|
+
for (var i = 0; i < colCount; i++) {
|
|
107
|
+
const childNode = i < node.childNodes.length ? node.childNodes[i] : null;
|
|
108
|
+
var border = getBorder(getColumnAlignment(parentTable, i));
|
|
109
|
+
borderCells += cell(border, childNode, i);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return "\n" + content + (borderCells ? "\n" + borderCells : "");
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
rules2.table = {
|
|
116
|
+
filter: function(node, options) {
|
|
117
|
+
return node.nodeName === "TABLE";
|
|
118
|
+
},
|
|
119
|
+
replacement: function(content, node) {
|
|
120
|
+
if (tableShouldBeHtml(node, options_)) {
|
|
121
|
+
let html = node.outerHTML;
|
|
122
|
+
let divParent = nodeParentDiv(node);
|
|
123
|
+
if (divParent === null || !divParent.classList.contains("joplin-table-wrapper")) {
|
|
124
|
+
return `
|
|
125
|
+
|
|
126
|
+
<div class="joplin-table-wrapper">${html}</div>
|
|
127
|
+
|
|
128
|
+
`;
|
|
129
|
+
} else {
|
|
130
|
+
return html;
|
|
131
|
+
}
|
|
132
|
+
} else {
|
|
133
|
+
if (tableShouldBeSkipped(node)) return content;
|
|
134
|
+
content = content.replace(/\n+/g, "\n");
|
|
135
|
+
var secondLine = content.trim().split("\n");
|
|
136
|
+
if (secondLine.length >= 2) secondLine = secondLine[1];
|
|
137
|
+
var secondLineIsDivider = /\| :?---/.test(secondLine);
|
|
138
|
+
var columnCount = tableColCount(node);
|
|
139
|
+
var emptyHeader = "";
|
|
140
|
+
if (columnCount && !secondLineIsDivider) {
|
|
141
|
+
emptyHeader = "|" + " |".repeat(columnCount) + "\n|";
|
|
142
|
+
for (var columnIndex = 0; columnIndex < columnCount; ++columnIndex) {
|
|
143
|
+
emptyHeader += " " + getBorder(getColumnAlignment(node, columnIndex)) + " |";
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const captionNode = node.querySelector ? node.querySelector("caption") : node.caption;
|
|
147
|
+
const captionContent = captionNode ? captionNode.textContent || "" : "";
|
|
148
|
+
const caption = captionContent ? `${captionContent}
|
|
149
|
+
|
|
150
|
+
` : "";
|
|
151
|
+
const tableContent = `${emptyHeader}${content}`.trimStart();
|
|
152
|
+
return `
|
|
153
|
+
|
|
154
|
+
${caption}${tableContent}
|
|
155
|
+
|
|
156
|
+
`;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
rules2.tableCaption = {
|
|
161
|
+
filter: ["caption"],
|
|
162
|
+
replacement: () => ""
|
|
163
|
+
};
|
|
164
|
+
rules2.tableColgroup = {
|
|
165
|
+
filter: ["colgroup", "col"],
|
|
166
|
+
replacement: () => ""
|
|
167
|
+
};
|
|
168
|
+
rules2.tableSection = {
|
|
169
|
+
filter: ["thead", "tbody", "tfoot"],
|
|
170
|
+
replacement: function(content) {
|
|
171
|
+
return content;
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
function isHeadingRow(tr) {
|
|
175
|
+
var parentNode = tr.parentNode;
|
|
176
|
+
return parentNode.nodeName === "THEAD" || parentNode.firstChild === tr && (parentNode.nodeName === "TABLE" || isFirstTbody(parentNode)) && every.call(tr.childNodes, function(n) {
|
|
177
|
+
return n.nodeName === "TH";
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
function isFirstTbody(element) {
|
|
181
|
+
var previousSibling = element.previousSibling;
|
|
182
|
+
return element.nodeName === "TBODY" && (!previousSibling || previousSibling.nodeName === "THEAD" && /^\s*$/i.test(previousSibling.textContent));
|
|
183
|
+
}
|
|
184
|
+
function cell(content, node = null, index = null) {
|
|
185
|
+
if (index === null) index = indexOf.call(node.parentNode.childNodes, node);
|
|
186
|
+
var prefix = " ";
|
|
187
|
+
if (index === 0) prefix = "| ";
|
|
188
|
+
let filteredContent = content.trim().replace(/\n\r/g, "<br>").replace(/\n/g, "<br>");
|
|
189
|
+
filteredContent = filteredContent.replace(/\|+/g, "\\|");
|
|
190
|
+
while (filteredContent.length < 3) filteredContent += " ";
|
|
191
|
+
if (node) filteredContent = handleColSpan(filteredContent, node, " ");
|
|
192
|
+
return prefix + filteredContent + " |";
|
|
193
|
+
}
|
|
194
|
+
function nodeContainsTable(node) {
|
|
195
|
+
if (!node.childNodes) return false;
|
|
196
|
+
for (let i = 0; i < node.childNodes.length; i++) {
|
|
197
|
+
const child = node.childNodes[i];
|
|
198
|
+
if (child.nodeName === "TABLE") return true;
|
|
199
|
+
if (nodeContainsTable(child)) return true;
|
|
200
|
+
}
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
var nodeContains = (node, types) => {
|
|
204
|
+
if (!node.childNodes) return false;
|
|
205
|
+
for (let i = 0; i < node.childNodes.length; i++) {
|
|
206
|
+
const child = node.childNodes[i];
|
|
207
|
+
if (types === "code" && isCodeBlock_ && isCodeBlock_(child)) return true;
|
|
208
|
+
if (types.includes(child.nodeName)) return true;
|
|
209
|
+
if (nodeContains(child, types)) return true;
|
|
210
|
+
}
|
|
211
|
+
return false;
|
|
212
|
+
};
|
|
213
|
+
var customStyleProperties = [
|
|
214
|
+
"background-color",
|
|
215
|
+
"background",
|
|
216
|
+
"border-color",
|
|
217
|
+
"border",
|
|
218
|
+
"border-top",
|
|
219
|
+
"border-right",
|
|
220
|
+
"border-bottom",
|
|
221
|
+
"border-left",
|
|
222
|
+
"border-style",
|
|
223
|
+
"border-width",
|
|
224
|
+
"padding",
|
|
225
|
+
"padding-top",
|
|
226
|
+
"padding-right",
|
|
227
|
+
"padding-bottom",
|
|
228
|
+
"padding-left",
|
|
229
|
+
"float",
|
|
230
|
+
"margin-left",
|
|
231
|
+
"margin-right"
|
|
232
|
+
];
|
|
233
|
+
var customAttributeNames = [
|
|
234
|
+
"bgcolor",
|
|
235
|
+
"bordercolor",
|
|
236
|
+
"background"
|
|
237
|
+
];
|
|
238
|
+
var nodeHasCustomStyle = (node) => {
|
|
239
|
+
if (!node || !node.getAttribute) return false;
|
|
240
|
+
const styleAttr = node.getAttribute("style");
|
|
241
|
+
if (!styleAttr) return false;
|
|
242
|
+
const properties = styleAttr.split(";").map((s) => s.split(":")[0].trim().toLowerCase()).filter((s) => s.length > 0);
|
|
243
|
+
for (let i = 0; i < properties.length; i++) {
|
|
244
|
+
if (customStyleProperties.includes(properties[i])) return true;
|
|
245
|
+
}
|
|
246
|
+
return false;
|
|
247
|
+
};
|
|
248
|
+
var hasNonDefaultSpacingAttribute = (node, name2) => {
|
|
249
|
+
if (!node || !node.getAttribute) return false;
|
|
250
|
+
const value = node.getAttribute(name2);
|
|
251
|
+
if (value === null) return false;
|
|
252
|
+
const normalisedValue = `${value}`.trim().toLowerCase();
|
|
253
|
+
if (!normalisedValue) return false;
|
|
254
|
+
if (normalisedValue === "0" || normalisedValue === "0px") return false;
|
|
255
|
+
return true;
|
|
256
|
+
};
|
|
257
|
+
var nodeHasCustomAttributes = (node) => {
|
|
258
|
+
if (!node || !node.getAttribute) return false;
|
|
259
|
+
for (let i = 0; i < customAttributeNames.length; i++) {
|
|
260
|
+
const value = node.getAttribute(customAttributeNames[i]);
|
|
261
|
+
if (value !== null && `${value}`.trim() !== "") return true;
|
|
262
|
+
}
|
|
263
|
+
if (node.nodeName === "TABLE") {
|
|
264
|
+
if (hasNonDefaultSpacingAttribute(node, "cellpadding")) return true;
|
|
265
|
+
if (hasNonDefaultSpacingAttribute(node, "cellspacing")) return true;
|
|
266
|
+
}
|
|
267
|
+
return false;
|
|
268
|
+
};
|
|
269
|
+
var nodeHasCustomFormatting = (node) => {
|
|
270
|
+
return nodeHasCustomStyle(node) || nodeHasCustomAttributes(node);
|
|
271
|
+
};
|
|
272
|
+
var tableHasCustomStyles = (tableNode) => {
|
|
273
|
+
if (nodeHasCustomFormatting(tableNode)) return true;
|
|
274
|
+
const rows = tableNode.rows;
|
|
275
|
+
if (!rows) return false;
|
|
276
|
+
for (let i = 0; i < rows.length; i++) {
|
|
277
|
+
const row = rows[i];
|
|
278
|
+
if (nodeHasCustomFormatting(row)) return true;
|
|
279
|
+
for (let j = 0; j < row.childNodes.length; j++) {
|
|
280
|
+
const cell2 = row.childNodes[j];
|
|
281
|
+
if ((cell2.nodeName === "TD" || cell2.nodeName === "TH") && nodeHasCustomFormatting(cell2)) {
|
|
282
|
+
return true;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return false;
|
|
287
|
+
};
|
|
288
|
+
var tableShouldBeHtml = (tableNode, options) => {
|
|
289
|
+
const possibleTags = [
|
|
290
|
+
"UL",
|
|
291
|
+
"OL",
|
|
292
|
+
"H1",
|
|
293
|
+
"H2",
|
|
294
|
+
"H3",
|
|
295
|
+
"H4",
|
|
296
|
+
"H5",
|
|
297
|
+
"H6",
|
|
298
|
+
"HR",
|
|
299
|
+
"BLOCKQUOTE"
|
|
300
|
+
];
|
|
301
|
+
if (options.preserveNestedTables) possibleTags.push("TABLE");
|
|
302
|
+
return nodeContains(tableNode, "code") || nodeContains(tableNode, possibleTags) || options.preserveTableStyles && tableHasCustomStyles(tableNode);
|
|
303
|
+
};
|
|
304
|
+
function tableShouldBeSkipped(tableNode) {
|
|
305
|
+
const cached = tableShouldBeSkippedCache_.get(tableNode);
|
|
306
|
+
if (cached !== void 0) return cached;
|
|
307
|
+
const result = tableShouldBeSkipped_(tableNode);
|
|
308
|
+
tableShouldBeSkippedCache_.set(tableNode, result);
|
|
309
|
+
return result;
|
|
310
|
+
}
|
|
311
|
+
function tableShouldBeSkipped_(tableNode) {
|
|
312
|
+
if (!tableNode) return true;
|
|
313
|
+
if (!tableNode.rows) return true;
|
|
314
|
+
if (tableNode.rows.length === 1 && tableNode.rows[0].childNodes.length <= 1) return true;
|
|
315
|
+
if (nodeContainsTable(tableNode)) return true;
|
|
316
|
+
return false;
|
|
317
|
+
}
|
|
318
|
+
function nodeParentDiv(node) {
|
|
319
|
+
let parent = node.parentNode;
|
|
320
|
+
while (parent.nodeName !== "DIV") {
|
|
321
|
+
parent = parent.parentNode;
|
|
322
|
+
if (!parent) return null;
|
|
323
|
+
}
|
|
324
|
+
return parent;
|
|
325
|
+
}
|
|
326
|
+
function nodeParentTable(node) {
|
|
327
|
+
let parent = node.parentNode;
|
|
328
|
+
while (parent.nodeName !== "TABLE") {
|
|
329
|
+
parent = parent.parentNode;
|
|
330
|
+
if (!parent) return null;
|
|
331
|
+
}
|
|
332
|
+
return parent;
|
|
333
|
+
}
|
|
334
|
+
function handleColSpan(content, node, emptyChar) {
|
|
335
|
+
const colspan = node.getAttribute("colspan") || 1;
|
|
336
|
+
for (let i = 1; i < colspan; i++) {
|
|
337
|
+
content += " | " + emptyChar.repeat(3);
|
|
338
|
+
}
|
|
339
|
+
return content;
|
|
340
|
+
}
|
|
341
|
+
function tableColCount(node) {
|
|
342
|
+
let maxColCount = 0;
|
|
343
|
+
for (let i = 0; i < node.rows.length; i++) {
|
|
344
|
+
const row = node.rows[i];
|
|
345
|
+
const colCount = row.childNodes.length;
|
|
346
|
+
if (colCount > maxColCount) maxColCount = colCount;
|
|
347
|
+
}
|
|
348
|
+
return maxColCount;
|
|
349
|
+
}
|
|
350
|
+
function tables(turndownService) {
|
|
351
|
+
isCodeBlock_ = turndownService.isCodeBlock;
|
|
352
|
+
options_ = turndownService.options;
|
|
353
|
+
turndownService.keep(function(node) {
|
|
354
|
+
if (node.nodeName === "TABLE" && tableShouldBeHtml(node, turndownService.options)) return true;
|
|
355
|
+
return false;
|
|
356
|
+
});
|
|
357
|
+
for (var key in rules2) turndownService.addRule(key, rules2[key]);
|
|
358
|
+
}
|
|
359
|
+
function taskListItems(turndownService) {
|
|
360
|
+
turndownService.addRule("taskListItems", {
|
|
361
|
+
filter: function(node) {
|
|
362
|
+
const parent = node.parentNode;
|
|
363
|
+
const grandparent = parent.parentNode;
|
|
364
|
+
const grandparentIsListItem = !!grandparent && grandparent.nodeName === "LI";
|
|
365
|
+
return (node.type === "checkbox" || node.getAttribute("role") === "checkbox") && (parent.nodeName === "LI" || parent.nodeName === "LABEL" && grandparentIsListItem || parent.nodeName === "SPAN" && grandparentIsListItem);
|
|
366
|
+
},
|
|
367
|
+
replacement: function(content, node) {
|
|
368
|
+
const checked = node.nodeName === "INPUT" ? node.checked : node.getAttribute("aria-checked") === "true";
|
|
369
|
+
return (checked ? "[x]" : "[ ]") + " ";
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
function gfm2(turndownService) {
|
|
374
|
+
turndownService.use([
|
|
375
|
+
highlightedCodeBlock,
|
|
376
|
+
strikethrough,
|
|
377
|
+
tables,
|
|
378
|
+
taskListItems
|
|
379
|
+
]);
|
|
380
|
+
}
|
|
381
|
+
exports.gfm = gfm2;
|
|
382
|
+
exports.highlightedCodeBlock = highlightedCodeBlock;
|
|
383
|
+
exports.strikethrough = strikethrough;
|
|
384
|
+
exports.tables = tables;
|
|
385
|
+
exports.taskListItems = taskListItems;
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
// packages/web/tool-web/src/index.ts
|
|
390
|
+
import z from "@deepseek-ai/schemastery";
|
|
391
|
+
|
|
392
|
+
// packages/web/tool-web/src/search.ts
|
|
393
|
+
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
394
|
+
var WEB_SEARCH_MAX_RESULTS = 8;
|
|
395
|
+
function parseSearchArgs(args) {
|
|
396
|
+
if (args.query.trim().length === 0) throw new Error("query must be a non-empty string");
|
|
397
|
+
return { query: args.query };
|
|
398
|
+
}
|
|
399
|
+
function sourceLabel(url, title) {
|
|
400
|
+
if (title !== void 0 && title.length > 0) return title;
|
|
401
|
+
try {
|
|
402
|
+
return new URL(url).hostname;
|
|
403
|
+
} catch {
|
|
404
|
+
return url;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
function formatSearchOutput(result) {
|
|
408
|
+
const parts = [];
|
|
409
|
+
if (result.content !== void 0 && result.content.length > 0) parts.push(result.content);
|
|
410
|
+
if (result.sources.length > 0) {
|
|
411
|
+
const lines = result.sources.map((source) => {
|
|
412
|
+
const label = sourceLabel(source.url, source.title);
|
|
413
|
+
const meta = [];
|
|
414
|
+
if (source.snippet !== void 0 && source.snippet.length > 0) meta.push(source.snippet);
|
|
415
|
+
if (source.publishedAt !== void 0 && source.publishedAt.length > 0) meta.push(`(${source.publishedAt})`);
|
|
416
|
+
const suffix = meta.length > 0 ? ` \u2014 ${meta.join(" ")}` : "";
|
|
417
|
+
return `- [${label}](${source.url})${suffix}`;
|
|
418
|
+
});
|
|
419
|
+
parts.push(`Sources:
|
|
420
|
+
${lines.join("\n")}`);
|
|
421
|
+
} else if (result.content === void 0 || result.content.length === 0) {
|
|
422
|
+
parts.push("No results found.");
|
|
423
|
+
}
|
|
424
|
+
if (result.truncated) parts.push(`(Showing the first ${result.sources.length} sources. Refine the query for more.)`);
|
|
425
|
+
parts.push("Cite the relevant URLs above as markdown links in your answer.");
|
|
426
|
+
return parts.join("\n\n");
|
|
427
|
+
}
|
|
428
|
+
function presentSearchCall(args) {
|
|
429
|
+
return { card: "generic", title: args.query, kind: "search", rawInput: args.query };
|
|
430
|
+
}
|
|
431
|
+
function projectSource(source) {
|
|
432
|
+
return {
|
|
433
|
+
url: source.url,
|
|
434
|
+
...source.title !== void 0 ? { title: source.title } : {},
|
|
435
|
+
...source.snippet !== void 0 ? { snippet: source.snippet } : {},
|
|
436
|
+
...source.publishedAt !== void 0 ? { publishedAt: source.publishedAt } : {}
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
function searchMetaFromValue(value) {
|
|
440
|
+
return {
|
|
441
|
+
sources: value.sources.map(projectSource),
|
|
442
|
+
truncated: value.truncated,
|
|
443
|
+
...value.content !== void 0 ? { answer: value.content } : {}
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
function isWebSource(value) {
|
|
447
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
448
|
+
const { url, title, snippet, publishedAt } = value;
|
|
449
|
+
return typeof url === "string" && (title === void 0 || typeof title === "string") && (snippet === void 0 || typeof snippet === "string") && (publishedAt === void 0 || typeof publishedAt === "string");
|
|
450
|
+
}
|
|
451
|
+
function searchMetaFromResult(meta) {
|
|
452
|
+
if (typeof meta !== "object" || meta === null || Array.isArray(meta)) return void 0;
|
|
453
|
+
const { sources, truncated, answer } = meta;
|
|
454
|
+
if (!Array.isArray(sources) || !sources.every(isWebSource)) return void 0;
|
|
455
|
+
if (typeof truncated !== "boolean") return void 0;
|
|
456
|
+
if (answer !== void 0 && typeof answer !== "string") return void 0;
|
|
457
|
+
return {
|
|
458
|
+
sources,
|
|
459
|
+
truncated,
|
|
460
|
+
...answer !== void 0 ? { answer } : {}
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
function presentSearchResult(args, result) {
|
|
464
|
+
if (result.isError) return void 0;
|
|
465
|
+
const meta = searchMetaFromResult(result.meta);
|
|
466
|
+
if (meta === void 0) return void 0;
|
|
467
|
+
return {
|
|
468
|
+
card: "web",
|
|
469
|
+
kind: "search",
|
|
470
|
+
title: args.query,
|
|
471
|
+
sources: meta.sources,
|
|
472
|
+
truncated: meta.truncated,
|
|
473
|
+
...meta.answer !== void 0 ? { answer: meta.answer } : {}
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
function applyWebSearchTool(ctx, maxResults, timeoutMs, fetchEnabled) {
|
|
477
|
+
ctx.systemPrompt.section({
|
|
478
|
+
name: "tool:web_search",
|
|
479
|
+
order: 110,
|
|
480
|
+
text: fetchEnabled ? "Use the web_search tool to discover current information on the web. It returns an optional answer plus a list of source URLs. Follow up with web_fetch when you need the full content of a specific result, and cite the relevant URLs as markdown links." : "Use the web_search tool to discover current information on the web. It returns an optional answer plus a list of source URLs. Use the returned source snippets when available, and cite the relevant URLs as markdown links."
|
|
481
|
+
});
|
|
482
|
+
ctx.tools.register(defineTool({
|
|
483
|
+
name: "web_search",
|
|
484
|
+
description: "Search the web for current information. Returns an optional summary answer and a list of source URLs.",
|
|
485
|
+
parameters: {
|
|
486
|
+
query: { type: "string", required: true, description: "The search query." }
|
|
487
|
+
},
|
|
488
|
+
output: {
|
|
489
|
+
schema: {
|
|
490
|
+
type: "object",
|
|
491
|
+
additionalProperties: false,
|
|
492
|
+
properties: {
|
|
493
|
+
content: { type: "string" },
|
|
494
|
+
sources: {
|
|
495
|
+
type: "array",
|
|
496
|
+
required: true,
|
|
497
|
+
items: {
|
|
498
|
+
type: "object",
|
|
499
|
+
additionalProperties: false,
|
|
500
|
+
properties: {
|
|
501
|
+
url: { type: "string", required: true },
|
|
502
|
+
title: { type: "string" },
|
|
503
|
+
snippet: { type: "string" },
|
|
504
|
+
publishedAt: { type: "string" }
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
},
|
|
508
|
+
truncated: { type: "boolean", required: true }
|
|
509
|
+
}
|
|
510
|
+
},
|
|
511
|
+
render: (_args, value) => [{ type: "text", text: formatSearchOutput(value) }],
|
|
512
|
+
presentationMeta: (_args, value) => searchMetaFromValue(value)
|
|
513
|
+
},
|
|
514
|
+
timeoutMs,
|
|
515
|
+
// Provider reads do not mutate parent-agent state.
|
|
516
|
+
isConcurrencySafe: () => true,
|
|
517
|
+
async execute(args, exec) {
|
|
518
|
+
const input = parseSearchArgs(args);
|
|
519
|
+
const result = await ctx.web.search(
|
|
520
|
+
{ query: input.query, maxResults },
|
|
521
|
+
exec.signal
|
|
522
|
+
);
|
|
523
|
+
return {
|
|
524
|
+
...result.content !== void 0 ? { content: result.content } : {},
|
|
525
|
+
sources: result.sources.map(projectSource),
|
|
526
|
+
truncated: result.truncated
|
|
527
|
+
};
|
|
528
|
+
},
|
|
529
|
+
presentCall: presentSearchCall,
|
|
530
|
+
presentResult: (args, result) => presentSearchResult(args, result)
|
|
531
|
+
}));
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// node_modules/.pnpm/turndown@7.2.4/node_modules/turndown/lib/turndown.browser.es.js
|
|
535
|
+
function extend(destination) {
|
|
536
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
537
|
+
var source = arguments[i];
|
|
538
|
+
for (var key in source) {
|
|
539
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) destination[key] = source[key];
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
return destination;
|
|
543
|
+
}
|
|
544
|
+
function repeat(character, count) {
|
|
545
|
+
return Array(count + 1).join(character);
|
|
546
|
+
}
|
|
547
|
+
function trimLeadingNewlines(string) {
|
|
548
|
+
return string.replace(/^\n*/, "");
|
|
549
|
+
}
|
|
550
|
+
function trimTrailingNewlines(string) {
|
|
551
|
+
var indexEnd = string.length;
|
|
552
|
+
while (indexEnd > 0 && string[indexEnd - 1] === "\n") indexEnd--;
|
|
553
|
+
return string.substring(0, indexEnd);
|
|
554
|
+
}
|
|
555
|
+
function trimNewlines(string) {
|
|
556
|
+
return trimTrailingNewlines(trimLeadingNewlines(string));
|
|
557
|
+
}
|
|
558
|
+
var blockElements = ["ADDRESS", "ARTICLE", "ASIDE", "AUDIO", "BLOCKQUOTE", "BODY", "CANVAS", "CENTER", "DD", "DIR", "DIV", "DL", "DT", "FIELDSET", "FIGCAPTION", "FIGURE", "FOOTER", "FORM", "FRAMESET", "H1", "H2", "H3", "H4", "H5", "H6", "HEADER", "HGROUP", "HR", "HTML", "ISINDEX", "LI", "MAIN", "MENU", "NAV", "NOFRAMES", "NOSCRIPT", "OL", "OUTPUT", "P", "PRE", "SECTION", "TABLE", "TBODY", "TD", "TFOOT", "TH", "THEAD", "TR", "UL"];
|
|
559
|
+
function isBlock(node) {
|
|
560
|
+
return is(node, blockElements);
|
|
561
|
+
}
|
|
562
|
+
var voidElements = ["AREA", "BASE", "BR", "COL", "COMMAND", "EMBED", "HR", "IMG", "INPUT", "KEYGEN", "LINK", "META", "PARAM", "SOURCE", "TRACK", "WBR"];
|
|
563
|
+
function isVoid(node) {
|
|
564
|
+
return is(node, voidElements);
|
|
565
|
+
}
|
|
566
|
+
function hasVoid(node) {
|
|
567
|
+
return has(node, voidElements);
|
|
568
|
+
}
|
|
569
|
+
var meaningfulWhenBlankElements = ["A", "TABLE", "THEAD", "TBODY", "TFOOT", "TH", "TD", "IFRAME", "SCRIPT", "AUDIO", "VIDEO"];
|
|
570
|
+
function isMeaningfulWhenBlank(node) {
|
|
571
|
+
return is(node, meaningfulWhenBlankElements);
|
|
572
|
+
}
|
|
573
|
+
function hasMeaningfulWhenBlank(node) {
|
|
574
|
+
return has(node, meaningfulWhenBlankElements);
|
|
575
|
+
}
|
|
576
|
+
function is(node, tagNames) {
|
|
577
|
+
return tagNames.indexOf(node.nodeName) >= 0;
|
|
578
|
+
}
|
|
579
|
+
function has(node, tagNames) {
|
|
580
|
+
return node.getElementsByTagName && tagNames.some(function(tagName) {
|
|
581
|
+
return node.getElementsByTagName(tagName).length;
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
var markdownEscapes = [[/\\/g, "\\\\"], [/\*/g, "\\*"], [/^-/g, "\\-"], [/^\+ /g, "\\+ "], [/^(=+)/g, "\\$1"], [/^(#{1,6}) /g, "\\$1 "], [/`/g, "\\`"], [/^~~~/g, "\\~~~"], [/\[/g, "\\["], [/\]/g, "\\]"], [/^>/g, "\\>"], [/_/g, "\\_"], [/^(\d+)\. /g, "$1\\. "]];
|
|
585
|
+
function escapeMarkdown(string) {
|
|
586
|
+
return markdownEscapes.reduce(function(accumulator, escape) {
|
|
587
|
+
return accumulator.replace(escape[0], escape[1]);
|
|
588
|
+
}, string);
|
|
589
|
+
}
|
|
590
|
+
var rules = {};
|
|
591
|
+
rules.paragraph = {
|
|
592
|
+
filter: "p",
|
|
593
|
+
replacement: function(content) {
|
|
594
|
+
return "\n\n" + content + "\n\n";
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
rules.lineBreak = {
|
|
598
|
+
filter: "br",
|
|
599
|
+
replacement: function(content, node, options) {
|
|
600
|
+
return options.br + "\n";
|
|
601
|
+
}
|
|
602
|
+
};
|
|
603
|
+
rules.heading = {
|
|
604
|
+
filter: ["h1", "h2", "h3", "h4", "h5", "h6"],
|
|
605
|
+
replacement: function(content, node, options) {
|
|
606
|
+
var hLevel = Number(node.nodeName.charAt(1));
|
|
607
|
+
if (options.headingStyle === "setext" && hLevel < 3) {
|
|
608
|
+
var underline = repeat(hLevel === 1 ? "=" : "-", content.length);
|
|
609
|
+
return "\n\n" + content + "\n" + underline + "\n\n";
|
|
610
|
+
} else {
|
|
611
|
+
return "\n\n" + repeat("#", hLevel) + " " + content + "\n\n";
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
rules.blockquote = {
|
|
616
|
+
filter: "blockquote",
|
|
617
|
+
replacement: function(content) {
|
|
618
|
+
content = trimNewlines(content).replace(/^/gm, "> ");
|
|
619
|
+
return "\n\n" + content + "\n\n";
|
|
620
|
+
}
|
|
621
|
+
};
|
|
622
|
+
rules.list = {
|
|
623
|
+
filter: ["ul", "ol"],
|
|
624
|
+
replacement: function(content, node) {
|
|
625
|
+
var parent = node.parentNode;
|
|
626
|
+
if (parent.nodeName === "LI" && parent.lastElementChild === node) {
|
|
627
|
+
return "\n" + content;
|
|
628
|
+
} else {
|
|
629
|
+
return "\n\n" + content + "\n\n";
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
};
|
|
633
|
+
rules.listItem = {
|
|
634
|
+
filter: "li",
|
|
635
|
+
replacement: function(content, node, options) {
|
|
636
|
+
var prefix = options.bulletListMarker + " ";
|
|
637
|
+
var parent = node.parentNode;
|
|
638
|
+
if (parent.nodeName === "OL") {
|
|
639
|
+
var start = parent.getAttribute("start");
|
|
640
|
+
var index = Array.prototype.indexOf.call(parent.children, node);
|
|
641
|
+
prefix = (start ? Number(start) + index : index + 1) + ". ";
|
|
642
|
+
}
|
|
643
|
+
var isParagraph = /\n$/.test(content);
|
|
644
|
+
content = trimNewlines(content) + (isParagraph ? "\n" : "");
|
|
645
|
+
content = content.replace(/\n/gm, "\n" + " ".repeat(prefix.length));
|
|
646
|
+
return prefix + content + (node.nextSibling ? "\n" : "");
|
|
647
|
+
}
|
|
648
|
+
};
|
|
649
|
+
rules.indentedCodeBlock = {
|
|
650
|
+
filter: function(node, options) {
|
|
651
|
+
return options.codeBlockStyle === "indented" && node.nodeName === "PRE" && node.firstChild && node.firstChild.nodeName === "CODE";
|
|
652
|
+
},
|
|
653
|
+
replacement: function(content, node, options) {
|
|
654
|
+
return "\n\n " + node.firstChild.textContent.replace(/\n/g, "\n ") + "\n\n";
|
|
655
|
+
}
|
|
656
|
+
};
|
|
657
|
+
rules.fencedCodeBlock = {
|
|
658
|
+
filter: function(node, options) {
|
|
659
|
+
return options.codeBlockStyle === "fenced" && node.nodeName === "PRE" && node.firstChild && node.firstChild.nodeName === "CODE";
|
|
660
|
+
},
|
|
661
|
+
replacement: function(content, node, options) {
|
|
662
|
+
var className = node.firstChild.getAttribute("class") || "";
|
|
663
|
+
var language = (className.match(/language-(\S+)/) || [null, ""])[1];
|
|
664
|
+
var code = node.firstChild.textContent;
|
|
665
|
+
var fenceChar = options.fence.charAt(0);
|
|
666
|
+
var fenceSize = 3;
|
|
667
|
+
var fenceInCodeRegex = new RegExp("^" + fenceChar + "{3,}", "gm");
|
|
668
|
+
var match;
|
|
669
|
+
while (match = fenceInCodeRegex.exec(code)) {
|
|
670
|
+
if (match[0].length >= fenceSize) {
|
|
671
|
+
fenceSize = match[0].length + 1;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
var fence = repeat(fenceChar, fenceSize);
|
|
675
|
+
return "\n\n" + fence + language + "\n" + code.replace(/\n$/, "") + "\n" + fence + "\n\n";
|
|
676
|
+
}
|
|
677
|
+
};
|
|
678
|
+
rules.horizontalRule = {
|
|
679
|
+
filter: "hr",
|
|
680
|
+
replacement: function(content, node, options) {
|
|
681
|
+
return "\n\n" + options.hr + "\n\n";
|
|
682
|
+
}
|
|
683
|
+
};
|
|
684
|
+
rules.inlineLink = {
|
|
685
|
+
filter: function(node, options) {
|
|
686
|
+
return options.linkStyle === "inlined" && node.nodeName === "A" && node.getAttribute("href");
|
|
687
|
+
},
|
|
688
|
+
replacement: function(content, node) {
|
|
689
|
+
var href = escapeLinkDestination(node.getAttribute("href"));
|
|
690
|
+
var title = escapeLinkTitle(cleanAttribute(node.getAttribute("title")));
|
|
691
|
+
var titlePart = title ? ' "' + title + '"' : "";
|
|
692
|
+
return "[" + content + "](" + href + titlePart + ")";
|
|
693
|
+
}
|
|
694
|
+
};
|
|
695
|
+
rules.referenceLink = {
|
|
696
|
+
filter: function(node, options) {
|
|
697
|
+
return options.linkStyle === "referenced" && node.nodeName === "A" && node.getAttribute("href");
|
|
698
|
+
},
|
|
699
|
+
replacement: function(content, node, options) {
|
|
700
|
+
var href = escapeLinkDestination(node.getAttribute("href"));
|
|
701
|
+
var title = cleanAttribute(node.getAttribute("title"));
|
|
702
|
+
if (title) title = ' "' + escapeLinkTitle(title) + '"';
|
|
703
|
+
var replacement;
|
|
704
|
+
var reference;
|
|
705
|
+
switch (options.linkReferenceStyle) {
|
|
706
|
+
case "collapsed":
|
|
707
|
+
replacement = "[" + content + "][]";
|
|
708
|
+
reference = "[" + content + "]: " + href + title;
|
|
709
|
+
break;
|
|
710
|
+
case "shortcut":
|
|
711
|
+
replacement = "[" + content + "]";
|
|
712
|
+
reference = "[" + content + "]: " + href + title;
|
|
713
|
+
break;
|
|
714
|
+
default:
|
|
715
|
+
var id = this.references.length + 1;
|
|
716
|
+
replacement = "[" + content + "][" + id + "]";
|
|
717
|
+
reference = "[" + id + "]: " + href + title;
|
|
718
|
+
}
|
|
719
|
+
this.references.push(reference);
|
|
720
|
+
return replacement;
|
|
721
|
+
},
|
|
722
|
+
references: [],
|
|
723
|
+
append: function(options) {
|
|
724
|
+
var references = "";
|
|
725
|
+
if (this.references.length) {
|
|
726
|
+
references = "\n\n" + this.references.join("\n") + "\n\n";
|
|
727
|
+
this.references = [];
|
|
728
|
+
}
|
|
729
|
+
return references;
|
|
730
|
+
}
|
|
731
|
+
};
|
|
732
|
+
rules.emphasis = {
|
|
733
|
+
filter: ["em", "i"],
|
|
734
|
+
replacement: function(content, node, options) {
|
|
735
|
+
if (!content.trim()) return "";
|
|
736
|
+
return options.emDelimiter + content + options.emDelimiter;
|
|
737
|
+
}
|
|
738
|
+
};
|
|
739
|
+
rules.strong = {
|
|
740
|
+
filter: ["strong", "b"],
|
|
741
|
+
replacement: function(content, node, options) {
|
|
742
|
+
if (!content.trim()) return "";
|
|
743
|
+
return options.strongDelimiter + content + options.strongDelimiter;
|
|
744
|
+
}
|
|
745
|
+
};
|
|
746
|
+
rules.code = {
|
|
747
|
+
filter: function(node) {
|
|
748
|
+
var hasSiblings = node.previousSibling || node.nextSibling;
|
|
749
|
+
var isCodeBlock = node.parentNode.nodeName === "PRE" && !hasSiblings;
|
|
750
|
+
return node.nodeName === "CODE" && !isCodeBlock;
|
|
751
|
+
},
|
|
752
|
+
replacement: function(content) {
|
|
753
|
+
if (!content) return "";
|
|
754
|
+
content = content.replace(/\r?\n|\r/g, " ");
|
|
755
|
+
var extraSpace = /^`|^ .*?[^ ].* $|`$/.test(content) ? " " : "";
|
|
756
|
+
var delimiter = "`";
|
|
757
|
+
var matches = content.match(/`+/gm) || [];
|
|
758
|
+
while (matches.indexOf(delimiter) !== -1) delimiter = delimiter + "`";
|
|
759
|
+
return delimiter + extraSpace + content + extraSpace + delimiter;
|
|
760
|
+
}
|
|
761
|
+
};
|
|
762
|
+
rules.image = {
|
|
763
|
+
filter: "img",
|
|
764
|
+
replacement: function(content, node) {
|
|
765
|
+
var alt = escapeMarkdown(cleanAttribute(node.getAttribute("alt")));
|
|
766
|
+
var src = escapeLinkDestination(node.getAttribute("src") || "");
|
|
767
|
+
var title = cleanAttribute(node.getAttribute("title"));
|
|
768
|
+
var titlePart = title ? ' "' + escapeLinkTitle(title) + '"' : "";
|
|
769
|
+
return src ? "" : "";
|
|
770
|
+
}
|
|
771
|
+
};
|
|
772
|
+
function cleanAttribute(attribute) {
|
|
773
|
+
return attribute ? attribute.replace(/(\n+\s*)+/g, "\n") : "";
|
|
774
|
+
}
|
|
775
|
+
function escapeLinkDestination(destination) {
|
|
776
|
+
var escaped = destination.replace(/([<>()])/g, "\\$1");
|
|
777
|
+
return escaped.indexOf(" ") >= 0 ? "<" + escaped + ">" : escaped;
|
|
778
|
+
}
|
|
779
|
+
function escapeLinkTitle(title) {
|
|
780
|
+
return title.replace(/"/g, '\\"');
|
|
781
|
+
}
|
|
782
|
+
function Rules(options) {
|
|
783
|
+
this.options = options;
|
|
784
|
+
this._keep = [];
|
|
785
|
+
this._remove = [];
|
|
786
|
+
this.blankRule = {
|
|
787
|
+
replacement: options.blankReplacement
|
|
788
|
+
};
|
|
789
|
+
this.keepReplacement = options.keepReplacement;
|
|
790
|
+
this.defaultRule = {
|
|
791
|
+
replacement: options.defaultReplacement
|
|
792
|
+
};
|
|
793
|
+
this.array = [];
|
|
794
|
+
for (var key in options.rules) this.array.push(options.rules[key]);
|
|
795
|
+
}
|
|
796
|
+
Rules.prototype = {
|
|
797
|
+
add: function(key, rule) {
|
|
798
|
+
this.array.unshift(rule);
|
|
799
|
+
},
|
|
800
|
+
keep: function(filter) {
|
|
801
|
+
this._keep.unshift({
|
|
802
|
+
filter,
|
|
803
|
+
replacement: this.keepReplacement
|
|
804
|
+
});
|
|
805
|
+
},
|
|
806
|
+
remove: function(filter) {
|
|
807
|
+
this._remove.unshift({
|
|
808
|
+
filter,
|
|
809
|
+
replacement: function() {
|
|
810
|
+
return "";
|
|
811
|
+
}
|
|
812
|
+
});
|
|
813
|
+
},
|
|
814
|
+
forNode: function(node) {
|
|
815
|
+
if (node.isBlank) return this.blankRule;
|
|
816
|
+
var rule;
|
|
817
|
+
if (rule = findRule(this.array, node, this.options)) return rule;
|
|
818
|
+
if (rule = findRule(this._keep, node, this.options)) return rule;
|
|
819
|
+
if (rule = findRule(this._remove, node, this.options)) return rule;
|
|
820
|
+
return this.defaultRule;
|
|
821
|
+
},
|
|
822
|
+
forEach: function(fn) {
|
|
823
|
+
for (var i = 0; i < this.array.length; i++) fn(this.array[i], i);
|
|
824
|
+
}
|
|
825
|
+
};
|
|
826
|
+
function findRule(rules2, node, options) {
|
|
827
|
+
for (var i = 0; i < rules2.length; i++) {
|
|
828
|
+
var rule = rules2[i];
|
|
829
|
+
if (filterValue(rule, node, options)) return rule;
|
|
830
|
+
}
|
|
831
|
+
return void 0;
|
|
832
|
+
}
|
|
833
|
+
function filterValue(rule, node, options) {
|
|
834
|
+
var filter = rule.filter;
|
|
835
|
+
if (typeof filter === "string") {
|
|
836
|
+
if (filter === node.nodeName.toLowerCase()) return true;
|
|
837
|
+
} else if (Array.isArray(filter)) {
|
|
838
|
+
if (filter.indexOf(node.nodeName.toLowerCase()) > -1) return true;
|
|
839
|
+
} else if (typeof filter === "function") {
|
|
840
|
+
if (filter.call(rule, node, options)) return true;
|
|
841
|
+
} else {
|
|
842
|
+
throw new TypeError("`filter` needs to be a string, array, or function");
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
function collapseWhitespace(options) {
|
|
846
|
+
var element = options.element;
|
|
847
|
+
var isBlock2 = options.isBlock;
|
|
848
|
+
var isVoid2 = options.isVoid;
|
|
849
|
+
var isPre = options.isPre || function(node2) {
|
|
850
|
+
return node2.nodeName === "PRE";
|
|
851
|
+
};
|
|
852
|
+
if (!element.firstChild || isPre(element)) return;
|
|
853
|
+
var prevText = null;
|
|
854
|
+
var keepLeadingWs = false;
|
|
855
|
+
var prev = null;
|
|
856
|
+
var node = next(prev, element, isPre);
|
|
857
|
+
while (node !== element) {
|
|
858
|
+
if (node.nodeType === 3 || node.nodeType === 4) {
|
|
859
|
+
var text = node.data.replace(/[ \r\n\t]+/g, " ");
|
|
860
|
+
if ((!prevText || / $/.test(prevText.data)) && !keepLeadingWs && text[0] === " ") {
|
|
861
|
+
text = text.substr(1);
|
|
862
|
+
}
|
|
863
|
+
if (!text) {
|
|
864
|
+
node = remove(node);
|
|
865
|
+
continue;
|
|
866
|
+
}
|
|
867
|
+
node.data = text;
|
|
868
|
+
prevText = node;
|
|
869
|
+
} else if (node.nodeType === 1) {
|
|
870
|
+
if (isBlock2(node) || node.nodeName === "BR") {
|
|
871
|
+
if (prevText) {
|
|
872
|
+
prevText.data = prevText.data.replace(/ $/, "");
|
|
873
|
+
}
|
|
874
|
+
prevText = null;
|
|
875
|
+
keepLeadingWs = false;
|
|
876
|
+
} else if (isVoid2(node) || isPre(node)) {
|
|
877
|
+
prevText = null;
|
|
878
|
+
keepLeadingWs = true;
|
|
879
|
+
} else if (prevText) {
|
|
880
|
+
keepLeadingWs = false;
|
|
881
|
+
}
|
|
882
|
+
} else {
|
|
883
|
+
node = remove(node);
|
|
884
|
+
continue;
|
|
885
|
+
}
|
|
886
|
+
var nextNode = next(prev, node, isPre);
|
|
887
|
+
prev = node;
|
|
888
|
+
node = nextNode;
|
|
889
|
+
}
|
|
890
|
+
if (prevText) {
|
|
891
|
+
prevText.data = prevText.data.replace(/ $/, "");
|
|
892
|
+
if (!prevText.data) {
|
|
893
|
+
remove(prevText);
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
function remove(node) {
|
|
898
|
+
var next2 = node.nextSibling || node.parentNode;
|
|
899
|
+
node.parentNode.removeChild(node);
|
|
900
|
+
return next2;
|
|
901
|
+
}
|
|
902
|
+
function next(prev, current, isPre) {
|
|
903
|
+
if (prev && prev.parentNode === current || isPre(current)) {
|
|
904
|
+
return current.nextSibling || current.parentNode;
|
|
905
|
+
}
|
|
906
|
+
return current.firstChild || current.nextSibling || current.parentNode;
|
|
907
|
+
}
|
|
908
|
+
var root = typeof window !== "undefined" ? window : {};
|
|
909
|
+
function canParseHTMLNatively() {
|
|
910
|
+
var Parser = root.DOMParser;
|
|
911
|
+
var canParse = false;
|
|
912
|
+
try {
|
|
913
|
+
if (new Parser().parseFromString("", "text/html")) {
|
|
914
|
+
canParse = true;
|
|
915
|
+
}
|
|
916
|
+
} catch (e) {
|
|
917
|
+
}
|
|
918
|
+
return canParse;
|
|
919
|
+
}
|
|
920
|
+
function createHTMLParser() {
|
|
921
|
+
var Parser = function() {
|
|
922
|
+
};
|
|
923
|
+
{
|
|
924
|
+
if (shouldUseActiveX()) {
|
|
925
|
+
Parser.prototype.parseFromString = function(string) {
|
|
926
|
+
var doc = new window.ActiveXObject("htmlfile");
|
|
927
|
+
doc.designMode = "on";
|
|
928
|
+
doc.open();
|
|
929
|
+
doc.write(string);
|
|
930
|
+
doc.close();
|
|
931
|
+
return doc;
|
|
932
|
+
};
|
|
933
|
+
} else {
|
|
934
|
+
Parser.prototype.parseFromString = function(string) {
|
|
935
|
+
var doc = document.implementation.createHTMLDocument("");
|
|
936
|
+
doc.open();
|
|
937
|
+
doc.write(string);
|
|
938
|
+
doc.close();
|
|
939
|
+
return doc;
|
|
940
|
+
};
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
return Parser;
|
|
944
|
+
}
|
|
945
|
+
function shouldUseActiveX() {
|
|
946
|
+
var useActiveX = false;
|
|
947
|
+
try {
|
|
948
|
+
document.implementation.createHTMLDocument("").open();
|
|
949
|
+
} catch (e) {
|
|
950
|
+
if (root.ActiveXObject) useActiveX = true;
|
|
951
|
+
}
|
|
952
|
+
return useActiveX;
|
|
953
|
+
}
|
|
954
|
+
var HTMLParser = canParseHTMLNatively() ? root.DOMParser : createHTMLParser();
|
|
955
|
+
function RootNode(input, options) {
|
|
956
|
+
var root2;
|
|
957
|
+
if (typeof input === "string") {
|
|
958
|
+
var doc = htmlParser().parseFromString(
|
|
959
|
+
// DOM parsers arrange elements in the <head> and <body>.
|
|
960
|
+
// Wrapping in a custom element ensures elements are reliably arranged in
|
|
961
|
+
// a single element.
|
|
962
|
+
'<x-turndown id="turndown-root">' + input + "</x-turndown>",
|
|
963
|
+
"text/html"
|
|
964
|
+
);
|
|
965
|
+
root2 = doc.getElementById("turndown-root");
|
|
966
|
+
} else {
|
|
967
|
+
root2 = input.cloneNode(true);
|
|
968
|
+
}
|
|
969
|
+
collapseWhitespace({
|
|
970
|
+
element: root2,
|
|
971
|
+
isBlock,
|
|
972
|
+
isVoid,
|
|
973
|
+
isPre: options.preformattedCode ? isPreOrCode : null
|
|
974
|
+
});
|
|
975
|
+
return root2;
|
|
976
|
+
}
|
|
977
|
+
var _htmlParser;
|
|
978
|
+
function htmlParser() {
|
|
979
|
+
_htmlParser = _htmlParser || new HTMLParser();
|
|
980
|
+
return _htmlParser;
|
|
981
|
+
}
|
|
982
|
+
function isPreOrCode(node) {
|
|
983
|
+
return node.nodeName === "PRE" || node.nodeName === "CODE";
|
|
984
|
+
}
|
|
985
|
+
function Node(node, options) {
|
|
986
|
+
node.isBlock = isBlock(node);
|
|
987
|
+
node.isCode = node.nodeName === "CODE" || node.parentNode.isCode;
|
|
988
|
+
node.isBlank = isBlank(node);
|
|
989
|
+
node.flankingWhitespace = flankingWhitespace(node, options);
|
|
990
|
+
return node;
|
|
991
|
+
}
|
|
992
|
+
function isBlank(node) {
|
|
993
|
+
return !isVoid(node) && !isMeaningfulWhenBlank(node) && /^\s*$/i.test(node.textContent) && !hasVoid(node) && !hasMeaningfulWhenBlank(node);
|
|
994
|
+
}
|
|
995
|
+
function flankingWhitespace(node, options) {
|
|
996
|
+
if (node.isBlock || options.preformattedCode && node.isCode) {
|
|
997
|
+
return {
|
|
998
|
+
leading: "",
|
|
999
|
+
trailing: ""
|
|
1000
|
+
};
|
|
1001
|
+
}
|
|
1002
|
+
var edges = edgeWhitespace(node.textContent);
|
|
1003
|
+
if (edges.leadingAscii && isFlankedByWhitespace("left", node, options)) {
|
|
1004
|
+
edges.leading = edges.leadingNonAscii;
|
|
1005
|
+
}
|
|
1006
|
+
if (edges.trailingAscii && isFlankedByWhitespace("right", node, options)) {
|
|
1007
|
+
edges.trailing = edges.trailingNonAscii;
|
|
1008
|
+
}
|
|
1009
|
+
return {
|
|
1010
|
+
leading: edges.leading,
|
|
1011
|
+
trailing: edges.trailing
|
|
1012
|
+
};
|
|
1013
|
+
}
|
|
1014
|
+
function edgeWhitespace(string) {
|
|
1015
|
+
var m = string.match(/^(([ \t\r\n]*)(\s*))(?:(?=\S)[\s\S]*\S)?((\s*?)([ \t\r\n]*))$/);
|
|
1016
|
+
return {
|
|
1017
|
+
leading: m[1],
|
|
1018
|
+
// whole string for whitespace-only strings
|
|
1019
|
+
leadingAscii: m[2],
|
|
1020
|
+
leadingNonAscii: m[3],
|
|
1021
|
+
trailing: m[4],
|
|
1022
|
+
// empty for whitespace-only strings
|
|
1023
|
+
trailingNonAscii: m[5],
|
|
1024
|
+
trailingAscii: m[6]
|
|
1025
|
+
};
|
|
1026
|
+
}
|
|
1027
|
+
function isFlankedByWhitespace(side, node, options) {
|
|
1028
|
+
var sibling;
|
|
1029
|
+
var regExp;
|
|
1030
|
+
var isFlanked;
|
|
1031
|
+
if (side === "left") {
|
|
1032
|
+
sibling = node.previousSibling;
|
|
1033
|
+
regExp = / $/;
|
|
1034
|
+
} else {
|
|
1035
|
+
sibling = node.nextSibling;
|
|
1036
|
+
regExp = /^ /;
|
|
1037
|
+
}
|
|
1038
|
+
if (sibling) {
|
|
1039
|
+
if (sibling.nodeType === 3) {
|
|
1040
|
+
isFlanked = regExp.test(sibling.nodeValue);
|
|
1041
|
+
} else if (options.preformattedCode && sibling.nodeName === "CODE") {
|
|
1042
|
+
isFlanked = false;
|
|
1043
|
+
} else if (sibling.nodeType === 1 && !isBlock(sibling)) {
|
|
1044
|
+
isFlanked = regExp.test(sibling.textContent);
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
return isFlanked;
|
|
1048
|
+
}
|
|
1049
|
+
var reduce = Array.prototype.reduce;
|
|
1050
|
+
function TurndownService(options) {
|
|
1051
|
+
if (!(this instanceof TurndownService)) return new TurndownService(options);
|
|
1052
|
+
var defaults = {
|
|
1053
|
+
rules,
|
|
1054
|
+
headingStyle: "setext",
|
|
1055
|
+
hr: "* * *",
|
|
1056
|
+
bulletListMarker: "*",
|
|
1057
|
+
codeBlockStyle: "indented",
|
|
1058
|
+
fence: "```",
|
|
1059
|
+
emDelimiter: "_",
|
|
1060
|
+
strongDelimiter: "**",
|
|
1061
|
+
linkStyle: "inlined",
|
|
1062
|
+
linkReferenceStyle: "full",
|
|
1063
|
+
br: " ",
|
|
1064
|
+
preformattedCode: false,
|
|
1065
|
+
blankReplacement: function(content, node) {
|
|
1066
|
+
return node.isBlock ? "\n\n" : "";
|
|
1067
|
+
},
|
|
1068
|
+
keepReplacement: function(content, node) {
|
|
1069
|
+
return node.isBlock ? "\n\n" + node.outerHTML + "\n\n" : node.outerHTML;
|
|
1070
|
+
},
|
|
1071
|
+
defaultReplacement: function(content, node) {
|
|
1072
|
+
return node.isBlock ? "\n\n" + content + "\n\n" : content;
|
|
1073
|
+
}
|
|
1074
|
+
};
|
|
1075
|
+
this.options = extend({}, defaults, options);
|
|
1076
|
+
this.rules = new Rules(this.options);
|
|
1077
|
+
}
|
|
1078
|
+
TurndownService.prototype = {
|
|
1079
|
+
/**
|
|
1080
|
+
* The entry point for converting a string or DOM node to Markdown
|
|
1081
|
+
* @public
|
|
1082
|
+
* @param {String|HTMLElement} input The string or DOM node to convert
|
|
1083
|
+
* @returns A Markdown representation of the input
|
|
1084
|
+
* @type String
|
|
1085
|
+
*/
|
|
1086
|
+
turndown: function(input) {
|
|
1087
|
+
if (!canConvert(input)) {
|
|
1088
|
+
throw new TypeError(input + " is not a string, or an element/document/fragment node.");
|
|
1089
|
+
}
|
|
1090
|
+
if (input === "") return "";
|
|
1091
|
+
var output = process.call(this, new RootNode(input, this.options));
|
|
1092
|
+
return postProcess.call(this, output);
|
|
1093
|
+
},
|
|
1094
|
+
/**
|
|
1095
|
+
* Add one or more plugins
|
|
1096
|
+
* @public
|
|
1097
|
+
* @param {Function|Array} plugin The plugin or array of plugins to add
|
|
1098
|
+
* @returns The Turndown instance for chaining
|
|
1099
|
+
* @type Object
|
|
1100
|
+
*/
|
|
1101
|
+
use: function(plugin) {
|
|
1102
|
+
if (Array.isArray(plugin)) {
|
|
1103
|
+
for (var i = 0; i < plugin.length; i++) this.use(plugin[i]);
|
|
1104
|
+
} else if (typeof plugin === "function") {
|
|
1105
|
+
plugin(this);
|
|
1106
|
+
} else {
|
|
1107
|
+
throw new TypeError("plugin must be a Function or an Array of Functions");
|
|
1108
|
+
}
|
|
1109
|
+
return this;
|
|
1110
|
+
},
|
|
1111
|
+
/**
|
|
1112
|
+
* Adds a rule
|
|
1113
|
+
* @public
|
|
1114
|
+
* @param {String} key The unique key of the rule
|
|
1115
|
+
* @param {Object} rule The rule
|
|
1116
|
+
* @returns The Turndown instance for chaining
|
|
1117
|
+
* @type Object
|
|
1118
|
+
*/
|
|
1119
|
+
addRule: function(key, rule) {
|
|
1120
|
+
this.rules.add(key, rule);
|
|
1121
|
+
return this;
|
|
1122
|
+
},
|
|
1123
|
+
/**
|
|
1124
|
+
* Keep a node (as HTML) that matches the filter
|
|
1125
|
+
* @public
|
|
1126
|
+
* @param {String|Array|Function} filter The unique key of the rule
|
|
1127
|
+
* @returns The Turndown instance for chaining
|
|
1128
|
+
* @type Object
|
|
1129
|
+
*/
|
|
1130
|
+
keep: function(filter) {
|
|
1131
|
+
this.rules.keep(filter);
|
|
1132
|
+
return this;
|
|
1133
|
+
},
|
|
1134
|
+
/**
|
|
1135
|
+
* Remove a node that matches the filter
|
|
1136
|
+
* @public
|
|
1137
|
+
* @param {String|Array|Function} filter The unique key of the rule
|
|
1138
|
+
* @returns The Turndown instance for chaining
|
|
1139
|
+
* @type Object
|
|
1140
|
+
*/
|
|
1141
|
+
remove: function(filter) {
|
|
1142
|
+
this.rules.remove(filter);
|
|
1143
|
+
return this;
|
|
1144
|
+
},
|
|
1145
|
+
/**
|
|
1146
|
+
* Escapes Markdown syntax
|
|
1147
|
+
* @public
|
|
1148
|
+
* @param {String} string The string to escape
|
|
1149
|
+
* @returns A string with Markdown syntax escaped
|
|
1150
|
+
* @type String
|
|
1151
|
+
*/
|
|
1152
|
+
escape: function(string) {
|
|
1153
|
+
return escapeMarkdown(string);
|
|
1154
|
+
}
|
|
1155
|
+
};
|
|
1156
|
+
function process(parentNode) {
|
|
1157
|
+
var self = this;
|
|
1158
|
+
return reduce.call(parentNode.childNodes, function(output, node) {
|
|
1159
|
+
node = new Node(node, self.options);
|
|
1160
|
+
var replacement = "";
|
|
1161
|
+
if (node.nodeType === 3) {
|
|
1162
|
+
replacement = node.isCode ? node.nodeValue : self.escape(node.nodeValue);
|
|
1163
|
+
} else if (node.nodeType === 1) {
|
|
1164
|
+
replacement = replacementForNode.call(self, node);
|
|
1165
|
+
}
|
|
1166
|
+
return join(output, replacement);
|
|
1167
|
+
}, "");
|
|
1168
|
+
}
|
|
1169
|
+
function postProcess(output) {
|
|
1170
|
+
var self = this;
|
|
1171
|
+
this.rules.forEach(function(rule) {
|
|
1172
|
+
if (typeof rule.append === "function") {
|
|
1173
|
+
output = join(output, rule.append(self.options));
|
|
1174
|
+
}
|
|
1175
|
+
});
|
|
1176
|
+
return output.replace(/^[\t\r\n]+/, "").replace(/[\t\r\n\s]+$/, "");
|
|
1177
|
+
}
|
|
1178
|
+
function replacementForNode(node) {
|
|
1179
|
+
var rule = this.rules.forNode(node);
|
|
1180
|
+
var content = process.call(this, node);
|
|
1181
|
+
var whitespace = node.flankingWhitespace;
|
|
1182
|
+
if (whitespace.leading || whitespace.trailing) content = content.trim();
|
|
1183
|
+
return whitespace.leading + rule.replacement(content, node, this.options) + whitespace.trailing;
|
|
1184
|
+
}
|
|
1185
|
+
function join(output, replacement) {
|
|
1186
|
+
var s1 = trimTrailingNewlines(output);
|
|
1187
|
+
var s2 = trimLeadingNewlines(replacement);
|
|
1188
|
+
var nls = Math.max(output.length - s1.length, replacement.length - s2.length);
|
|
1189
|
+
var separator = "\n\n".substring(0, nls);
|
|
1190
|
+
return s1 + separator + s2;
|
|
1191
|
+
}
|
|
1192
|
+
function canConvert(input) {
|
|
1193
|
+
return input != null && (typeof input === "string" || input.nodeType && (input.nodeType === 1 || input.nodeType === 9 || input.nodeType === 11));
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
// packages/web/tool-web/src/fetch.ts
|
|
1197
|
+
var import_turndown_plugin_gfm = __toESM(require_turndown_plugin_gfm_cjs(), 1);
|
|
1198
|
+
import { defineTool as defineTool2 } from "@deepseek-ai/dsh-tools";
|
|
1199
|
+
import { assertNever } from "@deepseek-ai/dsh-llm";
|
|
1200
|
+
var turndown = new TurndownService({
|
|
1201
|
+
headingStyle: "atx",
|
|
1202
|
+
codeBlockStyle: "fenced",
|
|
1203
|
+
bulletListMarker: "-"
|
|
1204
|
+
});
|
|
1205
|
+
turndown.use(import_turndown_plugin_gfm.gfm);
|
|
1206
|
+
turndown.remove(["script", "style", "noscript"]);
|
|
1207
|
+
function renderTableCell(content, index) {
|
|
1208
|
+
const prefix = index === 0 ? "| " : " ";
|
|
1209
|
+
const escaped = content.trim().replace(/\n\r/g, "<br>").replace(/\n/g, "<br>").replace(/\|+/g, "\\|").padEnd(3, " ");
|
|
1210
|
+
return `${prefix}${escaped} |`;
|
|
1211
|
+
}
|
|
1212
|
+
function isTableHeadingRow(row) {
|
|
1213
|
+
const cells = Array.from(row.cells);
|
|
1214
|
+
const section = row.parentElement;
|
|
1215
|
+
const table = section.parentElement;
|
|
1216
|
+
return (section.nodeName === "THEAD" || table.rows[0] === row) && cells.every((cell) => cell.nodeName === "TH");
|
|
1217
|
+
}
|
|
1218
|
+
function tableBorder(cell) {
|
|
1219
|
+
const alignment = (cell.getAttribute("align") || cell.style.textAlign || "").toLowerCase();
|
|
1220
|
+
if (alignment === "left") return ":---";
|
|
1221
|
+
if (alignment === "right") return "---:";
|
|
1222
|
+
if (alignment === "center") return ":---:";
|
|
1223
|
+
return "---";
|
|
1224
|
+
}
|
|
1225
|
+
turndown.addRule("tableCellWithoutSpanExpansion", {
|
|
1226
|
+
filter: ["th", "td"],
|
|
1227
|
+
replacement(content, node) {
|
|
1228
|
+
const cell = node;
|
|
1229
|
+
const row = cell.parentNode;
|
|
1230
|
+
return renderTableCell(content, Array.prototype.indexOf.call(row.childNodes, cell));
|
|
1231
|
+
}
|
|
1232
|
+
});
|
|
1233
|
+
turndown.addRule("tableRowWithoutSpanExpansion", {
|
|
1234
|
+
filter: "tr",
|
|
1235
|
+
replacement(content, node) {
|
|
1236
|
+
const row = node;
|
|
1237
|
+
const border = isTableHeadingRow(row) ? Array.from(row.cells, (cell, index) => renderTableCell(tableBorder(cell), index)).join("") : "";
|
|
1238
|
+
return `
|
|
1239
|
+
${content}${border.length > 0 ? `
|
|
1240
|
+
${border}` : ""}`;
|
|
1241
|
+
}
|
|
1242
|
+
});
|
|
1243
|
+
function parseFetchArgs(args) {
|
|
1244
|
+
if (args.url.trim().length === 0) throw new Error("url must be a non-empty string");
|
|
1245
|
+
return { url: args.url };
|
|
1246
|
+
}
|
|
1247
|
+
var MAX_CONVERSION_DEPTH = 512;
|
|
1248
|
+
var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
1249
|
+
"area",
|
|
1250
|
+
"base",
|
|
1251
|
+
"br",
|
|
1252
|
+
"col",
|
|
1253
|
+
"embed",
|
|
1254
|
+
"hr",
|
|
1255
|
+
"img",
|
|
1256
|
+
"input",
|
|
1257
|
+
"link",
|
|
1258
|
+
"meta",
|
|
1259
|
+
"param",
|
|
1260
|
+
"source",
|
|
1261
|
+
"track",
|
|
1262
|
+
"wbr"
|
|
1263
|
+
]);
|
|
1264
|
+
var RAW_TEXT_ELEMENTS = /* @__PURE__ */ new Set(["script", "style", "noscript"]);
|
|
1265
|
+
function isTagBoundary(char) {
|
|
1266
|
+
return char === void 0 || char === ">" || char === "/" || /\s/.test(char);
|
|
1267
|
+
}
|
|
1268
|
+
function findRawTextEnd(lowerHtml, name2, from) {
|
|
1269
|
+
const prefix = `</${name2}`;
|
|
1270
|
+
let candidate = lowerHtml.indexOf(prefix, from);
|
|
1271
|
+
while (candidate !== -1 && !isTagBoundary(lowerHtml[candidate + prefix.length])) {
|
|
1272
|
+
candidate = lowerHtml.indexOf(prefix, candidate + prefix.length);
|
|
1273
|
+
}
|
|
1274
|
+
return candidate;
|
|
1275
|
+
}
|
|
1276
|
+
function exceedsConversionDepth(html) {
|
|
1277
|
+
const lowerHtml = html.toLowerCase();
|
|
1278
|
+
const openElements = [];
|
|
1279
|
+
let offset = 0;
|
|
1280
|
+
let inComment = false;
|
|
1281
|
+
while (offset < html.length) {
|
|
1282
|
+
const start = html.indexOf("<", offset);
|
|
1283
|
+
if (inComment) {
|
|
1284
|
+
const end = html.indexOf("-->", offset);
|
|
1285
|
+
if (end !== -1 && (start === -1 || end < start)) {
|
|
1286
|
+
inComment = false;
|
|
1287
|
+
offset = end + 3;
|
|
1288
|
+
continue;
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
if (start === -1) break;
|
|
1292
|
+
if (!inComment && html.startsWith("<!--", start)) {
|
|
1293
|
+
inComment = true;
|
|
1294
|
+
offset = start + 4;
|
|
1295
|
+
continue;
|
|
1296
|
+
}
|
|
1297
|
+
let cursor = start + 1;
|
|
1298
|
+
const closing = html[cursor] === "/";
|
|
1299
|
+
if (closing) cursor += 1;
|
|
1300
|
+
const nameStart = cursor;
|
|
1301
|
+
while (/[a-zA-Z0-9-]/.test(html[cursor] ?? "")) cursor += 1;
|
|
1302
|
+
if (cursor === nameStart || !/[a-zA-Z]/.test(html.charAt(nameStart))) {
|
|
1303
|
+
offset = start + 1;
|
|
1304
|
+
continue;
|
|
1305
|
+
}
|
|
1306
|
+
const name2 = lowerHtml.slice(nameStart, cursor);
|
|
1307
|
+
let quote;
|
|
1308
|
+
while (cursor < html.length) {
|
|
1309
|
+
const char = html[cursor];
|
|
1310
|
+
cursor += 1;
|
|
1311
|
+
if (quote !== void 0) {
|
|
1312
|
+
if (char === quote) quote = void 0;
|
|
1313
|
+
} else if (char === '"' || char === "'") {
|
|
1314
|
+
quote = char;
|
|
1315
|
+
} else if (char === ">") {
|
|
1316
|
+
break;
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
if (html[cursor - 1] !== ">") break;
|
|
1320
|
+
if (closing) {
|
|
1321
|
+
if (!inComment && openElements.at(-1) === name2) openElements.pop();
|
|
1322
|
+
} else {
|
|
1323
|
+
let last = cursor - 2;
|
|
1324
|
+
while (/\s/.test(html.charAt(last))) last -= 1;
|
|
1325
|
+
if (!VOID_ELEMENTS.has(name2) && html[last] !== "/") {
|
|
1326
|
+
openElements.push(name2);
|
|
1327
|
+
if (openElements.length > MAX_CONVERSION_DEPTH) return true;
|
|
1328
|
+
if (!inComment && RAW_TEXT_ELEMENTS.has(name2)) {
|
|
1329
|
+
const end = findRawTextEnd(lowerHtml, name2, cursor);
|
|
1330
|
+
if (end === -1) break;
|
|
1331
|
+
offset = end;
|
|
1332
|
+
continue;
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
offset = cursor;
|
|
1337
|
+
}
|
|
1338
|
+
return false;
|
|
1339
|
+
}
|
|
1340
|
+
function renderBody(body, maxInputChars) {
|
|
1341
|
+
const content = body.content.slice(0, maxInputChars);
|
|
1342
|
+
const sourceTruncated = content.length !== body.content.length;
|
|
1343
|
+
switch (body.kind) {
|
|
1344
|
+
case "html":
|
|
1345
|
+
if (exceedsConversionDepth(content)) return { text: content, sourceTruncated };
|
|
1346
|
+
try {
|
|
1347
|
+
return { text: turndown.turndown(content), sourceTruncated };
|
|
1348
|
+
} catch {
|
|
1349
|
+
return { text: content, sourceTruncated };
|
|
1350
|
+
}
|
|
1351
|
+
case "text":
|
|
1352
|
+
return { text: content, sourceTruncated };
|
|
1353
|
+
/* v8 ignore next 2 -- WebFetchBody is a closed union; this arm is unreachable and only makes adding a kind a compile error. */
|
|
1354
|
+
default:
|
|
1355
|
+
return assertNever(body, "unhandled web fetch body kind");
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
var TRUNCATION_FOOTER = "\n\n(Content truncated. Fetch a more specific URL or section for the full text.)";
|
|
1359
|
+
function renderFetchOutput(result, maxOutputChars) {
|
|
1360
|
+
const byCap = renderCache.get(result) ?? /* @__PURE__ */ new Map();
|
|
1361
|
+
const cached = byCap.get(maxOutputChars);
|
|
1362
|
+
if (cached !== void 0) return cached;
|
|
1363
|
+
const computed = computeFetchOutput(result, maxOutputChars);
|
|
1364
|
+
byCap.set(maxOutputChars, computed);
|
|
1365
|
+
renderCache.set(result, byCap);
|
|
1366
|
+
return computed;
|
|
1367
|
+
}
|
|
1368
|
+
var renderCache = /* @__PURE__ */ new WeakMap();
|
|
1369
|
+
function computeFetchOutput(result, maxOutputChars) {
|
|
1370
|
+
const header = `Fetched ${result.url} (HTTP ${result.statusCode})
|
|
1371
|
+
|
|
1372
|
+
`;
|
|
1373
|
+
const rendered = renderBody(result.body, maxOutputChars);
|
|
1374
|
+
const prefix = `${header}${rendered.text}`;
|
|
1375
|
+
const truncated = result.truncated || rendered.sourceTruncated || prefix.length > maxOutputChars;
|
|
1376
|
+
const full = `${prefix}${truncated ? TRUNCATION_FOOTER : ""}`;
|
|
1377
|
+
if (full.length <= maxOutputChars) return { text: full, truncated };
|
|
1378
|
+
if (maxOutputChars < TRUNCATION_FOOTER.length) return { text: full.slice(0, maxOutputChars), truncated };
|
|
1379
|
+
return { text: `${prefix.slice(0, maxOutputChars - TRUNCATION_FOOTER.length)}${TRUNCATION_FOOTER}`, truncated };
|
|
1380
|
+
}
|
|
1381
|
+
function formatFetchOutput(result, maxOutputChars) {
|
|
1382
|
+
return renderFetchOutput(result, maxOutputChars).text;
|
|
1383
|
+
}
|
|
1384
|
+
function presentFetchCall(args) {
|
|
1385
|
+
return { card: "generic", title: args.url, kind: "fetch", rawInput: args.url };
|
|
1386
|
+
}
|
|
1387
|
+
function fetchMetaFromValue(value, maxOutputChars) {
|
|
1388
|
+
return { url: value.url, statusCode: value.statusCode, truncated: renderFetchOutput(value, maxOutputChars).truncated };
|
|
1389
|
+
}
|
|
1390
|
+
function fetchMetaFromResult(meta) {
|
|
1391
|
+
if (typeof meta !== "object" || meta === null || Array.isArray(meta)) return void 0;
|
|
1392
|
+
const { url, statusCode, truncated } = meta;
|
|
1393
|
+
if (typeof url !== "string" || typeof statusCode !== "number" || typeof truncated !== "boolean") return void 0;
|
|
1394
|
+
return { url, statusCode, truncated };
|
|
1395
|
+
}
|
|
1396
|
+
function presentFetchResult(args, result) {
|
|
1397
|
+
if (result.isError) return void 0;
|
|
1398
|
+
const meta = fetchMetaFromResult(result.meta);
|
|
1399
|
+
if (meta === void 0) return void 0;
|
|
1400
|
+
return {
|
|
1401
|
+
card: "web",
|
|
1402
|
+
kind: "fetch",
|
|
1403
|
+
title: args.url,
|
|
1404
|
+
url: meta.url,
|
|
1405
|
+
statusCode: meta.statusCode,
|
|
1406
|
+
truncated: meta.truncated
|
|
1407
|
+
};
|
|
1408
|
+
}
|
|
1409
|
+
function applyWebFetchTool(ctx, timeoutMs, maxOutputChars) {
|
|
1410
|
+
ctx.systemPrompt.section({
|
|
1411
|
+
name: "tool:web_fetch",
|
|
1412
|
+
order: 111,
|
|
1413
|
+
text: "Use the web_fetch tool to retrieve the content of a specific HTTP(S) URL (for example a result from web_search). It returns the page content decoded to text. Cite the URL as a markdown link when you use its content."
|
|
1414
|
+
});
|
|
1415
|
+
ctx.tools.register(defineTool2({
|
|
1416
|
+
name: "web_fetch",
|
|
1417
|
+
description: "Fetch the content of a specific HTTP(S) URL and return it decoded to text.",
|
|
1418
|
+
parameters: {
|
|
1419
|
+
url: { type: "string", required: true, description: "The HTTP(S) URL to fetch." }
|
|
1420
|
+
},
|
|
1421
|
+
output: {
|
|
1422
|
+
schema: {
|
|
1423
|
+
type: "object",
|
|
1424
|
+
additionalProperties: false,
|
|
1425
|
+
properties: {
|
|
1426
|
+
url: { type: "string", required: true },
|
|
1427
|
+
statusCode: { type: "integer", required: true },
|
|
1428
|
+
body: {
|
|
1429
|
+
required: true,
|
|
1430
|
+
oneOf: [
|
|
1431
|
+
{
|
|
1432
|
+
type: "object",
|
|
1433
|
+
additionalProperties: false,
|
|
1434
|
+
properties: {
|
|
1435
|
+
kind: { type: "string", required: true, const: "html" },
|
|
1436
|
+
content: { type: "string", required: true }
|
|
1437
|
+
}
|
|
1438
|
+
},
|
|
1439
|
+
{
|
|
1440
|
+
type: "object",
|
|
1441
|
+
additionalProperties: false,
|
|
1442
|
+
properties: {
|
|
1443
|
+
kind: { type: "string", required: true, const: "text" },
|
|
1444
|
+
content: { type: "string", required: true }
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
]
|
|
1448
|
+
},
|
|
1449
|
+
truncated: { type: "boolean", required: true }
|
|
1450
|
+
}
|
|
1451
|
+
},
|
|
1452
|
+
render: (_args, value) => [{ type: "text", text: formatFetchOutput(value, maxOutputChars) }],
|
|
1453
|
+
presentationMeta: (_args, value) => fetchMetaFromValue(value, maxOutputChars)
|
|
1454
|
+
},
|
|
1455
|
+
timeoutMs,
|
|
1456
|
+
// Provider reads do not mutate parent-agent state.
|
|
1457
|
+
isConcurrencySafe: () => true,
|
|
1458
|
+
async execute(args, exec) {
|
|
1459
|
+
const input = parseFetchArgs(args);
|
|
1460
|
+
const result = await ctx.web.fetch(
|
|
1461
|
+
{ url: input.url },
|
|
1462
|
+
exec.signal
|
|
1463
|
+
);
|
|
1464
|
+
return {
|
|
1465
|
+
url: result.url,
|
|
1466
|
+
statusCode: result.statusCode,
|
|
1467
|
+
body: { kind: result.body.kind, content: result.body.content },
|
|
1468
|
+
truncated: result.truncated
|
|
1469
|
+
};
|
|
1470
|
+
},
|
|
1471
|
+
presentCall: presentFetchCall,
|
|
1472
|
+
presentResult: (args, result) => presentFetchResult(args, result)
|
|
1473
|
+
}));
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
// packages/web/tool-web/src/index.ts
|
|
1477
|
+
var name = "tool-web";
|
|
1478
|
+
var inject = ["tools", "web", "systemPrompt"];
|
|
1479
|
+
var DEFAULT_WEB_TOOL_TIMEOUT_MS = 3e4;
|
|
1480
|
+
var DEFAULT_FETCH_MAX_OUTPUT_CHARS = 2e5;
|
|
1481
|
+
var Config = z.object({
|
|
1482
|
+
search: z.boolean().default(true),
|
|
1483
|
+
fetch: z.boolean().default(true),
|
|
1484
|
+
searchMaxResults: z.number().default(WEB_SEARCH_MAX_RESULTS),
|
|
1485
|
+
fetchTimeoutMs: z.number().default(DEFAULT_WEB_TOOL_TIMEOUT_MS),
|
|
1486
|
+
searchTimeoutMs: z.number().default(DEFAULT_WEB_TOOL_TIMEOUT_MS),
|
|
1487
|
+
fetchMaxOutputChars: z.number().default(DEFAULT_FETCH_MAX_OUTPUT_CHARS)
|
|
1488
|
+
});
|
|
1489
|
+
function assertPositiveInteger(name2, value) {
|
|
1490
|
+
if (!Number.isInteger(value) || value < 1) {
|
|
1491
|
+
throw new Error(`tool-web: ${name2} must be a positive integer`);
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
function apply(ctx, config) {
|
|
1495
|
+
const resolved = config;
|
|
1496
|
+
assertPositiveInteger("searchMaxResults", resolved.searchMaxResults);
|
|
1497
|
+
assertPositiveInteger("fetchTimeoutMs", resolved.fetchTimeoutMs);
|
|
1498
|
+
assertPositiveInteger("searchTimeoutMs", resolved.searchTimeoutMs);
|
|
1499
|
+
assertPositiveInteger("fetchMaxOutputChars", resolved.fetchMaxOutputChars);
|
|
1500
|
+
if (resolved.search) {
|
|
1501
|
+
applyWebSearchTool(ctx, resolved.searchMaxResults, resolved.searchTimeoutMs, resolved.fetch);
|
|
1502
|
+
}
|
|
1503
|
+
if (resolved.fetch) applyWebFetchTool(ctx, resolved.fetchTimeoutMs, resolved.fetchMaxOutputChars);
|
|
1504
|
+
}
|
|
1505
|
+
export {
|
|
1506
|
+
Config,
|
|
1507
|
+
DEFAULT_FETCH_MAX_OUTPUT_CHARS,
|
|
1508
|
+
DEFAULT_WEB_TOOL_TIMEOUT_MS,
|
|
1509
|
+
WEB_SEARCH_MAX_RESULTS,
|
|
1510
|
+
apply,
|
|
1511
|
+
applyWebFetchTool,
|
|
1512
|
+
applyWebSearchTool,
|
|
1513
|
+
fetchMetaFromResult,
|
|
1514
|
+
fetchMetaFromValue,
|
|
1515
|
+
formatFetchOutput,
|
|
1516
|
+
formatSearchOutput,
|
|
1517
|
+
inject,
|
|
1518
|
+
name,
|
|
1519
|
+
parseFetchArgs,
|
|
1520
|
+
parseSearchArgs,
|
|
1521
|
+
presentFetchCall,
|
|
1522
|
+
presentFetchResult,
|
|
1523
|
+
presentSearchCall,
|
|
1524
|
+
presentSearchResult,
|
|
1525
|
+
searchMetaFromResult,
|
|
1526
|
+
searchMetaFromValue
|
|
1527
|
+
};
|