zdashboard 1.3.2 → 1.4.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/README.md CHANGED
@@ -70,4 +70,5 @@ npx zdashboard --mode bugs --dir /path/to/project --port 4190
70
70
  - [x] zview-dashboard → zdashboard(v1.0.0)
71
71
  - [x] zreview-dashboard → zdashboard plugin(v1.2.0)
72
72
  - [x] zdesign-dashboard → zdashboard plugin(v1.2.0)
73
+ - [x] zapply execution progress → zdashboard plugin(v1.3.3)
73
74
  - [x] zskills skill SKILL.md 统一调用 zdashboard
package/dist/cli.js CHANGED
@@ -71,7 +71,8 @@ function scanTree(root2, hasOpenspec, hasDocs) {
71
71
  const ext = path.extname(ent.name).toLowerCase();
72
72
  if (ent.isFile() && (ext === ".md" || ext === ".markdown")) etc.push({ name: ent.name, kind: "file", path: ent.name });
73
73
  }
74
- } catch {
74
+ } catch (e) {
75
+ console.error("[zdashboard] scan root etc failed:", e);
75
76
  }
76
77
  etc.sort((a, b) => a.name.localeCompare(b.name));
77
78
  if (etc.length) tree.push({ name: `\u5176\u4ED6 (${etc.length})`, kind: "dir", children: etc });
