zdashboard 2.6.1 → 2.6.2
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/dist/cli.js +157 -22
- package/dist/cli.js.map +1 -1
- package/dist/web/assets/FileIcon-Bc03q6Gz.js +279 -0
- package/dist/web/assets/{FilterPills-B6u1IBeC.js → FilterPills-CSZQenbh.js} +1 -1
- package/dist/web/assets/{ProgressBar-CbyvyLzw.js → ProgressBar-ycyJBwG-.js} +1 -1
- package/dist/web/assets/{Workspace-DQmfVJh6.js → Workspace-jCfxaTOM.js} +1 -1
- package/dist/web/assets/badge-DUO7nDks.js +1 -0
- package/dist/web/assets/index-4aiRmNbP.css +1 -0
- package/dist/web/assets/{index-BvuOeKbq.js → index-BrvOKJRF.js} +1 -1
- package/dist/web/assets/{index-BfA6l4to.js → index-Co_rMXPa.js} +2 -2
- package/dist/web/assets/web-BKh2HY35.js +2 -0
- package/dist/web/assets/web-BNjs9lCy.js +139 -0
- package/dist/web/assets/{web-BcTJQUKr.js → web-BrsVNrGk.js} +1 -1
- package/dist/web/assets/{web-BXCBKn6i.js → web-Bt0s1qFE.js} +1 -1
- package/dist/web/assets/{web-C8I10oqh.js → web-CCoznDNk.js} +1 -1
- package/dist/web/assets/web-DxK2pSVl.js +1 -0
- package/dist/web/assets/web-ShIDOvFD.js +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/dist/web/assets/FileIcon-B0-2gV6a.js +0 -10
- package/dist/web/assets/MdViewer-Cvh3TNQI.js +0 -270
- package/dist/web/assets/badge-DTb6qo3S.js +0 -1
- package/dist/web/assets/index-DQkehbup.css +0 -1
- package/dist/web/assets/web-5newSm97.js +0 -1
- package/dist/web/assets/web-BOg9UnpC.js +0 -1
- package/dist/web/assets/web-CLCAgjmg.js +0 -1
- package/dist/web/assets/web-CXE89yN1.js +0 -2
- /package/dist/web/assets/{MdViewer-BTcE7LSd.css → FileIcon-BTcE7LSd.css} +0 -0
package/dist/cli.js
CHANGED
|
@@ -167,7 +167,7 @@ import { fileURLToPath } from "url";
|
|
|
167
167
|
// package.json
|
|
168
168
|
var package_default = {
|
|
169
169
|
name: "zdashboard",
|
|
170
|
-
version: "2.6.
|
|
170
|
+
version: "2.6.2",
|
|
171
171
|
description: "ZCode skill dashboard platform \u2014 pluggable viewers for zdesign/zview/zreview/zgoal",
|
|
172
172
|
type: "module",
|
|
173
173
|
bin: {
|
|
@@ -841,7 +841,7 @@ function scanTree(root, hasOpenspec, hasDocs) {
|
|
|
841
841
|
const docs = buildTree(paths).map((n) => ({ ...n, path: n.path ? `docs/${n.path}` : void 0 }));
|
|
842
842
|
if (docs.length) tree.push({ name: "docs", kind: "dir", children: docs });
|
|
843
843
|
}
|
|
844
|
-
const skip = /* @__PURE__ */ new Set(["openspec", "docs", "node_modules", ".git", "dist", "playground"]);
|
|
844
|
+
const skip = /* @__PURE__ */ new Set(["openspec", "docs", "node_modules", ".git", "dist", "playground", ".zreview"]);
|
|
845
845
|
const etc = [];
|
|
846
846
|
try {
|
|
847
847
|
for (const ent of fs7.readdirSync(root, { withFileTypes: true })) {
|
|
@@ -1247,62 +1247,148 @@ var apply4 = {
|
|
|
1247
1247
|
import fs8 from "fs";
|
|
1248
1248
|
import path7 from "path";
|
|
1249
1249
|
import YAML2 from "yaml";
|
|
1250
|
-
var
|
|
1250
|
+
var REVIEW_DIR = ".zreview";
|
|
1251
|
+
var REVIEW_FILE = path7.join(REVIEW_DIR, "review.yaml");
|
|
1252
|
+
var DOCS_DIR = path7.join(REVIEW_DIR, "docs");
|
|
1253
|
+
var DIAGRAMS_DIR = path7.join(REVIEW_DIR, "diagrams");
|
|
1251
1254
|
var ReviewStore = class {
|
|
1252
1255
|
root;
|
|
1253
|
-
file;
|
|
1254
1256
|
onChange;
|
|
1255
1257
|
constructor(root, onChange) {
|
|
1256
1258
|
this.root = root;
|
|
1257
1259
|
this.onChange = onChange;
|
|
1258
|
-
const existing = REVIEW_CANDIDATES.find((rel) => fs8.existsSync(path7.join(root, rel)));
|
|
1259
|
-
this.file = path7.join(root, existing ?? REVIEW_CANDIDATES[0]);
|
|
1260
1260
|
}
|
|
1261
1261
|
exists() {
|
|
1262
|
-
return fs8.existsSync(this.
|
|
1262
|
+
return fs8.existsSync(path7.join(this.root, REVIEW_FILE));
|
|
1263
1263
|
}
|
|
1264
1264
|
read() {
|
|
1265
|
+
const fullPath = path7.join(this.root, REVIEW_FILE);
|
|
1266
|
+
if (!fs8.existsSync(fullPath)) {
|
|
1267
|
+
return { status: "draft", summary: "", documents: [], codebases: [], diagrams: [], items: [] };
|
|
1268
|
+
}
|
|
1265
1269
|
try {
|
|
1266
|
-
const parsed = YAML2.parse(fs8.readFileSync(
|
|
1267
|
-
if (!parsed || !Array.isArray(parsed.items))
|
|
1268
|
-
|
|
1270
|
+
const parsed = YAML2.parse(fs8.readFileSync(fullPath, "utf8"));
|
|
1271
|
+
if (!parsed || !Array.isArray(parsed.items)) {
|
|
1272
|
+
return { status: "draft", summary: parsed?.summary ?? "", documents: parsed?.documents ?? [], codebases: parsed?.codebases ?? [], diagrams: parsed?.diagrams ?? [], items: [] };
|
|
1273
|
+
}
|
|
1274
|
+
return {
|
|
1275
|
+
status: parsed.status ?? "draft",
|
|
1276
|
+
summary: parsed.summary ?? "",
|
|
1277
|
+
documents: parsed.documents ?? [],
|
|
1278
|
+
codebases: parsed.codebases ?? [],
|
|
1279
|
+
diagrams: parsed.diagrams ?? [],
|
|
1280
|
+
items: parsed.items
|
|
1281
|
+
};
|
|
1269
1282
|
} catch {
|
|
1270
|
-
return { status: "draft", items: [] };
|
|
1283
|
+
return { status: "draft", summary: "", documents: [], codebases: [], diagrams: [], items: [] };
|
|
1271
1284
|
}
|
|
1272
1285
|
}
|
|
1273
1286
|
write(data) {
|
|
1274
|
-
fs8.mkdirSync(path7.
|
|
1275
|
-
fs8.writeFileSync(this.
|
|
1287
|
+
fs8.mkdirSync(path7.join(this.root, REVIEW_DIR), { recursive: true });
|
|
1288
|
+
fs8.writeFileSync(path7.join(this.root, REVIEW_FILE), YAML2.stringify(data), "utf8");
|
|
1276
1289
|
this.onChange?.();
|
|
1277
1290
|
}
|
|
1278
1291
|
updateItem(id, patch) {
|
|
1279
1292
|
const data = this.read();
|
|
1280
|
-
const item = data.items
|
|
1293
|
+
const item = this.findItem(data.items, id);
|
|
1281
1294
|
if (!item) throw new Error(`item ${id} not found`);
|
|
1282
1295
|
if (patch.answer !== void 0) item.answer = patch.answer;
|
|
1283
1296
|
if (patch.state !== void 0) item.state = patch.state;
|
|
1297
|
+
if (patch.priority !== void 0) item.priority = patch.priority;
|
|
1298
|
+
if (patch.title !== void 0) item.title = patch.title;
|
|
1284
1299
|
if (patch.state === "answered" && !patch.answer && !item.answer) item.answer = "";
|
|
1285
1300
|
this.write(data);
|
|
1286
1301
|
return data;
|
|
1287
1302
|
}
|
|
1303
|
+
addChild(parentId, title, priority = "medium") {
|
|
1304
|
+
const data = this.read();
|
|
1305
|
+
const parent = this.findItem(data.items, parentId);
|
|
1306
|
+
if (!parent) throw new Error(`parent ${parentId} not found`);
|
|
1307
|
+
if (!parent.children) parent.children = [];
|
|
1308
|
+
const newId = `${parentId}-${parent.children.length + 1}`;
|
|
1309
|
+
parent.children.push({
|
|
1310
|
+
id: newId,
|
|
1311
|
+
type: "decomposition",
|
|
1312
|
+
state: "open",
|
|
1313
|
+
title,
|
|
1314
|
+
priority
|
|
1315
|
+
});
|
|
1316
|
+
this.write(data);
|
|
1317
|
+
return data;
|
|
1318
|
+
}
|
|
1319
|
+
removeItem(id) {
|
|
1320
|
+
const data = this.read();
|
|
1321
|
+
const removed = this.removeItemFromList(data.items, id);
|
|
1322
|
+
if (!removed) throw new Error(`item ${id} not found`);
|
|
1323
|
+
this.write(data);
|
|
1324
|
+
return data;
|
|
1325
|
+
}
|
|
1288
1326
|
setStatus(status) {
|
|
1289
1327
|
const data = this.read();
|
|
1290
|
-
if (status === "passed" && data.items
|
|
1328
|
+
if (status === "passed" && this.hasOpenItems(data.items)) {
|
|
1291
1329
|
throw new Error("\u5B58\u5728\u672A\u5904\u7406\u7684\u8BC4\u5BA1\u9879(open),\u4E0D\u80FD\u901A\u8FC7");
|
|
1292
1330
|
}
|
|
1293
1331
|
data.status = status;
|
|
1294
1332
|
this.write(data);
|
|
1295
1333
|
return data;
|
|
1296
1334
|
}
|
|
1297
|
-
|
|
1335
|
+
listDocs() {
|
|
1336
|
+
const docsDir = path7.join(this.root, DOCS_DIR);
|
|
1337
|
+
if (!fs8.existsSync(docsDir)) return [];
|
|
1298
1338
|
try {
|
|
1299
|
-
|
|
1300
|
-
if (!fs8.existsSync(zdevDir) || !fs8.statSync(zdevDir).isDirectory()) return [];
|
|
1301
|
-
return fs8.readdirSync(zdevDir).filter((f) => /\.(md|markdown)$/i.test(f) && fs8.statSync(path7.join(zdevDir, f)).isFile()).sort();
|
|
1339
|
+
return fs8.readdirSync(docsDir).filter((f) => /\.(md|markdown|txt)$/i.test(f)).sort();
|
|
1302
1340
|
} catch {
|
|
1303
1341
|
return [];
|
|
1304
1342
|
}
|
|
1305
1343
|
}
|
|
1344
|
+
readDoc(name) {
|
|
1345
|
+
const fullPath = path7.join(this.root, DOCS_DIR, name);
|
|
1346
|
+
if (!fs8.existsSync(fullPath)) throw new Error(`doc ${name} not found`);
|
|
1347
|
+
return fs8.readFileSync(fullPath, "utf8");
|
|
1348
|
+
}
|
|
1349
|
+
listDiagrams() {
|
|
1350
|
+
const dir = path7.join(this.root, DIAGRAMS_DIR);
|
|
1351
|
+
if (!fs8.existsSync(dir)) return [];
|
|
1352
|
+
try {
|
|
1353
|
+
return fs8.readdirSync(dir).filter((f) => /\.html$/i.test(f)).sort();
|
|
1354
|
+
} catch {
|
|
1355
|
+
return [];
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
readDiagram(name) {
|
|
1359
|
+
const fullPath = path7.join(this.root, DIAGRAMS_DIR, name);
|
|
1360
|
+
if (!fs8.existsSync(fullPath)) throw new Error(`diagram ${name} not found`);
|
|
1361
|
+
return fs8.readFileSync(fullPath, "utf8");
|
|
1362
|
+
}
|
|
1363
|
+
findItem(items, id) {
|
|
1364
|
+
for (const item of items) {
|
|
1365
|
+
if (item.id === id) return item;
|
|
1366
|
+
if (item.children) {
|
|
1367
|
+
const found = this.findItem(item.children, id);
|
|
1368
|
+
if (found) return found;
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
return null;
|
|
1372
|
+
}
|
|
1373
|
+
removeItemFromList(items, id) {
|
|
1374
|
+
for (let i = 0; i < items.length; i++) {
|
|
1375
|
+
if (items[i].id === id) {
|
|
1376
|
+
items.splice(i, 1);
|
|
1377
|
+
return true;
|
|
1378
|
+
}
|
|
1379
|
+
if (items[i].children && this.removeItemFromList(items[i].children, id)) {
|
|
1380
|
+
return true;
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
return false;
|
|
1384
|
+
}
|
|
1385
|
+
hasOpenItems(items) {
|
|
1386
|
+
for (const item of items) {
|
|
1387
|
+
if (item.state === "open") return true;
|
|
1388
|
+
if (item.children && this.hasOpenItems(item.children)) return true;
|
|
1389
|
+
}
|
|
1390
|
+
return false;
|
|
1391
|
+
}
|
|
1306
1392
|
};
|
|
1307
1393
|
|
|
1308
1394
|
// src/plugins/review/index.ts
|
|
@@ -1312,7 +1398,7 @@ var apply5 = {
|
|
|
1312
1398
|
const root = config.root;
|
|
1313
1399
|
ctx.inject(["server"], () => {
|
|
1314
1400
|
if (!ctx.server?.route) return;
|
|
1315
|
-
ctx.dashboard.register({ mode: "review", label: "\u6587\u6863\u8BC4\u5BA1", icon: "\u2705", description: "
|
|
1401
|
+
ctx.dashboard.register({ mode: "review", label: "\u6587\u6863\u8BC4\u5BA1", icon: "\u2705", description: "\u591A\u6587\u6863\u9700\u6C42\u8BC4\u5BA1\u4E0E\u62C6\u89E3 \xB7 zreview" });
|
|
1316
1402
|
const reviewStore = new ReviewStore(root, () => {
|
|
1317
1403
|
ctx.reload.broadcast("files");
|
|
1318
1404
|
});
|
|
@@ -1328,7 +1414,44 @@ var apply5 = {
|
|
|
1328
1414
|
}
|
|
1329
1415
|
try {
|
|
1330
1416
|
const body = JSON.parse(await readBody(req) || "{}");
|
|
1331
|
-
const data = reviewStore.updateItem(body.id, {
|
|
1417
|
+
const data = reviewStore.updateItem(body.id, {
|
|
1418
|
+
answer: body.answer,
|
|
1419
|
+
state: body.state,
|
|
1420
|
+
priority: body.priority,
|
|
1421
|
+
title: body.title
|
|
1422
|
+
});
|
|
1423
|
+
res.writeHead(200, { "Content-Type": "application/json; charset=utf-8", "Cache-Control": "no-cache" });
|
|
1424
|
+
res.end(JSON.stringify(data));
|
|
1425
|
+
} catch (e) {
|
|
1426
|
+
res.writeHead(400, { "Content-Type": "application/json; charset=utf-8" });
|
|
1427
|
+
res.end(JSON.stringify({ error: e instanceof Error ? e.message : "unknown error" }));
|
|
1428
|
+
}
|
|
1429
|
+
});
|
|
1430
|
+
ctx.server.route("/__review/item/add-child", async (req, res) => {
|
|
1431
|
+
if (req.headers["x-stop-token"] !== ctx.server.stopToken) {
|
|
1432
|
+
res.writeHead(403);
|
|
1433
|
+
res.end("forbidden");
|
|
1434
|
+
return;
|
|
1435
|
+
}
|
|
1436
|
+
try {
|
|
1437
|
+
const body = JSON.parse(await readBody(req) || "{}");
|
|
1438
|
+
const data = reviewStore.addChild(body.parentId, body.title, body.priority);
|
|
1439
|
+
res.writeHead(200, { "Content-Type": "application/json; charset=utf-8", "Cache-Control": "no-cache" });
|
|
1440
|
+
res.end(JSON.stringify(data));
|
|
1441
|
+
} catch (e) {
|
|
1442
|
+
res.writeHead(400, { "Content-Type": "application/json; charset=utf-8" });
|
|
1443
|
+
res.end(JSON.stringify({ error: e instanceof Error ? e.message : "unknown error" }));
|
|
1444
|
+
}
|
|
1445
|
+
});
|
|
1446
|
+
ctx.server.route("/__review/item/remove", async (req, res) => {
|
|
1447
|
+
if (req.headers["x-stop-token"] !== ctx.server.stopToken) {
|
|
1448
|
+
res.writeHead(403);
|
|
1449
|
+
res.end("forbidden");
|
|
1450
|
+
return;
|
|
1451
|
+
}
|
|
1452
|
+
try {
|
|
1453
|
+
const body = JSON.parse(await readBody(req) || "{}");
|
|
1454
|
+
const data = reviewStore.removeItem(body.id);
|
|
1332
1455
|
res.writeHead(200, { "Content-Type": "application/json; charset=utf-8", "Cache-Control": "no-cache" });
|
|
1333
1456
|
res.end(JSON.stringify(data));
|
|
1334
1457
|
} catch (e) {
|
|
@@ -1354,7 +1477,19 @@ var apply5 = {
|
|
|
1354
1477
|
});
|
|
1355
1478
|
ctx.server.route("/__docs", async (_req, res) => {
|
|
1356
1479
|
res.writeHead(200, { "Content-Type": "application/json; charset=utf-8", "Cache-Control": "no-cache" });
|
|
1357
|
-
res.end(JSON.stringify(reviewStore.
|
|
1480
|
+
res.end(JSON.stringify(reviewStore.listDocs()));
|
|
1481
|
+
});
|
|
1482
|
+
ctx.server.route("/__docs/:name", async (req, res) => {
|
|
1483
|
+
try {
|
|
1484
|
+
const name = req.params?.name;
|
|
1485
|
+
if (!name) throw new Error("missing doc name");
|
|
1486
|
+
const content = reviewStore.readDoc(name);
|
|
1487
|
+
res.writeHead(200, { "Content-Type": "text/markdown; charset=utf-8", "Cache-Control": "no-cache" });
|
|
1488
|
+
res.end(content);
|
|
1489
|
+
} catch (e) {
|
|
1490
|
+
res.writeHead(404, { "Content-Type": "application/json; charset=utf-8" });
|
|
1491
|
+
res.end(JSON.stringify({ error: e instanceof Error ? e.message : "not found" }));
|
|
1492
|
+
}
|
|
1358
1493
|
});
|
|
1359
1494
|
});
|
|
1360
1495
|
}
|