dsh-m 0.2.9 → 0.2.11
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.en.md +6 -3
- package/README.md +6 -3
- package/docs/DESIGN.md +2 -2
- package/lib/client.js +331 -244
- package/lib/core/dsh-cli.js +0 -29
- package/lib/core/host-api.js +2 -1
- package/lib/core/installed.js +89 -38
- package/lib/core/market.js +2 -1
- package/lib/core/restart.js +149 -27
- package/lib/host.js +7 -2
- package/lib/tools.js +12 -23
- package/package.json +3 -2
package/lib/client.js
CHANGED
|
@@ -112,6 +112,304 @@ var init_market_state = __esm({
|
|
|
112
112
|
}
|
|
113
113
|
});
|
|
114
114
|
|
|
115
|
+
// src/client/markdown.js
|
|
116
|
+
var markdown_exports = {};
|
|
117
|
+
__export(markdown_exports, {
|
|
118
|
+
createMarkdown: () => createMarkdown,
|
|
119
|
+
safeUrl: () => safeUrl
|
|
120
|
+
});
|
|
121
|
+
function safeUrl(u) {
|
|
122
|
+
const t = String(u || "").trim();
|
|
123
|
+
if (/^(https?:\/\/|mailto:)/i.test(t)) return t;
|
|
124
|
+
if (/^[/#]/.test(t)) return t;
|
|
125
|
+
return "#";
|
|
126
|
+
}
|
|
127
|
+
function createMarkdown(h2) {
|
|
128
|
+
function ExtLink2({ href, className, children }) {
|
|
129
|
+
return h2(
|
|
130
|
+
"a",
|
|
131
|
+
{
|
|
132
|
+
className: className || "dshm-md-a",
|
|
133
|
+
href: safeUrl(href),
|
|
134
|
+
target: "_blank",
|
|
135
|
+
rel: "noopener noreferrer",
|
|
136
|
+
onClick: (e) => e.stopPropagation()
|
|
137
|
+
},
|
|
138
|
+
children
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
function MdImg2({ src, alt }) {
|
|
142
|
+
return h2("img", {
|
|
143
|
+
className: "dshm-md-img",
|
|
144
|
+
src: safeUrl(src),
|
|
145
|
+
alt: alt || "",
|
|
146
|
+
referrerPolicy: "no-referrer",
|
|
147
|
+
onError: (e) => {
|
|
148
|
+
e.currentTarget.style.display = "none";
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
function mdInline(text, kb) {
|
|
153
|
+
const re = /(\[!\[[^\]]*\]\([^)]*\)\]\([^)]*\))|(!\[[^\]]*\]\([^)]*\))|(\[[^\]]*\]\([^)]*\))|(`[^`]+`)|(\*\*[^*]+\*\*)|(~~[^~]+~~)|(\*[^*\s][^*]*\*)|(<https?:\/\/[^>\s]+>)|(https?:\/\/[^\s<>()\[\]{}"'「」【】]+[^\s<>()\[\]{}"'「」【】.,;:!?…,。;:!?)】」"')])/g;
|
|
154
|
+
const src = String(text);
|
|
155
|
+
const nodes = [];
|
|
156
|
+
let last = 0;
|
|
157
|
+
let m;
|
|
158
|
+
let i = 0;
|
|
159
|
+
while (m = re.exec(src)) {
|
|
160
|
+
if (m.index > last) nodes.push(src.slice(last, m.index));
|
|
161
|
+
const tok = m[0];
|
|
162
|
+
const k = `${kb}-${i++}`;
|
|
163
|
+
if (tok.startsWith("[![")) {
|
|
164
|
+
const im = /^!\[([^\]]*)\]\(([^)]*)\)/.exec(tok.slice(1));
|
|
165
|
+
const lm = /\]\(([^)]*)\)\s*$/.exec(tok);
|
|
166
|
+
const img = h2(MdImg2, { src: im && im[2], alt: im && im[1] });
|
|
167
|
+
const href = lm && lm[1];
|
|
168
|
+
nodes.push(href && safeUrl(href) !== "#" ? h2(ExtLink2, { key: k, href }, img) : h2("span", { key: k }, img));
|
|
169
|
+
} else if (tok.startsWith("![") || tok.startsWith("<![")) {
|
|
170
|
+
const im = /^!\[([^\]]*)\]\(([^)]*)\)$/.exec(tok);
|
|
171
|
+
nodes.push(h2(MdImg2, { key: k, src: im && im[2], alt: im && im[1] }));
|
|
172
|
+
} else if (tok.startsWith("[")) {
|
|
173
|
+
const lm = /^\[([^\]]*)\]\(([^)]*)\)$/.exec(tok);
|
|
174
|
+
nodes.push(h2(ExtLink2, { key: k, href: lm && lm[2] }, mdInline(lm ? lm[1] : tok, k)));
|
|
175
|
+
} else if (tok.startsWith("`")) {
|
|
176
|
+
nodes.push(h2("code", { key: k }, tok.slice(1, -1)));
|
|
177
|
+
} else if (tok.startsWith("**")) {
|
|
178
|
+
nodes.push(h2("strong", { key: k }, mdInline(tok.slice(2, -2), k)));
|
|
179
|
+
} else if (tok.startsWith("~~")) {
|
|
180
|
+
nodes.push(h2("del", { key: k }, mdInline(tok.slice(2, -2), k)));
|
|
181
|
+
} else if (tok.startsWith("*")) {
|
|
182
|
+
nodes.push(h2("em", { key: k }, mdInline(tok.slice(1, -1), k)));
|
|
183
|
+
} else if (tok.startsWith("<")) {
|
|
184
|
+
const u = tok.slice(1, -1);
|
|
185
|
+
nodes.push(h2(ExtLink2, { key: k, href: u }, u));
|
|
186
|
+
} else {
|
|
187
|
+
nodes.push(h2(ExtLink2, { key: k, href: tok }, tok.length > 72 ? `${tok.slice(0, 69)}\u2026` : tok));
|
|
188
|
+
}
|
|
189
|
+
last = m.index + tok.length;
|
|
190
|
+
}
|
|
191
|
+
if (last < src.length) nodes.push(src.slice(last));
|
|
192
|
+
return nodes;
|
|
193
|
+
}
|
|
194
|
+
function mdBlocks(lines, kb) {
|
|
195
|
+
const out = [];
|
|
196
|
+
let i = 0;
|
|
197
|
+
let n = 0;
|
|
198
|
+
const isFence = (s) => /^\s*```/.test(s);
|
|
199
|
+
const isHeading = (s) => /^#{1,6}\s+/.test(s);
|
|
200
|
+
const isHr = (s) => /^\s*(-{3,}|\*{3,}|_{3,})\s*$/.test(s);
|
|
201
|
+
const isQuote = (s) => /^\s*>/.test(s);
|
|
202
|
+
const isUl = (s) => /^\s*[-*+]\s+/.test(s);
|
|
203
|
+
const isOl = (s) => /^\s*\d+[.)]\s+/.test(s);
|
|
204
|
+
const isTableRow = (s) => s.includes("|") && /^\s*\|/.test(s);
|
|
205
|
+
while (i < lines.length) {
|
|
206
|
+
const line = lines[i];
|
|
207
|
+
if (!line.trim()) {
|
|
208
|
+
i++;
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
const k = `${kb}-b${n++}`;
|
|
212
|
+
if (isFence(line)) {
|
|
213
|
+
const buf2 = [];
|
|
214
|
+
i++;
|
|
215
|
+
while (i < lines.length && !/^\s*```\s*$/.test(lines[i])) buf2.push(lines[i++]);
|
|
216
|
+
i++;
|
|
217
|
+
out.push(h2("pre", { key: k }, h2("code", null, buf2.join("\n"))));
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
if (isHeading(line)) {
|
|
221
|
+
const hm = /^(#{1,6})\s+(.*)$/.exec(line);
|
|
222
|
+
out.push(h2(`h${hm[1].length}`, { key: k }, mdInline(hm[2], k)));
|
|
223
|
+
i++;
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
if (isHr(line)) {
|
|
227
|
+
out.push(h2("hr", { key: k }));
|
|
228
|
+
i++;
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
if (isQuote(line)) {
|
|
232
|
+
const buf2 = [];
|
|
233
|
+
while (i < lines.length && isQuote(lines[i])) buf2.push(lines[i++].replace(/^\s*>\s?/, ""));
|
|
234
|
+
out.push(h2("blockquote", { key: k }, mdBlocks(buf2, k)));
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
if (isUl(line) || isOl(line)) {
|
|
238
|
+
const ordered = isOl(line);
|
|
239
|
+
const re = ordered ? /^\s*\d+[.)]\s+(.*)$/ : /^\s*[-*+]\s+(.*)$/;
|
|
240
|
+
const items = [];
|
|
241
|
+
while (i < lines.length && (ordered ? isOl(lines[i]) : isUl(lines[i]))) {
|
|
242
|
+
items.push(h2("li", { key: `li${items.length}` }, mdInline(re.exec(lines[i])[1], `${k}-${items.length}`)));
|
|
243
|
+
i++;
|
|
244
|
+
}
|
|
245
|
+
out.push(h2(ordered ? "ol" : "ul", { key: k }, items));
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
if (isTableRow(line) && i + 1 < lines.length && lines[i + 1].includes("-") && /^\s*\|?[\s:|-]+\|?\s*$/.test(lines[i + 1])) {
|
|
249
|
+
const cells = (s) => s.trim().replace(/^\|/, "").replace(/\|$/, "").split("|").map((c) => c.trim());
|
|
250
|
+
const head = cells(lines[i]);
|
|
251
|
+
i += 2;
|
|
252
|
+
const rows = [];
|
|
253
|
+
while (i < lines.length && isTableRow(lines[i])) {
|
|
254
|
+
rows.push(cells(lines[i]));
|
|
255
|
+
i++;
|
|
256
|
+
}
|
|
257
|
+
out.push(
|
|
258
|
+
h2(
|
|
259
|
+
"table",
|
|
260
|
+
{ key: k },
|
|
261
|
+
h2("thead", null, h2("tr", null, head.map((c, x) => h2("th", { key: x }, mdInline(c, `${k}h${x}`))))),
|
|
262
|
+
h2("tbody", null, rows.map((r, y) => h2("tr", { key: y }, r.map((c, x) => h2("td", { key: x }, mdInline(c, `${k}${y}x${x}`))))))
|
|
263
|
+
)
|
|
264
|
+
);
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
const buf = [line];
|
|
268
|
+
i++;
|
|
269
|
+
while (i < lines.length && lines[i].trim() && !isFence(lines[i]) && !isHeading(lines[i]) && !isHr(lines[i]) && !isQuote(lines[i]) && !isUl(lines[i]) && !isOl(lines[i])) {
|
|
270
|
+
buf.push(lines[i]);
|
|
271
|
+
i++;
|
|
272
|
+
}
|
|
273
|
+
out.push(h2("p", { key: k }, mdInline(buf.join(" "), k)));
|
|
274
|
+
}
|
|
275
|
+
return out;
|
|
276
|
+
}
|
|
277
|
+
function renderMarkdown2(src) {
|
|
278
|
+
return mdBlocks(String(src || "").replace(/\r\n?/g, "\n").split("\n"), "md");
|
|
279
|
+
}
|
|
280
|
+
return { ExtLink: ExtLink2, MdImg: MdImg2, renderMarkdown: renderMarkdown2 };
|
|
281
|
+
}
|
|
282
|
+
var init_markdown = __esm({
|
|
283
|
+
"src/client/markdown.js"() {
|
|
284
|
+
"use strict";
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
// src/client/installed-view.js
|
|
289
|
+
var installed_view_exports = {};
|
|
290
|
+
__export(installed_view_exports, {
|
|
291
|
+
installedViewModel: () => installedViewModel,
|
|
292
|
+
registrySourceKey: () => registrySourceKey
|
|
293
|
+
});
|
|
294
|
+
function uninstallGuardKeys(it) {
|
|
295
|
+
if (it.source === "link") {
|
|
296
|
+
return { confirmKey: "confirm.unlink", warnKey: "warn.unlink", warnParams: { path: it.path } };
|
|
297
|
+
}
|
|
298
|
+
if (it.source === "file") {
|
|
299
|
+
return { confirmKey: "confirm.core", warnKey: "warn.core", warnParams: {} };
|
|
300
|
+
}
|
|
301
|
+
return { confirmKey: "confirm.uninstall", warnKey: null, warnParams: {} };
|
|
302
|
+
}
|
|
303
|
+
function installedViewModel(it) {
|
|
304
|
+
return {
|
|
305
|
+
githubRepo: it.registryGithub || it.githubRepo || (it.spec.startsWith("github:") ? it.spec.slice(7).split("#")[0] : null),
|
|
306
|
+
sourceLabelKey: { npm: "src.npm", github: "src.github", link: "src.link", file: "src.file", unknown: "src.unknown" }[it.source] || null,
|
|
307
|
+
guard: uninstallGuardKeys(it),
|
|
308
|
+
latestLabel: it.latestTag || (it.latestVersion ? `v${it.latestVersion}` : ""),
|
|
309
|
+
latestLabelDetail: it.latestTag || (it.latestVersion ? `v${it.latestVersion}` : "\u2014")
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
function registrySourceKey(data) {
|
|
313
|
+
if (!data) return null;
|
|
314
|
+
const map = {
|
|
315
|
+
"default-raw": "src.default.raw",
|
|
316
|
+
"default-jsdelivr": "src.default.jsdelivr",
|
|
317
|
+
"default-cache": "src.default.cache",
|
|
318
|
+
bundled: "src.bundled",
|
|
319
|
+
"custom-url": "src.custom.url",
|
|
320
|
+
"custom-file": "src.custom.file",
|
|
321
|
+
"custom-cache": "src.custom.cache",
|
|
322
|
+
"custom-unavailable": "src.custom.unavailable",
|
|
323
|
+
// 旧字段兼容
|
|
324
|
+
override: "src.override",
|
|
325
|
+
jsdelivr: "src.jsdelivr",
|
|
326
|
+
raw: "src.raw",
|
|
327
|
+
cache: "src.cache"
|
|
328
|
+
};
|
|
329
|
+
return map[data.source] || data.source;
|
|
330
|
+
}
|
|
331
|
+
var init_installed_view = __esm({
|
|
332
|
+
"src/client/installed-view.js"() {
|
|
333
|
+
"use strict";
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
// src/client/tool-view.js
|
|
338
|
+
var tool_view_exports = {};
|
|
339
|
+
__export(tool_view_exports, {
|
|
340
|
+
parseToolArgs: () => parseToolArgs,
|
|
341
|
+
pickPayload: () => pickPayload
|
|
342
|
+
});
|
|
343
|
+
function pickPayload(props) {
|
|
344
|
+
const found = [];
|
|
345
|
+
const visit = (node, depth) => {
|
|
346
|
+
if (!node || depth > 6) return;
|
|
347
|
+
if (typeof node === "string") {
|
|
348
|
+
const t = node.trim();
|
|
349
|
+
if ((t.startsWith("{") || t.startsWith("[")) && t.length > 8) {
|
|
350
|
+
try {
|
|
351
|
+
visit(JSON.parse(t), depth + 1);
|
|
352
|
+
} catch {
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
if (typeof node !== "object") return;
|
|
358
|
+
if (Array.isArray(node)) {
|
|
359
|
+
for (const x of node) visit(x, depth + 1);
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
if (Array.isArray(node.items)) found.push(node);
|
|
363
|
+
for (const key of ["block", "meta", "result", "resultView", "view", "data", "value", "payload", "content", "message"]) {
|
|
364
|
+
if (node[key] != null) visit(node[key], depth + 1);
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
visit(props, 0);
|
|
368
|
+
return found.find((x) => x && Array.isArray(x.items)) || null;
|
|
369
|
+
}
|
|
370
|
+
function parseToolArgs(props) {
|
|
371
|
+
const block = props?.block;
|
|
372
|
+
const raw = (block && "kind" in block ? block.call?.argsRaw : block?.argsRaw) || "";
|
|
373
|
+
if (!raw || typeof raw !== "string") return {};
|
|
374
|
+
try {
|
|
375
|
+
return JSON.parse(raw);
|
|
376
|
+
} catch {
|
|
377
|
+
return {};
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
var init_tool_view = __esm({
|
|
381
|
+
"src/client/tool-view.js"() {
|
|
382
|
+
"use strict";
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
// src/client/restart-wait.js
|
|
387
|
+
var restart_wait_exports = {};
|
|
388
|
+
__export(restart_wait_exports, {
|
|
389
|
+
RESTART_DEADLINE_MS: () => RESTART_DEADLINE_MS,
|
|
390
|
+
RESTART_POLL_MS: () => RESTART_POLL_MS,
|
|
391
|
+
isAmbiguousRestartRequestError: () => isAmbiguousRestartRequestError,
|
|
392
|
+
nextRestartWait: () => nextRestartWait
|
|
393
|
+
});
|
|
394
|
+
function nextRestartWait({ phase, now = 0, deadlineAt = Infinity, bootChanged = false }) {
|
|
395
|
+
if (phase === "before-ping") {
|
|
396
|
+
return now > deadlineAt ? "timeout" : "continue";
|
|
397
|
+
}
|
|
398
|
+
return bootChanged ? "done" : "continue";
|
|
399
|
+
}
|
|
400
|
+
function isAmbiguousRestartRequestError(error) {
|
|
401
|
+
const name = error && typeof error === "object" ? error.name : "";
|
|
402
|
+
return name === "TypeError" || name === "AbortError" || name === "NetworkError";
|
|
403
|
+
}
|
|
404
|
+
var RESTART_POLL_MS, RESTART_DEADLINE_MS;
|
|
405
|
+
var init_restart_wait = __esm({
|
|
406
|
+
"src/client/restart-wait.js"() {
|
|
407
|
+
"use strict";
|
|
408
|
+
RESTART_POLL_MS = 2e3;
|
|
409
|
+
RESTART_DEADLINE_MS = 9e4;
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
|
|
115
413
|
// src/client/main.jsx
|
|
116
414
|
var React = require("react");
|
|
117
415
|
var rd = require("react-dom");
|
|
@@ -120,6 +418,11 @@ var { useState, useEffect, useCallback, useMemo, useRef } = React;
|
|
|
120
418
|
var PLUGIN_ID = "dsh-m";
|
|
121
419
|
var API = "/dshm";
|
|
122
420
|
var { MARKET_PAGE_SIZE: MARKET_PAGE_SIZE2, normalizeMarketQuery: normalizeMarketQuery2, resetPageOnFilterChange: resetPageOnFilterChange2, normalizeMarketResponse: normalizeMarketResponse2, registryNotice: registryNotice2 } = (init_market_state(), __toCommonJS(market_state_exports));
|
|
421
|
+
var { createMarkdown: createMarkdown2 } = (init_markdown(), __toCommonJS(markdown_exports));
|
|
422
|
+
var { ExtLink, MdImg, renderMarkdown } = createMarkdown2(h);
|
|
423
|
+
var { installedViewModel: installedViewModel2, registrySourceKey: registrySourceKey2 } = (init_installed_view(), __toCommonJS(installed_view_exports));
|
|
424
|
+
var { pickPayload: pickPayload2, parseToolArgs: parseToolArgs2 } = (init_tool_view(), __toCommonJS(tool_view_exports));
|
|
425
|
+
var { RESTART_POLL_MS: RESTART_POLL_MS2, RESTART_DEADLINE_MS: RESTART_DEADLINE_MS2, nextRestartWait: nextRestartWait2, isAmbiguousRestartRequestError: isAmbiguousRestartRequestError2 } = (init_restart_wait(), __toCommonJS(restart_wait_exports));
|
|
123
426
|
var ZH = {
|
|
124
427
|
"market.title": "\u63D2\u4EF6\u5E02\u573A",
|
|
125
428
|
"tab.market": "\u5E02\u573A",
|
|
@@ -269,7 +572,7 @@ var ZH = {
|
|
|
269
572
|
"restart.now": "\u26A1 \u4E00\u952E\u91CD\u542F",
|
|
270
573
|
"restart.failed": "\u91CD\u542F\u5931\u8D25\uFF1A{err}",
|
|
271
574
|
"restart.timeout": "\u91CD\u542F\u8D85\u65F6\uFF0C\u8BF7\u624B\u52A8\u68C0\u67E5 dsh web \u670D\u52A1\u72B6\u6001",
|
|
272
|
-
"restart.hint.done": "\u5DF2\u8BF7\u6C42\u91CD\u542F DSH web\uFF08via {via}\uFF09\u3002\u670D\u52A1\
|
|
575
|
+
"restart.hint.done": "\u5DF2\u8BF7\u6C42\u91CD\u542F DSH web\uFF08via {via}\uFF09\u3002\u670D\u52A1\u6062\u590D\u540E DSH Web \u4F1A\u5728\u540E\u53F0\u81EA\u52A8\u91CD\u8FDE\u3002",
|
|
273
576
|
"phase.resolving": "\u89E3\u6790\u4F9D\u8D56",
|
|
274
577
|
"phase.downloading": "\u4E0B\u8F7D",
|
|
275
578
|
"phase.linking": "\u94FE\u63A5\u5B89\u88C5",
|
|
@@ -288,8 +591,6 @@ var ZH = {
|
|
|
288
591
|
};
|
|
289
592
|
var EN = {
|
|
290
593
|
"market.title": "Plugin Marketplace",
|
|
291
|
-
"title.panel": "Plugin Marketplace",
|
|
292
|
-
"title.full": "DeepSeek Harness Plugin Marketplace",
|
|
293
594
|
"tab.market": "Market",
|
|
294
595
|
"tab.installed": "Installed",
|
|
295
596
|
"tab.settings": "Settings",
|
|
@@ -437,7 +738,7 @@ var EN = {
|
|
|
437
738
|
"restart.now": "\u26A1 Restart",
|
|
438
739
|
"restart.failed": "Restart failed: {err}",
|
|
439
740
|
"restart.timeout": "Restart timed out \u2014 check the dsh web service manually",
|
|
440
|
-
"restart.hint.done": "Restart requested (via {via}).
|
|
741
|
+
"restart.hint.done": "Restart requested (via {via}). DSH Web will reconnect in the background after the service returns.",
|
|
441
742
|
"phase.resolving": "Resolving",
|
|
442
743
|
"phase.downloading": "Downloading",
|
|
443
744
|
"phase.linking": "Linking",
|
|
@@ -664,164 +965,6 @@ function Icon({ entry }) {
|
|
|
664
965
|
function Spin() {
|
|
665
966
|
return h("span", { className: "dshm-spin" });
|
|
666
967
|
}
|
|
667
|
-
function safeUrl(u) {
|
|
668
|
-
const t = String(u || "").trim();
|
|
669
|
-
if (/^(https?:\/\/|mailto:)/i.test(t)) return t;
|
|
670
|
-
if (/^[/#]/.test(t)) return t;
|
|
671
|
-
return "#";
|
|
672
|
-
}
|
|
673
|
-
function ExtLink({ href, className, children }) {
|
|
674
|
-
return h(
|
|
675
|
-
"a",
|
|
676
|
-
{
|
|
677
|
-
className: className || "dshm-md-a",
|
|
678
|
-
href: safeUrl(href),
|
|
679
|
-
target: "_blank",
|
|
680
|
-
rel: "noopener noreferrer",
|
|
681
|
-
onClick: (e) => e.stopPropagation()
|
|
682
|
-
},
|
|
683
|
-
children
|
|
684
|
-
);
|
|
685
|
-
}
|
|
686
|
-
function MdImg({ src, alt }) {
|
|
687
|
-
return h("img", {
|
|
688
|
-
className: "dshm-md-img",
|
|
689
|
-
src: safeUrl(src),
|
|
690
|
-
alt: alt || "",
|
|
691
|
-
referrerPolicy: "no-referrer",
|
|
692
|
-
onError: (e) => {
|
|
693
|
-
e.currentTarget.style.display = "none";
|
|
694
|
-
}
|
|
695
|
-
});
|
|
696
|
-
}
|
|
697
|
-
function mdInline(text, kb) {
|
|
698
|
-
const re = /(\[!\[[^\]]*\]\([^)]*\)\]\([^)]*\))|(!\[[^\]]*\]\([^)]*\))|(\[[^\]]*\]\([^)]*\))|(`[^`]+`)|(\*\*[^*]+\*\*)|(~~[^~]+~~)|(\*[^*\s][^*]*\*)|(<https?:\/\/[^>\s]+>)|(https?:\/\/[^\s<>()\[\]{}"'「」【】]+[^\s<>()\[\]{}"'「」【】.,;:!?…,。;:!?)】」"')])/g;
|
|
699
|
-
const src = String(text);
|
|
700
|
-
const nodes = [];
|
|
701
|
-
let last = 0;
|
|
702
|
-
let m;
|
|
703
|
-
let i = 0;
|
|
704
|
-
while (m = re.exec(src)) {
|
|
705
|
-
if (m.index > last) nodes.push(src.slice(last, m.index));
|
|
706
|
-
const tok = m[0];
|
|
707
|
-
const k = `${kb}-${i++}`;
|
|
708
|
-
if (tok.startsWith("[![")) {
|
|
709
|
-
const im = /^!\[([^\]]*)\]\(([^)]*)\)/.exec(tok.slice(1));
|
|
710
|
-
const lm = /\]\(([^)]*)\)\s*$/.exec(tok);
|
|
711
|
-
const img = h(MdImg, { src: im && im[2], alt: im && im[1] });
|
|
712
|
-
const href = lm && lm[1];
|
|
713
|
-
nodes.push(href && safeUrl(href) !== "#" ? h(ExtLink, { key: k, href }, img) : h("span", { key: k }, img));
|
|
714
|
-
} else if (tok.startsWith("![") || tok.startsWith("<![")) {
|
|
715
|
-
const im = /^!\[([^\]]*)\]\(([^)]*)\)$/.exec(tok);
|
|
716
|
-
nodes.push(h(MdImg, { key: k, src: im && im[2], alt: im && im[1] }));
|
|
717
|
-
} else if (tok.startsWith("[")) {
|
|
718
|
-
const lm = /^\[([^\]]*)\]\(([^)]*)\)$/.exec(tok);
|
|
719
|
-
nodes.push(h(ExtLink, { key: k, href: lm && lm[2] }, mdInline(lm ? lm[1] : tok, k)));
|
|
720
|
-
} else if (tok.startsWith("`")) {
|
|
721
|
-
nodes.push(h("code", { key: k }, tok.slice(1, -1)));
|
|
722
|
-
} else if (tok.startsWith("**")) {
|
|
723
|
-
nodes.push(h("strong", { key: k }, mdInline(tok.slice(2, -2), k)));
|
|
724
|
-
} else if (tok.startsWith("~~")) {
|
|
725
|
-
nodes.push(h("del", { key: k }, mdInline(tok.slice(2, -2), k)));
|
|
726
|
-
} else if (tok.startsWith("*")) {
|
|
727
|
-
nodes.push(h("em", { key: k }, mdInline(tok.slice(1, -1), k)));
|
|
728
|
-
} else if (tok.startsWith("<")) {
|
|
729
|
-
const u = tok.slice(1, -1);
|
|
730
|
-
nodes.push(h(ExtLink, { key: k, href: u }, u));
|
|
731
|
-
} else {
|
|
732
|
-
nodes.push(h(ExtLink, { key: k, href: tok }, tok.length > 72 ? `${tok.slice(0, 69)}\u2026` : tok));
|
|
733
|
-
}
|
|
734
|
-
last = m.index + tok.length;
|
|
735
|
-
}
|
|
736
|
-
if (last < src.length) nodes.push(src.slice(last));
|
|
737
|
-
return nodes;
|
|
738
|
-
}
|
|
739
|
-
function mdBlocks(lines, kb) {
|
|
740
|
-
const out = [];
|
|
741
|
-
let i = 0;
|
|
742
|
-
let n = 0;
|
|
743
|
-
const isFence = (s) => /^\s*```/.test(s);
|
|
744
|
-
const isHeading = (s) => /^#{1,6}\s+/.test(s);
|
|
745
|
-
const isHr = (s) => /^\s*(-{3,}|\*{3,}|_{3,})\s*$/.test(s);
|
|
746
|
-
const isQuote = (s) => /^\s*>/.test(s);
|
|
747
|
-
const isUl = (s) => /^\s*[-*+]\s+/.test(s);
|
|
748
|
-
const isOl = (s) => /^\s*\d+[.)]\s+/.test(s);
|
|
749
|
-
const isTableRow = (s) => s.includes("|") && /^\s*\|/.test(s);
|
|
750
|
-
while (i < lines.length) {
|
|
751
|
-
const line = lines[i];
|
|
752
|
-
if (!line.trim()) {
|
|
753
|
-
i++;
|
|
754
|
-
continue;
|
|
755
|
-
}
|
|
756
|
-
const k = `${kb}-b${n++}`;
|
|
757
|
-
if (isFence(line)) {
|
|
758
|
-
const buf2 = [];
|
|
759
|
-
i++;
|
|
760
|
-
while (i < lines.length && !/^\s*```\s*$/.test(lines[i])) buf2.push(lines[i++]);
|
|
761
|
-
i++;
|
|
762
|
-
out.push(h("pre", { key: k }, h("code", null, buf2.join("\n"))));
|
|
763
|
-
continue;
|
|
764
|
-
}
|
|
765
|
-
if (isHeading(line)) {
|
|
766
|
-
const hm = /^(#{1,6})\s+(.*)$/.exec(line);
|
|
767
|
-
out.push(h(`h${hm[1].length}`, { key: k }, mdInline(hm[2], k)));
|
|
768
|
-
i++;
|
|
769
|
-
continue;
|
|
770
|
-
}
|
|
771
|
-
if (isHr(line)) {
|
|
772
|
-
out.push(h("hr", { key: k }));
|
|
773
|
-
i++;
|
|
774
|
-
continue;
|
|
775
|
-
}
|
|
776
|
-
if (isQuote(line)) {
|
|
777
|
-
const buf2 = [];
|
|
778
|
-
while (i < lines.length && isQuote(lines[i])) buf2.push(lines[i++].replace(/^\s*>\s?/, ""));
|
|
779
|
-
out.push(h("blockquote", { key: k }, mdBlocks(buf2, k)));
|
|
780
|
-
continue;
|
|
781
|
-
}
|
|
782
|
-
if (isUl(line) || isOl(line)) {
|
|
783
|
-
const ordered = isOl(line);
|
|
784
|
-
const re = ordered ? /^\s*\d+[.)]\s+(.*)$/ : /^\s*[-*+]\s+(.*)$/;
|
|
785
|
-
const items = [];
|
|
786
|
-
while (i < lines.length && (ordered ? isOl(lines[i]) : isUl(lines[i]))) {
|
|
787
|
-
items.push(h("li", { key: `li${items.length}` }, mdInline(re.exec(lines[i])[1], `${k}-${items.length}`)));
|
|
788
|
-
i++;
|
|
789
|
-
}
|
|
790
|
-
out.push(h(ordered ? "ol" : "ul", { key: k }, items));
|
|
791
|
-
continue;
|
|
792
|
-
}
|
|
793
|
-
if (isTableRow(line) && i + 1 < lines.length && lines[i + 1].includes("-") && /^\s*\|?[\s:|-]+\|?\s*$/.test(lines[i + 1])) {
|
|
794
|
-
const cells = (s) => s.trim().replace(/^\|/, "").replace(/\|$/, "").split("|").map((c) => c.trim());
|
|
795
|
-
const head = cells(lines[i]);
|
|
796
|
-
i += 2;
|
|
797
|
-
const rows = [];
|
|
798
|
-
while (i < lines.length && isTableRow(lines[i])) {
|
|
799
|
-
rows.push(cells(lines[i]));
|
|
800
|
-
i++;
|
|
801
|
-
}
|
|
802
|
-
out.push(
|
|
803
|
-
h(
|
|
804
|
-
"table",
|
|
805
|
-
{ key: k },
|
|
806
|
-
h("thead", null, h("tr", null, head.map((c, x) => h("th", { key: x }, mdInline(c, `${k}h${x}`))))),
|
|
807
|
-
h("tbody", null, rows.map((r, y) => h("tr", { key: y }, r.map((c, x) => h("td", { key: x }, mdInline(c, `${k}${y}x${x}`))))))
|
|
808
|
-
)
|
|
809
|
-
);
|
|
810
|
-
continue;
|
|
811
|
-
}
|
|
812
|
-
const buf = [line];
|
|
813
|
-
i++;
|
|
814
|
-
while (i < lines.length && lines[i].trim() && !isFence(lines[i]) && !isHeading(lines[i]) && !isHr(lines[i]) && !isQuote(lines[i]) && !isUl(lines[i]) && !isOl(lines[i])) {
|
|
815
|
-
buf.push(lines[i]);
|
|
816
|
-
i++;
|
|
817
|
-
}
|
|
818
|
-
out.push(h("p", { key: k }, mdInline(buf.join(" "), k)));
|
|
819
|
-
}
|
|
820
|
-
return out;
|
|
821
|
-
}
|
|
822
|
-
function renderMarkdown(src) {
|
|
823
|
-
return mdBlocks(String(src || "").replace(/\r\n?/g, "\n").split("\n"), "md");
|
|
824
|
-
}
|
|
825
968
|
function officialLinks({ npm, github, homepage }) {
|
|
826
969
|
const links = [];
|
|
827
970
|
if (github) links.push(["GitHub", `https://github.com/${github}`]);
|
|
@@ -872,17 +1015,25 @@ function RestartBanner({ note, onDone }) {
|
|
|
872
1015
|
setPhase("restarting");
|
|
873
1016
|
try {
|
|
874
1017
|
const ping0 = await api("ping");
|
|
875
|
-
|
|
1018
|
+
try {
|
|
1019
|
+
await api("restart");
|
|
1020
|
+
} catch (requestError) {
|
|
1021
|
+
if (!isAmbiguousRestartRequestError2(requestError)) throw requestError;
|
|
1022
|
+
}
|
|
876
1023
|
setPhase("waiting");
|
|
877
|
-
const
|
|
1024
|
+
const deadlineAt = Date.now() + RESTART_DEADLINE_MS2;
|
|
878
1025
|
for (; ; ) {
|
|
879
|
-
await new Promise((r) => setTimeout(r,
|
|
880
|
-
if (Date.now()
|
|
1026
|
+
await new Promise((r) => setTimeout(r, RESTART_POLL_MS2));
|
|
1027
|
+
if (nextRestartWait2({ phase: "before-ping", now: Date.now(), deadlineAt }) === "timeout") {
|
|
1028
|
+
throw new Error(lookup("restart.timeout"));
|
|
1029
|
+
}
|
|
1030
|
+
let bootChanged = false;
|
|
881
1031
|
try {
|
|
882
1032
|
const ping = await api("ping");
|
|
883
|
-
|
|
1033
|
+
bootChanged = ping.boot !== ping0.boot;
|
|
884
1034
|
} catch {
|
|
885
1035
|
}
|
|
1036
|
+
if (nextRestartWait2({ phase: "after-ping", bootChanged }) === "done") break;
|
|
886
1037
|
}
|
|
887
1038
|
setPhase("idle");
|
|
888
1039
|
onDone(true);
|
|
@@ -1091,18 +1242,6 @@ function ReadmeBlock({ pkg }) {
|
|
|
1091
1242
|
state.truncated ? h("div", { className: "dshm-md-note" }, lookup("readme.truncated")) : null
|
|
1092
1243
|
);
|
|
1093
1244
|
}
|
|
1094
|
-
function uninstallGuard(it) {
|
|
1095
|
-
if (it.source === "link") {
|
|
1096
|
-
return {
|
|
1097
|
-
confirm: lookup("confirm.unlink"),
|
|
1098
|
-
warn: lookup("warn.unlink", { path: it.path })
|
|
1099
|
-
};
|
|
1100
|
-
}
|
|
1101
|
-
if (it.source === "file") {
|
|
1102
|
-
return { confirm: lookup("confirm.core"), warn: lookup("warn.core") };
|
|
1103
|
-
}
|
|
1104
|
-
return { confirm: lookup("confirm.uninstall"), warn: null };
|
|
1105
|
-
}
|
|
1106
1245
|
function InstalledTab({ notify, installed }) {
|
|
1107
1246
|
const { loading, data, error, reload } = installed;
|
|
1108
1247
|
const [openPkg, setOpenPkg] = useState(null);
|
|
@@ -1158,33 +1297,33 @@ function InstalledTab({ notify, installed }) {
|
|
|
1158
1297
|
"div",
|
|
1159
1298
|
{ className: "dshm-cards" },
|
|
1160
1299
|
items.map((it) => {
|
|
1161
|
-
const
|
|
1300
|
+
const vm = installedViewModel2(it);
|
|
1162
1301
|
return Card({
|
|
1163
1302
|
key: it.pkg,
|
|
1164
|
-
icon: h(Icon, { entry: { name: it.name, github:
|
|
1303
|
+
icon: h(Icon, { entry: { name: it.name, github: vm.githubRepo, icon: null } }),
|
|
1165
1304
|
name: it.name,
|
|
1166
1305
|
badges: [
|
|
1167
|
-
it.outdated ? h("span", { className: "dshm-badge warn", key: "u" }, `\u2B06 ${
|
|
1306
|
+
it.outdated ? h("span", { className: "dshm-badge warn", key: "u" }, `\u2B06 ${vm.latestLabel}`.trim()) : null,
|
|
1168
1307
|
it.registryId ? h("span", { className: "dshm-badge", key: "r" }, lookup("badge.market")) : h("span", { className: "dshm-badge info", key: "r" }, lookup("badge.nonmarket"))
|
|
1169
1308
|
],
|
|
1170
1309
|
desc: it.description || "\uFF08\u65E0\u63CF\u8FF0\uFF09",
|
|
1171
1310
|
sub: [
|
|
1172
1311
|
`v${it.version || "?"}`,
|
|
1173
|
-
|
|
1312
|
+
vm.sourceLabelKey ? lookup(vm.sourceLabelKey) : it.source
|
|
1174
1313
|
].join(" \xB7 "),
|
|
1175
1314
|
links: h(LinksRow, {
|
|
1176
1315
|
npm: it.source === "npm" ? it.pkg : null,
|
|
1177
|
-
github:
|
|
1316
|
+
github: vm.githubRepo
|
|
1178
1317
|
}),
|
|
1179
1318
|
open: openPkg === it.pkg,
|
|
1180
1319
|
onToggle: () => setOpenPkg(openPkg === it.pkg ? null : it.pkg),
|
|
1181
1320
|
detail: readmePkg === it.pkg ? h(ReadmeBlock, { pkg: it.pkg }) : DetailRows([
|
|
1182
1321
|
[lookup("detail.pkg"), it.pkg],
|
|
1183
1322
|
[lookup("detail.spec"), it.spec],
|
|
1184
|
-
[lookup("detail.latest"),
|
|
1323
|
+
[lookup("detail.latest"), vm.latestLabelDetail],
|
|
1185
1324
|
[lookup("detail.listed"), it.registryId || lookup("detail.listed.no")],
|
|
1186
1325
|
[lookup("detail.path"), it.path],
|
|
1187
|
-
guard.
|
|
1326
|
+
vm.guard.warnKey ? [lookup("detail.note"), lookup(vm.guard.warnKey, vm.guard.warnParams)] : null
|
|
1188
1327
|
]),
|
|
1189
1328
|
actions: [
|
|
1190
1329
|
h("button", {
|
|
@@ -1211,7 +1350,7 @@ function InstalledTab({ notify, installed }) {
|
|
|
1211
1350
|
h(TwoStepButton, {
|
|
1212
1351
|
key: "un",
|
|
1213
1352
|
label: lookup("action.uninstall"),
|
|
1214
|
-
confirmLabel: guard.
|
|
1353
|
+
confirmLabel: lookup(vm.guard.confirmKey),
|
|
1215
1354
|
className: "dshm-btn sm",
|
|
1216
1355
|
disabled: busyPkg === it.pkg,
|
|
1217
1356
|
onConfirm: () => doUninstall(it)
|
|
@@ -1223,23 +1362,8 @@ function InstalledTab({ notify, installed }) {
|
|
|
1223
1362
|
);
|
|
1224
1363
|
}
|
|
1225
1364
|
function regSourceLabel(data) {
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
"default-raw": "src.default.raw",
|
|
1229
|
-
"default-jsdelivr": "src.default.jsdelivr",
|
|
1230
|
-
"default-cache": "src.default.cache",
|
|
1231
|
-
bundled: "src.bundled",
|
|
1232
|
-
"custom-url": "src.custom.url",
|
|
1233
|
-
"custom-file": "src.custom.file",
|
|
1234
|
-
"custom-cache": "src.custom.cache",
|
|
1235
|
-
"custom-unavailable": "src.custom.unavailable",
|
|
1236
|
-
// 旧字段兼容
|
|
1237
|
-
override: "src.override",
|
|
1238
|
-
jsdelivr: "src.jsdelivr",
|
|
1239
|
-
raw: "src.raw",
|
|
1240
|
-
cache: "src.cache"
|
|
1241
|
-
};
|
|
1242
|
-
return lookup(map[data.source] || data.source);
|
|
1365
|
+
const key = registrySourceKey2(data);
|
|
1366
|
+
return key === null ? "\u2014" : lookup(key);
|
|
1243
1367
|
}
|
|
1244
1368
|
function configStatusLabel(status) {
|
|
1245
1369
|
return lookup(`settings.status.${status || "loading"}` || "settings.status.loading");
|
|
@@ -1646,43 +1770,6 @@ function registerSlot(slots, options, component) {
|
|
|
1646
1770
|
if (next.key == null && next.id != null) next.key = next.id;
|
|
1647
1771
|
return slots.register(next, component);
|
|
1648
1772
|
}
|
|
1649
|
-
function pickPayload(props) {
|
|
1650
|
-
const found = [];
|
|
1651
|
-
const visit = (node, depth) => {
|
|
1652
|
-
if (!node || depth > 6) return;
|
|
1653
|
-
if (typeof node === "string") {
|
|
1654
|
-
const t = node.trim();
|
|
1655
|
-
if ((t.startsWith("{") || t.startsWith("[")) && t.length > 8) {
|
|
1656
|
-
try {
|
|
1657
|
-
visit(JSON.parse(t), depth + 1);
|
|
1658
|
-
} catch {
|
|
1659
|
-
}
|
|
1660
|
-
}
|
|
1661
|
-
return;
|
|
1662
|
-
}
|
|
1663
|
-
if (typeof node !== "object") return;
|
|
1664
|
-
if (Array.isArray(node)) {
|
|
1665
|
-
for (const x of node) visit(x, depth + 1);
|
|
1666
|
-
return;
|
|
1667
|
-
}
|
|
1668
|
-
if (Array.isArray(node.items)) found.push(node);
|
|
1669
|
-
for (const key of ["block", "meta", "result", "resultView", "view", "data", "value", "payload", "content", "message"]) {
|
|
1670
|
-
if (node[key] != null) visit(node[key], depth + 1);
|
|
1671
|
-
}
|
|
1672
|
-
};
|
|
1673
|
-
visit(props, 0);
|
|
1674
|
-
return found.find((x) => x && Array.isArray(x.items)) || null;
|
|
1675
|
-
}
|
|
1676
|
-
function parseToolArgs(props) {
|
|
1677
|
-
const block = props?.block;
|
|
1678
|
-
const raw = (block && "kind" in block ? block.call?.argsRaw : block?.argsRaw) || "";
|
|
1679
|
-
if (!raw || typeof raw !== "string") return {};
|
|
1680
|
-
try {
|
|
1681
|
-
return JSON.parse(raw);
|
|
1682
|
-
} catch {
|
|
1683
|
-
return {};
|
|
1684
|
-
}
|
|
1685
|
-
}
|
|
1686
1773
|
function ToolCardRow({ it, onInstalled }) {
|
|
1687
1774
|
const [busy, setBusy] = useState(false);
|
|
1688
1775
|
const install = async (e) => {
|
|
@@ -1723,8 +1810,8 @@ function ToolCardRow({ it, onInstalled }) {
|
|
|
1723
1810
|
}
|
|
1724
1811
|
function SearchToolView(props) {
|
|
1725
1812
|
useEffect(() => ensureCss(), []);
|
|
1726
|
-
const payload =
|
|
1727
|
-
const args =
|
|
1813
|
+
const payload = pickPayload2(props);
|
|
1814
|
+
const args = parseToolArgs2(props);
|
|
1728
1815
|
const query = String(payload?.query || args.query || "").trim();
|
|
1729
1816
|
const fromTool = Array.isArray(payload?.items) && payload.items.length ? payload.items : null;
|
|
1730
1817
|
const running = !!(props?.block && !("kind" in props.block));
|
|
@@ -1764,7 +1851,7 @@ function SearchToolView(props) {
|
|
|
1764
1851
|
}
|
|
1765
1852
|
function ListToolView(props) {
|
|
1766
1853
|
useEffect(() => ensureCss(), []);
|
|
1767
|
-
const payload =
|
|
1854
|
+
const payload = pickPayload2(props);
|
|
1768
1855
|
const items = Array.isArray(payload?.items) ? payload.items : [];
|
|
1769
1856
|
if (!items.length) return null;
|
|
1770
1857
|
return h(
|