@@ -442,7 +443,7 @@ function scanAssets(root2) {
442
443
  // package.json
443
444
  var package_default = {
444
445
  name: "zdashboard",
445
- version: "1.3.2",
446
+ version: "1.4.0",
446
447
  description: "ZCode skill dashboard platform \u2014 pluggable viewers for zdesign/zview/zreview/zgoal",
447
448
  type: "module",
448
449
  bin: {
@@ -630,6 +631,42 @@ function createServer(opts) {
630
631
  }
631
632
  });
632
633
  registerBuiltin({ mode: "design", label: "\u8BBE\u8BA1\u8D44\u4EA7", icon: "\u{1F3A8}" });
634
+ registerBuiltin({
635
+ mode: "apply",
636
+ label: "\u6267\u884C\u8FDB\u5EA6",
637
+ icon: "\u2699\uFE0F",
638
+ apiRoutes: {
639
+ "/__apply": async (_, res) => {
640
+ res.writeHead(200, { "Content-Type": "application/json; charset=utf-8", "Cache-Control": "no-cache" });
641
+ res.end(JSON.stringify(scanApplyChanges(ROOT)));
642
+ },
643
+ "/__apply/change": async (req, res) => {
644
+ if (req.headers["x-stop-token"] !== STOP_TOKEN) {
645
+ res.writeHead(403);
646
+ res.end("forbidden");
647
+ return;
648
+ }
649
+ (async () => {
650
+ try {
651
+ const url = new URL(req.url || "", "http://x");
652
+ const name = url.searchParams.get("name");
653
+ if (!name) {
654
+ res.writeHead(400);
655
+ res.end(JSON.stringify({ error: "missing name" }));
656
+ return;
657
+ }
658
+ const data = readApplyChange(ROOT, name);
659
+ res.writeHead(200, { "Content-Type": "application/json; charset=utf-8", "Cache-Control": "no-cache" });
660
+ res.end(JSON.stringify(data));
661
+ } catch (e) {
662
+ res.writeHead(400);
663
+ res.end(JSON.stringify({ error: e.message }));
664
+ }
665
+ })();
666
+ return;
667
+ }
668
+ }
669
+ });
633
670
  const clients = /* @__PURE__ */ new Set();
634
671
  const broadcast = (ev, data = "") => {
635
672
  const payload = `event: ${ev}
@@ -676,7 +713,8 @@ data: ${JSON.stringify(data == null ? "" : data)}
676
713
  setTimeout(() => {
677
714
  try {
678
715
  server.close();
679
- } catch {
716
+ } catch (e) {
717
+ console.error("[zdashboard] server close failed:", e);
680
718
  }
681
719
  process.exit(0);
682
720
  }, 50);
@@ -722,7 +760,8 @@ data: ${JSON.stringify(data == null ? "" : data)}
722
760
  let recipe;
723
761
  try {
724
762
  recipe = JSON.parse(body || "{}").recipe;
725
- } catch {
763
+ } catch (e) {
764
+ console.error("[zdashboard] invalid just action body:", e);
726
765
  }
727
766
  const act = justAction[1];
728
767
  if (act === "start" || act === "restart") {
@@ -815,6 +854,40 @@ data: ${JSON.stringify(data == null ? "" : data)}
815
854
  }
816
855
  start(PORT0);
817
856
  }
857
+ function countTasks(md) {
858
+ const all = (md.match(/^\s*-\s*\[[ xX]\]\s*/gm) || []).length;
859
+ const done = (md.match(/^\s*-\s*\[[xX]\]\s*/gm) || []).length;
860
+ return { total: all, done };
861
+ }
862
+ function readText(p) {
863
+ try {
864
+ return fs6.readFileSync(p, "utf8");
865
+ } catch {
866
+ return "";
867
+ }
868
+ }
869
+ function scanApplyChanges(root2) {
870
+ const changesDir = path6.join(root2, "openspec", "changes");
871
+ if (!fs6.existsSync(changesDir)) return [];
872
+ const out = [];
873
+ for (const ent of fs6.readdirSync(changesDir, { withFileTypes: true })) {
874
+ if (!ent.isDirectory() || ent.name.startsWith(".") || ent.name === "archive") continue;
875
+ const dir = path6.join(changesDir, ent.name);
876
+ const tasks = readText(path6.join(dir, "tasks.md"));
877
+ const { total, done } = countTasks(tasks);
878
+ out.push({ name: ent.name, path: `openspec/changes/${ent.name}`, total, done, hasProposal: fs6.existsSync(path6.join(dir, "proposal.md")), hasDesign: fs6.existsSync(path6.join(dir, "design.md")) });
879
+ }
880
+ out.sort((a, b) => a.name.localeCompare(b.name));
881
+ return out;
882
+ }
883
+ function readApplyChange(root2, name) {
884
+ const dir = path6.join(root2, "openspec", "changes", name);
885
+ const proposal = readText(path6.join(dir, "proposal.md"));
886
+ const design = readText(path6.join(dir, "design.md"));
887
+ const tasks = readText(path6.join(dir, "tasks.md"));
888
+ const { total, done } = countTasks(tasks);
889
+ return { name, path: `openspec/changes/${name}`, total, done, hasProposal: !!proposal, hasDesign: !!design, proposal, design, tasks };
890
+ }
818
891
 
819
892
  // src/server/detect.ts
820
893
  import fs7 from "fs";
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server/index.ts","../src/server/spec-scan.ts","../src/server/just-runner.ts","../src/server/bugs.ts","../src/server/api/fetch.ts","../src/server/errors.ts","../src/server/plugins.ts","../src/server/review-store.ts","../src/server/design-assets.ts","../package.json","../src/server/detect.ts","../src/cli.ts"],"sourcesContent":["import http from 'node:http';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport crypto from 'node:crypto';\nimport { exec } from 'node:child_process';\nimport { fileURLToPath } from 'node:url';\nimport { scanTree } from './spec-scan.js';\nimport { JustRunner } from './just-runner.js';\nimport { fetchBugs } from './bugs.js';\nimport { registerBuiltin, allBuiltins, type DashboardPlugin } from './plugins.js';\nimport { ReviewStore, type ItemState, type ReviewStatus } from './review-store.js';\nimport { scanAssets } from './design-assets.js';\nimport type { DetectResult } from './detect.js';\nimport pkg from '../../package.json' with { type: 'json' };\n\nconst VERSION = pkg.version;\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst STOP_TOKEN = crypto.randomBytes(12).toString('hex');\nconst INJECT = `<script>(function(){try{var es=new EventSource('/__reload');es.addEventListener('reload',function(){location.reload();});es.onerror=function(){es.close();};}catch(e){}document.addEventListener('click',function(e){var t=e.target;if(t&&t.closest){var a=t.closest('a[target]');if(a&&a.target!=='_self'){a.target='_self';}}},true);})();</script>`;\n\nconst MIME: Record<string, string> = {\n '.html': 'text/html; charset=utf-8', '.htm': 'text/html; charset=utf-8',\n '.css': 'text/css; charset=utf-8', '.js': 'application/javascript; charset=utf-8',\n '.mjs': 'application/javascript; charset=utf-8', '.json': 'application/json; charset=utf-8',\n '.svg': 'image/svg+xml', '.png': 'image/png', '.ico': 'image/x-icon',\n '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.gif': 'image/gif', '.webp': 'image/webp',\n '.md': 'text/markdown; charset=utf-8', '.txt': 'text/plain; charset=utf-8',\n '.yml': 'text/yaml; charset=utf-8', '.yaml': 'text/yaml; charset=utf-8',\n '.woff': 'font/woff', '.woff2': 'font/woff2', '.ttf': 'font/ttf',\n '.map': 'application/json; charset=utf-8',\n};\n\nexport interface ServerOptions {\n root: string;\n port?: number;\n open?: boolean;\n detect: DetectResult;\n dashboardDir?: string;\n mode?: string;\n}\n\nfunction readBody(req: http.IncomingMessage): Promise<string> {\n return new Promise((resolve) => {\n let data = '';\n req.on('data', (c) => (data += c));\n req.on('end', () => resolve(data));\n });\n}\n\nexport function createServer(opts: ServerOptions) {\n const ROOT = path.resolve(opts.root);\n const PORT0 = opts.port ?? 4190;\n const OPEN = !!opts.open;\n const APP_DIR = opts.dashboardDir ?? path.resolve(__dirname, 'web');\n if (!fs.existsSync(ROOT)) fs.mkdirSync(ROOT, { recursive: true });\n const det = opts.detect;\n const runner = new JustRunner(ROOT);\n const MODE = opts.mode;\n\n // register builtin plugins (server-side: apiRoutes only; viewer loaded by frontend)\n registerBuiltin({\n mode: 'bugs', label: '禅道 Bugs', icon: '🎯',\n apiRoutes: { '/__bugs': async (_, res) => { res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' }); fetchBugs(ROOT).then((r) => res.end(JSON.stringify(r))); } }\n });\n registerBuiltin({ mode: 'view', label: '项目浏览', icon: '👁️' });\n\n const reviewStore = new ReviewStore(ROOT);\n registerBuiltin({\n mode: 'review', label: '文档评审', icon: '✅',\n apiRoutes: {\n '/__review': async (_, res) => {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(reviewStore.read()));\n },\n '/__review/item': async (req, res) => {\n if (req.headers['x-stop-token'] !== STOP_TOKEN) { res.writeHead(403); res.end('forbidden'); return; }\n (async () => {\n try {\n const body = JSON.parse(await readBody(req) || '{}');\n const data = reviewStore.updateItem(body.id, { answer: body.answer, state: body.state as ItemState | undefined });\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify(data));\n } catch (e) {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: (e as Error).message }));\n }\n })();\n return;\n },\n '/__review/status': async (req, res) => {\n if (req.headers['x-stop-token'] !== STOP_TOKEN) { res.writeHead(403); res.end('forbidden'); return; }\n (async () => {\n try {\n const body = JSON.parse(await readBody(req) || '{}');\n const data = reviewStore.setStatus(body.status as ReviewStatus);\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify(data));\n } catch (e) {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: (e as Error).message }));\n }\n })();\n return;\n },\n '/__docs': async (_, res) => {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(reviewStore.docs()));\n },\n }\n });\n\n registerBuiltin({ mode: 'design', label: '设计资产', icon: '🎨' });\n\n const clients = new Set<http.ServerResponse>();\n const broadcast = (ev: string, data: unknown = '') => {\n const payload = `event: ${ev}\\ndata: ${JSON.stringify(data == null ? '' : data)}\\n\\n`;\n for (const c of clients) c.write(payload);\n };\n\n function serveFile(filePath: string, res: http.ServerResponse, injectHtml: boolean) {\n fs.readFile(filePath, (err, data) => {\n if (err) { res.writeHead(404); return res.end('Not found'); }\n const ext = path.extname(filePath).toLowerCase();\n const ct = MIME[ext] ?? 'application/octet-stream';\n let body = data;\n if (injectHtml && ext === '.html') {\n const s = data.toString('utf8');\n body = Buffer.from(s.indexOf('</body>') >= 0 ? s.replace('</body>', INJECT + '</body>') : s + INJECT);\n }\n res.writeHead(200, { 'Content-Type': ct, 'Cache-Control': 'no-cache' });\n res.end(body);\n });\n }\n\n function handler(req: http.IncomingMessage, res: http.ServerResponse) {\n const url = req.url!.split('?')[0];\n\n // ── SSE:文件变更 ──\n if (url === '/__reload') {\n res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', Connection: 'keep-alive' });\n res.write(': connected\\n\\n');\n clients.add(res);\n req.on('close', () => clients.delete(res));\n return;\n }\n if (url === '/__config') {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n return res.end(JSON.stringify({ stopToken: STOP_TOKEN }));\n }\n if (url === '/__stop' && req.method === 'POST') {\n if (req.headers['x-stop-token'] === STOP_TOKEN) {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end('{\"ok\":true}');\n runner.stop();\n setTimeout(() => { try { server.close(); } catch {} process.exit(0); }, 50);\n } else { res.writeHead(403); res.end('forbidden'); }\n return;\n }\n\n // ── 方案模式:树形文件清单(+探测结果) / 设计模式:资产分类清单 ──\n if (url === '/__files') {\n if (MODE === 'design') {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n return res.end(JSON.stringify(scanAssets(ROOT)));\n }\n const tree = scanTree(ROOT, det.hasOpenspec, det.hasDocs);\n const payload: TreeNodePayload = { tree, ...det };\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n return res.end(JSON.stringify(payload));\n }\n\n // ── 日志能力 ──\n if (url === '/__just/recipes') {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n runner.recipes().then((r) => res.end(JSON.stringify(r)));\n return;\n }\n if (url === '/__just/logs') {\n res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', Connection: 'keep-alive' });\n res.write(': connected\\n\\n');\n const unsub = runner.subscribe((ev) => res.write(`data: ${JSON.stringify(ev)}\\n\\n`));\n req.on('close', unsub);\n return;\n }\n const justAction = url.match(/^\\/__just\\/(start|stop|restart)$/);\n if (justAction && req.method === 'POST') {\n (async () => {\n if (req.headers['x-stop-token'] !== STOP_TOKEN) { res.writeHead(403); res.end('forbidden'); return; }\n const body = await readBody(req);\n let recipe: string | undefined;\n try { recipe = JSON.parse(body || '{}').recipe; } catch { /* ignore */ }\n const act = justAction[1];\n if (act === 'start' || act === 'restart') {\n const target = recipe ?? runner.info().recipe;\n if (!target) { res.writeHead(400); res.end('{\"error\":\"no recipe\"}'); return; }\n const recipes = await runner.recipes();\n if (!recipes.some((r) => r.name === target)) { res.writeHead(403); res.end('{\"error\":\"unknown recipe\"}'); return; }\n runner.start(target);\n } else {\n runner.stop();\n }\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify(runner.info()));\n })();\n return;\n }\n\n // ── plugin API routes ──\n let handled = false;\n for (const plugin of allBuiltins()) {\n if (!plugin.apiRoutes) continue;\n for (const [route, handler] of Object.entries(plugin.apiRoutes)) {\n if (url === route) {\n handled = true;\n handler(req, res, ROOT);\n return;\n }\n }\n }\n\n // ── dashboard 前端 ──\n if (url === '/') return serveFile(path.join(APP_DIR, 'index.html'), res, false);\n if (url.indexOf('/__app/') === 0) {\n const fp = path.join(APP_DIR, url.slice(7));\n if (fp !== APP_DIR && fp.indexOf(APP_DIR + path.sep) !== 0) { res.writeHead(403); return res.end('Forbidden'); }\n return serveFile(fp, res, false);\n }\n if (url.indexOf('/assets/') === 0) {\n const fp = path.join(APP_DIR, decodeURIComponent(url));\n if (fp.indexOf(APP_DIR + path.sep) !== 0) { res.writeHead(403); return res.end('Forbidden'); }\n return serveFile(fp, res, false);\n }\n\n // ── 用户资产 ──\n const fp = path.join(ROOT, decodeURIComponent(url));\n if (fp !== ROOT && fp.indexOf(ROOT + path.sep) !== 0) { res.writeHead(403); return res.end('Forbidden'); }\n return serveFile(fp, res, true);\n }\n\n let server: http.Server;\n function start(port: number) {\n server = http.createServer(handler);\n server.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') { console.log(`[zdashboard] port ${port} busy, trying ${port + 1}`); start(port + 1); }\n else throw err;\n });\n server.listen(port, () => {\n const u = `http://localhost:${port}`;\n console.log(`[zdashboard] v${VERSION} dashboard -> ${u}`);\n console.log(`[zdashboard] project -> ${ROOT}`);\n console.log(`[zdashboard] mode -> ${MODE ?? '(auto)'}`);\n console.log(`[zdashboard] detect -> openspec:${det.hasOpenspec} docs:${det.hasDocs} just:${det.hasJust} bugs:${det.hasBugs}`);\n if (OPEN) exec(process.platform === 'darwin' ? `open ${u}` : `start ${u}`);\n });\n }\n\n let debounce: NodeJS.Timeout;\n try {\n fs.watch(ROOT, { recursive: true }, () => {\n clearTimeout(debounce);\n debounce = setTimeout(() => {\n broadcast('reload');\n broadcast('files');\n console.log(`[zdashboard] change -> reload + refresh tree (${clients.size} client${clients.size === 1 ? '' : 's'})`);\n }, 150);\n });\n } catch { console.log('[zdashboard] watch unavailable - static only.'); }\n\n start(PORT0);\n}\n\ninterface TreeNodePayload { tree: unknown; hasOpenspec: boolean; hasDocs: boolean; hasJust: boolean; hasBugs: boolean; }\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nexport type NodeKind = 'file' | 'dir' | 'log';\nexport interface TreeNode {\n name: string;\n kind: NodeKind;\n path?: string; // file: 相对 root 的路径(点击预览用)\n defaultCollapsed?: boolean;\n children?: TreeNode[];\n}\n\nfunction walkFiles(absDir: string, relDir: string, depth = 0): TreeNode[] {\n if (depth > 4) return [];\n let ents: fs.Dirent[];\n try { ents = fs.readdirSync(absDir, { withFileTypes: true }); } catch { return []; }\n const nodes: TreeNode[] = [];\n for (const ent of ents) {\n if (ent.name.startsWith('.') || ent.name === 'node_modules') continue;\n const rel = relDir ? `${relDir}/${ent.name}` : ent.name;\n if (ent.isDirectory()) {\n nodes.push({ name: ent.name, kind: 'dir', children: walkFiles(path.join(absDir, ent.name), rel, depth + 1) });\n } else {\n nodes.push({ name: ent.name, kind: 'file', path: rel });\n }\n }\n nodes.sort((a, b) => (a.kind === b.kind ? a.name.localeCompare(b.name) : a.kind === 'dir' ? -1 : 1));\n return nodes;\n}\n\n/** 方案模式树形扫描:openspec 感知 + docs 聚合 + 其他兜底 */\nexport function scanTree(root: string, hasOpenspec: boolean, hasDocs: boolean): TreeNode[] {\n const tree: TreeNode[] = [];\n if (hasOpenspec && fs.existsSync(path.join(root, 'openspec', 'changes'))) {\n const changesDir = path.join(root, 'openspec', 'changes');\n const active: TreeNode[] = [];\n const archived: TreeNode[] = [];\n for (const ent of fs.readdirSync(changesDir, { withFileTypes: true })) {\n if (!ent.isDirectory() || ent.name.startsWith('.') || ent.name === 'archive') continue;\n active.push({ name: ent.name, kind: 'dir', children: walkFiles(path.join(changesDir, ent.name), `openspec/changes/${ent.name}`) });\n }\n active.sort((a, b) => a.name.localeCompare(b.name));\n const archiveDir = path.join(changesDir, 'archive');\n if (fs.existsSync(archiveDir)) {\n for (const ent of fs.readdirSync(archiveDir, { withFileTypes: true })) {\n if (!ent.isDirectory() || ent.name.startsWith('.')) continue;\n archived.push({ name: ent.name, kind: 'dir', children: walkFiles(path.join(archiveDir, ent.name), `openspec/changes/archive/${ent.name}`) });\n }\n archived.sort((a, b) => b.name.localeCompare(a.name)); // 日期前缀倒序\n }\n if (active.length) tree.push({ name: `进行中 (${active.length})`, kind: 'dir', children: active });\n if (archived.length) tree.push({ name: `归档 (${archived.length})`, kind: 'dir', defaultCollapsed: true, children: archived });\n const specsDir = path.join(root, 'openspec', 'specs');\n if (fs.existsSync(specsDir)) {\n const specs = walkFiles(specsDir, 'openspec/specs');\n if (specs.length) tree.push({ name: '能力 Specs', kind: 'dir', children: specs });\n }\n }\n if (hasDocs && fs.existsSync(path.join(root, 'docs'))) {\n const docs = walkFiles(path.join(root, 'docs'), 'docs');\n if (docs.length) tree.push({ name: 'docs', kind: 'dir', children: docs });\n }\n const skip = new Set(['openspec', 'docs', 'node_modules', '.git', 'dist', 'test-server']);\n // \"其他\"只收根目录的 md 文档(README/CLAUDE 等);构建配置(pom.xml/justfile 等)不收——对\"方案+日志\"定位是噪音\n const etc: TreeNode[] = [];\n try {\n for (const ent of fs.readdirSync(root, { withFileTypes: true })) {\n if (ent.name.startsWith('.') || skip.has(ent.name)) continue;\n const ext = path.extname(ent.name).toLowerCase();\n if (ent.isFile() && (ext === '.md' || ext === '.markdown')) etc.push({ name: ent.name, kind: 'file', path: ent.name });\n }\n } catch {}\n etc.sort((a, b) => a.name.localeCompare(b.name));\n if (etc.length) tree.push({ name: `其他 (${etc.length})`, kind: 'dir', children: etc });\n return tree;\n}\n","import { spawn, execFile, type ChildProcess } from 'node:child_process';\n\nexport interface Recipe { name: string; description: string; }\nexport type JustState = 'idle' | 'running' | 'exited';\nexport type JustEvent =\n | { type: 'log'; text: string }\n | { type: 'clear' }\n | { type: 'state'; state: JustState; recipe: string | null; code: number | null };\n\nconst MAX_BUFFER = 1000;\n\nexport class JustRunner {\n private cwd: string;\n private child: ChildProcess | null = null;\n private recipe: string | null = null;\n private state: JustState = 'idle';\n private code: number | null = null;\n private buffer: string[] = [];\n private pending = ''; // 行缓冲:块缓冲输出(如 maven)的 chunk 会在行中间断开,攒到 \\n 才切行\n private clients = new Set<(ev: JustEvent) => void>();\n private recipesCache: Recipe[] | null = null;\n\n constructor(cwd: string) { this.cwd = cwd; }\n\n recipes(): Promise<Recipe[]> {\n if (this.recipesCache) return Promise.resolve(this.recipesCache);\n return new Promise((resolve) => {\n execFile('just', ['--list', '--unsorted'], { cwd: this.cwd, maxBuffer: 1 << 20, timeout: 8000 }, (err, stdout) => {\n if (err) { resolve([]); return; }\n const out: Recipe[] = [];\n const seen = new Set<string>();\n for (const line of stdout.split(/\\r?\\n/).slice(1)) { // 跳过 \"Available recipes:\"\n const trimmed = line.trim();\n if (!trimmed) continue;\n const hashIdx = trimmed.indexOf('#');\n const sig = (hashIdx >= 0 ? trimmed.slice(0, hashIdx) : trimmed).trim();\n if (!sig) continue;\n const name = sig.split(/\\s+/)[0]; // \"hello msg=...\" -> \"hello\"\n if (seen.has(name)) continue;\n seen.add(name);\n out.push({ name, description: hashIdx >= 0 ? trimmed.slice(hashIdx + 1).trim() : '' });\n }\n this.recipesCache = out;\n resolve(out);\n });\n });\n }\n\n subscribe(fn: (ev: JustEvent) => void): () => void {\n this.clients.add(fn);\n // 连上即重放:历史日志 + 当前状态\n for (const text of this.buffer) fn({ type: 'log', text });\n fn({ type: 'state', state: this.state, recipe: this.recipe, code: this.code });\n return () => this.clients.delete(fn);\n }\n\n private emit(ev: JustEvent) { for (const fn of this.clients) fn(ev); }\n\n info() { return { state: this.state, recipe: this.recipe, code: this.code }; }\n\n /** 启动 recipe(调用方须先用 recipes() 校验名字);自动停旧进程 */\n start(recipe: string) {\n this.killChild();\n this.recipe = recipe;\n this.code = null;\n this.state = 'running';\n this.buffer = [];\n this.pending = '';\n this.emit({ type: 'clear' }); // 广播清屏:已连接的订阅者同步清掉上一个任务的残留日志\n this.emit({ type: 'state', state: 'running', recipe, code: null });\n const child = spawn('just', [recipe], {\n cwd: this.cwd,\n shell: true,\n env: {\n ...process.env,\n FORCE_COLOR: '1', // node 生态(chalk 等)\n // maven 检测非 tty 会关颜色;经 MAVEN_OPTS 强制开(保留用户已有值)\n MAVEN_OPTS: `${process.env.MAVEN_OPTS ?? ''} -Dstyle.color=always`.trim(),\n CI: '',\n },\n });\n this.child = child;\n const push = (d: Buffer) => {\n this.pending += d.toString();\n let idx: number;\n while ((idx = this.pending.indexOf('\\n')) >= 0) {\n const line = this.pending.slice(0, idx + 1);\n this.pending = this.pending.slice(idx + 1);\n this.pushLine(line);\n }\n // 无 \\n 的尾巴留在 pending,等下个 chunk(块缓冲输出会在行中断开,不能当独立行)\n };\n child.stdout?.on('data', push);\n child.stderr?.on('data', push);\n child.on('error', (err) => { this.pushLine(`[zdashboard] spawn error: ${err.message}\\n`); });\n child.on('exit', (code) => {\n if (this.pending) { this.pushLine(this.pending + '\\n'); this.pending = ''; } // flush 末尾无换行的残留\n this.child = null;\n this.state = 'exited';\n this.code = code ?? 0;\n this.emit({ type: 'state', state: 'exited', recipe: this.recipe, code: this.code });\n });\n }\n\n private pushLine(line: string) {\n this.buffer.push(line);\n if (this.buffer.length > MAX_BUFFER) this.buffer.shift();\n this.emit({ type: 'log', text: line });\n }\n\n stop() {\n this.killChild();\n }\n\n restart(recipe?: string) {\n const target = recipe ?? this.recipe;\n if (target) this.start(target);\n }\n\n private killChild() {\n const child = this.child;\n if (child?.pid) {\n try {\n if (process.platform === 'win32') spawn('taskkill', ['/PID', String(child.pid), '/T', '/F']);\n else child.kill('SIGTERM');\n } catch { /* 已退出 */ }\n }\n this.child = null;\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { fetchJson } from './api/fetch.js';\n\n/** .zgoal/config.yaml(zgoal skill 的禅道凭据配置,扁平 key: value) */\nexport interface ZgoalConfig {\n url: string;\n account: string;\n password?: string;\n token?: string;\n product: number;\n}\n\nexport interface ZenBug {\n id: number;\n title: string;\n severity: number | string;\n pri: number | string;\n status: string;\n assignedTo: string;\n openedBy?: string;\n /** 指派给 config.account 的本人 */\n mine: boolean;\n}\n\nexport type BugsResult =\n | { ok: true; url: string; total: number; bugs: ZenBug[] }\n | { ok: false; error: string };\n\n/** 极简扁平 yaml 解析(仅 key: value 行,够 .zgoal/config.yaml 用) */\nfunction loadZgoalConfig(root: string): ZgoalConfig | null {\n const file = path.join(root, '.zgoal', 'config.yaml');\n if (!fs.existsSync(file)) return null;\n const kv: Record<string, string> = {};\n for (const line of fs.readFileSync(file, 'utf8').split('\\n')) {\n const m = line.match(/^\\s*([A-Za-z_]\\w*)\\s*:\\s*(.+?)\\s*$/);\n if (m && !m[2].startsWith('#')) kv[m[1]] = m[2].replace(/^[\"']|[\"']$/g, '');\n }\n const product = Number(kv.product);\n if (!kv.url || !product) return null;\n return {\n url: kv.url.replace(/\\/+$/, ''),\n account: kv.account ?? '',\n password: kv.password,\n token: kv.token,\n product,\n };\n}\n\nlet tokenCache: { key: string; token: string; at: number } | null = null;\n\nasync function getToken(cfg: ZgoalConfig): Promise<string> {\n if (cfg.token) return cfg.token;\n const key = `${cfg.url}|${cfg.account}|${cfg.password ?? ''}`;\n if (tokenCache && tokenCache.key === key && Date.now() - tokenCache.at < 10 * 60_000) return tokenCache.token;\n const json = await fetchJson(`${cfg.url}/api.php/v1/tokens`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ account: cfg.account, password: cfg.password }),\n });\n const token = typeof json.token === 'string' ? json.token : '';\n if (!token) throw new Error('token 获取失败:检查 account / password');\n tokenCache = { key, token, at: Date.now() };\n return token;\n}\n\nfunction normBug(b: Record<string, unknown>, account: string): ZenBug {\n const assigned = b.assignedTo;\n const assignedTo =\n typeof assigned === 'string'\n ? assigned\n : assigned && typeof assigned === 'object' && 'realname' in (assigned as Record<string, unknown>)\n ? String((assigned as Record<string, unknown>).realname ?? '')\n : '';\n const assignedAccount =\n typeof assigned === 'string'\n ? assigned\n : assigned && typeof assigned === 'object'\n ? String((assigned as Record<string, unknown>).account ?? '')\n : '';\n const mine = !!account && (assignedAccount === account || assignedTo === account);\n return {\n id: Number(b.id),\n title: String(b.title ?? ''),\n severity: (b.severity as number | string) ?? 4,\n pri: (b.pri as number | string) ?? 3,\n status: String(b.status ?? ''),\n assignedTo,\n openedBy: typeof b.openedBy === 'string' ? b.openedBy : undefined,\n mine,\n };\n}\n\n/** 只读拉取禅道 bug 列表(GET,绝不写)。失败返回 ok:false,不抛。 */\nexport async function fetchBugs(root: string): Promise<BugsResult> {\n const cfg = loadZgoalConfig(root);\n if (!cfg) return { ok: false, error: '.zgoal/config.yaml 缺失或 url/product 未配置(由 zgoal skill 创建)' };\n try {\n const token = await getToken(cfg);\n const json = await fetchJson(\n `${cfg.url}/api.php/v1/products/${cfg.product}/bugs?page=1&limit=100`,\n { headers: { Token: token } },\n );\n const raw = Array.isArray(json.bugs) ? (json.bugs as Record<string, unknown>[]) : [];\n return { ok: true, url: cfg.url, total: Number(json.total ?? raw.length), bugs: raw.map((b) => normBug(b, cfg.account)) };\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return { ok: false, error: `禅道请求失败(${msg})——检查 url / 凭据 / 是否开启 RESTful API v1` };\n }\n}\n","import ky from 'ky';\nimport { HttpError, NetworkError } from '../errors.js';\n\nexport async function fetchJson(url: string, init?: RequestInit): Promise<Record<string, unknown>> {\n try {\n const res = await ky(url, { ...init, timeout: 8000, retry: 2 });\n return await res.json() as Record<string, unknown>;\n } catch (e) {\n if (e instanceof HttpError) throw e;\n if (e instanceof Error && e.name === 'TimeoutError') {\n throw new NetworkError(`请求超时: ${url}`);\n }\n if (e instanceof Error && e.name === 'HTTPError') {\n throw new HttpError((e as Error & { status?: number }).status ?? 500, e.message);\n }\n throw new NetworkError(`请求失败: ${url}`, e);\n }\n}\n","export class HttpError extends Error {\n constructor(\n public status: number,\n message: string,\n public body?: unknown,\n ) {\n super(message);\n this.name = 'HttpError';\n }\n}\n\nexport class NetworkError extends Error {\n constructor(message: string, public cause?: unknown) {\n super(message);\n this.name = 'NetworkError';\n }\n}\n\nexport function isHttpError(e: unknown): e is HttpError {\n return e instanceof HttpError;\n}\n","/**\n * zdashboard plugin system\n *\n * Plugin contract:\n * {\n * mode: string; // unique mode identifier, e.g. 'bugs'\n * label: string; // human label, e.g. '禅道'\n * icon?: string; // optional emoji or icon name\n * viewer: () => Promise<{ default: React.ComponentType }>;\n * sidebar?: () => Promise<{ default: React.ComponentType }>;\n * apiRoutes?: Record<string, (req: http.IncomingMessage, res: http.ServerResponse, root: string) => void>;\n * }\n */\n\nimport http from 'node:http';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface DashboardPlugin {\n mode: string;\n label: string;\n icon?: string;\n viewer?: () => Promise<{ default: React.ComponentType }>;\n sidebar?: () => Promise<{ default: React.ComponentType }>;\n apiRoutes?: Record<string, (req: http.IncomingMessage, res: http.ServerResponse, root: string) => void>;\n}\n\nexport interface PluginContext {\n root: string;\n appDir: string;\n}\n\nconst builtinPlugins = new Map<string, DashboardPlugin>();\n\nexport function registerBuiltin(plugin: DashboardPlugin) {\n builtinPlugins.set(plugin.mode, plugin);\n}\n\nexport function getBuiltin(mode: string): DashboardPlugin | undefined {\n return builtinPlugins.get(mode);\n}\n\nexport function allBuiltins(): DashboardPlugin[] {\n return Array.from(builtinPlugins.values());\n}\n\nexport async function loadExternalPlugins(pluginDirs: string[]): Promise<DashboardPlugin[]> {\n const plugins: DashboardPlugin[] = [];\n for (const dir of pluginDirs) {\n if (!fs.existsSync(dir)) continue;\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const indexPath = path.join(dir, entry.name, 'index.ts');\n if (!fs.existsSync(indexPath)) continue;\n try {\n const mod = await import(path.join(dir, entry.name, 'index.ts'));\n const plugin = mod.default as DashboardPlugin;\n if (plugin?.mode) {\n plugins.push(plugin);\n }\n } catch (e) {\n console.error(`[zdashboard] failed to load plugin ${entry.name}:`, e);\n }\n }\n }\n return plugins;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport YAML from 'yaml';\n\nexport type ItemState = 'open' | 'answered' | 'accepted' | 'dismissed';\nexport type ReviewStatus = 'draft' | 'reviewing' | 'passed' | 'rejected';\n\nexport interface ReviewItem {\n id: string;\n doc?: string;\n category?: string;\n severity?: 'high' | 'medium' | 'low';\n state: ItemState;\n question: string;\n answer?: string;\n}\n\nexport interface ReviewData {\n status: ReviewStatus;\n items: ReviewItem[];\n}\n\nconst REVIEW_FILE = 'review.yaml';\n\nexport class ReviewStore {\n private root: string;\n private file: string;\n private onChange?: () => void;\n\n constructor(root: string, onChange?: () => void) {\n this.root = root;\n this.file = path.join(root, REVIEW_FILE);\n this.onChange = onChange;\n }\n\n exists(): boolean { return fs.existsSync(this.file); }\n\n read(): ReviewData {\n try {\n const parsed = YAML.parse(fs.readFileSync(this.file, 'utf8')) as ReviewData;\n if (!parsed || !Array.isArray(parsed.items)) return { status: 'draft', items: [] };\n return parsed;\n } catch {\n return { status: 'draft', items: [] };\n }\n }\n\n private write(data: ReviewData) {\n fs.writeFileSync(this.file, YAML.stringify(data), 'utf8');\n this.onChange?.();\n }\n\n updateItem(id: string, patch: { answer?: string; state?: ItemState }): ReviewData {\n const data = this.read();\n const item = data.items.find((i) => i.id === id);\n if (!item) throw new Error(`item ${id} not found`);\n if (patch.answer !== undefined) item.answer = patch.answer;\n if (patch.state !== undefined) item.state = patch.state;\n if (patch.state === 'answered' && !patch.answer && !item.answer) item.answer = '';\n this.write(data);\n return data;\n }\n\n setStatus(status: ReviewStatus): ReviewData {\n const data = this.read();\n if (status === 'passed' && data.items.some((i) => i.state === 'open')) {\n throw new Error('存在未处理的评审项(open),不能通过');\n }\n data.status = status;\n this.write(data);\n return data;\n }\n\n docs(): string[] {\n try {\n return fs.readdirSync(this.root)\n .filter((f) => /\\.(md|markdown)$/i.test(f) && fs.statSync(path.join(this.root, f)).isFile())\n .sort();\n } catch { return []; }\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nexport type AssetType = 'page' | 'component' | 'icon' | 'token' | 'md' | 'video' | 'audio' | 'pdf' | 'code' | 'font' | 'other';\n\nconst PAGE_EXTS = ['.html', '.htm'];\nconst ICON_EXTS = ['.svg', '.png', '.ico', '.jpg', '.jpeg', '.gif', '.webp'];\nconst VIDEO_EXTS = ['.mp4', '.webm', '.mov', '.ogg', '.ogv'];\nconst AUDIO_EXTS = ['.mp3', '.wav', '.flac', '.aac', '.m4a'];\nconst CODE_EXTS = ['.js', '.mjs', '.ts', '.tsx', '.jsx', '.css', '.json', '.txt', '.xml', '.yml', '.yaml', '.sh', '.md'];\nconst FONT_EXTS = ['.woff', '.woff2', '.ttf', '.otf'];\nconst TOKEN_RE = /token|theme|design|color|palette|typograph/i;\n\nexport function categorize(rel: string, ext: string): AssetType {\n if (rel.indexOf('components/') === 0) return 'component';\n if (VIDEO_EXTS.includes(ext)) return 'video';\n if (AUDIO_EXTS.includes(ext)) return 'audio';\n if (ext === '.pdf') return 'pdf';\n if (ext === '.md') return 'md';\n if (FONT_EXTS.includes(ext)) return 'font';\n if (ICON_EXTS.includes(ext)) return 'icon';\n if (PAGE_EXTS.includes(ext)) return 'page';\n if (CODE_EXTS.includes(ext)) return TOKEN_RE.test(rel) && (ext === '.css' || ext === '.json') ? 'token' : 'code';\n return 'other';\n}\n\nexport interface AssetFile { path: string; name: string; ext: string; type: AssetType; }\nexport type ScanResult = Record<AssetType, AssetFile[]>;\n\nexport function scanAssets(root: string): ScanResult {\n const out: ScanResult = {} as ScanResult;\n const keys: AssetType[] = ['page','component','icon','token','md','video','audio','pdf','code','font','other'];\n for (const k of keys) out[k] = [];\n const SKIP = new Set(['node_modules', '.git', 'dist', 'build', 'coverage', '.next', '.cache']);\n function walk(dir: string, rel: string) {\n let ents: fs.Dirent[];\n try { ents = fs.readdirSync(dir, { withFileTypes: true }); } catch { return; }\n for (const ent of ents) {\n if (ent.name.startsWith('.') || SKIP.has(ent.name)) continue;\n const r = rel ? `${rel}/${ent.name}` : ent.name;\n if (ent.isDirectory()) { walk(path.join(dir, ent.name), r); continue; }\n const ext = path.extname(ent.name).toLowerCase();\n const t = categorize(r, ext);\n out[t].push({ path: r, name: ent.name, ext, type: t });\n }\n }\n walk(root, '');\n return out;\n}\n","{\n \"name\": \"zdashboard\",\n \"version\": \"1.3.2\",\n \"description\": \"ZCode skill dashboard platform — pluggable viewers for zdesign/zview/zreview/zgoal\",\n \"type\": \"module\",\n \"bin\": {\n \"zdashboard\": \"./dist/cli.js\"\n },\n \"files\": [\n \"dist\"\n ],\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"dev\": \"vite\",\n \"build\": \"tsup && vite build\",\n \"build:web\": \"vite build\",\n \"build:node\": \"tsup\",\n \"start\": \"node dist/cli.js\",\n \"preview\": \"vite preview\"\n },\n \"dependencies\": {\n \"@radix-ui/react-scroll-area\": \"^1.2.0\",\n \"@radix-ui/react-separator\": \"^1.1.0\",\n \"@radix-ui/react-slot\": \"^1.1.0\",\n \"@radix-ui/react-tooltip\": \"^1.1.2\",\n \"@uidotdev/usehooks\": \"^2.4.0\",\n \"ansi-to-react\": \"^6.1.6\",\n \"class-variance-authority\": \"^0.7.0\",\n \"clsx\": \"^2.1.1\",\n \"date-fns\": \"^3.6.0\",\n \"filesize\": \"^11.0.0\",\n \"highlight.js\": \"^11.11.1\",\n \"katex\": \"^0.16.11\",\n \"ky\": \"^1.7.0\",\n \"lodash-es\": \"^4.17.21\",\n \"lucide-react\": \"^0.460.0\",\n \"react\": \"^18.3.1\",\n \"react-dom\": \"^18.3.1\",\n \"react-error-boundary\": \"^5.0.0\",\n \"react-markdown\": \"^9.0.1\",\n \"rehype-autolink-headings\": \"^7.1.0\",\n \"rehype-highlight\": \"^7.0.1\",\n \"rehype-katex\": \"^7.0.1\",\n \"rehype-raw\": \"^7.0.0\",\n \"rehype-slug\": \"^6.0.0\",\n \"remark-frontmatter\": \"^5.0.0\",\n \"remark-gfm\": \"^4.0.0\",\n \"remark-math\": \"^6.0.0\",\n \"sonner\": \"^1.5.0\",\n \"tailwind-merge\": \"^2.5.4\",\n \"use-debounce\": \"^10.0.0\",\n \"yaml\": \"^2.9.0\"\n },\n \"devDependencies\": {\n \"@tailwindcss/typography\": \"^0.5.20\",\n \"@testing-library/jest-dom\": \"^7.0.1\",\n \"@testing-library/react\": \"^16.3.2\",\n \"@types/lodash-es\": \"^4.17.12\",\n \"@types/node\": \"^22.9.0\",\n \"@types/react\": \"^18.3.12\",\n \"@types/react-dom\": \"^18.3.1\",\n \"@vitejs/plugin-react\": \"^4.7.0\",\n \"autoprefixer\": \"^10.4.20\",\n \"jsdom\": \"^30.0.1\",\n \"postcss\": \"^8.4.49\",\n \"tailwindcss\": \"^3.4.14\",\n \"tailwindcss-animate\": \"^1.0.7\",\n \"tsup\": \"^8.3.5\",\n \"typescript\": \"^5.6.3\",\n \"vite\": \"^5.4.10\",\n \"vitest\": \"^1.6.0\"\n },\n \"pnpm\": {\n \"onlyBuiltDependencies\": [\n \"esbuild\"\n ]\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { execFile } from 'node:child_process';\n\nexport interface DetectResult {\n hasOpenspec: boolean;\n hasDocs: boolean;\n hasJust: boolean;\n hasBugs: boolean;\n}\n\nfunction justAvailable(cwd: string): Promise<boolean> {\n return new Promise((resolve) => {\n const child = execFile('just', ['--list', '--unsorted'], { cwd, timeout: 5000 }, (err) => {\n resolve(!err);\n });\n if (child.killed) resolve(false);\n });\n}\n\nexport async function detect(root: string): Promise<DetectResult> {\n const hasOpenspec = fs.existsSync(path.join(root, 'openspec'));\n const hasDocs = fs.existsSync(path.join(root, 'docs'));\n const hasJust = await justAvailable(root);\n const hasBugs = fs.existsSync(path.join(root, '.zgoal', 'config.yaml'));\n return { hasOpenspec, hasDocs, hasJust, hasBugs };\n}\n","import { createServer } from './server/index.js';\nimport { detect } from './server/detect.js';\n\nfunction parseArgs(a: string[]): Record<string, string | true> {\n const o: Record<string, string | true> = {};\n for (let i = 0; i < a.length; i++) {\n if (a[i].indexOf('--') === 0) {\n const n = a[i + 1];\n o[a[i].slice(2)] = n && n.indexOf('--') !== 0 ? a[++i] : true;\n }\n }\n return o;\n}\n\nconst args = parseArgs(process.argv.slice(2));\nconst root = (args.dir as string) ?? '.';\n\nconst det = await detect(root);\ncreateServer({\n root,\n port: args.port ? parseInt(args.port as string, 10) : undefined,\n open: !!args.open,\n detect: det,\n mode: args.mode as string | undefined,\n});\n"],"mappings":"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","names":["fs","path","fileURLToPath","root","fs","path","root","path","fs","fs","path","fs","path","root","fs","path","root","__dirname","path","fileURLToPath","fs","det","handler","fp","fs","path","execFile","root"]}
1
+ {"version":3,"sources":["../src/server/index.ts","../src/server/spec-scan.ts","../src/server/just-runner.ts","../src/server/bugs.ts","../src/server/api/fetch.ts","../src/server/errors.ts","../src/server/plugins.ts","../src/server/review-store.ts","../src/server/design-assets.ts","../package.json","../src/server/detect.ts","../src/cli.ts"],"sourcesContent":["import http from 'node:http';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport crypto from 'node:crypto';\nimport { exec } from 'node:child_process';\nimport { fileURLToPath } from 'node:url';\nimport { scanTree } from './spec-scan.js';\nimport { JustRunner } from './just-runner.js';\nimport { fetchBugs } from './bugs.js';\nimport { registerBuiltin, allBuiltins, type DashboardPlugin } from './plugins.js';\nimport { ReviewStore, type ItemState, type ReviewStatus } from './review-store.js';\nimport { scanAssets } from './design-assets.js';\nimport type { DetectResult } from './detect.js';\nimport pkg from '../../package.json' with { type: 'json' };\n\nconst VERSION = pkg.version;\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst STOP_TOKEN = crypto.randomBytes(12).toString('hex');\nconst INJECT = `<script>(function(){try{var es=new EventSource('/__reload');es.addEventListener('reload',function(){location.reload();});es.onerror=function(){es.close();};}catch(e){}document.addEventListener('click',function(e){var t=e.target;if(t&&t.closest){var a=t.closest('a[target]');if(a&&a.target!=='_self'){a.target='_self';}}},true);})();</script>`;\n\nconst MIME: Record<string, string> = {\n '.html': 'text/html; charset=utf-8', '.htm': 'text/html; charset=utf-8',\n '.css': 'text/css; charset=utf-8', '.js': 'application/javascript; charset=utf-8',\n '.mjs': 'application/javascript; charset=utf-8', '.json': 'application/json; charset=utf-8',\n '.svg': 'image/svg+xml', '.png': 'image/png', '.ico': 'image/x-icon',\n '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.gif': 'image/gif', '.webp': 'image/webp',\n '.md': 'text/markdown; charset=utf-8', '.txt': 'text/plain; charset=utf-8',\n '.yml': 'text/yaml; charset=utf-8', '.yaml': 'text/yaml; charset=utf-8',\n '.woff': 'font/woff', '.woff2': 'font/woff2', '.ttf': 'font/ttf',\n '.map': 'application/json; charset=utf-8',\n};\n\nexport interface ServerOptions {\n root: string;\n port?: number;\n open?: boolean;\n detect: DetectResult;\n dashboardDir?: string;\n mode?: string;\n}\n\nfunction readBody(req: http.IncomingMessage): Promise<string> {\n return new Promise((resolve) => {\n let data = '';\n req.on('data', (c) => (data += c));\n req.on('end', () => resolve(data));\n });\n}\n\nexport function createServer(opts: ServerOptions) {\n const ROOT = path.resolve(opts.root);\n const PORT0 = opts.port ?? 4190;\n const OPEN = !!opts.open;\n const APP_DIR = opts.dashboardDir ?? path.resolve(__dirname, 'web');\n if (!fs.existsSync(ROOT)) fs.mkdirSync(ROOT, { recursive: true });\n const det = opts.detect;\n const runner = new JustRunner(ROOT);\n const MODE = opts.mode;\n\n // register builtin plugins (server-side: apiRoutes only; viewer loaded by frontend)\n registerBuiltin({\n mode: 'bugs', label: '禅道 Bugs', icon: '🎯',\n apiRoutes: { '/__bugs': async (_, res) => { res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' }); fetchBugs(ROOT).then((r) => res.end(JSON.stringify(r))); } }\n });\n registerBuiltin({ mode: 'view', label: '项目浏览', icon: '👁️' });\n\n const reviewStore = new ReviewStore(ROOT);\n registerBuiltin({\n mode: 'review', label: '文档评审', icon: '✅',\n apiRoutes: {\n '/__review': async (_, res) => {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(reviewStore.read()));\n },\n '/__review/item': async (req, res) => {\n if (req.headers['x-stop-token'] !== STOP_TOKEN) { res.writeHead(403); res.end('forbidden'); return; }\n (async () => {\n try {\n const body = JSON.parse(await readBody(req) || '{}');\n const data = reviewStore.updateItem(body.id, { answer: body.answer, state: body.state as ItemState | undefined });\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify(data));\n } catch (e) {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: (e as Error).message }));\n }\n })();\n return;\n },\n '/__review/status': async (req, res) => {\n if (req.headers['x-stop-token'] !== STOP_TOKEN) { res.writeHead(403); res.end('forbidden'); return; }\n (async () => {\n try {\n const body = JSON.parse(await readBody(req) || '{}');\n const data = reviewStore.setStatus(body.status as ReviewStatus);\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify(data));\n } catch (e) {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: (e as Error).message }));\n }\n })();\n return;\n },\n '/__docs': async (_, res) => {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(reviewStore.docs()));\n },\n }\n });\n\n registerBuiltin({ mode: 'design', label: '设计资产', icon: '🎨' });\n\n // apply plugin routes\n registerBuiltin({\n mode: 'apply', label: '执行进度', icon: '⚙️',\n apiRoutes: {\n '/__apply': async (_, res) => {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(scanApplyChanges(ROOT)));\n },\n '/__apply/change': async (req, res) => {\n if (req.headers['x-stop-token'] !== STOP_TOKEN) { res.writeHead(403); res.end('forbidden'); return; }\n (async () => {\n try {\n const url = new URL(req.url || '', 'http://x');\n const name = url.searchParams.get('name');\n if (!name) { res.writeHead(400); res.end(JSON.stringify({ error: 'missing name' })); return; }\n const data = readApplyChange(ROOT, name);\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(data));\n } catch (e) { res.writeHead(400); res.end(JSON.stringify({ error: (e as Error).message })); }\n })();\n return;\n },\n }\n });\n\n const clients = new Set<http.ServerResponse>();\n const broadcast = (ev: string, data: unknown = '') => {\n const payload = `event: ${ev}\\ndata: ${JSON.stringify(data == null ? '' : data)}\\n\\n`;\n for (const c of clients) c.write(payload);\n };\n\n function serveFile(filePath: string, res: http.ServerResponse, injectHtml: boolean) {\n fs.readFile(filePath, (err, data) => {\n if (err) { res.writeHead(404); return res.end('Not found'); }\n const ext = path.extname(filePath).toLowerCase();\n const ct = MIME[ext] ?? 'application/octet-stream';\n let body = data;\n if (injectHtml && ext === '.html') {\n const s = data.toString('utf8');\n body = Buffer.from(s.indexOf('</body>') >= 0 ? s.replace('</body>', INJECT + '</body>') : s + INJECT);\n }\n res.writeHead(200, { 'Content-Type': ct, 'Cache-Control': 'no-cache' });\n res.end(body);\n });\n }\n\n function handler(req: http.IncomingMessage, res: http.ServerResponse) {\n const url = req.url!.split('?')[0];\n\n // ── SSE:文件变更 ──\n if (url === '/__reload') {\n res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', Connection: 'keep-alive' });\n res.write(': connected\\n\\n');\n clients.add(res);\n req.on('close', () => clients.delete(res));\n return;\n }\n if (url === '/__config') {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n return res.end(JSON.stringify({ stopToken: STOP_TOKEN }));\n }\n if (url === '/__stop' && req.method === 'POST') {\n if (req.headers['x-stop-token'] === STOP_TOKEN) {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end('{\"ok\":true}');\n runner.stop();\n setTimeout(() => { try { server.close(); } catch (e) { console.error('[zdashboard] server close failed:', e); } process.exit(0); }, 50);\n } else { res.writeHead(403); res.end('forbidden'); }\n return;\n }\n\n // ── 方案模式:树形文件清单(+探测结果) / 设计模式:资产分类清单 ──\n if (url === '/__files') {\n if (MODE === 'design') {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n return res.end(JSON.stringify(scanAssets(ROOT)));\n }\n const tree = scanTree(ROOT, det.hasOpenspec, det.hasDocs);\n const payload: TreeNodePayload = { tree, ...det };\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n return res.end(JSON.stringify(payload));\n }\n\n // ── 日志能力 ──\n if (url === '/__just/recipes') {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n runner.recipes().then((r) => res.end(JSON.stringify(r)));\n return;\n }\n if (url === '/__just/logs') {\n res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', Connection: 'keep-alive' });\n res.write(': connected\\n\\n');\n const unsub = runner.subscribe((ev) => res.write(`data: ${JSON.stringify(ev)}\\n\\n`));\n req.on('close', unsub);\n return;\n }\n const justAction = url.match(/^\\/__just\\/(start|stop|restart)$/);\n if (justAction && req.method === 'POST') {\n (async () => {\n if (req.headers['x-stop-token'] !== STOP_TOKEN) { res.writeHead(403); res.end('forbidden'); return; }\n const body = await readBody(req);\n let recipe: string | undefined;\n try { recipe = JSON.parse(body || '{}').recipe; } catch (e) { console.error('[zdashboard] invalid just action body:', e); }\n const act = justAction[1];\n if (act === 'start' || act === 'restart') {\n const target = recipe ?? runner.info().recipe;\n if (!target) { res.writeHead(400); res.end('{\"error\":\"no recipe\"}'); return; }\n const recipes = await runner.recipes();\n if (!recipes.some((r) => r.name === target)) { res.writeHead(403); res.end('{\"error\":\"unknown recipe\"}'); return; }\n runner.start(target);\n } else {\n runner.stop();\n }\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify(runner.info()));\n })();\n return;\n }\n\n // ── plugin API routes ──\n let handled = false;\n for (const plugin of allBuiltins()) {\n if (!plugin.apiRoutes) continue;\n for (const [route, handler] of Object.entries(plugin.apiRoutes)) {\n if (url === route) {\n handled = true;\n handler(req, res, ROOT);\n return;\n }\n }\n }\n\n // ── dashboard 前端 ──\n if (url === '/') return serveFile(path.join(APP_DIR, 'index.html'), res, false);\n if (url.indexOf('/__app/') === 0) {\n const fp = path.join(APP_DIR, url.slice(7));\n if (fp !== APP_DIR && fp.indexOf(APP_DIR + path.sep) !== 0) { res.writeHead(403); return res.end('Forbidden'); }\n return serveFile(fp, res, false);\n }\n if (url.indexOf('/assets/') === 0) {\n const fp = path.join(APP_DIR, decodeURIComponent(url));\n if (fp.indexOf(APP_DIR + path.sep) !== 0) { res.writeHead(403); return res.end('Forbidden'); }\n return serveFile(fp, res, false);\n }\n\n // ── 用户资产 ──\n const fp = path.join(ROOT, decodeURIComponent(url));\n if (fp !== ROOT && fp.indexOf(ROOT + path.sep) !== 0) { res.writeHead(403); return res.end('Forbidden'); }\n return serveFile(fp, res, true);\n }\n\n let server: http.Server;\n function start(port: number) {\n server = http.createServer(handler);\n server.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') { console.log(`[zdashboard] port ${port} busy, trying ${port + 1}`); start(port + 1); }\n else throw err;\n });\n server.listen(port, () => {\n const u = `http://localhost:${port}`;\n console.log(`[zdashboard] v${VERSION} dashboard -> ${u}`);\n console.log(`[zdashboard] project -> ${ROOT}`);\n console.log(`[zdashboard] mode -> ${MODE ?? '(auto)'}`);\n console.log(`[zdashboard] detect -> openspec:${det.hasOpenspec} docs:${det.hasDocs} just:${det.hasJust} bugs:${det.hasBugs}`);\n if (OPEN) exec(process.platform === 'darwin' ? `open ${u}` : `start ${u}`);\n });\n }\n\n let debounce: NodeJS.Timeout;\n try {\n fs.watch(ROOT, { recursive: true }, () => {\n clearTimeout(debounce);\n debounce = setTimeout(() => {\n broadcast('reload');\n broadcast('files');\n console.log(`[zdashboard] change -> reload + refresh tree (${clients.size} client${clients.size === 1 ? '' : 's'})`);\n }, 150);\n });\n } catch { console.log('[zdashboard] watch unavailable - static only.'); }\n\n start(PORT0);\n}\n\ninterface TreeNodePayload { tree: unknown; hasOpenspec: boolean; hasDocs: boolean; hasJust: boolean; hasBugs: boolean; }\n\ninterface ChangeSummary { name: string; path: string; total: number; done: number; hasProposal: boolean; hasDesign: boolean; }\ninterface ChangeDetail extends ChangeSummary { proposal?: string; design?: string; tasks: string; }\n\nfunction countTasks(md: string): { total: number; done: number } {\n const all = (md.match(/^\\s*-\\s*\\[[ xX]\\]\\s*/gm) || []).length;\n const done = (md.match(/^\\s*-\\s*\\[[xX]\\]\\s*/gm) || []).length;\n return { total: all, done };\n}\n\nfunction readText(p: string): string {\n try { return fs.readFileSync(p, 'utf8'); } catch { return ''; }\n}\n\nfunction scanApplyChanges(root: string): ChangeSummary[] {\n const changesDir = path.join(root, 'openspec', 'changes');\n if (!fs.existsSync(changesDir)) return [];\n const out: ChangeSummary[] = [];\n for (const ent of fs.readdirSync(changesDir, { withFileTypes: true })) {\n if (!ent.isDirectory() || ent.name.startsWith('.') || ent.name === 'archive') continue;\n const dir = path.join(changesDir, ent.name);\n const tasks = readText(path.join(dir, 'tasks.md'));\n const { total, done } = countTasks(tasks);\n out.push({ name: ent.name, path: `openspec/changes/${ent.name}`, total, done, hasProposal: fs.existsSync(path.join(dir, 'proposal.md')), hasDesign: fs.existsSync(path.join(dir, 'design.md')) });\n }\n out.sort((a, b) => a.name.localeCompare(b.name));\n return out;\n}\n\nfunction readApplyChange(root: string, name: string): ChangeDetail {\n const dir = path.join(root, 'openspec', 'changes', name);\n const proposal = readText(path.join(dir, 'proposal.md'));\n const design = readText(path.join(dir, 'design.md'));\n const tasks = readText(path.join(dir, 'tasks.md'));\n const { total, done } = countTasks(tasks);\n return { name, path: `openspec/changes/${name}`, total, done, hasProposal: !!proposal, hasDesign: !!design, proposal, design, tasks };\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nexport type NodeKind = 'file' | 'dir' | 'log';\nexport interface TreeNode {\n name: string;\n kind: NodeKind;\n path?: string; // file: 相对 root 的路径(点击预览用)\n defaultCollapsed?: boolean;\n children?: TreeNode[];\n}\n\nfunction walkFiles(absDir: string, relDir: string, depth = 0): TreeNode[] {\n if (depth > 4) return [];\n let ents: fs.Dirent[];\n try { ents = fs.readdirSync(absDir, { withFileTypes: true }); } catch { return []; }\n const nodes: TreeNode[] = [];\n for (const ent of ents) {\n if (ent.name.startsWith('.') || ent.name === 'node_modules') continue;\n const rel = relDir ? `${relDir}/${ent.name}` : ent.name;\n if (ent.isDirectory()) {\n nodes.push({ name: ent.name, kind: 'dir', children: walkFiles(path.join(absDir, ent.name), rel, depth + 1) });\n } else {\n nodes.push({ name: ent.name, kind: 'file', path: rel });\n }\n }\n nodes.sort((a, b) => (a.kind === b.kind ? a.name.localeCompare(b.name) : a.kind === 'dir' ? -1 : 1));\n return nodes;\n}\n\n/** 方案模式树形扫描:openspec 感知 + docs 聚合 + 其他兜底 */\nexport function scanTree(root: string, hasOpenspec: boolean, hasDocs: boolean): TreeNode[] {\n const tree: TreeNode[] = [];\n if (hasOpenspec && fs.existsSync(path.join(root, 'openspec', 'changes'))) {\n const changesDir = path.join(root, 'openspec', 'changes');\n const active: TreeNode[] = [];\n const archived: TreeNode[] = [];\n for (const ent of fs.readdirSync(changesDir, { withFileTypes: true })) {\n if (!ent.isDirectory() || ent.name.startsWith('.') || ent.name === 'archive') continue;\n active.push({ name: ent.name, kind: 'dir', children: walkFiles(path.join(changesDir, ent.name), `openspec/changes/${ent.name}`) });\n }\n active.sort((a, b) => a.name.localeCompare(b.name));\n const archiveDir = path.join(changesDir, 'archive');\n if (fs.existsSync(archiveDir)) {\n for (const ent of fs.readdirSync(archiveDir, { withFileTypes: true })) {\n if (!ent.isDirectory() || ent.name.startsWith('.')) continue;\n archived.push({ name: ent.name, kind: 'dir', children: walkFiles(path.join(archiveDir, ent.name), `openspec/changes/archive/${ent.name}`) });\n }\n archived.sort((a, b) => b.name.localeCompare(a.name)); // 日期前缀倒序\n }\n if (active.length) tree.push({ name: `进行中 (${active.length})`, kind: 'dir', children: active });\n if (archived.length) tree.push({ name: `归档 (${archived.length})`, kind: 'dir', defaultCollapsed: true, children: archived });\n const specsDir = path.join(root, 'openspec', 'specs');\n if (fs.existsSync(specsDir)) {\n const specs = walkFiles(specsDir, 'openspec/specs');\n if (specs.length) tree.push({ name: '能力 Specs', kind: 'dir', children: specs });\n }\n }\n if (hasDocs && fs.existsSync(path.join(root, 'docs'))) {\n const docs = walkFiles(path.join(root, 'docs'), 'docs');\n if (docs.length) tree.push({ name: 'docs', kind: 'dir', children: docs });\n }\n const skip = new Set(['openspec', 'docs', 'node_modules', '.git', 'dist', 'test-server']);\n // \"其他\"只收根目录的 md 文档(README/CLAUDE 等);构建配置(pom.xml/justfile 等)不收——对\"方案+日志\"定位是噪音\n const etc: TreeNode[] = [];\n try {\n for (const ent of fs.readdirSync(root, { withFileTypes: true })) {\n if (ent.name.startsWith('.') || skip.has(ent.name)) continue;\n const ext = path.extname(ent.name).toLowerCase();\n if (ent.isFile() && (ext === '.md' || ext === '.markdown')) etc.push({ name: ent.name, kind: 'file', path: ent.name });\n }\n } catch (e) { console.error('[zdashboard] scan root etc failed:', e); }\n etc.sort((a, b) => a.name.localeCompare(b.name));\n if (etc.length) tree.push({ name: `其他 (${etc.length})`, kind: 'dir', children: etc });\n return tree;\n}\n","import { spawn, execFile, type ChildProcess } from 'node:child_process';\n\nexport interface Recipe { name: string; description: string; }\nexport type JustState = 'idle' | 'running' | 'exited';\nexport type JustEvent =\n | { type: 'log'; text: string }\n | { type: 'clear' }\n | { type: 'state'; state: JustState; recipe: string | null; code: number | null };\n\nconst MAX_BUFFER = 1000;\n\nexport class JustRunner {\n private cwd: string;\n private child: ChildProcess | null = null;\n private recipe: string | null = null;\n private state: JustState = 'idle';\n private code: number | null = null;\n private buffer: string[] = [];\n private pending = ''; // 行缓冲:块缓冲输出(如 maven)的 chunk 会在行中间断开,攒到 \\n 才切行\n private clients = new Set<(ev: JustEvent) => void>();\n private recipesCache: Recipe[] | null = null;\n\n constructor(cwd: string) { this.cwd = cwd; }\n\n recipes(): Promise<Recipe[]> {\n if (this.recipesCache) return Promise.resolve(this.recipesCache);\n return new Promise((resolve) => {\n execFile('just', ['--list', '--unsorted'], { cwd: this.cwd, maxBuffer: 1 << 20, timeout: 8000 }, (err, stdout) => {\n if (err) { resolve([]); return; }\n const out: Recipe[] = [];\n const seen = new Set<string>();\n for (const line of stdout.split(/\\r?\\n/).slice(1)) { // 跳过 \"Available recipes:\"\n const trimmed = line.trim();\n if (!trimmed) continue;\n const hashIdx = trimmed.indexOf('#');\n const sig = (hashIdx >= 0 ? trimmed.slice(0, hashIdx) : trimmed).trim();\n if (!sig) continue;\n const name = sig.split(/\\s+/)[0]; // \"hello msg=...\" -> \"hello\"\n if (seen.has(name)) continue;\n seen.add(name);\n out.push({ name, description: hashIdx >= 0 ? trimmed.slice(hashIdx + 1).trim() : '' });\n }\n this.recipesCache = out;\n resolve(out);\n });\n });\n }\n\n subscribe(fn: (ev: JustEvent) => void): () => void {\n this.clients.add(fn);\n // 连上即重放:历史日志 + 当前状态\n for (const text of this.buffer) fn({ type: 'log', text });\n fn({ type: 'state', state: this.state, recipe: this.recipe, code: this.code });\n return () => this.clients.delete(fn);\n }\n\n private emit(ev: JustEvent) { for (const fn of this.clients) fn(ev); }\n\n info() { return { state: this.state, recipe: this.recipe, code: this.code }; }\n\n /** 启动 recipe(调用方须先用 recipes() 校验名字);自动停旧进程 */\n start(recipe: string) {\n this.killChild();\n this.recipe = recipe;\n this.code = null;\n this.state = 'running';\n this.buffer = [];\n this.pending = '';\n this.emit({ type: 'clear' }); // 广播清屏:已连接的订阅者同步清掉上一个任务的残留日志\n this.emit({ type: 'state', state: 'running', recipe, code: null });\n const child = spawn('just', [recipe], {\n cwd: this.cwd,\n shell: true,\n env: {\n ...process.env,\n FORCE_COLOR: '1', // node 生态(chalk 等)\n // maven 检测非 tty 会关颜色;经 MAVEN_OPTS 强制开(保留用户已有值)\n MAVEN_OPTS: `${process.env.MAVEN_OPTS ?? ''} -Dstyle.color=always`.trim(),\n CI: '',\n },\n });\n this.child = child;\n const push = (d: Buffer) => {\n this.pending += d.toString();\n let idx: number;\n while ((idx = this.pending.indexOf('\\n')) >= 0) {\n const line = this.pending.slice(0, idx + 1);\n this.pending = this.pending.slice(idx + 1);\n this.pushLine(line);\n }\n // 无 \\n 的尾巴留在 pending,等下个 chunk(块缓冲输出会在行中断开,不能当独立行)\n };\n child.stdout?.on('data', push);\n child.stderr?.on('data', push);\n child.on('error', (err) => { this.pushLine(`[zdashboard] spawn error: ${err.message}\\n`); });\n child.on('exit', (code) => {\n if (this.pending) { this.pushLine(this.pending + '\\n'); this.pending = ''; } // flush 末尾无换行的残留\n this.child = null;\n this.state = 'exited';\n this.code = code ?? 0;\n this.emit({ type: 'state', state: 'exited', recipe: this.recipe, code: this.code });\n });\n }\n\n private pushLine(line: string) {\n this.buffer.push(line);\n if (this.buffer.length > MAX_BUFFER) this.buffer.shift();\n this.emit({ type: 'log', text: line });\n }\n\n stop() {\n this.killChild();\n }\n\n restart(recipe?: string) {\n const target = recipe ?? this.recipe;\n if (target) this.start(target);\n }\n\n private killChild() {\n const child = this.child;\n if (child?.pid) {\n try {\n if (process.platform === 'win32') spawn('taskkill', ['/PID', String(child.pid), '/T', '/F']);\n else child.kill('SIGTERM');\n } catch { /* 已退出 */ }\n }\n this.child = null;\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { fetchJson } from './api/fetch.js';\n\n/** .zgoal/config.yaml(zgoal skill 的禅道凭据配置,扁平 key: value) */\nexport interface ZgoalConfig {\n url: string;\n account: string;\n password?: string;\n token?: string;\n product: number;\n}\n\nexport interface ZenBug {\n id: number;\n title: string;\n severity: number | string;\n pri: number | string;\n status: string;\n assignedTo: string;\n openedBy?: string;\n /** 指派给 config.account 的本人 */\n mine: boolean;\n}\n\nexport type BugsResult =\n | { ok: true; url: string; total: number; bugs: ZenBug[] }\n | { ok: false; error: string };\n\n/** 极简扁平 yaml 解析(仅 key: value 行,够 .zgoal/config.yaml 用) */\nfunction loadZgoalConfig(root: string): ZgoalConfig | null {\n const file = path.join(root, '.zgoal', 'config.yaml');\n if (!fs.existsSync(file)) return null;\n const kv: Record<string, string> = {};\n for (const line of fs.readFileSync(file, 'utf8').split('\\n')) {\n const m = line.match(/^\\s*([A-Za-z_]\\w*)\\s*:\\s*(.+?)\\s*$/);\n if (m && !m[2].startsWith('#')) kv[m[1]] = m[2].replace(/^[\"']|[\"']$/g, '');\n }\n const product = Number(kv.product);\n if (!kv.url || !product) return null;\n return {\n url: kv.url.replace(/\\/+$/, ''),\n account: kv.account ?? '',\n password: kv.password,\n token: kv.token,\n product,\n };\n}\n\nlet tokenCache: { key: string; token: string; at: number } | null = null;\n\nasync function getToken(cfg: ZgoalConfig): Promise<string> {\n if (cfg.token) return cfg.token;\n const key = `${cfg.url}|${cfg.account}|${cfg.password ?? ''}`;\n if (tokenCache && tokenCache.key === key && Date.now() - tokenCache.at < 10 * 60_000) return tokenCache.token;\n const json = await fetchJson(`${cfg.url}/api.php/v1/tokens`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ account: cfg.account, password: cfg.password }),\n });\n const token = typeof json.token === 'string' ? json.token : '';\n if (!token) throw new Error('token 获取失败:检查 account / password');\n tokenCache = { key, token, at: Date.now() };\n return token;\n}\n\nfunction normBug(b: Record<string, unknown>, account: string): ZenBug {\n const assigned = b.assignedTo;\n const assignedTo =\n typeof assigned === 'string'\n ? assigned\n : assigned && typeof assigned === 'object' && 'realname' in (assigned as Record<string, unknown>)\n ? String((assigned as Record<string, unknown>).realname ?? '')\n : '';\n const assignedAccount =\n typeof assigned === 'string'\n ? assigned\n : assigned && typeof assigned === 'object'\n ? String((assigned as Record<string, unknown>).account ?? '')\n : '';\n const mine = !!account && (assignedAccount === account || assignedTo === account);\n return {\n id: Number(b.id),\n title: String(b.title ?? ''),\n severity: (b.severity as number | string) ?? 4,\n pri: (b.pri as number | string) ?? 3,\n status: String(b.status ?? ''),\n assignedTo,\n openedBy: typeof b.openedBy === 'string' ? b.openedBy : undefined,\n mine,\n };\n}\n\n/** 只读拉取禅道 bug 列表(GET,绝不写)。失败返回 ok:false,不抛。 */\nexport async function fetchBugs(root: string): Promise<BugsResult> {\n const cfg = loadZgoalConfig(root);\n if (!cfg) return { ok: false, error: '.zgoal/config.yaml 缺失或 url/product 未配置(由 zgoal skill 创建)' };\n try {\n const token = await getToken(cfg);\n const json = await fetchJson(\n `${cfg.url}/api.php/v1/products/${cfg.product}/bugs?page=1&limit=100`,\n { headers: { Token: token } },\n );\n const raw = Array.isArray(json.bugs) ? (json.bugs as Record<string, unknown>[]) : [];\n return { ok: true, url: cfg.url, total: Number(json.total ?? raw.length), bugs: raw.map((b) => normBug(b, cfg.account)) };\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return { ok: false, error: `禅道请求失败(${msg})——检查 url / 凭据 / 是否开启 RESTful API v1` };\n }\n}\n","import ky from 'ky';\nimport { HttpError, NetworkError } from '../errors.js';\n\nexport async function fetchJson(url: string, init?: RequestInit): Promise<Record<string, unknown>> {\n try {\n const res = await ky(url, { ...init, timeout: 8000, retry: 2 });\n return await res.json() as Record<string, unknown>;\n } catch (e) {\n if (e instanceof HttpError) throw e;\n if (e instanceof Error && e.name === 'TimeoutError') {\n throw new NetworkError(`请求超时: ${url}`);\n }\n if (e instanceof Error && e.name === 'HTTPError') {\n throw new HttpError((e as Error & { status?: number }).status ?? 500, e.message);\n }\n throw new NetworkError(`请求失败: ${url}`, e);\n }\n}\n","export class HttpError extends Error {\n constructor(\n public status: number,\n message: string,\n public body?: unknown,\n ) {\n super(message);\n this.name = 'HttpError';\n }\n}\n\nexport class NetworkError extends Error {\n constructor(message: string, public cause?: unknown) {\n super(message);\n this.name = 'NetworkError';\n }\n}\n\nexport function isHttpError(e: unknown): e is HttpError {\n return e instanceof HttpError;\n}\n","/**\n * zdashboard plugin system\n *\n * Plugin contract:\n * {\n * mode: string; // unique mode identifier, e.g. 'bugs'\n * label: string; // human label, e.g. '禅道'\n * icon?: string; // optional emoji or icon name\n * viewer: () => Promise<{ default: React.ComponentType }>;\n * sidebar?: () => Promise<{ default: React.ComponentType }>;\n * apiRoutes?: Record<string, (req: http.IncomingMessage, res: http.ServerResponse, root: string) => void>;\n * }\n */\n\nimport http from 'node:http';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport React from 'react';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface DashboardPlugin {\n mode: string;\n label: string;\n icon?: string;\n viewer?: () => Promise<{ default: React.ComponentType }>;\n sidebar?: () => Promise<{ default: React.ComponentType }>;\n apiRoutes?: Record<string, (req: http.IncomingMessage, res: http.ServerResponse, root: string) => void>;\n}\n\nexport interface PluginContext {\n root: string;\n appDir: string;\n}\n\nconst builtinPlugins = new Map<string, DashboardPlugin>();\n\nexport function registerBuiltin(plugin: DashboardPlugin) {\n builtinPlugins.set(plugin.mode, plugin);\n}\n\nexport function getBuiltin(mode: string): DashboardPlugin | undefined {\n return builtinPlugins.get(mode);\n}\n\nexport function allBuiltins(): DashboardPlugin[] {\n return Array.from(builtinPlugins.values());\n}\n\nexport async function loadExternalPlugins(pluginDirs: string[]): Promise<DashboardPlugin[]> {\n const plugins: DashboardPlugin[] = [];\n for (const dir of pluginDirs) {\n if (!fs.existsSync(dir)) continue;\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const indexPath = path.join(dir, entry.name, 'index.ts');\n if (!fs.existsSync(indexPath)) continue;\n try {\n const mod = await import(path.join(dir, entry.name, 'index.ts'));\n const plugin = mod.default as DashboardPlugin;\n if (plugin?.mode) {\n plugins.push(plugin);\n }\n } catch (e) {\n console.error(`[zdashboard] failed to load plugin ${entry.name}:`, e);\n }\n }\n }\n return plugins;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport YAML from 'yaml';\n\nexport type ItemState = 'open' | 'answered' | 'accepted' | 'dismissed';\nexport type ReviewStatus = 'draft' | 'reviewing' | 'passed' | 'rejected';\n\nexport interface ReviewItem {\n id: string;\n doc?: string;\n category?: string;\n severity?: 'high' | 'medium' | 'low';\n state: ItemState;\n question: string;\n answer?: string;\n}\n\nexport interface ReviewData {\n status: ReviewStatus;\n items: ReviewItem[];\n}\n\nconst REVIEW_FILE = 'review.yaml';\n\nexport class ReviewStore {\n private root: string;\n private file: string;\n private onChange?: () => void;\n\n constructor(root: string, onChange?: () => void) {\n this.root = root;\n this.file = path.join(root, REVIEW_FILE);\n this.onChange = onChange;\n }\n\n exists(): boolean { return fs.existsSync(this.file); }\n\n read(): ReviewData {\n try {\n const parsed = YAML.parse(fs.readFileSync(this.file, 'utf8')) as ReviewData;\n if (!parsed || !Array.isArray(parsed.items)) return { status: 'draft', items: [] };\n return parsed;\n } catch {\n return { status: 'draft', items: [] };\n }\n }\n\n private write(data: ReviewData) {\n fs.writeFileSync(this.file, YAML.stringify(data), 'utf8');\n this.onChange?.();\n }\n\n updateItem(id: string, patch: { answer?: string; state?: ItemState }): ReviewData {\n const data = this.read();\n const item = data.items.find((i) => i.id === id);\n if (!item) throw new Error(`item ${id} not found`);\n if (patch.answer !== undefined) item.answer = patch.answer;\n if (patch.state !== undefined) item.state = patch.state;\n if (patch.state === 'answered' && !patch.answer && !item.answer) item.answer = '';\n this.write(data);\n return data;\n }\n\n setStatus(status: ReviewStatus): ReviewData {\n const data = this.read();\n if (status === 'passed' && data.items.some((i) => i.state === 'open')) {\n throw new Error('存在未处理的评审项(open),不能通过');\n }\n data.status = status;\n this.write(data);\n return data;\n }\n\n docs(): string[] {\n try {\n return fs.readdirSync(this.root)\n .filter((f) => /\\.(md|markdown)$/i.test(f) && fs.statSync(path.join(this.root, f)).isFile())\n .sort();\n } catch { return []; }\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nexport type AssetType = 'page' | 'component' | 'icon' | 'token' | 'md' | 'video' | 'audio' | 'pdf' | 'code' | 'font' | 'other';\n\nconst PAGE_EXTS = ['.html', '.htm'];\nconst ICON_EXTS = ['.svg', '.png', '.ico', '.jpg', '.jpeg', '.gif', '.webp'];\nconst VIDEO_EXTS = ['.mp4', '.webm', '.mov', '.ogg', '.ogv'];\nconst AUDIO_EXTS = ['.mp3', '.wav', '.flac', '.aac', '.m4a'];\nconst CODE_EXTS = ['.js', '.mjs', '.ts', '.tsx', '.jsx', '.css', '.json', '.txt', '.xml', '.yml', '.yaml', '.sh', '.md'];\nconst FONT_EXTS = ['.woff', '.woff2', '.ttf', '.otf'];\nconst TOKEN_RE = /token|theme|design|color|palette|typograph/i;\n\nexport function categorize(rel: string, ext: string): AssetType {\n if (rel.indexOf('components/') === 0) return 'component';\n if (VIDEO_EXTS.includes(ext)) return 'video';\n if (AUDIO_EXTS.includes(ext)) return 'audio';\n if (ext === '.pdf') return 'pdf';\n if (ext === '.md') return 'md';\n if (FONT_EXTS.includes(ext)) return 'font';\n if (ICON_EXTS.includes(ext)) return 'icon';\n if (PAGE_EXTS.includes(ext)) return 'page';\n if (CODE_EXTS.includes(ext)) return TOKEN_RE.test(rel) && (ext === '.css' || ext === '.json') ? 'token' : 'code';\n return 'other';\n}\n\nexport interface AssetFile { path: string; name: string; ext: string; type: AssetType; }\nexport type ScanResult = Record<AssetType, AssetFile[]>;\n\nexport function scanAssets(root: string): ScanResult {\n const out: ScanResult = {} as ScanResult;\n const keys: AssetType[] = ['page','component','icon','token','md','video','audio','pdf','code','font','other'];\n for (const k of keys) out[k] = [];\n const SKIP = new Set(['node_modules', '.git', 'dist', 'build', 'coverage', '.next', '.cache']);\n function walk(dir: string, rel: string) {\n let ents: fs.Dirent[];\n try { ents = fs.readdirSync(dir, { withFileTypes: true }); } catch { return; }\n for (const ent of ents) {\n if (ent.name.startsWith('.') || SKIP.has(ent.name)) continue;\n const r = rel ? `${rel}/${ent.name}` : ent.name;\n if (ent.isDirectory()) { walk(path.join(dir, ent.name), r); continue; }\n const ext = path.extname(ent.name).toLowerCase();\n const t = categorize(r, ext);\n out[t].push({ path: r, name: ent.name, ext, type: t });\n }\n }\n walk(root, '');\n return out;\n}\n","{\n \"name\": \"zdashboard\",\n \"version\": \"1.4.0\",\n \"description\": \"ZCode skill dashboard platform — pluggable viewers for zdesign/zview/zreview/zgoal\",\n \"type\": \"module\",\n \"bin\": {\n \"zdashboard\": \"./dist/cli.js\"\n },\n \"files\": [\n \"dist\"\n ],\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"dev\": \"vite\",\n \"build\": \"tsup && vite build\",\n \"build:web\": \"vite build\",\n \"build:node\": \"tsup\",\n \"start\": \"node dist/cli.js\",\n \"preview\": \"vite preview\"\n },\n \"dependencies\": {\n \"@radix-ui/react-scroll-area\": \"^1.2.0\",\n \"@radix-ui/react-separator\": \"^1.1.0\",\n \"@radix-ui/react-slot\": \"^1.1.0\",\n \"@radix-ui/react-tooltip\": \"^1.1.2\",\n \"@uidotdev/usehooks\": \"^2.4.0\",\n \"ansi-to-react\": \"^6.1.6\",\n \"class-variance-authority\": \"^0.7.0\",\n \"clsx\": \"^2.1.1\",\n \"date-fns\": \"^3.6.0\",\n \"filesize\": \"^11.0.0\",\n \"highlight.js\": \"^11.11.1\",\n \"katex\": \"^0.16.11\",\n \"ky\": \"^1.7.0\",\n \"lodash-es\": \"^4.17.21\",\n \"lucide-react\": \"^0.460.0\",\n \"react\": \"^18.3.1\",\n \"react-dom\": \"^18.3.1\",\n \"react-error-boundary\": \"^5.0.0\",\n \"react-markdown\": \"^9.0.1\",\n \"rehype-autolink-headings\": \"^7.1.0\",\n \"rehype-highlight\": \"^7.0.1\",\n \"rehype-katex\": \"^7.0.1\",\n \"rehype-raw\": \"^7.0.0\",\n \"rehype-slug\": \"^6.0.0\",\n \"remark-frontmatter\": \"^5.0.0\",\n \"remark-gfm\": \"^4.0.0\",\n \"remark-math\": \"^6.0.0\",\n \"sonner\": \"^1.5.0\",\n \"tailwind-merge\": \"^2.5.4\",\n \"use-debounce\": \"^10.0.0\",\n \"yaml\": \"^2.9.0\"\n },\n \"devDependencies\": {\n \"@tailwindcss/typography\": \"^0.5.20\",\n \"@testing-library/jest-dom\": \"^7.0.1\",\n \"@testing-library/react\": \"^16.3.2\",\n \"@types/lodash-es\": \"^4.17.12\",\n \"@types/node\": \"^22.9.0\",\n \"@types/react\": \"^18.3.12\",\n \"@types/react-dom\": \"^18.3.1\",\n \"@vitejs/plugin-react\": \"^4.7.0\",\n \"autoprefixer\": \"^10.4.20\",\n \"jsdom\": \"^30.0.1\",\n \"postcss\": \"^8.4.49\",\n \"tailwindcss\": \"^3.4.14\",\n \"tailwindcss-animate\": \"^1.0.7\",\n \"tsup\": \"^8.3.5\",\n \"typescript\": \"^5.6.3\",\n \"vite\": \"^5.4.10\",\n \"vitest\": \"^1.6.0\"\n },\n \"pnpm\": {\n \"onlyBuiltDependencies\": [\n \"esbuild\"\n ]\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { execFile } from 'node:child_process';\n\nexport interface DetectResult {\n hasOpenspec: boolean;\n hasDocs: boolean;\n hasJust: boolean;\n hasBugs: boolean;\n}\n\nfunction justAvailable(cwd: string): Promise<boolean> {\n return new Promise((resolve) => {\n const child = execFile('just', ['--list', '--unsorted'], { cwd, timeout: 5000 }, (err) => {\n resolve(!err);\n });\n if (child.killed) resolve(false);\n });\n}\n\nexport async function detect(root: string): Promise<DetectResult> {\n const hasOpenspec = fs.existsSync(path.join(root, 'openspec'));\n const hasDocs = fs.existsSync(path.join(root, 'docs'));\n const hasJust = await justAvailable(root);\n const hasBugs = fs.existsSync(path.join(root, '.zgoal', 'config.yaml'));\n return { hasOpenspec, hasDocs, hasJust, hasBugs };\n}\n","import { createServer } from './server/index.js';\nimport { detect } from './server/detect.js';\n\nfunction parseArgs(a: string[]): Record<string, string | true> {\n const o: Record<string, string | true> = {};\n for (let i = 0; i < a.length; i++) {\n if (a[i].indexOf('--') === 0) {\n const n = a[i + 1];\n o[a[i].slice(2)] = n && n.indexOf('--') !== 0 ? a[++i] : true;\n }\n }\n return o;\n}\n\nconst args = parseArgs(process.argv.slice(2));\nconst root = (args.dir as string) ?? '.';\n\nconst det = await detect(root);\ncreateServer({\n root,\n port: args.port ? parseInt(args.port as string, 10) : undefined,\n open: !!args.open,\n detect: det,\n mode: args.mode as string | undefined,\n});\n"],"mappings":"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","names":["fs","path","fileURLToPath","root","fs","path","root","path","fs","fs","path","fs","path","root","fs","path","root","__dirname","path","fileURLToPath","fs","det","handler","fp","root","fs","path","execFile","root"]}
@@ -0,0 +1,26 @@
1
+ import{c as u,r as o,u as k,j as e,k as N}from"./index-C041WeTi.js";/**
2
+ * @license lucide-react v0.460.0 - ISC
3
+ *
4
+ * This source code is licensed under the ISC license.
5
+ * See the LICENSE file in the root directory of this source tree.
6
+ */const w=u("ImageOff",[["line",{x1:"2",x2:"22",y1:"2",y2:"22",key:"a6p6uj"}],["path",{d:"M10.41 10.41a2 2 0 1 1-2.83-2.83",key:"1bzlo9"}],["line",{x1:"13.5",x2:"6",y1:"13.5",y2:"21",key:"1q0aeu"}],["line",{x1:"18",x2:"21",y1:"12",y2:"15",key:"5mozeu"}],["path",{d:"M3.59 3.59A1.99 1.99 0 0 0 3 5v14a2 2 0 0 0 2 2h14c.55 0 1.052-.22 1.41-.59",key:"mmje98"}],["path",{d:"M21 15V5a2 2 0 0 0-2-2H9",key:"43el77"}]]);/**
7
+ * @license lucide-react v0.460.0 - ISC
8
+ *
9
+ * This source code is licensed under the ISC license.
10
+ * See the LICENSE file in the root directory of this source tree.
11
+ */const S=u("Monitor",[["rect",{width:"20",height:"14",x:"2",y:"3",rx:"2",key:"48i651"}],["line",{x1:"8",x2:"16",y1:"21",y2:"21",key:"1svkeh"}],["line",{x1:"12",x2:"12",y1:"17",y2:"21",key:"vw1qmm"}]]);/**
12
+ * @license lucide-react v0.460.0 - ISC
13
+ *
14
+ * This source code is licensed under the ISC license.
15
+ * See the LICENSE file in the root directory of this source tree.
16
+ */const $=u("SlidersHorizontal",[["line",{x1:"21",x2:"14",y1:"4",y2:"4",key:"obuewd"}],["line",{x1:"10",x2:"3",y1:"4",y2:"4",key:"1q6298"}],["line",{x1:"21",x2:"12",y1:"12",y2:"12",key:"1iu8h1"}],["line",{x1:"8",x2:"3",y1:"12",y2:"12",key:"ntss68"}],["line",{x1:"21",x2:"16",y1:"20",y2:"20",key:"14d8ph"}],["line",{x1:"12",x2:"3",y1:"20",y2:"20",key:"m0wm8r"}],["line",{x1:"14",x2:"14",y1:"2",y2:"6",key:"14e1ph"}],["line",{x1:"8",x2:"8",y1:"10",y2:"14",key:"1i6ji0"}],["line",{x1:"16",x2:"16",y1:"18",y2:"22",key:"1lctlv"}]]);/**
17
+ * @license lucide-react v0.460.0 - ISC
18
+ *
19
+ * This source code is licensed under the ISC license.
20
+ * See the LICENSE file in the root directory of this source tree.
21
+ */const V=u("Smartphone",[["rect",{width:"14",height:"20",x:"5",y:"2",rx:"2",ry:"2",key:"1yt0o3"}],["path",{d:"M12 18h.01",key:"mhygvu"}]]);/**
22
+ * @license lucide-react v0.460.0 - ISC
23
+ *
24
+ * This source code is licensed under the ISC license.
25
+ * See the LICENSE file in the root directory of this source tree.
26
+ */const I=u("Tablet",[["rect",{width:"16",height:"20",x:"4",y:"2",rx:"2",ry:"2",key:"76otgf"}],["line",{x1:"12",x2:"12.01",y1:"18",y2:"18",key:"1dp563"}]]),C=[{key:"page",label:"页面"},{key:"component",label:"组件"},{key:"icon",label:"图标"},{key:"token",label:"Tokens"},{key:"md",label:"文档"},{key:"video",label:"视频"},{key:"audio",label:"音频"},{key:"pdf",label:"PDF"},{key:"code",label:"代码"},{key:"font",label:"字体"},{key:"other",label:"其他"}];function M({path:t}){return e.jsx("iframe",{src:"/"+encodeURI(t),title:"预览",className:"w-full h-full border-0 bg-white"})}function R({path:t}){const[i,c]=o.useState("-"),[x,n]=o.useState(1),[m,d]=o.useState(!1),l=t.split("/").pop(),r={backgroundImage:"linear-gradient(45deg,hsl(var(--border)) 25%,transparent 25%),linear-gradient(-45deg,hsl(var(--border)) 25%,transparent 25%),linear-gradient(45deg,transparent 75%,hsl(var(--border)) 75%),linear-gradient(-45deg,transparent 75%,hsl(var(--border)) 75%)",backgroundSize:"16px 16px",backgroundPosition:"0 0,0 8px,8px -8px,-8px 0"};return e.jsxs("div",{className:"flex flex-col h-full",children:[e.jsxs("div",{className:"flex-none px-4 py-2 border-b text-xs flex items-center gap-3",children:[e.jsx("span",{className:"font-mono text-foreground",children:l}),e.jsx("span",{className:"text-muted-foreground",children:i}),e.jsxs("div",{className:"ml-auto flex items-center gap-1",children:[e.jsx("button",{onClick:()=>n(s=>Math.max(.25,+(s-.25).toFixed(2))),className:"w-6 h-6 rounded bg-muted hover:bg-muted/70","aria-label":"缩小",children:"−"}),e.jsxs("span",{className:"w-10 text-center text-muted-foreground",children:[Math.round(x*100),"%"]}),e.jsx("button",{onClick:()=>n(s=>Math.min(8,+(s+.25).toFixed(2))),className:"w-6 h-6 rounded bg-muted hover:bg-muted/70","aria-label":"放大",children:"+"}),e.jsx("button",{onClick:()=>n(1),className:"ml-1 px-2 h-6 rounded bg-muted hover:bg-muted/70",children:"复位"})]})]}),e.jsx("div",{className:"flex-1 min-h-0 overflow-auto grid place-items-center p-6",style:r,children:m?e.jsx("p",{className:"text-muted-foreground",children:"该格式无法预览"}):e.jsx("img",{src:"/"+encodeURI(t),alt:l,style:{transform:`scale(${x})`},className:"max-w-full max-h-full object-contain transition-transform",onLoad:s=>c(`${s.currentTarget.naturalWidth} × ${s.currentTarget.naturalHeight} px`),onError:()=>d(!0)})})]})}function z({path:t}){const[i,c]=o.useState('<p class="p-3 text-xs text-muted-foreground">解析中…</p>');return o.useEffect(()=>{fetch("/"+encodeURI(t),{cache:"no-store"}).then(x=>x.text()).then(x=>{const n=x.match(/--[A-Za-z0-9_-]+\s*:\s*[^;}\n]+/g)??[];if(!n.length){c('<p class="p-3 text-xs">未发现 CSS 变量</p>');return}const m=a=>/^(#([0-9a-fA-F]{3,8})\b|rgb|rgba|hsl|hsla|oklch|oklab|color\()/i.test(a.trim()),d=n.filter(a=>m(a)),l=n.filter(a=>/font|family|type/.test(a.toLowerCase())&&!m(a)),r=n.filter(a=>!d.includes(a)&&!l.includes(a));let s="";if(d.length){s+=`<div class="mb-7"><div class="mb-3 text-[11px] font-semibold uppercase text-muted-foreground">配色 · ${d.length}</div><div class="grid gap-3" style="grid-template-columns:repeat(auto-fill,minmax(150px,1fr))">`;for(const a of d)s+=`<div class="overflow-hidden rounded-lg border bg-background"><div class="h-[72px] border-b" style="background:${a}"></div><div class="px-2.5 pt-2 font-mono text-[11px] break-all">${a.split(":")[0].trim()}</div><div class="px-2.5 pb-2 text-xs text-muted-foreground">${a.split(":").slice(1).join(":").trim()}</div></div>`;s+="</div></div>"}if(l.length){s+=`<div class="mb-7"><div class="mb-3 text-[11px] font-semibold uppercase text-muted-foreground">字体 · ${l.length}</div><div class="grid gap-3" style="grid-template-columns:repeat(auto-fill,minmax(150px,1fr))">`;for(const a of l)s+=`<div class="overflow-hidden rounded-lg border bg-background"><div class="grid h-[72px] place-items-center text-2xl" style="font-family:${a.split(":").slice(1).join(":").trim()}">Aa</div><div class="px-2.5 font-mono text-[11px]">${a.split(":")[0].trim()}</div></div>`;s+="</div></div>"}if(r.length){s+=`<div class="mb-7"><div class="mb-3 text-[11px] font-semibold uppercase text-muted-foreground">其他 · ${r.length}</div><div class="flex flex-col gap-1">`;for(const a of r)s+=`<div class="flex justify-between gap-3 px-2.5 py-1.5 rounded border bg-background text-xs"><span class="font-mono">${a.split(":")[0].trim()}</span><span class="text-muted-foreground">${a.split(":").slice(1).join(":").trim()}</span></div>`;s+="</div></div>"}c(s||'<p class="p-3 text-xs">无</p>')})},[t]),e.jsx("div",{className:"p-8",dangerouslySetInnerHTML:{__html:i}})}function E({path:t}){return e.jsx("div",{className:"grid place-items-center p-8",children:e.jsx("video",{src:"/"+encodeURI(t),controls:!0,className:"max-w-full max-h-[80vh] rounded border"})})}function U({path:t}){return e.jsx("div",{className:"grid place-items-center p-8",children:e.jsx("audio",{src:"/"+encodeURI(t),controls:!0,className:"w-full max-w-2xl"})})}function T({path:t}){return e.jsx("div",{className:"grid place-items-center p-8 h-full",children:e.jsx("iframe",{src:"/"+encodeURI(t),title:"PDF",className:"w-full h-full max-h-[80vh] rounded border bg-white"})})}function h({path:t}){const[i,c]=o.useState("");return o.useEffect(()=>{fetch("/"+encodeURI(t),{cache:"no-store"}).then(x=>x.text()).then(c)},[t]),e.jsx("pre",{className:"p-6 text-xs leading-relaxed overflow-auto h-full",children:i||"加载中…"})}function F({path:t}){const[i,c]=o.useState("");return o.useEffect(()=>{c("/"+encodeURI(t))},[t]),e.jsxs("div",{className:"p-8 h-full flex flex-col gap-4",children:[e.jsxs("div",{className:"text-xs text-muted-foreground",children:["字体文件: ",t]}),e.jsxs("div",{className:"flex-1 grid place-items-center",children:[i&&e.jsx("link",{rel:"preload",as:"font",href:i,crossOrigin:"anonymous"}),e.jsx("div",{className:"text-6xl",style:{fontFamily:i?`url(${i})`:"serif"},children:"Aa 字体"})]})]})}function H({path:t}){return e.jsx("div",{className:"grid place-items-center h-full text-center text-muted-foreground",children:e.jsxs("div",{children:[e.jsx(w,{className:"h-10 w-10 mx-auto mb-3 opacity-50"}),e.jsx("p",{children:"该格式无法预览"}),e.jsx("p",{className:"mt-1 font-mono text-xs break-all",children:t})]})})}const A={page:M,icon:R,token:z,md:N,video:E,audio:U,pdf:T,code:h,component:h,font:F};function O(t){return A[t]??H}function P({mode:t,onMode:i,w:c,h:x,onW:n,onH:m}){const d=[{v:0,icon:e.jsx(S,{className:"h-3.5 w-3.5"}),label:"桌面"},{v:768,icon:e.jsx(I,{className:"h-3.5 w-3.5"}),label:"768"},{v:375,icon:e.jsx(V,{className:"h-3.5 w-3.5"}),label:"375"},{v:"custom",icon:e.jsx($,{className:"h-3.5 w-3.5"}),label:"自定义"}],l="w-[50px] h-7 px-1 text-center text-xs rounded border border-border bg-background text-foreground [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none focus:outline-none focus:border-primary";return e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"flex items-center gap-1 rounded-md border border-border p-0.5 bg-muted",children:d.map(r=>e.jsxs("button",{onClick:()=>i(r.v),className:`h-7 gap-1.5 px-2.5 rounded text-xs inline-flex items-center ${t===r.v?"bg-secondary text-secondary-foreground":"hover:bg-muted/70"}`,children:[r.icon,e.jsx("span",{className:"hidden sm:inline",children:r.label})]},String(r.v)))}),e.jsxs("span",{className:"flex items-center gap-1 text-xs text-muted-foreground",children:[e.jsx("input",{type:"number",value:c,min:280,max:3e3,step:8,onChange:r=>n(Number(r.target.value)),"aria-label":"自定义宽度",className:l}),e.jsx("span",{className:"text-muted-foreground/70",children:"×"}),e.jsx("input",{type:"number",value:x,min:400,max:3e3,step:8,onChange:r=>m(Number(r.target.value)),"aria-label":"自定义高度",className:l}),e.jsx("span",{className:"text-[11px] text-muted-foreground/70",children:"px"})]})]})}function D({open:t,current:i,onSelect:c,refreshKey:x}){const[n,m]=o.useState(null);if(o.useEffect(()=>{fetch("/__files",{cache:"no-store"}).then(l=>l.json()).then(m)},[x]),!n)return t?e.jsx("p",{className:"p-3 text-xs text-muted-foreground",children:"加载中…"}):null;let d=0;for(const l in n)d+=n[l].length;return e.jsxs("aside",{className:`border-r bg-background overflow-auto fixed sm:static z-20 h-full sm:h-auto w-[78%] max-w-[252px] sm:max-w-none sm:w-[252px] transition-transform duration-200 ${t?"translate-x-0":"-translate-x-full sm:hidden"}`,children:[e.jsxs("div",{className:"p-3 text-xs text-muted-foreground",children:[d," 个资产"]}),C.map(l=>{const r=n[l.key]??[];return r.length?e.jsxs("div",{className:"mb-1",children:[e.jsxs("div",{className:"px-3.5 pt-2 pb-1 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground",children:[l.label," ",e.jsx("span",{className:"font-normal",children:r.length})]}),r.map(s=>e.jsxs("button",{onClick:()=>c(s.path,s.type),className:`w-full text-left flex items-center gap-2 px-3.5 py-1.5 text-xs border-l-2 border-transparent hover:bg-muted ${i===s.path?"bg-muted font-medium border-primary":"text-muted-foreground"}`,children:[e.jsx("span",{className:"break-all",children:s.name}),e.jsx("span",{className:"font-mono text-[10px] text-muted-foreground",children:s.ext})]},s.path))]},l.key):null})]})}function W(){const[t,i]=o.useState(null),[c,x]=o.useState(0),[n,m]=o.useState(0),[d,l]=o.useState(1024),[r,s]=o.useState(768),[a,g]=o.useState(!0),b=o.useRef(!1);k(()=>{},()=>x(f=>f+1),b);const p=t?O(t.type):null,y=n===0?"桌面":n==="custom"?`${d} × ${r}`:`${n}px`,v={backgroundImage:"radial-gradient(circle at 1px 1px, hsl(var(--border)) 1px, transparent 0)",backgroundSize:"20px 20px"};return e.jsxs("div",{className:"flex h-full",children:[e.jsx(D,{open:a,current:(t==null?void 0:t.path)??null,onSelect:(f,j)=>i({path:f,type:j}),refreshKey:c}),a&&e.jsx("div",{className:"absolute inset-0 z-10 bg-black/40 sm:hidden",onClick:()=>g(!1)}),e.jsx("section",{className:"flex-1 min-h-0 flex flex-col",children:t&&p?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"h-[38px] flex-none flex items-center justify-between px-3.5 border-b bg-background text-xs",children:[e.jsx("span",{className:"font-mono truncate",children:t.path}),e.jsx("span",{className:"text-muted-foreground ml-3 flex-none",children:y}),e.jsx(P,{mode:n,onMode:m,w:d,h:r,onW:l,onH:s})]}),e.jsx("div",{className:"flex-1 min-h-0 overflow-auto p-6 relative",style:v,children:t.type==="page"?e.jsx("div",{className:"mx-auto bg-background border rounded-lg shadow-sm overflow-hidden",style:{maxWidth:n===0?void 0:n==="custom"?d:n,height:n==="custom"?r:"100%"},children:e.jsx(p,{path:t.path})}):e.jsx("div",{className:"mx-auto max-w-5xl h-full bg-background border rounded-lg shadow-sm overflow-auto",children:e.jsx(p,{path:t.path})})})]}):e.jsx("div",{className:"flex-1 grid place-items-center text-muted-foreground",children:e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"mx-auto mb-3.5 grid h-14 w-14 place-items-center rounded-[14px] bg-primary text-primary-foreground text-2xl font-bold",children:"z"}),e.jsx("p",{children:"从左侧选择一个资产预览"}),e.jsx("p",{className:"mt-1 text-xs",children:"点顶栏菜单按钮展开文件树 · 改文件即时刷新"})]})})})]})}export{W as default};
@@ -0,0 +1,16 @@
1
+ import{c as m,r as o,u as k,j as e,M as v,b as N,d as S,e as T,f as C,g as _,a as E,h as A,i as M}from"./index-C041WeTi.js";/**
2
+ * @license lucide-react v0.460.0 - ISC
3
+ *
4
+ * This source code is licensed under the ISC license.
5
+ * See the LICENSE file in the root directory of this source tree.
6
+ */const R=m("Check",[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]]);/**
7
+ * @license lucide-react v0.460.0 - ISC
8
+ *
9
+ * This source code is licensed under the ISC license.
10
+ * See the LICENSE file in the root directory of this source tree.
11
+ */const z=m("Send",[["path",{d:"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z",key:"1ffxy3"}],["path",{d:"m21.854 2.147-10.94 10.939",key:"12cjpa"}]]);/**
12
+ * @license lucide-react v0.460.0 - ISC
13
+ *
14
+ * This source code is licensed under the ISC license.
15
+ * See the LICENSE file in the root directory of this source tree.
16
+ */const I=m("X",[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]]),L={draft:"bg-zinc-500 text-white",reviewing:"bg-amber-500 text-white",passed:"bg-emerald-600 text-white",rejected:"bg-red-500 text-white"},O={draft:"草案",reviewing:"评审中",passed:"已通过",rejected:"未通过"},X=[{key:"all",label:"全部"},{key:"open",label:"待处理"},{key:"answered",label:"已答复"},{key:"accepted",label:"已采纳"},{key:"dismissed",label:"已驳回"}],$={high:"bg-red-500",medium:"bg-amber-500",low:"bg-sky-500"},D={high:"高",medium:"中",low:"低"},P={open:"border-l-red-500",answered:"border-l-sky-500",accepted:"border-l-emerald-500",dismissed:"border-l-zinc-400"},U={open:"待处理",answered:"已答复",accepted:"已采纳",dismissed:"已驳回"};function V({children:s}){const d=o.useRef(null),[i,a]=o.useState(!1),n=async()=>{var r;const c=((r=d.current)==null?void 0:r.innerText)??"";try{await navigator.clipboard.writeText(c),a(!0),setTimeout(()=>a(!1),1500)}catch(l){console.error("[zdashboard] clipboard copy failed:",l)}};return e.jsxs("div",{className:"not-prose relative my-4 group",children:[e.jsx("button",{onClick:n,className:"absolute right-2 top-2 z-10 px-2 py-0.5 rounded border border-border bg-background/80 text-[11px] opacity-0 group-hover:opacity-100 transition-opacity",children:i?"已复制":"复制"}),e.jsx("pre",{ref:d,className:"overflow-auto rounded-md border bg-[#0d1117] p-3 text-xs leading-relaxed",children:s})]})}function F({path:s}){const[d,i]=o.useState(null);if(o.useEffect(()=>{let r=!0;return fetch("/"+encodeURI(s),{cache:"no-store"}).then(l=>l.text()).then(l=>{r&&i(l)}).catch(()=>{r&&i("")}),()=>{r=!1}},[s]),d===null)return e.jsx("p",{className:"p-3 text-xs text-muted-foreground",children:"加载中…"});const a=d.match(/^---\n([\s\S]*?)\n---\n?/),n=(a==null?void 0:a[1])??null,c=n?d.slice(a[0].length):d;return e.jsxs("div",{className:"prose dark:prose-invert mx-auto max-w-3xl p-8 prose-headings:scroll-mt-4 prose-pre:bg-transparent prose-pre:p-0 prose-pre:m-0",children:[n&&e.jsxs("details",{className:"not-prose mb-4 rounded border p-3 text-sm",children:[e.jsx("summary",{className:"cursor-pointer font-medium",children:"YAML frontmatter"}),e.jsx("pre",{className:"mt-2 whitespace-pre-wrap text-xs",children:n})]}),e.jsx(v,{remarkPlugins:[E,A,M],rehypePlugins:[N,S,[T,{behavior:"wrap",properties:{className:["no-underline"]}}],[C,{detect:!0,ignoreMissing:!0}],[_,{strict:!1}]],components:{pre:({children:r})=>e.jsx(V,{children:r}),a:({href:r,children:l})=>{const x=r==null?void 0:r.startsWith("http");return e.jsx("a",{href:r,target:x?"_blank":void 0,rel:x?"noreferrer noopener":void 0,children:l})}},children:c})]})}function B({item:s,token:d,onUpdated:i}){const[a,n]=o.useState(s.answer??"");o.useEffect(()=>n(s.answer??""),[s.id,s.answer]);const c=async r=>{const l=await fetch("/__review/item",{method:"POST",headers:{"x-stop-token":d,"Content-Type":"application/json"},body:JSON.stringify({id:s.id,...r})});l.ok&&i(await l.json())};return e.jsxs("div",{className:`border rounded-lg bg-background shadow-sm border-l-4 ${P[s.state]??""}`,children:[e.jsxs("div",{className:"flex items-center gap-2 px-3 pt-2.5 text-[11px] text-muted-foreground",children:[s.severity&&e.jsx("span",{className:`h-2 w-2 rounded-full ${$[s.severity]??"bg-muted-foreground"}`}),e.jsx("span",{className:"font-medium",children:s.category??"通用"}),s.severity&&e.jsx("span",{className:"uppercase",children:D[s.severity]??s.severity}),e.jsx("span",{className:"ml-auto",children:U[s.state]??s.state})]}),e.jsx("p",{className:"px-3 py-2 text-sm leading-relaxed",children:s.question}),e.jsxs("div",{className:"px-3 pb-3 flex flex-col gap-2",children:[e.jsx("textarea",{value:a,onChange:r=>n(r.target.value),placeholder:"答复 / 补充说明…",rows:2,className:"w-full rounded border border-border bg-background px-2 py-1.5 text-xs focus:outline-none focus:border-primary resize-y"}),e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsxs("button",{onClick:()=>c({answer:a,state:"answered"}),className:"inline-flex items-center gap-1 h-7 px-2.5 rounded bg-muted hover:bg-muted/70 text-xs",children:[e.jsx(z,{className:"h-3 w-3"}),"答复"]}),e.jsxs("button",{onClick:()=>c({answer:a,state:"accepted"}),className:"inline-flex items-center gap-1 h-7 px-2.5 rounded bg-emerald-600 hover:bg-emerald-500 text-white text-xs",children:[e.jsx(R,{className:"h-3 w-3"}),"采纳"]}),e.jsxs("button",{onClick:()=>c({answer:a,state:"dismissed"}),className:"inline-flex items-center gap-1 h-7 px-2.5 rounded bg-muted hover:bg-muted/70 text-xs",children:[e.jsx(I,{className:"h-3 w-3"}),"驳回"]})]})]})]})}function H(){const[s,d]=o.useState(null),[i,a]=o.useState([]),[n,c]=o.useState(null),[r,l]=o.useState(""),[x,y]=o.useState("all"),[h,b]=o.useState(""),j=o.useRef(!1),f=()=>{fetch("/__review",{cache:"no-store"}).then(t=>t.json()).then(d),fetch("/__docs",{cache:"no-store"}).then(t=>t.json()).then(t=>{a(t),c(p=>p&&t.includes(p)?p:t[0]??null)})};o.useEffect(()=>{f(),fetch("/__config").then(t=>t.json()).then(t=>l(t.stopToken??""))},[]),k(()=>{},f,j);const u={all:0,open:0,answered:0,accepted:0,dismissed:0};for(const t of(s==null?void 0:s.items)??[])u.all++,u[t.state]++;const w=async()=>{b("");const t=await fetch("/__review/status",{method:"POST",headers:{"x-stop-token":r,"Content-Type":"application/json"},body:'{"status":"passed"}'});t.ok?d(await t.json()):b((await t.json()).error??"failed")},g=((s==null?void 0:s.items)??[]).filter(t=>n?(t.doc??"")===n||!t.doc:!0).filter(t=>x==="all"||t.state===x).sort((t,p)=>({high:0,medium:1,low:2})[t.severity??"medium"]-{high:0,medium:1,low:2}[p.severity??"medium"]);return e.jsxs("div",{className:"flex h-full",children:[e.jsxs("aside",{className:"w-[240px] flex-none border-r bg-background overflow-auto",children:[e.jsx("div",{className:"px-3 pt-3 pb-1 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground",children:"文档"}),i.map(t=>e.jsx("button",{onClick:()=>c(t),className:`w-full text-left px-3 py-1.5 text-xs border-l-2 border-transparent hover:bg-muted ${n===t?"bg-muted font-medium border-primary":"text-muted-foreground"}`,children:t},t)),e.jsx("div",{className:"px-3 pt-4 pb-1 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground",children:"评审项"}),X.map(t=>e.jsxs("button",{onClick:()=>y(t.key),className:`w-full text-left px-3 py-1.5 text-xs border-l-2 border-transparent hover:bg-muted flex justify-between ${x===t.key?"bg-muted font-medium border-primary text-foreground":"text-muted-foreground"}`,children:[e.jsx("span",{children:t.label}),e.jsx("span",{className:"font-mono text-[10px]",children:u[t.key]})]},t.key))]}),e.jsxs("div",{className:"flex-1 min-h-0 flex flex-col",children:[e.jsxs("div",{className:"flex-none flex items-center gap-2 px-3.5 border-b bg-background",children:[s&&e.jsx("span",{className:`px-2 py-0.5 rounded text-[11px] font-medium ${L[s.status]??""}`,children:O[s.status]??s.status}),e.jsx("button",{onClick:w,disabled:!s||s.status==="passed"||u.open>0,className:"ml-auto h-7 px-3 rounded bg-emerald-600 hover:bg-emerald-500 disabled:opacity-50 disabled:cursor-not-allowed text-white text-xs",children:"通过"})]}),h&&e.jsx("div",{className:"bg-red-500/10 text-red-600 dark:text-red-400 text-xs px-3.5 py-1.5 border-b border-red-500/20",children:h}),e.jsxs("div",{className:"flex-1 min-h-0 flex",children:[e.jsx("div",{className:"flex-1 min-h-0 overflow-auto border-r bg-background",children:n?e.jsx(F,{path:n}):e.jsx("p",{className:"p-6 text-sm text-muted-foreground",children:"左侧选择文档查看"})}),e.jsxs("div",{className:"w-[380px] flex-none overflow-auto p-3 flex flex-col gap-3",style:{backgroundImage:"radial-gradient(circle at 1px 1px, hsl(var(--border)) 1px, transparent 0)",backgroundSize:"20px 20px"},children:[g.length===0&&e.jsx("p",{className:"text-xs text-muted-foreground text-center pt-6",children:"无评审项(换文档 / 状态筛选试试)"}),g.map(t=>e.jsx(B,{item:t,token:r,onUpdated:d},t.id))]})]})]})]})}export{H as default};
@@ -0,0 +1,11 @@
1
+ import{c as x,r as a,j as e,B as h}from"./index-C041WeTi.js";/**
2
+ * @license lucide-react v0.460.0 - ISC
3
+ *
4
+ * This source code is licensed under the ISC license.
5
+ * See the LICENSE file in the root directory of this source tree.
6
+ */const p=x("ExternalLink",[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]]);/**
7
+ * @license lucide-react v0.460.0 - ISC
8
+ *
9
+ * This source code is licensed under the ISC license.
10
+ * See the LICENSE file in the root directory of this source tree.
11
+ */const g=x("RefreshCw",[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]]),f=[{key:"mine",label:"我的"},{key:"all",label:"全部"},{key:"active",label:"active"},{key:"resolved",label:"resolved"},{key:"closed",label:"closed"}];function b({status:s}){const r=s==="active"?"bg-red-500/10 text-red-600 dark:text-red-400 border-red-500/30":s==="resolved"?"bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 border-emerald-500/30":"bg-muted text-muted-foreground border-border";return e.jsx("span",{className:`inline-flex items-center px-1.5 py-0.5 rounded border text-[10px] font-mono ${r}`,children:s})}function y({severity:s}){const r=Number(s),n=r<=1?"bg-red-500/10 text-red-600 dark:text-red-400":r===2?"bg-orange-500/10 text-orange-600 dark:text-orange-400":r===3?"bg-yellow-500/10 text-yellow-600 dark:text-yellow-500":"bg-muted text-muted-foreground";return e.jsxs("span",{className:`inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-mono font-medium ${n}`,children:["S",r]})}function k(){const[s,r]=a.useState(null),[n,o]=a.useState(!1),[l,m]=a.useState("mine"),d=a.useCallback(()=>{o(!0),fetch("/__bugs",{cache:"no-store"}).then(t=>t.json()).then(r).finally(()=>o(!1))},[]);a.useEffect(d,[d]);const u=t=>l==="all"?!0:l==="mine"?t.mine:t.status===l,c=s!=null&&s.ok?s.bugs.filter(u):[],i=s!=null&&s.ok?{mine:s.bugs.filter(t=>t.mine).length,all:s.bugs.length,active:s.bugs.filter(t=>t.status==="active").length,resolved:s.bugs.filter(t=>t.status==="resolved").length,closed:s.bugs.filter(t=>t.status==="closed").length}:null;return e.jsxs("div",{className:"mx-auto max-w-5xl h-full flex flex-col bg-background border rounded-lg shadow-sm overflow-hidden",children:[e.jsxs("div",{className:"flex-none flex items-center gap-2 px-3 py-2 border-b",children:[f.map(t=>e.jsxs("button",{onClick:()=>m(t.key),className:`px-2 py-1 rounded text-xs border transition-colors ${l===t.key?"bg-primary text-primary-foreground border-primary":"border-border text-muted-foreground hover:bg-muted"}`,children:[t.label,i&&e.jsx("span",{className:"ml-1 opacity-70",children:i[t.key]})]},t.key)),e.jsx("span",{className:"ml-auto text-[11px] text-muted-foreground",children:"禅道 · 只读"}),e.jsx(h,{variant:"ghost",size:"sm",className:"h-7 w-7 p-0",onClick:d,title:"刷新",children:e.jsx(g,{className:`h-3.5 w-3.5 ${n?"animate-spin":""}`})})]}),e.jsx("div",{className:"flex-1 min-h-0 overflow-auto",children:s?s.ok?c.length?e.jsxs("table",{className:"w-full text-xs",children:[e.jsx("thead",{className:"sticky top-0 bg-background border-b",children:e.jsxs("tr",{className:"text-left text-muted-foreground",children:[e.jsx("th",{className:"px-3 py-2 font-medium w-16",children:"#"}),e.jsx("th",{className:"px-3 py-2 font-medium",children:"标题"}),e.jsx("th",{className:"px-3 py-2 font-medium w-14",children:"严重度"}),e.jsx("th",{className:"px-3 py-2 font-medium w-20",children:"状态"}),e.jsx("th",{className:"px-3 py-2 font-medium w-20",children:"指派"})]})}),e.jsx("tbody",{children:c.map(t=>e.jsxs("tr",{className:"border-b last:border-0 hover:bg-muted/50",children:[e.jsx("td",{className:"px-3 py-2 font-mono text-muted-foreground",children:t.id}),e.jsx("td",{className:"px-3 py-2",children:e.jsxs("button",{className:"text-left hover:text-primary hover:underline flex items-center gap-1",onClick:()=>window.open(`${s.url}/bug-view-${t.id}.html`,"_blank","noopener"),title:"在禅道打开",children:[e.jsx("span",{className:"truncate max-w-[420px]",children:t.title}),e.jsx(p,{className:"h-3 w-3 shrink-0 text-muted-foreground"})]})}),e.jsx("td",{className:"px-3 py-2",children:e.jsx(y,{severity:t.severity})}),e.jsx("td",{className:"px-3 py-2",children:e.jsx(b,{status:t.status})}),e.jsx("td",{className:"px-3 py-2 text-muted-foreground",children:t.assignedTo||"—"})]},t.id))})]}):e.jsx("p",{className:"p-4 text-xs text-muted-foreground",children:l==="mine"?"没有指派给你的 bug 🎉":"无 bug 🎉(该状态下)"}):e.jsx("p",{className:"p-4 text-xs text-destructive",children:s.error}):e.jsx("p",{className:"p-4 text-xs text-muted-foreground",children:"加载中…"})})]})}export{k as BugViewer,k as default};
@@ -0,0 +1,2 @@
1
+ import{r as l,j as e,F as i,M as f,a as g}from"./index-C041WeTi.js";import{F as b}from"./folder-open-m5HYQ2Fs.js";function v(s,t){return t===0?0:Math.round(s/t*100)}function j({done:s,total:t}){const n=v(s,t),d=n===100?"bg-emerald-500/10 text-emerald-600 border-emerald-500/30":n>0?"bg-amber-500/10 text-amber-600 border-amber-500/30":"bg-muted text-muted-foreground border-border";return e.jsxs("span",{className:`inline-flex items-center px-1.5 py-0.5 rounded border text-[10px] font-mono ${d}`,children:[s,"/",t," · ",n,"%"]})}function k({tasks:s}){const t=s.split(`
2
+ `).filter(n=>n.trim().startsWith("- ["));return t.length?e.jsx("ul",{className:"space-y-1 text-xs",children:t.map((n,d)=>{const r=/- \[[xX]\]/.test(n),c=n.replace(/^-\s*\[[ xX]\]\s*/,"");return e.jsxs("li",{className:`flex items-start gap-2 ${r?"text-foreground":"text-muted-foreground"}`,children:[r?e.jsx("span",{className:"mt-0.5 h-3.5 w-3.5 shrink-0 rounded-full bg-emerald-500 text-white flex items-center justify-center text-[8px]",children:"✓"}):e.jsx("span",{className:"mt-0.5 h-3.5 w-3.5 shrink-0 rounded-full border border-muted-foreground/50"}),e.jsx("span",{children:c})]},d)})}):e.jsx("p",{className:"text-xs text-muted-foreground",children:"无 tasks.md"})}function w({item:s,onSelect:t}){return e.jsxs("button",{type:"button",onClick:t,className:"w-full text-left rounded-lg border bg-card p-4 hover:bg-muted/50 transition-colors",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[e.jsx(b,{className:"h-4 w-4 text-muted-foreground"}),e.jsx("span",{className:"text-sm font-medium font-mono truncate",children:s.name}),e.jsx(j,{done:s.done,total:s.total})]}),e.jsxs("div",{className:"flex items-center gap-3 text-[11px] text-muted-foreground",children:[e.jsx("span",{className:s.hasProposal?"text-foreground":"",children:"proposal"}),e.jsx("span",{className:s.hasDesign?"text-foreground":"",children:"design"})]})]})}function C(){const[s,t]=l.useState([]),[n,d]=l.useState(null),[r,c]=l.useState(null),[m,o]=l.useState(!0),[u,h]=l.useState(null),p=l.useCallback(()=>{o(!0),d(null),c(null),fetch("/__apply",{cache:"no-store"}).then(a=>a.json()).then(t).catch(a=>h(a.message)).finally(()=>o(!1))},[]);l.useEffect(()=>{p()},[p]);const N=l.useCallback(a=>{o(!0),d(a),fetch(`/__apply/change?name=${encodeURIComponent(a)}`,{cache:"no-store",headers:{"x-stop-token":"skip"}}).then(x=>x.json()).then(c).catch(x=>h(x.message)).finally(()=>o(!1))},[]);return m&&!s.length?e.jsx("div",{className:"flex h-full items-center justify-center text-muted-foreground",children:e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"mx-auto mb-3.5 grid h-14 w-14 place-items-center rounded-[14px] bg-primary text-primary-foreground text-2xl font-bold animate-pulse",children:"⚙️"}),e.jsx("p",{children:"加载执行进度…"})]})}):u?e.jsx("div",{className:"flex h-full items-center justify-center text-destructive",children:e.jsx("p",{children:u})}):e.jsxs("div",{className:"mx-auto max-w-5xl h-full flex flex-col bg-background border rounded-lg shadow-sm overflow-hidden",children:[e.jsxs("div",{className:"flex-none px-4 py-3 border-b flex items-center gap-2",children:[e.jsx("span",{className:"text-sm font-medium",children:"OpenSpec 执行进度"}),e.jsx("span",{className:"ml-auto text-[11px] text-muted-foreground",children:"openspec/changes/"})]}),e.jsxs("div",{className:"flex-1 min-h-0 overflow-auto p-4 space-y-4",children:[s.length?e.jsx("div",{className:"grid gap-3 sm:grid-cols-2",children:s.map(a=>e.jsx(w,{item:a,onSelect:()=>N(a.name)},a.name))}):e.jsxs("div",{className:"text-center text-muted-foreground py-8",children:[e.jsx("p",{className:"text-sm",children:"没有进行中的 change"}),e.jsx("p",{className:"text-xs mt-1",children:"在 openspec/changes/ 下创建 change 后会显示在这里"})]}),n&&r&&!m&&e.jsxs("section",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("h3",{className:"text-sm font-medium",children:r.name}),e.jsx(j,{done:r.done,total:r.total})]}),r.proposal&&e.jsxs("div",{children:[e.jsxs("h4",{className:"text-xs font-medium text-muted-foreground mb-2 flex items-center gap-1",children:[e.jsx(i,{className:"h-3 w-3"})," proposal.md"]}),e.jsx("div",{className:"prose dark:prose-invert max-w-none text-xs border rounded-lg p-3 bg-card",children:e.jsx(f,{remarkPlugins:[g],children:r.proposal})})]}),r.design&&e.jsxs("div",{children:[e.jsxs("h4",{className:"text-xs font-medium text-muted-foreground mb-2 flex items-center gap-1",children:[e.jsx(i,{className:"h-3 w-3"})," design.md"]}),e.jsx("div",{className:"prose dark:prose-invert max-w-none text-xs border rounded-lg p-3 bg-card",children:e.jsx(f,{remarkPlugins:[g],children:r.design})})]}),e.jsxs("div",{children:[e.jsxs("h4",{className:"text-xs font-medium text-muted-foreground mb-2 flex items-center gap-1",children:[e.jsx(i,{className:"h-3 w-3"})," tasks.md"]}),e.jsx("div",{className:"border rounded-lg p-3 bg-card",children:e.jsx(k,{tasks:r.tasks})})]})]})]})]})}export{C as ApplyViewer,C as default};