zdashboard 1.3.0 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -17,7 +17,8 @@ zdashboard/ ← 一个核心包,永远不写业务逻辑
|
|
|
17
17
|
├── src/plugins/ ← 内置 plugins(随核心发版)
|
|
18
18
|
│ ├── bugs/
|
|
19
19
|
│ ├── view/
|
|
20
|
-
│
|
|
20
|
+
│ ├── review/
|
|
21
|
+
│ └── design/
|
|
21
22
|
└── package.json
|
|
22
23
|
```
|
|
23
24
|
|
|
@@ -58,6 +59,7 @@ export default {
|
|
|
58
59
|
npx zdashboard@latest --mode bugs --dir <项目根> --open
|
|
59
60
|
npx zdashboard@latest --mode view --dir <项目根> --open
|
|
60
61
|
npx zdashboard@latest --mode review --dir .zreview --open
|
|
62
|
+
npx zdashboard@latest --mode design --dir <产出根> --open
|
|
61
63
|
|
|
62
64
|
# 人类直接访问
|
|
63
65
|
npx zdashboard --mode bugs --dir /path/to/project --port 4190
|
|
@@ -66,6 +68,6 @@ npx zdashboard --mode bugs --dir /path/to/project --port 4190
|
|
|
66
68
|
## 迁移状态
|
|
67
69
|
|
|
68
70
|
- [x] zview-dashboard → zdashboard(v1.0.0)
|
|
69
|
-
- [
|
|
70
|
-
- [
|
|
71
|
-
- [
|
|
71
|
+
- [x] zreview-dashboard → zdashboard plugin(v1.2.0)
|
|
72
|
+
- [x] zdesign-dashboard → zdashboard plugin(v1.2.0)
|
|
73
|
+
- [x] zskills skill SKILL.md 统一调用 zdashboard
|
package/dist/cli.js
CHANGED
|
@@ -442,7 +442,7 @@ function scanAssets(root2) {
|
|
|
442
442
|
// package.json
|
|
443
443
|
var package_default = {
|
|
444
444
|
name: "zdashboard",
|
|
445
|
-
version: "1.3.
|
|
445
|
+
version: "1.3.2",
|
|
446
446
|
description: "ZCode skill dashboard platform \u2014 pluggable viewers for zdesign/zview/zreview/zgoal",
|
|
447
447
|
type: "module",
|
|
448
448
|
bin: {
|
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.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":";;;AAAA,OAAO,UAAU;AACjB,OAAOA,SAAQ;AACf,OAAOC,WAAU;AACjB,OAAO,YAAY;AACnB,SAAS,YAAY;AACrB,SAAS,iBAAAC,sBAAqB;;;ACL9B,OAAO,QAAQ;AACf,OAAO,UAAU;AAWjB,SAAS,UAAU,QAAgB,QAAgB,QAAQ,GAAe;AACxE,MAAI,QAAQ,EAAG,QAAO,CAAC;AACvB,MAAI;AACJ,MAAI;AAAE,WAAO,GAAG,YAAY,QAAQ,EAAE,eAAe,KAAK,CAAC;AAAA,EAAG,QAAQ;AAAE,WAAO,CAAC;AAAA,EAAG;AACnF,QAAM,QAAoB,CAAC;AAC3B,aAAW,OAAO,MAAM;AACtB,QAAI,IAAI,KAAK,WAAW,GAAG,KAAK,IAAI,SAAS,eAAgB;AAC7D,UAAM,MAAM,SAAS,GAAG,MAAM,IAAI,IAAI,IAAI,KAAK,IAAI;AACnD,QAAI,IAAI,YAAY,GAAG;AACrB,YAAM,KAAK,EAAE,MAAM,IAAI,MAAM,MAAM,OAAO,UAAU,UAAU,KAAK,KAAK,QAAQ,IAAI,IAAI,GAAG,KAAK,QAAQ,CAAC,EAAE,CAAC;AAAA,IAC9G,OAAO;AACL,YAAM,KAAK,EAAE,MAAM,IAAI,MAAM,MAAM,QAAQ,MAAM,IAAI,CAAC;AAAA,IACxD;AAAA,EACF;AACA,QAAM,KAAK,CAAC,GAAG,MAAO,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,IAAI,IAAI,EAAE,SAAS,QAAQ,KAAK,CAAE;AACnG,SAAO;AACT;AAGO,SAAS,SAASC,OAAc,aAAsB,SAA8B;AACzF,QAAM,OAAmB,CAAC;AAC1B,MAAI,eAAe,GAAG,WAAW,KAAK,KAAKA,OAAM,YAAY,SAAS,CAAC,GAAG;AACxE,UAAM,aAAa,KAAK,KAAKA,OAAM,YAAY,SAAS;AACxD,UAAM,SAAqB,CAAC;AAC5B,UAAM,WAAuB,CAAC;AAC9B,eAAW,OAAO,GAAG,YAAY,YAAY,EAAE,eAAe,KAAK,CAAC,GAAG;AACrE,UAAI,CAAC,IAAI,YAAY,KAAK,IAAI,KAAK,WAAW,GAAG,KAAK,IAAI,SAAS,UAAW;AAC9E,aAAO,KAAK,EAAE,MAAM,IAAI,MAAM,MAAM,OAAO,UAAU,UAAU,KAAK,KAAK,YAAY,IAAI,IAAI,GAAG,oBAAoB,IAAI,IAAI,EAAE,EAAE,CAAC;AAAA,IACnI;AACA,WAAO,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAClD,UAAM,aAAa,KAAK,KAAK,YAAY,SAAS;AAClD,QAAI,GAAG,WAAW,UAAU,GAAG;AAC7B,iBAAW,OAAO,GAAG,YAAY,YAAY,EAAE,eAAe,KAAK,CAAC,GAAG;AACrE,YAAI,CAAC,IAAI,YAAY,KAAK,IAAI,KAAK,WAAW,GAAG,EAAG;AACpD,iBAAS,KAAK,EAAE,MAAM,IAAI,MAAM,MAAM,OAAO,UAAU,UAAU,KAAK,KAAK,YAAY,IAAI,IAAI,GAAG,4BAA4B,IAAI,IAAI,EAAE,EAAE,CAAC;AAAA,MAC7I;AACA,eAAS,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAAA,IACtD;AACA,QAAI,OAAO,OAAQ,MAAK,KAAK,EAAE,MAAM,uBAAQ,OAAO,MAAM,KAAK,MAAM,OAAO,UAAU,OAAO,CAAC;AAC9F,QAAI,SAAS,OAAQ,MAAK,KAAK,EAAE,MAAM,iBAAO,SAAS,MAAM,KAAK,MAAM,OAAO,kBAAkB,MAAM,UAAU,SAAS,CAAC;AAC3H,UAAM,WAAW,KAAK,KAAKA,OAAM,YAAY,OAAO;AACpD,QAAI,GAAG,WAAW,QAAQ,GAAG;AAC3B,YAAM,QAAQ,UAAU,UAAU,gBAAgB;AAClD,UAAI,MAAM,OAAQ,MAAK,KAAK,EAAE,MAAM,sBAAY,MAAM,OAAO,UAAU,MAAM,CAAC;AAAA,IAChF;AAAA,EACF;AACA,MAAI,WAAW,GAAG,WAAW,KAAK,KAAKA,OAAM,MAAM,CAAC,GAAG;AACrD,UAAM,OAAO,UAAU,KAAK,KAAKA,OAAM,MAAM,GAAG,MAAM;AACtD,QAAI,KAAK,OAAQ,MAAK,KAAK,EAAE,MAAM,QAAQ,MAAM,OAAO,UAAU,KAAK,CAAC;AAAA,EAC1E;AACA,QAAM,OAAO,oBAAI,IAAI,CAAC,YAAY,QAAQ,gBAAgB,QAAQ,QAAQ,aAAa,CAAC;AAExF,QAAM,MAAkB,CAAC;AACzB,MAAI;AACF,eAAW,OAAO,GAAG,YAAYA,OAAM,EAAE,eAAe,KAAK,CAAC,GAAG;AAC/D,UAAI,IAAI,KAAK,WAAW,GAAG,KAAK,KAAK,IAAI,IAAI,IAAI,EAAG;AACpD,YAAM,MAAM,KAAK,QAAQ,IAAI,IAAI,EAAE,YAAY;AAC/C,UAAI,IAAI,OAAO,MAAM,QAAQ,SAAS,QAAQ,aAAc,KAAI,KAAK,EAAE,MAAM,IAAI,MAAM,MAAM,QAAQ,MAAM,IAAI,KAAK,CAAC;AAAA,IACvH;AAAA,EACF,QAAQ;AAAA,EAAC;AACT,MAAI,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAC/C,MAAI,IAAI,OAAQ,MAAK,KAAK,EAAE,MAAM,iBAAO,IAAI,MAAM,KAAK,MAAM,OAAO,UAAU,IAAI,CAAC;AACpF,SAAO;AACT;;;AC3EA,SAAS,OAAO,gBAAmC;AASnD,IAAM,aAAa;AAEZ,IAAM,aAAN,MAAiB;AAAA,EACd;AAAA,EACA,QAA6B;AAAA,EAC7B,SAAwB;AAAA,EACxB,QAAmB;AAAA,EACnB,OAAsB;AAAA,EACtB,SAAmB,CAAC;AAAA,EACpB,UAAU;AAAA;AAAA,EACV,UAAU,oBAAI,IAA6B;AAAA,EAC3C,eAAgC;AAAA,EAExC,YAAY,KAAa;AAAE,SAAK,MAAM;AAAA,EAAK;AAAA,EAE3C,UAA6B;AAC3B,QAAI,KAAK,aAAc,QAAO,QAAQ,QAAQ,KAAK,YAAY;AAC/D,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,eAAS,QAAQ,CAAC,UAAU,YAAY,GAAG,EAAE,KAAK,KAAK,KAAK,WAAW,KAAK,IAAI,SAAS,IAAK,GAAG,CAAC,KAAK,WAAW;AAChH,YAAI,KAAK;AAAE,kBAAQ,CAAC,CAAC;AAAG;AAAA,QAAQ;AAChC,cAAM,MAAgB,CAAC;AACvB,cAAM,OAAO,oBAAI,IAAY;AAC7B,mBAAW,QAAQ,OAAO,MAAM,OAAO,EAAE,MAAM,CAAC,GAAG;AACjD,gBAAM,UAAU,KAAK,KAAK;AAC1B,cAAI,CAAC,QAAS;AACd,gBAAM,UAAU,QAAQ,QAAQ,GAAG;AACnC,gBAAM,OAAO,WAAW,IAAI,QAAQ,MAAM,GAAG,OAAO,IAAI,SAAS,KAAK;AACtE,cAAI,CAAC,IAAK;AACV,gBAAM,OAAO,IAAI,MAAM,KAAK,EAAE,CAAC;AAC/B,cAAI,KAAK,IAAI,IAAI,EAAG;AACpB,eAAK,IAAI,IAAI;AACb,cAAI,KAAK,EAAE,MAAM,aAAa,WAAW,IAAI,QAAQ,MAAM,UAAU,CAAC,EAAE,KAAK,IAAI,GAAG,CAAC;AAAA,QACvF;AACA,aAAK,eAAe;AACpB,gBAAQ,GAAG;AAAA,MACb,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEA,UAAU,IAAyC;AACjD,SAAK,QAAQ,IAAI,EAAE;AAEnB,eAAW,QAAQ,KAAK,OAAQ,IAAG,EAAE,MAAM,OAAO,KAAK,CAAC;AACxD,OAAG,EAAE,MAAM,SAAS,OAAO,KAAK,OAAO,QAAQ,KAAK,QAAQ,MAAM,KAAK,KAAK,CAAC;AAC7E,WAAO,MAAM,KAAK,QAAQ,OAAO,EAAE;AAAA,EACrC;AAAA,EAEQ,KAAK,IAAe;AAAE,eAAW,MAAM,KAAK,QAAS,IAAG,EAAE;AAAA,EAAG;AAAA,EAErE,OAAO;AAAE,WAAO,EAAE,OAAO,KAAK,OAAO,QAAQ,KAAK,QAAQ,MAAM,KAAK,KAAK;AAAA,EAAG;AAAA;AAAA,EAG7E,MAAM,QAAgB;AACpB,SAAK,UAAU;AACf,SAAK,SAAS;AACd,SAAK,OAAO;AACZ,SAAK,QAAQ;AACb,SAAK,SAAS,CAAC;AACf,SAAK,UAAU;AACf,SAAK,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC3B,SAAK,KAAK,EAAE,MAAM,SAAS,OAAO,WAAW,QAAQ,MAAM,KAAK,CAAC;AACjE,UAAM,QAAQ,MAAM,QAAQ,CAAC,MAAM,GAAG;AAAA,MACpC,KAAK,KAAK;AAAA,MACV,OAAO;AAAA,MACP,KAAK;AAAA,QACH,GAAG,QAAQ;AAAA,QACX,aAAa;AAAA;AAAA;AAAA,QAEb,YAAY,GAAG,QAAQ,IAAI,cAAc,EAAE,wBAAwB,KAAK;AAAA,QACxE,IAAI;AAAA,MACN;AAAA,IACF,CAAC;AACD,SAAK,QAAQ;AACb,UAAM,OAAO,CAAC,MAAc;AAC1B,WAAK,WAAW,EAAE,SAAS;AAC3B,UAAI;AACJ,cAAQ,MAAM,KAAK,QAAQ,QAAQ,IAAI,MAAM,GAAG;AAC9C,cAAM,OAAO,KAAK,QAAQ,MAAM,GAAG,MAAM,CAAC;AAC1C,aAAK,UAAU,KAAK,QAAQ,MAAM,MAAM,CAAC;AACzC,aAAK,SAAS,IAAI;AAAA,MACpB;AAAA,IAEF;AACA,UAAM,QAAQ,GAAG,QAAQ,IAAI;AAC7B,UAAM,QAAQ,GAAG,QAAQ,IAAI;AAC7B,UAAM,GAAG,SAAS,CAAC,QAAQ;AAAE,WAAK,SAAS,6BAA6B,IAAI,OAAO;AAAA,CAAI;AAAA,IAAG,CAAC;AAC3F,UAAM,GAAG,QAAQ,CAAC,SAAS;AACzB,UAAI,KAAK,SAAS;AAAE,aAAK,SAAS,KAAK,UAAU,IAAI;AAAG,aAAK,UAAU;AAAA,MAAI;AAC3E,WAAK,QAAQ;AACb,WAAK,QAAQ;AACb,WAAK,OAAO,QAAQ;AACpB,WAAK,KAAK,EAAE,MAAM,SAAS,OAAO,UAAU,QAAQ,KAAK,QAAQ,MAAM,KAAK,KAAK,CAAC;AAAA,IACpF,CAAC;AAAA,EACH;AAAA,EAEQ,SAAS,MAAc;AAC7B,SAAK,OAAO,KAAK,IAAI;AACrB,QAAI,KAAK,OAAO,SAAS,WAAY,MAAK,OAAO,MAAM;AACvD,SAAK,KAAK,EAAE,MAAM,OAAO,MAAM,KAAK,CAAC;AAAA,EACvC;AAAA,EAEA,OAAO;AACL,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,QAAQ,QAAiB;AACvB,UAAM,SAAS,UAAU,KAAK;AAC9B,QAAI,OAAQ,MAAK,MAAM,MAAM;AAAA,EAC/B;AAAA,EAEQ,YAAY;AAClB,UAAM,QAAQ,KAAK;AACnB,QAAI,OAAO,KAAK;AACd,UAAI;AACF,YAAI,QAAQ,aAAa,QAAS,OAAM,YAAY,CAAC,QAAQ,OAAO,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC;AAAA,YACtF,OAAM,KAAK,SAAS;AAAA,MAC3B,QAAQ;AAAA,MAAY;AAAA,IACtB;AACA,SAAK,QAAQ;AAAA,EACf;AACF;;;ACjIA,OAAOC,SAAQ;AACf,OAAOC,WAAU;;;ACDjB,OAAO,QAAQ;;;ACAR,IAAM,YAAN,cAAwB,MAAM;AAAA,EACnC,YACS,QACP,SACO,MACP;AACA,UAAM,OAAO;AAJN;AAEA;AAGP,SAAK,OAAO;AAAA,EACd;AAAA,EANS;AAAA,EAEA;AAKX;AAEO,IAAM,eAAN,cAA2B,MAAM;AAAA,EACtC,YAAY,SAAwB,OAAiB;AACnD,UAAM,OAAO;AADqB;AAElC,SAAK,OAAO;AAAA,EACd;AAAA,EAHoC;AAItC;;;ADbA,eAAsB,UAAU,KAAa,MAAsD;AACjG,MAAI;AACF,UAAM,MAAM,MAAM,GAAG,KAAK,EAAE,GAAG,MAAM,SAAS,KAAM,OAAO,EAAE,CAAC;AAC9D,WAAO,MAAM,IAAI,KAAK;AAAA,EACxB,SAAS,GAAG;AACV,QAAI,aAAa,UAAW,OAAM;AAClC,QAAI,aAAa,SAAS,EAAE,SAAS,gBAAgB;AACnD,YAAM,IAAI,aAAa,6BAAS,GAAG,EAAE;AAAA,IACvC;AACA,QAAI,aAAa,SAAS,EAAE,SAAS,aAAa;AAChD,YAAM,IAAI,UAAW,EAAkC,UAAU,KAAK,EAAE,OAAO;AAAA,IACjF;AACA,UAAM,IAAI,aAAa,6BAAS,GAAG,IAAI,CAAC;AAAA,EAC1C;AACF;;;ADaA,SAAS,gBAAgBC,OAAkC;AACzD,QAAM,OAAOC,MAAK,KAAKD,OAAM,UAAU,aAAa;AACpD,MAAI,CAACE,IAAG,WAAW,IAAI,EAAG,QAAO;AACjC,QAAM,KAA6B,CAAC;AACpC,aAAW,QAAQA,IAAG,aAAa,MAAM,MAAM,EAAE,MAAM,IAAI,GAAG;AAC5D,UAAM,IAAI,KAAK,MAAM,oCAAoC;AACzD,QAAI,KAAK,CAAC,EAAE,CAAC,EAAE,WAAW,GAAG,EAAG,IAAG,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,QAAQ,gBAAgB,EAAE;AAAA,EAC5E;AACA,QAAM,UAAU,OAAO,GAAG,OAAO;AACjC,MAAI,CAAC,GAAG,OAAO,CAAC,QAAS,QAAO;AAChC,SAAO;AAAA,IACL,KAAK,GAAG,IAAI,QAAQ,QAAQ,EAAE;AAAA,IAC9B,SAAS,GAAG,WAAW;AAAA,IACvB,UAAU,GAAG;AAAA,IACb,OAAO,GAAG;AAAA,IACV;AAAA,EACF;AACF;AAEA,IAAI,aAAgE;AAEpE,eAAe,SAAS,KAAmC;AACzD,MAAI,IAAI,MAAO,QAAO,IAAI;AAC1B,QAAM,MAAM,GAAG,IAAI,GAAG,IAAI,IAAI,OAAO,IAAI,IAAI,YAAY,EAAE;AAC3D,MAAI,cAAc,WAAW,QAAQ,OAAO,KAAK,IAAI,IAAI,WAAW,KAAK,KAAK,IAAQ,QAAO,WAAW;AACxG,QAAM,OAAO,MAAM,UAAU,GAAG,IAAI,GAAG,sBAAsB;AAAA,IAC3D,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAC9C,MAAM,KAAK,UAAU,EAAE,SAAS,IAAI,SAAS,UAAU,IAAI,SAAS,CAAC;AAAA,EACvE,CAAC;AACD,QAAM,QAAQ,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ;AAC5D,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,gEAAkC;AAC9D,eAAa,EAAE,KAAK,OAAO,IAAI,KAAK,IAAI,EAAE;AAC1C,SAAO;AACT;AAEA,SAAS,QAAQ,GAA4B,SAAyB;AACpE,QAAM,WAAW,EAAE;AACnB,QAAM,aACJ,OAAO,aAAa,WAChB,WACA,YAAY,OAAO,aAAa,YAAY,cAAe,WACzD,OAAQ,SAAqC,YAAY,EAAE,IAC3D;AACR,QAAM,kBACJ,OAAO,aAAa,WAChB,WACA,YAAY,OAAO,aAAa,WAC9B,OAAQ,SAAqC,WAAW,EAAE,IAC1D;AACR,QAAM,OAAO,CAAC,CAAC,YAAY,oBAAoB,WAAW,eAAe;AACzE,SAAO;AAAA,IACL,IAAI,OAAO,EAAE,EAAE;AAAA,IACf,OAAO,OAAO,EAAE,SAAS,EAAE;AAAA,IAC3B,UAAW,EAAE,YAAgC;AAAA,IAC7C,KAAM,EAAE,OAA2B;AAAA,IACnC,QAAQ,OAAO,EAAE,UAAU,EAAE;AAAA,IAC7B;AAAA,IACA,UAAU,OAAO,EAAE,aAAa,WAAW,EAAE,WAAW;AAAA,IACxD;AAAA,EACF;AACF;AAGA,eAAsB,UAAUF,OAAmC;AACjE,QAAM,MAAM,gBAAgBA,KAAI;AAChC,MAAI,CAAC,IAAK,QAAO,EAAE,IAAI,OAAO,OAAO,wGAA2D;AAChG,MAAI;AACF,UAAM,QAAQ,MAAM,SAAS,GAAG;AAChC,UAAM,OAAO,MAAM;AAAA,MACjB,GAAG,IAAI,GAAG,wBAAwB,IAAI,OAAO;AAAA,MAC7C,EAAE,SAAS,EAAE,OAAO,MAAM,EAAE;AAAA,IAC9B;AACA,UAAM,MAAM,MAAM,QAAQ,KAAK,IAAI,IAAK,KAAK,OAAqC,CAAC;AACnF,WAAO,EAAE,IAAI,MAAM,KAAK,IAAI,KAAK,OAAO,OAAO,KAAK,SAAS,IAAI,MAAM,GAAG,MAAM,IAAI,IAAI,CAAC,MAAM,QAAQ,GAAG,IAAI,OAAO,CAAC,EAAE;AAAA,EAC1H,SAAS,GAAG;AACV,UAAM,MAAM,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AACrD,WAAO,EAAE,IAAI,OAAO,OAAO,wCAAU,GAAG,yFAAuC;AAAA,EACjF;AACF;;;AG9FA,OAAOG,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,qBAAqB;AAE9B,IAAM,YAAYA,MAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAgB7D,IAAM,iBAAiB,oBAAI,IAA6B;AAEjD,SAAS,gBAAgB,QAAyB;AACvD,iBAAe,IAAI,OAAO,MAAM,MAAM;AACxC;AAMO,SAAS,cAAiC;AAC/C,SAAO,MAAM,KAAK,eAAe,OAAO,CAAC;AAC3C;;;AC/CA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,OAAO,UAAU;AAoBjB,IAAM,cAAc;AAEb,IAAM,cAAN,MAAkB;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAYC,OAAc,UAAuB;AAC/C,SAAK,OAAOA;AACZ,SAAK,OAAOD,MAAK,KAAKC,OAAM,WAAW;AACvC,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,SAAkB;AAAE,WAAOF,IAAG,WAAW,KAAK,IAAI;AAAA,EAAG;AAAA,EAErD,OAAmB;AACjB,QAAI;AACF,YAAM,SAAS,KAAK,MAAMA,IAAG,aAAa,KAAK,MAAM,MAAM,CAAC;AAC5D,UAAI,CAAC,UAAU,CAAC,MAAM,QAAQ,OAAO,KAAK,EAAG,QAAO,EAAE,QAAQ,SAAS,OAAO,CAAC,EAAE;AACjF,aAAO;AAAA,IACT,QAAQ;AACN,aAAO,EAAE,QAAQ,SAAS,OAAO,CAAC,EAAE;AAAA,IACtC;AAAA,EACF;AAAA,EAEQ,MAAM,MAAkB;AAC9B,IAAAA,IAAG,cAAc,KAAK,MAAM,KAAK,UAAU,IAAI,GAAG,MAAM;AACxD,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,WAAW,IAAY,OAA2D;AAChF,UAAM,OAAO,KAAK,KAAK;AACvB,UAAM,OAAO,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAC/C,QAAI,CAAC,KAAM,OAAM,IAAI,MAAM,QAAQ,EAAE,YAAY;AACjD,QAAI,MAAM,WAAW,OAAW,MAAK,SAAS,MAAM;AACpD,QAAI,MAAM,UAAU,OAAW,MAAK,QAAQ,MAAM;AAClD,QAAI,MAAM,UAAU,cAAc,CAAC,MAAM,UAAU,CAAC,KAAK,OAAQ,MAAK,SAAS;AAC/E,SAAK,MAAM,IAAI;AACf,WAAO;AAAA,EACT;AAAA,EAEA,UAAU,QAAkC;AAC1C,UAAM,OAAO,KAAK,KAAK;AACvB,QAAI,WAAW,YAAY,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,UAAU,MAAM,GAAG;AACrE,YAAM,IAAI,MAAM,uFAAsB;AAAA,IACxC;AACA,SAAK,SAAS;AACd,SAAK,MAAM,IAAI;AACf,WAAO;AAAA,EACT;AAAA,EAEA,OAAiB;AACf,QAAI;AACF,aAAOA,IAAG,YAAY,KAAK,IAAI,EAC5B,OAAO,CAAC,MAAM,oBAAoB,KAAK,CAAC,KAAKA,IAAG,SAASC,MAAK,KAAK,KAAK,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC,EAC1F,KAAK;AAAA,IACV,QAAQ;AAAE,aAAO,CAAC;AAAA,IAAG;AAAA,EACvB;AACF;;;AChFA,OAAOE,SAAQ;AACf,OAAOC,WAAU;AAIjB,IAAM,YAAY,CAAC,SAAS,MAAM;AAClC,IAAM,YAAY,CAAC,QAAQ,QAAQ,QAAQ,QAAQ,SAAS,QAAQ,OAAO;AAC3E,IAAM,aAAa,CAAC,QAAQ,SAAS,QAAQ,QAAQ,MAAM;AAC3D,IAAM,aAAa,CAAC,QAAQ,QAAQ,SAAS,QAAQ,MAAM;AAC3D,IAAM,YAAY,CAAC,OAAO,QAAQ,OAAO,QAAQ,QAAQ,QAAQ,SAAS,QAAQ,QAAQ,QAAQ,SAAS,OAAO,KAAK;AACvH,IAAM,YAAY,CAAC,SAAS,UAAU,QAAQ,MAAM;AACpD,IAAM,WAAW;AAEV,SAAS,WAAW,KAAa,KAAwB;AAC9D,MAAI,IAAI,QAAQ,aAAa,MAAM,EAAG,QAAO;AAC7C,MAAI,WAAW,SAAS,GAAG,EAAG,QAAO;AACrC,MAAI,WAAW,SAAS,GAAG,EAAG,QAAO;AACrC,MAAI,QAAQ,OAAQ,QAAO;AAC3B,MAAI,QAAQ,MAAO,QAAO;AAC1B,MAAI,UAAU,SAAS,GAAG,EAAG,QAAO;AACpC,MAAI,UAAU,SAAS,GAAG,EAAG,QAAO;AACpC,MAAI,UAAU,SAAS,GAAG,EAAG,QAAO;AACpC,MAAI,UAAU,SAAS,GAAG,EAAG,QAAO,SAAS,KAAK,GAAG,MAAM,QAAQ,UAAU,QAAQ,WAAW,UAAU;AAC1G,SAAO;AACT;AAKO,SAAS,WAAWC,OAA0B;AACnD,QAAM,MAAkB,CAAC;AACzB,QAAM,OAAoB,CAAC,QAAO,aAAY,QAAO,SAAQ,MAAK,SAAQ,SAAQ,OAAM,QAAO,QAAO,OAAO;AAC7G,aAAW,KAAK,KAAM,KAAI,CAAC,IAAI,CAAC;AAChC,QAAM,OAAO,oBAAI,IAAI,CAAC,gBAAgB,QAAQ,QAAQ,SAAS,YAAY,SAAS,QAAQ,CAAC;AAC7F,WAAS,KAAK,KAAa,KAAa;AACtC,QAAI;AACJ,QAAI;AAAE,aAAOF,IAAG,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC;AAAA,IAAG,QAAQ;AAAE;AAAA,IAAQ;AAC7E,eAAW,OAAO,MAAM;AACtB,UAAI,IAAI,KAAK,WAAW,GAAG,KAAK,KAAK,IAAI,IAAI,IAAI,EAAG;AACpD,YAAM,IAAI,MAAM,GAAG,GAAG,IAAI,IAAI,IAAI,KAAK,IAAI;AAC3C,UAAI,IAAI,YAAY,GAAG;AAAE,aAAKC,MAAK,KAAK,KAAK,IAAI,IAAI,GAAG,CAAC;AAAG;AAAA,MAAU;AACtE,YAAM,MAAMA,MAAK,QAAQ,IAAI,IAAI,EAAE,YAAY;AAC/C,YAAM,IAAI,WAAW,GAAG,GAAG;AAC3B,UAAI,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;AAAA,IACvD;AAAA,EACF;AACA,OAAKC,OAAM,EAAE;AACb,SAAO;AACT;;;AChDA;AAAA,EACE,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,aAAe;AAAA,EACf,MAAQ;AAAA,EACR,KAAO;AAAA,IACL,YAAc;AAAA,EAChB;AAAA,EACA,OAAS;AAAA,IACP;AAAA,EACF;AAAA,EACA,eAAiB;AAAA,IACf,QAAU;AAAA,EACZ;AAAA,EACA,SAAW;AAAA,IACT,KAAO;AAAA,IACP,OAAS;AAAA,IACT,aAAa;AAAA,IACb,cAAc;AAAA,IACd,OAAS;AAAA,IACT,SAAW;AAAA,EACb;AAAA,EACA,cAAgB;AAAA,IACd,+BAA+B;AAAA,IAC/B,6BAA6B;AAAA,IAC7B,wBAAwB;AAAA,IACxB,2BAA2B;AAAA,IAC3B,sBAAsB;AAAA,IACtB,iBAAiB;AAAA,IACjB,4BAA4B;AAAA,IAC5B,MAAQ;AAAA,IACR,YAAY;AAAA,IACZ,UAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,OAAS;AAAA,IACT,IAAM;AAAA,IACN,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,OAAS;AAAA,IACT,aAAa;AAAA,IACb,wBAAwB;AAAA,IACxB,kBAAkB;AAAA,IAClB,4BAA4B;AAAA,IAC5B,oBAAoB;AAAA,IACpB,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,eAAe;AAAA,IACf,sBAAsB;AAAA,IACtB,cAAc;AAAA,IACd,eAAe;AAAA,IACf,QAAU;AAAA,IACV,kBAAkB;AAAA,IAClB,gBAAgB;AAAA,IAChB,MAAQ;AAAA,EACV;AAAA,EACA,iBAAmB;AAAA,IACjB,2BAA2B;AAAA,IAC3B,6BAA6B;AAAA,IAC7B,0BAA0B;AAAA,IAC1B,oBAAoB;AAAA,IACpB,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,oBAAoB;AAAA,IACpB,wBAAwB;AAAA,IACxB,cAAgB;AAAA,IAChB,OAAS;AAAA,IACT,SAAW;AAAA,IACX,aAAe;AAAA,IACf,uBAAuB;AAAA,IACvB,MAAQ;AAAA,IACR,YAAc;AAAA,IACd,MAAQ;AAAA,IACR,QAAU;AAAA,EACZ;AAAA,EACA,MAAQ;AAAA,IACN,uBAAyB;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AACF;;;AThEA,IAAM,UAAU,gBAAI;AAEpB,IAAMC,aAAYC,MAAK,QAAQC,eAAc,YAAY,GAAG,CAAC;AAC7D,IAAM,aAAa,OAAO,YAAY,EAAE,EAAE,SAAS,KAAK;AACxD,IAAM,SAAS;AAEf,IAAM,OAA+B;AAAA,EACnC,SAAS;AAAA,EAA4B,QAAQ;AAAA,EAC7C,QAAQ;AAAA,EAA2B,OAAO;AAAA,EAC1C,QAAQ;AAAA,EAAyC,SAAS;AAAA,EAC1D,QAAQ;AAAA,EAAiB,QAAQ;AAAA,EAAa,QAAQ;AAAA,EACtD,QAAQ;AAAA,EAAc,SAAS;AAAA,EAAc,QAAQ;AAAA,EAAa,SAAS;AAAA,EAC3E,OAAO;AAAA,EAAgC,QAAQ;AAAA,EAC/C,QAAQ;AAAA,EAA4B,SAAS;AAAA,EAC7C,SAAS;AAAA,EAAa,UAAU;AAAA,EAAc,QAAQ;AAAA,EACtD,QAAQ;AACV;AAWA,SAAS,SAAS,KAA4C;AAC5D,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,QAAI,OAAO;AACX,QAAI,GAAG,QAAQ,CAAC,MAAO,QAAQ,CAAE;AACjC,QAAI,GAAG,OAAO,MAAM,QAAQ,IAAI,CAAC;AAAA,EACnC,CAAC;AACH;AAEO,SAAS,aAAa,MAAqB;AAChD,QAAM,OAAOD,MAAK,QAAQ,KAAK,IAAI;AACnC,QAAM,QAAQ,KAAK,QAAQ;AAC3B,QAAM,OAAO,CAAC,CAAC,KAAK;AACpB,QAAM,UAAU,KAAK,gBAAgBA,MAAK,QAAQD,YAAW,KAAK;AAClE,MAAI,CAACG,IAAG,WAAW,IAAI,EAAG,CAAAA,IAAG,UAAU,MAAM,EAAE,WAAW,KAAK,CAAC;AAChE,QAAMC,OAAM,KAAK;AACjB,QAAM,SAAS,IAAI,WAAW,IAAI;AAClC,QAAM,OAAO,KAAK;AAGlB,kBAAgB;AAAA,IACd,MAAM;AAAA,IAAQ,OAAO;AAAA,IAAW,MAAM;AAAA,IACtC,WAAW,EAAE,WAAW,OAAO,GAAG,QAAQ;AAAE,UAAI,UAAU,KAAK,EAAE,gBAAgB,mCAAmC,iBAAiB,WAAW,CAAC;AAAG,gBAAU,IAAI,EAAE,KAAK,CAAC,MAAM,IAAI,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC;AAAA,IAAG,EAAE;AAAA,EACjN,CAAC;AACD,kBAAgB,EAAE,MAAM,QAAQ,OAAO,4BAAQ,MAAM,kBAAM,CAAC;AAE5D,QAAM,cAAc,IAAI,YAAY,IAAI;AACxC,kBAAgB;AAAA,IACd,MAAM;AAAA,IAAU,OAAO;AAAA,IAAQ,MAAM;AAAA,IACrC,WAAW;AAAA,MACT,aAAa,OAAO,GAAG,QAAQ;AAC7B,YAAI,UAAU,KAAK,EAAE,gBAAgB,mCAAmC,iBAAiB,WAAW,CAAC;AACrG,YAAI,IAAI,KAAK,UAAU,YAAY,KAAK,CAAC,CAAC;AAAA,MAC5C;AAAA,MACA,kBAAkB,OAAO,KAAK,QAAQ;AACpC,YAAI,IAAI,QAAQ,cAAc,MAAM,YAAY;AAAE,cAAI,UAAU,GAAG;AAAG,cAAI,IAAI,WAAW;AAAG;AAAA,QAAQ;AACpG,SAAC,YAAY;AACX,cAAI;AACF,kBAAM,OAAO,KAAK,MAAM,MAAM,SAAS,GAAG,KAAK,IAAI;AACnD,kBAAM,OAAO,YAAY,WAAW,KAAK,IAAI,EAAE,QAAQ,KAAK,QAAQ,OAAO,KAAK,MAA+B,CAAC;AAChH,gBAAI,UAAU,KAAK,EAAE,gBAAgB,kCAAkC,CAAC;AACxE,gBAAI,IAAI,KAAK,UAAU,IAAI,CAAC;AAAA,UAC9B,SAAS,GAAG;AACV,gBAAI,UAAU,KAAK,EAAE,gBAAgB,kCAAkC,CAAC;AACxE,gBAAI,IAAI,KAAK,UAAU,EAAE,OAAQ,EAAY,QAAQ,CAAC,CAAC;AAAA,UACzD;AAAA,QACF,GAAG;AACH;AAAA,MACF;AAAA,MACA,oBAAoB,OAAO,KAAK,QAAQ;AACtC,YAAI,IAAI,QAAQ,cAAc,MAAM,YAAY;AAAE,cAAI,UAAU,GAAG;AAAG,cAAI,IAAI,WAAW;AAAG;AAAA,QAAQ;AACpG,SAAC,YAAY;AACX,cAAI;AACF,kBAAM,OAAO,KAAK,MAAM,MAAM,SAAS,GAAG,KAAK,IAAI;AACnD,kBAAM,OAAO,YAAY,UAAU,KAAK,MAAsB;AAC9D,gBAAI,UAAU,KAAK,EAAE,gBAAgB,kCAAkC,CAAC;AACxE,gBAAI,IAAI,KAAK,UAAU,IAAI,CAAC;AAAA,UAC9B,SAAS,GAAG;AACV,gBAAI,UAAU,KAAK,EAAE,gBAAgB,kCAAkC,CAAC;AACxE,gBAAI,IAAI,KAAK,UAAU,EAAE,OAAQ,EAAY,QAAQ,CAAC,CAAC;AAAA,UACzD;AAAA,QACF,GAAG;AACH;AAAA,MACF;AAAA,MACA,WAAW,OAAO,GAAG,QAAQ;AAC3B,YAAI,UAAU,KAAK,EAAE,gBAAgB,mCAAmC,iBAAiB,WAAW,CAAC;AACrG,YAAI,IAAI,KAAK,UAAU,YAAY,KAAK,CAAC,CAAC;AAAA,MAC5C;AAAA,IACF;AAAA,EACF,CAAC;AAED,kBAAgB,EAAE,MAAM,UAAU,OAAO,4BAAQ,MAAM,YAAK,CAAC;AAE7D,QAAM,UAAU,oBAAI,IAAyB;AAC7C,QAAM,YAAY,CAAC,IAAY,OAAgB,OAAO;AACpD,UAAM,UAAU,UAAU,EAAE;AAAA,QAAW,KAAK,UAAU,QAAQ,OAAO,KAAK,IAAI,CAAC;AAAA;AAAA;AAC/E,eAAW,KAAK,QAAS,GAAE,MAAM,OAAO;AAAA,EAC1C;AAEA,WAAS,UAAU,UAAkB,KAA0B,YAAqB;AAClF,IAAAD,IAAG,SAAS,UAAU,CAAC,KAAK,SAAS;AACnC,UAAI,KAAK;AAAE,YAAI,UAAU,GAAG;AAAG,eAAO,IAAI,IAAI,WAAW;AAAA,MAAG;AAC5D,YAAM,MAAMF,MAAK,QAAQ,QAAQ,EAAE,YAAY;AAC/C,YAAM,KAAK,KAAK,GAAG,KAAK;AACxB,UAAI,OAAO;AACX,UAAI,cAAc,QAAQ,SAAS;AACjC,cAAM,IAAI,KAAK,SAAS,MAAM;AAC9B,eAAO,OAAO,KAAK,EAAE,QAAQ,SAAS,KAAK,IAAI,EAAE,QAAQ,WAAW,SAAS,SAAS,IAAI,IAAI,MAAM;AAAA,MACtG;AACA,UAAI,UAAU,KAAK,EAAE,gBAAgB,IAAI,iBAAiB,WAAW,CAAC;AACtE,UAAI,IAAI,IAAI;AAAA,IACd,CAAC;AAAA,EACH;AAEA,WAAS,QAAQ,KAA2B,KAA0B;AACpE,UAAM,MAAM,IAAI,IAAK,MAAM,GAAG,EAAE,CAAC;AAGjC,QAAI,QAAQ,aAAa;AACvB,UAAI,UAAU,KAAK,EAAE,gBAAgB,qBAAqB,iBAAiB,YAAY,YAAY,aAAa,CAAC;AACjH,UAAI,MAAM,iBAAiB;AAC3B,cAAQ,IAAI,GAAG;AACf,UAAI,GAAG,SAAS,MAAM,QAAQ,OAAO,GAAG,CAAC;AACzC;AAAA,IACF;AACA,QAAI,QAAQ,aAAa;AACvB,UAAI,UAAU,KAAK,EAAE,gBAAgB,mCAAmC,iBAAiB,WAAW,CAAC;AACrG,aAAO,IAAI,IAAI,KAAK,UAAU,EAAE,WAAW,WAAW,CAAC,CAAC;AAAA,IAC1D;AACA,QAAI,QAAQ,aAAa,IAAI,WAAW,QAAQ;AAC9C,UAAI,IAAI,QAAQ,cAAc,MAAM,YAAY;AAC9C,YAAI,UAAU,KAAK,EAAE,gBAAgB,kCAAkC,CAAC;AACxE,YAAI,IAAI,aAAa;AACrB,eAAO,KAAK;AACZ,mBAAW,MAAM;AAAE,cAAI;AAAE,mBAAO,MAAM;AAAA,UAAG,QAAQ;AAAA,UAAC;AAAE,kBAAQ,KAAK,CAAC;AAAA,QAAG,GAAG,EAAE;AAAA,MAC5E,OAAO;AAAE,YAAI,UAAU,GAAG;AAAG,YAAI,IAAI,WAAW;AAAA,MAAG;AACnD;AAAA,IACF;AAGA,QAAI,QAAQ,YAAY;AACtB,UAAI,SAAS,UAAU;AACrB,YAAI,UAAU,KAAK,EAAE,gBAAgB,mCAAmC,iBAAiB,WAAW,CAAC;AACrG,eAAO,IAAI,IAAI,KAAK,UAAU,WAAW,IAAI,CAAC,CAAC;AAAA,MACjD;AACA,YAAM,OAAO,SAAS,MAAMG,KAAI,aAAaA,KAAI,OAAO;AACxD,YAAM,UAA2B,EAAE,MAAM,GAAGA,KAAI;AAChD,UAAI,UAAU,KAAK,EAAE,gBAAgB,mCAAmC,iBAAiB,WAAW,CAAC;AACrG,aAAO,IAAI,IAAI,KAAK,UAAU,OAAO,CAAC;AAAA,IACxC;AAGA,QAAI,QAAQ,mBAAmB;AAC7B,UAAI,UAAU,KAAK,EAAE,gBAAgB,mCAAmC,iBAAiB,WAAW,CAAC;AACrG,aAAO,QAAQ,EAAE,KAAK,CAAC,MAAM,IAAI,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC;AACvD;AAAA,IACF;AACA,QAAI,QAAQ,gBAAgB;AAC1B,UAAI,UAAU,KAAK,EAAE,gBAAgB,qBAAqB,iBAAiB,YAAY,YAAY,aAAa,CAAC;AACjH,UAAI,MAAM,iBAAiB;AAC3B,YAAM,QAAQ,OAAO,UAAU,CAAC,OAAO,IAAI,MAAM,SAAS,KAAK,UAAU,EAAE,CAAC;AAAA;AAAA,CAAM,CAAC;AACnF,UAAI,GAAG,SAAS,KAAK;AACrB;AAAA,IACF;AACA,UAAM,aAAa,IAAI,MAAM,kCAAkC;AAC/D,QAAI,cAAc,IAAI,WAAW,QAAQ;AACvC,OAAC,YAAY;AACX,YAAI,IAAI,QAAQ,cAAc,MAAM,YAAY;AAAE,cAAI,UAAU,GAAG;AAAG,cAAI,IAAI,WAAW;AAAG;AAAA,QAAQ;AACpG,cAAM,OAAO,MAAM,SAAS,GAAG;AAC/B,YAAI;AACJ,YAAI;AAAE,mBAAS,KAAK,MAAM,QAAQ,IAAI,EAAE;AAAA,QAAQ,QAAQ;AAAA,QAAe;AACvE,cAAM,MAAM,WAAW,CAAC;AACxB,YAAI,QAAQ,WAAW,QAAQ,WAAW;AACxC,gBAAM,SAAS,UAAU,OAAO,KAAK,EAAE;AACvC,cAAI,CAAC,QAAQ;AAAE,gBAAI,UAAU,GAAG;AAAG,gBAAI,IAAI,uBAAuB;AAAG;AAAA,UAAQ;AAC7E,gBAAM,UAAU,MAAM,OAAO,QAAQ;AACrC,cAAI,CAAC,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,GAAG;AAAE,gBAAI,UAAU,GAAG;AAAG,gBAAI,IAAI,4BAA4B;AAAG;AAAA,UAAQ;AAClH,iBAAO,MAAM,MAAM;AAAA,QACrB,OAAO;AACL,iBAAO,KAAK;AAAA,QACd;AACA,YAAI,UAAU,KAAK,EAAE,gBAAgB,kCAAkC,CAAC;AACxE,YAAI,IAAI,KAAK,UAAU,OAAO,KAAK,CAAC,CAAC;AAAA,MACvC,GAAG;AACH;AAAA,IACF;AAGA,QAAI,UAAU;AACd,eAAW,UAAU,YAAY,GAAG;AAClC,UAAI,CAAC,OAAO,UAAW;AACvB,iBAAW,CAAC,OAAOC,QAAO,KAAK,OAAO,QAAQ,OAAO,SAAS,GAAG;AAC/D,YAAI,QAAQ,OAAO;AACjB,oBAAU;AACV,UAAAA,SAAQ,KAAK,KAAK,IAAI;AACtB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,QAAI,QAAQ,IAAK,QAAO,UAAUJ,MAAK,KAAK,SAAS,YAAY,GAAG,KAAK,KAAK;AAC9E,QAAI,IAAI,QAAQ,SAAS,MAAM,GAAG;AAChC,YAAMK,MAAKL,MAAK,KAAK,SAAS,IAAI,MAAM,CAAC,CAAC;AAC1C,UAAIK,QAAO,WAAWA,IAAG,QAAQ,UAAUL,MAAK,GAAG,MAAM,GAAG;AAAE,YAAI,UAAU,GAAG;AAAG,eAAO,IAAI,IAAI,WAAW;AAAA,MAAG;AAC/G,aAAO,UAAUK,KAAI,KAAK,KAAK;AAAA,IACjC;AACA,QAAI,IAAI,QAAQ,UAAU,MAAM,GAAG;AACjC,YAAMA,MAAKL,MAAK,KAAK,SAAS,mBAAmB,GAAG,CAAC;AACrD,UAAIK,IAAG,QAAQ,UAAUL,MAAK,GAAG,MAAM,GAAG;AAAE,YAAI,UAAU,GAAG;AAAG,eAAO,IAAI,IAAI,WAAW;AAAA,MAAG;AAC7F,aAAO,UAAUK,KAAI,KAAK,KAAK;AAAA,IACjC;AAGA,UAAM,KAAKL,MAAK,KAAK,MAAM,mBAAmB,GAAG,CAAC;AAClD,QAAI,OAAO,QAAQ,GAAG,QAAQ,OAAOA,MAAK,GAAG,MAAM,GAAG;AAAE,UAAI,UAAU,GAAG;AAAG,aAAO,IAAI,IAAI,WAAW;AAAA,IAAG;AACzG,WAAO,UAAU,IAAI,KAAK,IAAI;AAAA,EAChC;AAEA,MAAI;AACJ,WAAS,MAAM,MAAc;AAC3B,aAAS,KAAK,aAAa,OAAO;AAClC,WAAO,GAAG,SAAS,CAAC,QAA+B;AACjD,UAAI,IAAI,SAAS,cAAc;AAAE,gBAAQ,IAAI,qBAAqB,IAAI,iBAAiB,OAAO,CAAC,EAAE;AAAG,cAAM,OAAO,CAAC;AAAA,MAAG,MAChH,OAAM;AAAA,IACb,CAAC;AACD,WAAO,OAAO,MAAM,MAAM;AACxB,YAAM,IAAI,oBAAoB,IAAI;AAClC,cAAQ,IAAI,iBAAiB,OAAO,iBAAiB,CAAC,EAAE;AACxD,cAAQ,IAAI,6BAA6B,IAAI,EAAE;AAC/C,cAAQ,IAAI,6BAA6B,QAAQ,QAAQ,EAAE;AAC3D,cAAQ,IAAI,sCAAsCG,KAAI,WAAW,SAASA,KAAI,OAAO,SAASA,KAAI,OAAO,SAASA,KAAI,OAAO,EAAE;AAC/H,UAAI,KAAM,MAAK,QAAQ,aAAa,WAAW,QAAQ,CAAC,KAAK,SAAS,CAAC,EAAE;AAAA,IAC3E,CAAC;AAAA,EACH;AAEA,MAAI;AACJ,MAAI;AACF,IAAAD,IAAG,MAAM,MAAM,EAAE,WAAW,KAAK,GAAG,MAAM;AACxC,mBAAa,QAAQ;AACrB,iBAAW,WAAW,MAAM;AAC1B,kBAAU,QAAQ;AAClB,kBAAU,OAAO;AACjB,gBAAQ,IAAI,iDAAiD,QAAQ,IAAI,UAAU,QAAQ,SAAS,IAAI,KAAK,GAAG,GAAG;AAAA,MACrH,GAAG,GAAG;AAAA,IACR,CAAC;AAAA,EACH,QAAQ;AAAE,YAAQ,IAAI,+CAA+C;AAAA,EAAG;AAExE,QAAM,KAAK;AACb;;;AU9QA,OAAOI,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,YAAAC,iBAAgB;AASzB,SAAS,cAAc,KAA+B;AACpD,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,QAAQA,UAAS,QAAQ,CAAC,UAAU,YAAY,GAAG,EAAE,KAAK,SAAS,IAAK,GAAG,CAAC,QAAQ;AACxF,cAAQ,CAAC,GAAG;AAAA,IACd,CAAC;AACD,QAAI,MAAM,OAAQ,SAAQ,KAAK;AAAA,EACjC,CAAC;AACH;AAEA,eAAsB,OAAOC,OAAqC;AAChE,QAAM,cAAcH,IAAG,WAAWC,MAAK,KAAKE,OAAM,UAAU,CAAC;AAC7D,QAAM,UAAUH,IAAG,WAAWC,MAAK,KAAKE,OAAM,MAAM,CAAC;AACrD,QAAM,UAAU,MAAM,cAAcA,KAAI;AACxC,QAAM,UAAUH,IAAG,WAAWC,MAAK,KAAKE,OAAM,UAAU,aAAa,CAAC;AACtE,SAAO,EAAE,aAAa,SAAS,SAAS,QAAQ;AAClD;;;ACvBA,SAAS,UAAU,GAA4C;AAC7D,QAAM,IAAmC,CAAC;AAC1C,WAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;AACjC,QAAI,EAAE,CAAC,EAAE,QAAQ,IAAI,MAAM,GAAG;AAC5B,YAAM,IAAI,EAAE,IAAI,CAAC;AACjB,QAAE,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,KAAK,EAAE,QAAQ,IAAI,MAAM,IAAI,EAAE,EAAE,CAAC,IAAI;AAAA,IAC3D;AAAA,EACF;AACA,SAAO;AACT;AAEA,IAAM,OAAO,UAAU,QAAQ,KAAK,MAAM,CAAC,CAAC;AAC5C,IAAM,OAAQ,KAAK,OAAkB;AAErC,IAAM,MAAM,MAAM,OAAO,IAAI;AAC7B,aAAa;AAAA,EACX;AAAA,EACA,MAAM,KAAK,OAAO,SAAS,KAAK,MAAgB,EAAE,IAAI;AAAA,EACtD,MAAM,CAAC,CAAC,KAAK;AAAA,EACb,QAAQ;AAAA,EACR,MAAM,KAAK;AACb,CAAC;","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 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"]}
|