release: v0.2.2 - cross-platform paths, health version, update-check hardening, clean packaging

This commit is contained in:
Aisland
2026-08-25 02:14:02 +08:00
parent d71ac54bb9
commit b6a96405e8
17 changed files with 369 additions and 305 deletions
-194
View File
@@ -1,194 +0,0 @@
/* node_modules/xterm/css/xterm.css */
.xterm {
cursor: text;
position: relative;
user-select: none;
-ms-user-select: none;
-webkit-user-select: none;
}
.xterm.focus,
.xterm:focus {
outline: none;
}
.xterm .xterm-helpers {
position: absolute;
top: 0;
z-index: 5;
}
.xterm .xterm-helper-textarea {
padding: 0;
border: 0;
margin: 0;
position: absolute;
opacity: 0;
left: -9999em;
top: 0;
width: 0;
height: 0;
z-index: -5;
white-space: nowrap;
overflow: hidden;
resize: none;
}
.xterm .composition-view {
background: #000;
color: #FFF;
display: none;
position: absolute;
white-space: nowrap;
z-index: 1;
}
.xterm .composition-view.active {
display: block;
}
.xterm .xterm-viewport {
background-color: #000;
overflow-y: scroll;
cursor: default;
position: absolute;
right: 0;
left: 0;
top: 0;
bottom: 0;
}
.xterm .xterm-screen {
position: relative;
}
.xterm .xterm-screen canvas {
position: absolute;
left: 0;
top: 0;
}
.xterm .xterm-scroll-area {
visibility: hidden;
}
.xterm-char-measure-element {
display: inline-block;
visibility: hidden;
position: absolute;
top: 0;
left: -9999em;
line-height: normal;
}
.xterm.enable-mouse-events {
cursor: default;
}
.xterm.xterm-cursor-pointer,
.xterm .xterm-cursor-pointer {
cursor: pointer;
}
.xterm.column-select.focus {
cursor: crosshair;
}
.xterm .xterm-accessibility,
.xterm .xterm-message {
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
z-index: 10;
color: transparent;
pointer-events: none;
}
.xterm .live-region {
position: absolute;
left: -9999px;
width: 1px;
height: 1px;
overflow: hidden;
}
.xterm-dim {
opacity: 1 !important;
}
.xterm-underline-1 {
text-decoration: underline;
}
.xterm-underline-2 {
text-decoration: double underline;
}
.xterm-underline-3 {
text-decoration: wavy underline;
}
.xterm-underline-4 {
text-decoration: dotted underline;
}
.xterm-underline-5 {
text-decoration: dashed underline;
}
.xterm-overline {
text-decoration: overline;
}
.xterm-overline.xterm-underline-1 {
text-decoration: overline underline;
}
.xterm-overline.xterm-underline-2 {
text-decoration: overline double underline;
}
.xterm-overline.xterm-underline-3 {
text-decoration: overline wavy underline;
}
.xterm-overline.xterm-underline-4 {
text-decoration: overline dotted underline;
}
.xterm-overline.xterm-underline-5 {
text-decoration: overline dashed underline;
}
.xterm-strikethrough {
text-decoration: line-through;
}
.xterm-screen .xterm-decoration-container .xterm-decoration {
z-index: 6;
position: absolute;
}
.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer {
z-index: 7;
}
.xterm-decoration-overview-ruler {
z-index: 8;
position: absolute;
top: 0;
right: 0;
pointer-events: none;
}
.xterm-decoration-top {
z-index: 2;
position: relative;
}
/*! Bundled license information:
xterm/css/xterm.css:
(**
* Copyright (c) 2014 The xterm.js authors. All rights reserved.
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
* https://github.com/chjj/term.js
* @license MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Originally forked from (with the author's permission):
* Fabrice Bellard's javascript vt100 for jslinux:
* http://bellard.org/jslinux/
* Copyright (c) 2011 Fabrice Bellard
* The original design remains. The terminal itself
* has been extended to include xterm CSI codes, among
* other features.
*)
*/
/*# sourceMappingURL=client.css.map */
+82 -46
View File
@@ -8580,6 +8580,34 @@ var en = {
};
var NS = "worktable";
// src/client/pathutil.ts
function isAbs(p) {
if (/^[A-Za-z]:[\\/]/.test(p)) return true;
if (p.startsWith("\\\\")) return true;
if (p.startsWith("/")) return true;
return false;
}
function joinPath(base2, rel) {
const relTrim = rel.replace(/^[\\/]+/, "").replace(/[\\/]+$/, "");
const sep = base2.includes("\\") ? "\\" : "/";
if (base2 === "/" || base2 === "\\") return base2 + relTrim;
if (/^[A-Za-z]:[\\/]$/.test(base2)) return base2 + relTrim;
const baseTrim = base2.replace(/[\\/]+$/, "");
if (!baseTrim) return relTrim || sep;
return baseTrim + sep + relTrim;
}
function parentPathOf(p) {
const idx = Math.max(p.lastIndexOf("/"), p.lastIndexOf("\\"));
if (idx < 0) return p;
if (idx === 0) return p[0];
if (idx === 2 && /^[A-Za-z]:[\\/]/.test(p)) return p.slice(0, 3);
return p.slice(0, idx);
}
function basenameOf(p) {
const idx = Math.max(p.lastIndexOf("/"), p.lastIndexOf("\\"));
return idx < 0 ? p : p.slice(idx + 1);
}
// src/client/split.tsx
var import_react = require("react");
var import_xterm2 = __toESM(require_xterm(), 1);
@@ -16386,7 +16414,7 @@ var BUILTIN_LABEL_KEYS = {
};
function tabTitleOf(content) {
if (content.kind === "builtin") return T(BUILTIN_LABEL_KEYS[content.type]);
if (content.kind === "file") return basenameOf(content.path);
if (content.kind === "file") return basenameOf2(content.path);
if (content.kind === "iframe" && content.title) return content.title;
try {
const u = new URL(content.url);
@@ -16395,7 +16423,7 @@ function tabTitleOf(content) {
return content.url;
}
}
function basenameOf(p) {
function basenameOf2(p) {
const parts = String(p).replace(/[\\/]+$/, "").split(/[\\/]/);
return parts[parts.length - 1] || String(p);
}
@@ -16423,13 +16451,6 @@ async function postJson(url, body) {
if (!res.ok) throw new Error("HTTP " + res.status);
return res.json();
}
function parentPathOf(p) {
const idx = Math.max(p.lastIndexOf("/"), p.lastIndexOf("\\"));
if (idx <= 0) return p;
let parent = p.slice(0, idx);
if (/^[A-Za-z]:$/.test(parent)) parent += "\\";
return parent;
}
var dragPane = null;
var dragTab = null;
var dropTarget = null;
@@ -17555,10 +17576,10 @@ function FileViewer(props) {
const ext = (props.path.split(".").pop() || "").toLowerCase();
const fileUrl = "/api/worktable/file?path=" + encodeURIComponent(props.path);
if (ext === "pdf") {
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("iframe", { className: "dsh-wt_paneFrame", src: fileUrl, title: basenameOf(props.path) });
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("iframe", { className: "dsh-wt_paneFrame", src: fileUrl, title: basenameOf2(props.path) });
}
if (IMAGE_EXTS.test("." + ext)) {
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dsh-wt_imgView", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: fileUrl, alt: basenameOf(props.path) }) });
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dsh-wt_imgView", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: fileUrl, alt: basenameOf2(props.path) }) });
}
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TextViewer, { path: props.path, fileUrl, isMd: MD_EXTS.test("." + ext) });
}
@@ -18266,7 +18287,7 @@ try {
// src/client/index.tsx
var import_jsx_runtime2 = require("react/jsx-runtime");
var LOCAL_VERSION = false ? "0.2.0" : "0.2.1";
var LOCAL_VERSION = false ? "dev" : "0.2.2";
var UPDATE_REPO = "Aisland-SJL/dsh-worktable";
var UPGRADE_CMD = 'dsh plugin --profile web add "https://github.com/Aisland-SJL/dsh-worktable/releases/latest/download/dsh-worktable.tgz"';
var UPGRADE_AI = "\u5E2E\u6211\u5347\u7EA7 dsh-worktable\uFF1A\u6267\u884C " + UPGRADE_CMD + "\uFF0C\u5B8C\u6210\u540E\u63D0\u9192\u6211\u91CD\u542F dsh web \u5E76\u5237\u65B0\u9875\u9762";
@@ -18889,7 +18910,7 @@ async function promptIntoSession(sessionId, text2) {
}
var KNOWLEDGE_PACK = [
"\u3010\u63D2\u4EF6\u77E5\u8BC6\u5305\xB7\u8BF7\u76F4\u63A5\u91C7\u7528\uFF0C\u4E0D\u8981\u91CD\u65B0\u4FA6\u5BDF\u63D2\u4EF6\u6E90\u7801\u3011",
"- dsh-worktable \u662F\u672C\u673A DeepSeek Harness \u7684\u81EA\u5EFA\u5BB9\u5668\u63D2\u4EF6\uFF08\u4ED3\u5E93 E:\\AI_Workspace\\DeepseekHarness\\Projects\\dsh-worktable\uFF0C\u63D2\u4EF6\u5305\u6839\u76EE\u5F55 01_content/\uFF09\u3002",
"- dsh-worktable \u662F DeepSeek Harness \u7684\u81EA\u5EFA\u5BB9\u5668\u63D2\u4EF6\uFF08\u5DE5\u4F5C\u53F0\uFF1A\u4FA7\u8FB9\u680F\u91CC\u7684\u9879\u76EE\u5E94\u7528\u62BD\u5C49\uFF1B\u4E0D\u4E86\u89E3\u7684\u7EC6\u8282\u53EF\u76F4\u63A5\u5411\u7528\u6237\u63D0\u95EE\uFF09\u3002",
"- \u7A97\u53E3\uFF08\u5185\u5BB9\u7A97\uFF09\u6A21\u578B\uFF1A\u6BCF\u4E2A\u7A97 = \u4E00\u4E2A\u6807\u7B7E\u9875\uFF1B\u672A\u6307\u6D3E\u65F6\u663E\u793A\u9009\u62E9\u5668\uFF08\u6D4F\u89C8\u5668/\u52A8\u753B/\u8D44\u6E90\u7BA1\u7406\u5668/\u7EC8\u7AEF/\u2728\u81EA\u5B9A\u4E49\uFF09\uFF1B",
" \u7A97\u5185\u5BB9\u8FD8\u53EF\u653E iframe \u7F51\u9875\u4E0E\u6587\u4EF6\u9884\u89C8\uFF08.md/.txt/.tsx/.css/.html \u7B49\uFF09\u3002",
"- \u7A97\u53E3\u53EF\u88C5\u8F7D\u7684\u5F62\u5F0F\uFF1AHTML \u5355\u6587\u4EF6\uFF08\u4EA4\u4E92 UI\uFF0C\u653E\u9879\u76EE\u6587\u4EF6\u5939\u540E\u5728\u8D44\u6E90\u7BA1\u7406\u5668\u70B9\u51FB\u6E32\u67D3\uFF09\u3001\u7F51\u9875 URL\u3001",
@@ -18936,7 +18957,7 @@ async function createCustomSession(projectId, projectName, requirement, group, w
const parent = g.parent.replace(/[\\/]+$/, "");
const name = g.name.replace(/^[\\/]+/, "").replace(/[\\/]+$/, "");
if (!parent || !name) throw new Error("invalid group path");
const full = parent + "\\" + name;
const full = joinPath(parent, name);
try {
await ws.createDirectory?.(parent, name);
} catch {
@@ -19057,10 +19078,10 @@ function buildMountContent(folder, d) {
const p = String(d?.path ?? "").trim();
if (!p) return null;
if (d?.kind === "url") return { kind: "iframe", url: p, title: p };
const full = p.indexOf(":") >= 0 ? p : folder + "\\" + p.replace(/^[\\/]+/, "");
const full = isAbs(p) ? p : joinPath(folder, p);
if (d?.kind === "file") return { kind: "file", path: full };
const dir = full.replace(/[\\/][^\\/]*$/, "");
const name = full.split(/[\\/]/).pop() ?? full;
const dir = parentPathOf(full);
const name = basenameOf(full);
return { kind: "iframe", url: "/api/worktable/site/" + encodeURIComponent(dir) + "/" + encodeURIComponent(name), title: name };
}
var notifyStateSeenRef = { current: {} };
@@ -19189,35 +19210,51 @@ function WorktableSection(props) {
const [updateCheckOn, setUpdateCheckOn] = (0, import_react2.useState)(() => localStorage.getItem("dsh.worktable.updateCheck.v1") !== "0");
const [updateCopied, setUpdateCopied] = (0, import_react2.useState)(false);
const [updateStatus, setUpdateStatus] = (0, import_react2.useState)("idle");
const updateCheckingRef = (0, import_react2.useRef)(false);
const updateAliveRef = (0, import_react2.useRef)(true);
(0, import_react2.useEffect)(() => () => {
updateAliveRef.current = false;
}, []);
const checkUpdates = (0, import_react2.useCallback)(async (force = false) => {
if (updateCheckingRef.current) return;
const last = Number(localStorage.getItem("dsh.worktable.lastUpdateCheck.v1") ?? "0");
if (!force && Date.now() - last < 24 * 3600 * 1e3) return;
updateCheckingRef.current = true;
setUpdateStatus("checking");
let d = null;
for (let attempt = 0; attempt < 3 && !d; attempt++) {
try {
const r = await fetch("https://api.github.com/repos/" + UPDATE_REPO + "/releases/latest", { headers: { Accept: "application/vnd.github+json" }, cache: "no-store" });
if (r.ok) d = await r.json();
else if (r.status === 403 || r.status === 404) break;
} catch {
try {
let d = null;
for (let attempt = 0; attempt < 3 && !d && updateAliveRef.current; attempt++) {
const ctrl = new AbortController();
const timer = setTimeout(() => ctrl.abort(), 8e3);
try {
const r = await fetch("https://api.github.com/repos/" + UPDATE_REPO + "/releases/latest", { headers: { Accept: "application/vnd.github+json" }, cache: "no-store", signal: ctrl.signal });
if (r.ok) d = await r.json();
else if (r.status === 403 || r.status === 404) break;
} catch {
} finally {
clearTimeout(timer);
}
}
}
if (!d) {
setUpdateStatus("failed");
return;
}
localStorage.setItem("dsh.worktable.lastUpdateCheck.v1", String(Date.now()));
const tag = (d.tag_name ?? "").replace(/^v/, "");
if (!tag || cmpVer(tag, LOCAL_VERSION) <= 0) {
if (!updateAliveRef.current) return;
if (!d) {
setUpdateStatus("failed");
return;
}
localStorage.setItem("dsh.worktable.lastUpdateCheck.v1", String(Date.now()));
const tag = (d.tag_name ?? "").replace(/^v/, "");
if (!tag || cmpVer(tag, LOCAL_VERSION) <= 0) {
setUpdateStatus("uptodate");
return;
}
if ((localStorage.getItem("dsh.worktable.skipVersion.v1") ?? "") === tag) {
setUpdateStatus("uptodate");
return;
}
setUpdateInfo({ latest: tag, notes: (d.body ?? "").slice(0, 800), url: d.html_url ?? "" });
setUpdateStatus("uptodate");
return;
} finally {
updateCheckingRef.current = false;
}
if ((localStorage.getItem("dsh.worktable.skipVersion.v1") ?? "") === tag) {
setUpdateStatus("uptodate");
return;
}
setUpdateInfo({ latest: tag, notes: (d.body ?? "").slice(0, 800), url: d.html_url ?? "" });
setUpdateStatus("uptodate");
}, []);
(0, import_react2.useEffect)(() => {
if (updateCheckOn) void checkUpdates();
@@ -19674,7 +19711,7 @@ function WorktableSection(props) {
return [
"\u3010\u4E3A dsh-worktable\uFF08\u5DE5\u4F5C\u53F0\uFF09\u63D2\u4EF6\u589E\u52A0\u4E00\u4E2A\u65B0\u7684\u5E03\u5C40\u9884\u8BBE\u3011",
"",
"\u80CC\u666F\uFF1Adsh-worktable \u662F DeepSeek Harness \u7684\u81EA\u5EFA\u5BB9\u5668\u63D2\u4EF6\uFF08\u672C\u673A\u4ED3\u5E93 dsh-worktable\uFF0C\u63D2\u4EF6\u5305\u6839\u76EE\u5F55 01_content/\uFF09\u3002",
"\u80CC\u666F\uFF1Adsh-worktable \u662F DeepSeek Harness \u7684\u81EA\u5EFA\u5BB9\u5668\u63D2\u4EF6\uFF08\u672C\u673A\u4ED3\u5E93 dsh-worktable\uFF1B\u4E0D\u4E86\u89E3\u7684\u7EC6\u8282\u53EF\u76F4\u63A5\u5411\u7528\u6237\u63D0\u95EE\uFF09\u3002",
"\u4FA7\u8FB9\u680F\u300C\u5DE5\u4F5C\u53F0\u300D\u533A\u5757\u7BA1\u7406\u9879\u76EE\uFF0C\u6BCF\u4E2A\u9879\u76EE\u6253\u5F00\u540E\u662F\u4E00\u4E2A\u5E73\u94FA\u5DE5\u4F5C\u533A\uFF08\u82E5\u5E72\u5185\u5BB9\u7A97 + \u53F3\u4FA7\u5BF9\u8BDD\u7A97\uFF09\u3002",
"\u5E03\u5C40\u9884\u8BBE\u5B9A\u4E49\u5728 01_content/src/client/index.tsx \u7684 PRESET_DEFS \u6570\u7EC4\uFF0C\u9009\u62E9\u5668\u7F29\u7565\u56FE\u5728 presetThumb() \u51FD\u6570\u3002",
"",
@@ -19804,13 +19841,13 @@ function WorktableSection(props) {
const ws = b.workspaces;
const parent = consoleParent.replace(/[\\/]+$/, "");
const name = consoleName.replace(/^[\\/]+/, "").replace(/[\\/]+$/, "");
const full = parent + "\\" + name;
const full = joinPath(parent, name);
try {
await ws?.createDirectory?.(parent, name);
} catch {
}
try {
const r = await fetch("/api/worktable/mkdir", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ parent, name }) });
const r = await fetch("/api/worktable/mkdir", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ path: full }) });
const d = await r.json();
if (!r.ok || !d?.ok) throw new Error(d?.error ?? "mkdir failed");
} catch {
@@ -19926,7 +19963,7 @@ function WorktableSection(props) {
try {
let raw = rawManifest;
if (raw == null) {
const r = await fetch("/api/worktable/file?path=" + encodeURIComponent(folder + "\\widget-result.json"), { cache: "no-store" });
const r = await fetch("/api/worktable/file?path=" + encodeURIComponent(joinPath(folder, "widget-result.json")), { cache: "no-store" });
if (!r.ok) return;
raw = (await r.text()).trim();
}
@@ -19997,7 +20034,7 @@ function WorktableSection(props) {
const folder = folders[pid];
if (!folder) continue;
try {
const r = await fetch("/api/worktable/file?path=" + encodeURIComponent(folder + "\\widget-result.json"), { cache: "no-store" });
const r = await fetch("/api/worktable/file?path=" + encodeURIComponent(joinPath(folder, "widget-result.json")), { cache: "no-store" });
if (!r.ok) continue;
const raw = (await r.text()).trim();
if (!raw) continue;
@@ -20918,7 +20955,7 @@ function WorktableSection(props) {
updateStatus === "failed" && !updateInfo ? " \xB7 " + t("update.checkFail") : ""
] }),
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dsh-wt_versionActions", children: [
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "dsh-wt_updateBtn", onClick: () => void checkUpdates(true), children: updateStatus === "checking" ? t("update.checking") : t("update.checkNow") }),
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "dsh-wt_updateBtn", disabled: updateStatus === "checking", onClick: () => void checkUpdates(true), children: updateStatus === "checking" ? t("update.checking") : t("update.checkNow") }),
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dsh-wt_updateToggle", onClick: toggleUpdateCheck, children: [
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: t("update.autoCheck") }),
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dsh-wt_updateSwitch", "data-off": updateCheckOn ? void 0 : "true" })
@@ -21343,4 +21380,3 @@ markdown-it/dist/markdown-it.mjs:
(*! markdown-it 15.0.0 https://github.com/markdown-it/markdown-it @license MIT *)
*/
return module.exports; } });
//# sourceMappingURL=client.js.map
+3 -3
View File
@@ -88,6 +88,7 @@ body {
var dshell_default2 = '<!doctype html>\n<!-- dsh-worktable \u539F\u751F\u76AE\u80A4\u6A21\u677F\uFF1A\u65B0\u9875\u9762\u4EE5\u6B64\u4E3A\u57FA\u7840\uFF0C\u66FF\u6362\u4E0B\u9762\u793A\u4F8B\u5185\u5BB9\u5373\u53EF\u3002\n \u6837\u5F0F\u8868\u7531\u63D2\u4EF6\u63D0\u4F9B\uFF08\u968F\u4E3B\u9898\u81EA\u52A8\u9002\u914D\uFF09\uFF0C\u4E0D\u8981\u590D\u5236\u6216\u6539\u5199\u5B83\u3002 -->\n<html lang="zh-CN">\n<head>\n <meta charset="utf-8" />\n <meta name="viewport" content="width=device-width, initial-scale=1" />\n <title>\u6211\u7684\u7A97\u53E3</title>\n <link rel="stylesheet" href="/api/worktable/template/dshell.css" />\n</head>\n<body>\n <div class="dshell">\n <!-- \u6807\u9898\u533A -->\n <h1 class="dshell-title">\u7A97\u53E3\u6807\u9898</h1>\n <p class="dshell-sub">\u4E00\u53E5\u8BDD\u8BF4\u660E\u8FD9\u4E2A\u7A97\u53E3\u505A\u4EC0\u4E48\u3002</p>\n\n <!-- \u72B6\u6001\u5FBD\u6807\uFF1A\u5DF2\u5B8C\u6210 dshell-badgeDone / \u8FDB\u884C\u4E2D dshell-badgeWait / \u9ED8\u8BA4 -->\n <div>\n <span class="dshell-badge dshell-badgeDone">\u5DF2\u5B8C\u6210</span>\n <span class="dshell-badge dshell-badgeWait">\u8FDB\u884C\u4E2D</span>\n <span class="dshell-badge">\u672A\u5F00\u59CB</span>\n </div>\n\n <!-- \u6807\u7B7E\u9875 -->\n <div class="dshell-tabs">\n <button class="dshell-tab dshell-tabOn">\u6982\u89C8</button>\n <button class="dshell-tab">\u8BE6\u60C5</button>\n <button class="dshell-tab">\u8BBE\u7F6E</button>\n </div>\n\n <!-- \u7EDF\u8BA1\u5361\u7247\u7F51\u683C -->\n <div class="dshell-grid">\n <div class="dshell-stat">\n <div class="dshell-statLabel">\u603B\u6570</div>\n <div class="dshell-statValue">128</div>\n <div class="dshell-statDelta">+12.4%</div>\n </div>\n <div class="dshell-stat">\n <div class="dshell-statLabel">\u8FDB\u884C\u4E2D</div>\n <div class="dshell-statValue">7</div>\n </div>\n <div class="dshell-stat">\n <div class="dshell-statLabel">\u5DF2\u5B8C\u6210</div>\n <div class="dshell-statValue">121</div>\n </div>\n </div>\n\n <!-- \u5217\u8868 -->\n <div class="dshell-list">\n <div class="dshell-listItem">\n <span class="dshell-listItemTitle">\u6761\u76EE\u4E00\uFF1A\u793A\u4F8B\u5185\u5BB9\u6807\u9898</span>\n <span class="dshell-listItemMeta">\u6628\u5929</span>\n </div>\n <div class="dshell-listItem">\n <span class="dshell-listItemTitle">\u6761\u76EE\u4E8C\uFF1A\u793A\u4F8B\u5185\u5BB9\u6807\u9898</span>\n <span class="dshell-badge dshell-badgeDone">\u5DF2\u53D1\u5E03</span>\n </div>\n </div>\n\n <!-- \u5361\u7247 + \u952E\u503C\u5BF9 -->\n <div class="dshell-card">\n <h2 class="dshell-sub" style="margin:0 0 8px">\u8BE6\u60C5</h2>\n <div class="dshell-kv">\n <div class="dshell-kvRow"><span class="dshell-kvKey">\u5B57\u6BB5 A</span><span class="dshell-kvValue">\u503C A</span></div>\n <div class="dshell-kvRow"><span class="dshell-kvKey">\u5B57\u6BB5 B</span><span class="dshell-kvValue">\u503C B</span></div>\n </div>\n <div class="dshell-divider"></div>\n <div class="dshell-progress"><div class="dshell-progressBar" style="width:72%"></div></div>\n </div>\n\n <!-- \u64CD\u4F5C\u533A -->\n <div style="display:flex;gap:8px">\n <button class="dshell-btn">\u4E3B\u8981\u64CD\u4F5C</button>\n <button class="dshell-btn dshell-btnGhost">\u6B21\u8981\u64CD\u4F5C</button>\n </div>\n </div>\n</body>\n</html>\n';
// src/index.ts
var PLUGIN_VERSION = false ? "dev" : "0.2.2";
var name = "dsh-worktable";
var inject = ["webServer", "sessions"];
var HEALTH_PATH = "/api/worktable/health";
@@ -300,7 +301,7 @@ function apply(ctx) {
kind: "exact",
path: HEALTH_PATH,
handler: (_req, res) => {
json(res, 200, { plugin: "dsh-worktable", version: "0.2.0", ok: true });
json(res, 200, { plugin: "dsh-worktable", version: PLUGIN_VERSION, ok: true });
}
});
webServer.register({
@@ -501,7 +502,7 @@ function apply(ctx) {
}
const abs = pathResolve(p);
const fsx = await import("node:fs/promises");
const parent = abs.split(/[\\/]/).slice(0, -1).join("\\") || "\\";
const parent = dirname(abs);
try {
await fsx.access(parent);
} catch {
@@ -532,4 +533,3 @@ export {
inject,
name
};
//# sourceMappingURL=index.js.map