zdashboard 2.12.2 → 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -9,7 +9,7 @@ import { access, readdir } from "fs/promises";
9
9
  // package.json
10
10
  var package_default = {
11
11
  name: "zdashboard",
12
- version: "2.12.2",
12
+ version: "2.13.0",
13
13
  description: "ZCode skill dashboard platform \u2014 pluggable viewers for zdesign/zview/zreview/zgoal",
14
14
  type: "module",
15
15
  bin: {
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../package.json","../src/server/detect.ts","../src/core/server.ts","../src/core/instance.ts","../src/core/open-url.ts","../src/core/reload.ts","../src/server/spec-scan.ts","../src/server/walk.ts","../src/core/tree.ts","../src/core/worktrees.ts","../src/core/manifest.ts","../src/core/read-body.ts","../src/plugins/just/index.ts","../src/server/just-runner.ts","../src/server/just-recipe-params.ts","../src/sdk/server.ts","../src/plugins/builtin.ts","../src/plugins/just/manifest.ts","../src/plugins/design/index.ts","../src/server/design-assets.ts","../src/plugins/design/manifest.ts","../src/plugins/view/manifest.ts","../src/plugins/view/index.ts","../src/plugins/stats/index.ts","../src/plugins/stats/manifest.ts"],"sourcesContent":["import path from 'node:path';\nimport fs from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport { access, readdir } from 'node:fs/promises';\nimport { exec } from 'node:child_process';\nimport pkg from '../package.json' with { type: 'json' };\nimport { parseArgs as utilParseArgs } from 'node:util';\nimport { detect } from './server/detect.js';\nimport type { DetectResult } from './server/detect.js';\nimport { Context, Service } from 'cordis';\nimport { ServerService, PLUGIN_STATIC_PREFIX } from './core/server.js';\nimport { ReloadService } from './core/reload.js';\nimport { apply as treeApply } from './core/tree.js';\nimport { apply as worktreesApply } from './core/worktrees.js';\nimport { DashboardService } from './core/manifest.js';\nimport {\n findReusable,\n stopInstance,\n writeRecord,\n clearRecord,\n stripDeadPluginConfig,\n} from './core/instance.js';\nimport { openUrl } from './core/open-url.js';\nimport { apply as justApply } from './plugins/just/index.js';\nimport { apply as designApply } from './plugins/design/index.js';\nimport { apply as viewApply } from './plugins/view/index.js';\nimport { apply as statsApply } from './plugins/stats/index.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nconst DEFAULT_PORT = 4190;\n\nfunction parseArgs() {\n const args = process.argv.slice(2);\n const { values } = utilParseArgs({\n options: {\n dir: { type: 'string' },\n port: { type: 'string' },\n open: { type: 'boolean', default: false },\n page: { type: 'string' },\n restart: { type: 'boolean', default: false },\n plugins: { type: 'string' },\n },\n args,\n strict: false,\n allowPositionals: false,\n });\n return {\n dir: typeof values.dir === 'string' ? values.dir : process.cwd(),\n port: typeof values.port === 'string' ? Number(values.port) : DEFAULT_PORT,\n portExplicit: args.some(a => a === '--port' || a.startsWith('--port=')),\n open: !!values.open,\n page: typeof values.page === 'string' ? values.page : null,\n restart: !!values.restart,\n plugins: typeof values.plugins === 'string' ? values.plugins : null,\n };\n}\n\nasync function pathExists(p: string): Promise<boolean> {\n try { await access(p); return true; } catch { return false; }\n}\n\nasync function loadExternal(ctx: Context, dir: string, root: string) {\n if (!dir) return;\n let tsxLoaded = false;\n try {\n const { register } = await import('tsx/esm/api');\n register();\n tsxLoaded = true;\n } catch {\n // tsx not available\n }\n\n try {\n const entries = await pathExists(dir) ? await readdir(dir, { withFileTypes: true }) : [];\n for (const ent of entries) {\n if (!ent.isDirectory()) continue;\n const candidates = tsxLoaded ? ['index.ts', 'index.js', 'index.mjs'] : ['index.js', 'index.mjs'];\n for (const name of candidates) {\n const p = path.join(dir, ent.name, name);\n if (await pathExists(p)) {\n try {\n const mod = await import(p);\n const plugin = mod.default ?? mod;\n if (plugin?.apply) {\n try {\n await ctx.plugin(plugin, { root });\n } catch (e) {\n console.error(`[zdashboard] failed to apply plugin ${ent.name}:`, e);\n break;\n }\n // 自动接线约定:mode === 目录名时补 external 标记与 viewerUrl\n const m = ctx.dashboard.get(ent.name);\n if (m && m.mode === ent.name) {\n const patch: Record<string, unknown> = { external: true };\n const webDir = path.join(dir, ent.name, 'web');\n if (await pathExists(path.join(webDir, 'index.html'))) {\n ctx.server.static(`${PLUGIN_STATIC_PREFIX}${ent.name}/`, webDir);\n if (!m.viewerUrl) patch.viewerUrl = `${PLUGIN_STATIC_PREFIX}${ent.name}/`;\n }\n ctx.dashboard.register({ ...m, ...patch });\n }\n }\n } catch (e) {\n console.error(`[zdashboard] failed to load plugin ${ent.name}:`, e);\n }\n break;\n }\n }\n }\n } catch {\n // ignore\n }\n}\n\nasync function main() {\n const args = parseArgs();\n const root = path.resolve(args.dir);\n\n // --- instance reuse (before creating Context) ---\n // 版本比对:活实例版本落后当前 CLI → 自动停旧接管(零操作升级);--restart 仍为强制重开\n const found = await findReusable(root, pkg.version);\n const existing = found?.record ?? null;\n const autoUpgrade = found?.status === 'stale-version';\n if (existing && !args.restart && !autoUpgrade) {\n const u = `http://localhost:${existing.port}` + (args.page ? `#${args.page}` : '');\n if (args.open) openUrl(u);\n console.log(`[zdashboard] 已复用实例 ${u}(--restart 可强制重开)`);\n // 管道场景下 stdout 是异步写,显式等 flush 再 exit,避免日志被截断\n await new Promise<void>((resolve) => process.stdout.write('', () => resolve()));\n process.exit(0);\n }\n // 记录旧端口(--restart/自动升级时用于端口继承;stopInstance 会清 record)\n const oldRecord = existing && (args.restart || autoUpgrade) ? existing : null;\n if (oldRecord) {\n if (autoUpgrade) {\n console.log(\n `[zdashboard] 检测到旧版本实例 v${found!.liveVersion ?? 'unknown'},自动升级到 v${pkg.version}(停止旧实例 pid=${oldRecord.pid})`,\n );\n } else {\n console.log(`[zdashboard] --restart:停止旧实例 pid=${oldRecord.pid}`);\n }\n await stopInstance(oldRecord);\n }\n\n const appDir = path.resolve(__dirname, 'web');\n\n // built-in plugins:统一数组注册(未来迁移为 definePlugin 产出后无需改动此处)\n const BUILTIN_PLUGINS = [statsApply, justApply, designApply, viewApply];\n\n // 约定化扫描:启动一次性剥离 dashboard.json 里内置插件的死配置键(未声明 config 即清,external/未知保留)\n if (stripDeadPluginConfig(root, BUILTIN_PLUGINS.map((p) => p.manifest))) {\n console.log('[zdashboard] 已清理 dashboard.json 中内置插件的过时配置键');\n }\n\n // P2: restart 且有旧记录时,起始端口用 record.port(用户显式 --port 则尊重)\n const startPort = oldRecord && !args.portExplicit ? oldRecord.port : args.port;\n\n // P0: 数据目录检测(.zdev/ 存在则优先)\n const zdevDir = path.join(root, '.zdev');\n const dataDir = fs.existsSync(zdevDir) ? '.zdev/' : '';\n\n const det = await detect(root);\n\n const ctx = new Context();\n\n // core services\n ctx.plugin(ServerService, {\n root,\n appDir,\n port: startPort,\n open: args.open,\n detect: det,\n page: args.page,\n dataDir: dataDir || undefined,\n onListen: (port: number) => writeRecord(root, port),\n });\n ctx.plugin(ReloadService, { root });\n ctx.plugin(treeApply, { root });\n ctx.plugin(worktreesApply, { root });\n ctx.plugin(DashboardService);\n\n for (const apply of BUILTIN_PLUGINS) {\n try {\n ctx.plugin(apply, { root });\n } catch (e) {\n console.error('[zdashboard] builtin plugin failed:', e);\n }\n }\n\n // external plugins\n if (args.plugins) {\n await loadExternal(ctx, path.resolve(args.plugins), root);\n }\n\n // graceful shutdown: clear .zdev record on SIGTERM / SIGINT\n const shutdown = () => {\n try { clearRecord(root); } catch {}\n process.exit(0);\n };\n process.on('SIGTERM', shutdown);\n process.on('SIGINT', shutdown);\n\n return ctx;\n}\n\nawait main().catch((e) => {\n console.error(e);\n process.exit(1);\n});\n","{\n \"name\": \"zdashboard\",\n \"version\": \"2.12.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 && node scripts/check-excalidraw-lazy.mjs\",\n \"build:web\": \"vite build\",\n \"build:node\": \"tsup\",\n \"start\": \"node dist/cli.js\",\n \"test\": \"vitest run\",\n \"typecheck\": \"tsc --noEmit\",\n \"test:coverage\": \"vitest run --coverage\",\n \"preview\": \"vite preview\"\n },\n \"dependencies\": {\n \"@excalidraw/excalidraw\": \"0.18.1\",\n \"@fontsource/vt323\": \"^5.3.0\",\n \"@phosphor-icons/react\": \"^2.1.10\",\n \"@radix-ui/react-dropdown-menu\": \"^2.1.24\",\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 \"cordis\": \"4.0.0-rc.8\",\n \"cosmokit\": \"^1.8.1\",\n \"date-fns\": \"^3.6.0\",\n \"filesize\": \"^11.0.0\",\n \"highlight.js\": \"^11.11.1\",\n \"iconv-lite\": \"0.7.3\",\n \"katex\": \"^0.16.11\",\n \"ky\": \"^1.7.0\",\n \"lodash-es\": \"^4.17.21\",\n \"lucide-react\": \"^0.460.0\",\n \"pixelarticons\": \"^2.4.1\",\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 \"tsx\": \"^4.7.0\",\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 \"@vitest/coverage-v8\": \"1.6.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}\n\n/** --list 主探测超时(与迁移前一致) */\nconst JUST_PROBE_TIMEOUT_MS = 5000;\n/** --version 兜底探测超时(快失败:二进制存在性检查无需长等) */\nconst JUST_FALLBACK_TIMEOUT_MS = 3000;\n\nfunction justAvailable(cwd: string): Promise<boolean> {\n /** 探测一次:进程正常退出即视为可用 */\n const probe = (args: string[], timeout: number) => new Promise<boolean>((resolve) => {\n const child = execFile('just', args, { cwd, timeout }, (err) => resolve(!err));\n if (child.killed) resolve(false);\n });\n // 旧版以 --list --unsupported 判定;新版 just 移除该旗标会报错(hasJust 恒 false),\n // 回退 --version 探测二进制本身可用\n return probe(['--list', '--unsupported'], JUST_PROBE_TIMEOUT_MS)\n .then((ok) => (ok ? true : probe(['--version'], JUST_FALLBACK_TIMEOUT_MS)));\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 return { hasOpenspec, hasDocs, hasJust };\n}\n\n/** /__detect 的响应形状:与 DetectResult 同形(bugs 期兼容字段已随清理 change 摘除) */\nexport type DetectResponse = DetectResult;\n\n/** 现场探测(每次请求重新跑),供 /__detect 独立路由使用 */\nexport async function detectLiveShape(root: string): Promise<DetectResponse> {\n return detect(root);\n}\n","import http from 'node:http';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport crypto from 'node:crypto';\nimport { fileURLToPath } from 'node:url';\nimport pkg from '../../package.json' with { type: 'json' };\nimport type { Context } from 'cordis';\nimport type { DetectResult, DetectResponse } from '../server/detect.js';\nimport { detectLiveShape } from '../server/detect.js';\nimport type { PluginManifest, ConfigField } from '../core/manifest.js';\nimport { Service } from 'cordis';\nimport { clearRecord, readPluginsConfig, writePluginsConfig } from './instance.js';\nimport { openUrl } from './open-url.js';\nimport { readBody } from './read-body.js';\nimport { execFile } from 'node:child_process';\n\nconst VERSION = pkg.version;\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface ServerOptions {\n root: string;\n appDir: string;\n port: number;\n open: boolean;\n page: string | null;\n detect: DetectResult;\n dataDir?: string;\n onListen?: (port: number) => void;\n}\n\ndeclare module 'cordis' {\n interface Context {\n server: ServerService;\n }\n}\n\n/** 扩展名 → Content-Type 表(SDK 插件路由等复用,勿在他处复制) */\nexport const MIME: Record<string, string> = {\n '.html': 'text/html; charset=utf-8', '.htm': 'text/html; charset=utf-8',\n '.pdf': 'application/pdf',\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 '.avif': 'image/avif',\n '.md': 'text/markdown; charset=utf-8', '.txt': 'text/plain; charset=utf-8',\n '.sql': 'text/plain; charset=utf-8', '.csv': 'text/plain; charset=utf-8',\n '.tsv': 'text/plain; charset=utf-8', '.yaml': 'text/yaml; charset=utf-8',\n '.yml': 'text/yaml; charset=utf-8', '.xml': 'application/xml; charset=utf-8',\n '.py': 'text/plain; charset=utf-8', '.ts': 'text/plain; charset=utf-8',\n '.java': 'text/plain; charset=utf-8', '.go': 'text/plain; charset=utf-8',\n '.rs': 'text/plain; charset=utf-8', '.rb': 'text/plain; charset=utf-8',\n '.php': 'text/plain; charset=utf-8', '.c': 'text/plain; charset=utf-8',\n '.cpp': 'text/plain; charset=utf-8', '.h': 'text/plain; charset=utf-8',\n '.cs': 'text/plain; charset=utf-8', '.swift': 'text/plain; charset=utf-8',\n '.kt': 'text/plain; charset=utf-8', '.scala': 'text/plain; charset=utf-8',\n '.sh': 'text/plain; charset=utf-8', '.bash': 'text/plain; charset=utf-8',\n '.zsh': 'text/plain; charset=utf-8', '.fish': 'text/plain; charset=utf-8',\n '.env': 'text/plain; charset=utf-8', '.gitignore': 'text/plain; charset=utf-8',\n '.dockerfile': 'text/plain; charset=utf-8',\n '.mp4': 'video/mp4', '.webm': 'video/webm', '.mov': 'video/quicktime',\n '.m4a': 'audio/mp4', '.aac': 'audio/aac',\n '.woff': 'font/woff', '.woff2': 'font/woff2', '.ttf': 'font/woff',\n '.map': 'application/json; charset=utf-8',\n};\n\n// 静态 HTML 注入脚本:仅保留 _self 链接补丁(文件预览页内跳转留在当前窗口)。\n// 旧 EventSource('/__reload') 注入已随沙箱收紧移除——sandbox=allow-scripts 下 iframe\n// 为不透明源,/__reload 属跨域请求,只会制造 console error 且其处理器本已为空。\nconst INJECT = `<script>(function(){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\nexport const PLUGIN_STATIC_PREFIX = '/__plugin/';\n\n/** json 响应助手:统一 Content-Type/缓存头与序列化,消灭 writeHead 样板 */\nexport function json(res: http.ServerResponse, data: unknown, status = 200): void {\n res.writeHead(status, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(data));\n}\n\n/** 错误码 → 中文说明(极简错误页单源) */\nconst ERROR_PAGE_TEXT: Record<number, string> = {\n 400: '请求无效',\n 403: '没有访问权限',\n 404: '页面不存在',\n};\n\n/**\n * 极简 HTML 错误页:标题/说明/返回首页链接,零外部资源(离线可用)。\n * 页面类路径(项目文件/静态资源)404/403 专用;`/__` 前缀 API 路径保持 JSON/原文不变。\n */\nexport function sendErrorPage(res: http.ServerResponse, code: number): void {\n if (res.headersSent) {\n // 头已发出(响应中途出错):不能再改状态码,只断开连接防悬挂\n try { res.destroy(); } catch { /* 已断 */ }\n return;\n }\n const text = ERROR_PAGE_TEXT[code] ?? '出错了';\n res.writeHead(code, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(\n `<!doctype html><html lang=\"zh-CN\"><head><meta charset=\"utf-8\">` +\n `<title>${code} ${text} · zdashboard</title></head>` +\n `<body><h1>${code} · ${text}</h1><p>请求的资源不可用或已被移动。</p>` +\n `<p><a href=\"/\">返回首页</a></p></body></html>`,\n );\n}\n\n/** x-stop-token 鉴权助手:通过返回 true;未通过时已写 403 响应并返回 false */\nexport function guarded(req: http.IncomingMessage, res: http.ServerResponse, token: string): boolean {\n if (req.headers['x-stop-token'] !== token) {\n res.writeHead(403);\n res.end('forbidden');\n return false;\n }\n return true;\n}\n\nexport class ServerService extends Service {\n stopToken: string;\n private root: string;\n private appDir: string;\n private open: boolean;\n private page: string | null;\n private det: DetectResult;\n private dataDir?: string;\n private routes = new Map<string, (req: http.IncomingMessage, res: http.ServerResponse) => void>();\n private sses = new Map<string, (res: http.ServerResponse) => (() => void) | void>();\n private prefixStatic = new Map<string, string>();\n private server?: http.Server;\n private onListen?: (port: number) => void;\n\n constructor(ctx: Context, config: ServerOptions) {\n super(ctx, 'server');\n this.stopToken = crypto.randomBytes(12).toString('hex');\n this.root = config.root;\n this.appDir = config.appDir;\n this.open = config.open;\n this.page = config.page;\n this.det = config.detect;\n this.dataDir = config.dataDir;\n this.onListen = config.onListen;\n ctx.effect(() => () => this.dispose());\n\n this.refreshGitInfo();\n this.route('/__config', (_req, res) => {\n json(res, { stopToken: this.stopToken, version: VERSION, root: this.root, ...this.gitInfo });\n });\n\n // 独立探测接口(轻量,替代 HomeGrid 借道 /__files 全量树)\n this.route('/__detect', async (_req, res) => {\n const shape: DetectResponse = await detectLiveShape(this.root);\n json(res, shape);\n });\n\n // 应用级静态文件(index.html 引用但不在 /assets/ 下),避免落到项目目录 404\n this.route('/favicon.svg', (req, res) => {\n this.serveFile(path.join(this.appDir, 'favicon.svg'), req, res, false);\n });\n\n this.route('/__file-content', async (req, res) => {\n const url = new URL(req.url || '/', 'http://localhost');\n const rawPath = url.pathname.replace(/^\\/__file-content\\/?/, '');\n if (!rawPath || rawPath === '/') {\n res.writeHead(400);\n res.end('missing path');\n return;\n }\n const filePath = path.join(this.root, decodeURIComponent(rawPath));\n if (!filePath.startsWith(this.root + path.sep) && filePath !== this.root) {\n res.writeHead(403);\n res.end('Forbidden');\n return;\n }\n fs.stat(filePath, (err) => {\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 res.writeHead(200, { 'Content-Type': ct, 'Cache-Control': 'no-cache' });\n fs.createReadStream(filePath).pipe(res);\n });\n });\n\n this.route('/__stop', async (req, res) => {\n if (!guarded(req, res, this.stopToken)) return;\n json(res, { ok: true });\n this.stop();\n });\n\n this.start(config.port);\n }\n\n route(path: string, handler: (req: http.IncomingMessage, res: http.ServerResponse) => void) {\n this.routes.set(path, handler);\n this.ctx.effect(() => () => this.routes.delete(path));\n }\n\n sse(path: string, onConnect: (res: http.ServerResponse) => (() => void) | void) {\n this.sses.set(path, onConnect);\n this.ctx.effect(() => () => this.sses.delete(path));\n }\n\n static(prefix: string, dir: string) {\n this.prefixStatic.set(prefix, dir);\n this.ctx.effect(() => () => this.prefixStatic.delete(prefix));\n }\n\n private pluginsConfig: Record<string, Record<string, unknown>> = {};\n\n getPluginConfig(mode: string): Record<string, unknown> {\n return this.pluginsConfig[mode] ?? {};\n }\n\n refreshPluginsConfig() {\n this.pluginsConfig = readPluginsConfig(this.root);\n }\n\n savePluginConfig(merged: Record<string, Record<string, unknown>>) {\n this.pluginsConfig = merged;\n writePluginsConfig(this.root, merged);\n }\n\n private serveFile(filePath: string, req: http.IncomingMessage, res: http.ServerResponse, injectHtml: boolean) {\n // `/__` 前缀为 API/插件资源路径:错误保持原样(不换 HTML 错误页)\n const apiPath = (req.url || '').startsWith('/__');\n fs.stat(filePath, (err, stat) => {\n if (err) {\n if (apiPath) { res.writeHead(404); return res.end('Not found'); }\n return sendErrorPage(res, 404);\n }\n const ext = path.extname(filePath).toLowerCase();\n const ct = MIME[ext] ?? 'application/octet-stream';\n\n // ---- HTTP Range support ----\n const rangeHeader = (req.headers['range'] as string | undefined);\n let range: { start: number; end: number } | null = null;\n if (rangeHeader) {\n const m = rangeHeader.match(/^bytes=(\\d+)-(\\d*)$/);\n if (m) {\n const start = Number(m[1]);\n const end = m[2] !== '' ? Number(m[2]) : stat.size - 1;\n if (!Number.isNaN(start) && !Number.isNaN(end) && start <= end && start < stat.size) {\n range = { start, end: Math.min(end, stat.size - 1) };\n }\n // malformed range → fall through to 200 full response\n }\n // unparseable range header → fall through to 200 full response\n }\n\n if (range) {\n const { start, end } = range;\n const chunkSize = end - start + 1;\n res.writeHead(206, {\n 'Content-Type': ct,\n 'Content-Length': String(chunkSize),\n 'Content-Range': `bytes ${start}-${end}/${stat.size}`,\n 'Accept-Ranges': 'bytes',\n 'Cache-Control': 'no-cache',\n });\n // stat 成功后文件仍可能在 open 前被删/换(高频增删的工作区),流错误无人接会崩进程\n const stream = fs.createReadStream(filePath, { start, end });\n stream.on('error', () => { try { res.destroy(); } catch { /* 已断 */ } });\n stream.pipe(res);\n return;\n }\n\n // Full response\n fs.readFile(filePath, (err, data) => {\n if (err) {\n if (apiPath) { res.writeHead(404); return res.end('Not found'); }\n return sendErrorPage(res, 404);\n }\n let body: string | Buffer = 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, 'Accept-Ranges': 'bytes', 'Cache-Control': 'no-cache' });\n res.end(body);\n });\n });\n }\n\n private servePrefix(url: string, req: http.IncomingMessage, res: http.ServerResponse): boolean {\n for (const [prefix, dir] of this.prefixStatic) {\n if (url.indexOf(prefix) === 0) {\n let rel = this.safeDecode(url.slice(prefix.length));\n if (!rel || rel === '/' || !path.extname(rel)) rel = path.join(rel || '', 'index.html');\n const fp = path.join(dir, rel);\n if (fp.indexOf(dir + path.sep) !== 0) { res.writeHead(403); res.end('Forbidden'); return false; }\n this.serveFile(fp, req, res, true);\n return true;\n }\n }\n return false;\n }\n\n private safeDecode(raw: string): string {\n try { return decodeURIComponent(raw); } catch { return raw; }\n }\n\n private handler = (req: http.IncomingMessage, res: http.ServerResponse) => {\n try {\n const rawUrl = req.url || '/';\n const url = rawUrl.split('?')[0];\n\n const rh = this.routes.get(url);\n if (rh) { rh(req, res); return; }\n for (const [rp, rh2] of this.routes) {\n if (url.startsWith(rp + '/')) { rh2(req, res); return; }\n }\n const sh = this.sses.get(url);\n if (sh) {\n res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', Connection: 'keep-alive' });\n res.write(': connected\\n\\n');\n const cleanup = sh(res);\n req.on('close', () => { cleanup?.(); });\n return;\n }\n\n if (this.servePrefix(url, req, res)) return;\n\n if (url === '/' || url.indexOf('/__app/') === 0 || url.indexOf('/assets/') === 0) {\n let fp = this.appDir;\n if (url !== '/') fp = path.join(this.appDir, this.safeDecode(url));\n if (url.indexOf('/__app/') === 0) fp = path.join(this.appDir, url.slice(7));\n if (fp !== this.appDir && fp.indexOf(this.appDir + path.sep) !== 0) { return sendErrorPage(res, 403); }\n if (url === '/') fp = path.join(this.appDir, 'index.html');\n return this.serveFile(fp, req, res, false);\n }\n\n const fp = path.join(this.root, this.safeDecode(url));\n if (fp !== this.root && fp.indexOf(this.root + path.sep) !== 0) {\n // `/__` 前缀 API 路径错误保持原文(S2);页面类路径走 HTML 错误页\n if ((req.url || '').startsWith('/__')) { res.writeHead(403); return res.end('Forbidden'); }\n return sendErrorPage(res, 403);\n }\n return this.serveFile(fp, req, res, true);\n } catch (e) {\n // 兜底错误:API 路径保持原文(S2),页面类 400 错误页;头已发出时 sendErrorPage 仅断连\n try {\n if ((req.url || '').startsWith('/__')) { res.writeHead(400); res.end('bad request'); }\n else sendErrorPage(res, 400);\n } catch { /* 已断 */ }\n console.error('[zdashboard] handler error', e);\n }\n };\n\n start(port: number) {\n this.server = http.createServer(this.handler);\n // 浏览器复用空闲 keep-alive 连接时若已被服务端关闭,请求会石沉大海(点击无响应)。\n // 拉长 keep-alive 使其远大于浏览器侧空闲窗口\n this.server.keepAliveTimeout = 65_000;\n this.server.headersTimeout = 66_000;\n this.server.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n console.log(`[zdashboard] port ${port} busy, trying ${port + 1}`);\n this.start(port + 1);\n } else throw err;\n });\n this.server.listen(port, '127.0.0.1', () => {\n // port=0(测试/随机端口)时上报实际绑定端口\n const addr = this.server?.address();\n const bound = typeof addr === 'object' && addr ? addr.port : port;\n const u = `http://localhost:${bound}`;\n const target = this.page ? `${u}#${this.page}` : u;\n console.log(`[zdashboard] v${VERSION} dashboard -> ${u}`);\n console.log(`[zdashboard] project -> ${this.root}`);\n console.log(`[zdashboard] detect -> openspec:${this.det.hasOpenspec} docs:${this.det.hasDocs} just:${this.det.hasJust}`);\n if (this.dataDir) console.log(`[zdashboard] data -> ${this.dataDir}`);\n if (this.open) openUrl(target);\n this.onListen?.(bound);\n });\n }\n\n /** 项目 git 信息(分支/脏文件数),启动探测一次,文件变更时刷新 */\n private gitInfo: { branch?: string; dirty?: number } = {};\n\n refreshGitInfo() {\n const run = (args: string[]) => new Promise<string>((resolve) => {\n execFile('git', args, { cwd: this.root, timeout: 3000 }, (err, stdout) => resolve(err ? '' : stdout));\n });\n void (async () => {\n const [branch, status] = await Promise.all([\n run(['rev-parse', '--abbrev-ref', 'HEAD']),\n run(['status', '--porcelain']),\n ]);\n const b = branch.trim();\n this.gitInfo = b ? { branch: b, dirty: status ? status.split('\\n').filter(Boolean).length : 0 } : {};\n })();\n }\n\n stop() {\n if (this.server) { try { this.server.close(); } catch {} }\n try { clearRecord(this.root); } catch {}\n setTimeout(() => {\n try { this.ctx.root.fiber.dispose(); } catch {}\n process.exit(0);\n }, 50);\n }\n\n dispose() {\n if (this.server) { try { this.server.close(); } catch {} }\n try { clearRecord(this.root); } catch {}\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport pkg from '../../package.json' with { type: 'json' };\n\nconst CURRENT_VERSION: string = pkg.version;\n\nexport interface InstanceRecord {\n pid: number;\n port: number;\n root: string;\n startedAt: string;\n /** 写入该记录的实例版本(信息用途;活实例版本以 /__config 实时值为准) */\n version?: string;\n plugins?: Record<string, Record<string, unknown>>;\n}\n\nexport const RECORD_FILE = '.zdev/dashboard.json';\nexport const VERIFY_TIMEOUT_MS = 1500;\nexport const STOP_POLL_MS = 2000;\nexport const STOP_POLL_INTERVAL_MS = 100;\nexport const STOP_FINAL_WAIT_MS = 100;\n\nfunction recordPath(root: string): string {\n return path.join(root, RECORD_FILE);\n}\n\nexport function readRecord(root: string): InstanceRecord | null {\n try {\n const fp = recordPath(root);\n const raw = fs.readFileSync(fp, 'utf-8');\n const rec = JSON.parse(raw) as Partial<InstanceRecord>;\n if (\n typeof rec.pid === 'number' &&\n typeof rec.port === 'number' &&\n typeof rec.root === 'string' &&\n typeof rec.startedAt === 'string'\n ) {\n return rec as InstanceRecord;\n }\n return null;\n } catch {\n return null;\n }\n}\n\nexport function writeRecord(root: string, port: number): void {\n const fp = recordPath(root);\n fs.mkdirSync(path.dirname(fp), { recursive: true });\n // 读改写:onListen 每次启动都会调 writeRecord,需沿用旧记录的 plugins 段,\n // 只更新运行字段(pid/port/root/startedAt),否则插件配置跨重启清零。\n const old = readRecord(root); // 记录缺失/损坏 → null,兜底最小记录\n const rec: InstanceRecord = {\n pid: process.pid,\n port,\n root,\n startedAt: new Date().toISOString(),\n version: CURRENT_VERSION,\n };\n if (old?.plugins && typeof old.plugins === 'object') {\n rec.plugins = old.plugins;\n }\n // tmp+rename 原子写(对齐 writePluginsConfig),避免半写状态被读到\n const tmp = fp + '.tmp';\n fs.writeFileSync(tmp, JSON.stringify(rec, null, 2) + '\\n');\n fs.renameSync(tmp, fp);\n}\n\nexport function readPluginsConfig(root: string): Record<string, Record<string, unknown>> {\n try {\n const rec = readRecord(root);\n if (rec?.plugins && typeof rec.plugins === 'object') {\n return rec.plugins as Record<string, Record<string, unknown>>;\n }\n } catch { /* ignore */ }\n return {};\n}\n\nexport function writePluginsConfig(root: string, plugins: Record<string, Record<string, unknown>>): void {\n const fp = recordPath(root);\n let rec: InstanceRecord;\n try {\n const raw = fs.readFileSync(fp, 'utf-8');\n rec = JSON.parse(raw) as InstanceRecord;\n } catch {\n rec = { pid: process.pid, port: 0, root, startedAt: new Date().toISOString() };\n }\n rec.plugins = plugins;\n const tmp = fp + '.tmp';\n fs.writeFileSync(tmp, JSON.stringify(rec, null, 2) + '\\n');\n fs.renameSync(tmp, fp);\n}\n\n/** 死键剥离判定所需的最小 manifest 投影(PluginManifest 结构兼容) */\nexport interface ConfigSchemaInfo {\n mode: string;\n external?: boolean;\n /** manifest.config 声明:缺省或空对象表示该内置插件无配置面 */\n config?: Record<string, unknown>;\n}\n\n/**\n * 启动一次性:剥离 dashboard.json 里内置插件的死配置键(通用规则,收敛自 view/design 约定化扫描)。\n * - 内置(非 external)未声明 config → 整段死键,清除;\n * - 内置已声明 config → 仅保留声明键(键级收敛);\n * - external 插件键保留;存储中无 manifest 声明的键(未知/未加载插件)保守保留。\n * 无变更/无记录时不写盘。返回是否发生了剥离。记录缺失/损坏跳过清理,不阻塞启动。\n */\nexport function stripDeadPluginConfig(root: string, manifests: readonly ConfigSchemaInfo[]): boolean {\n try {\n const rec = readRecord(root);\n if (!rec?.plugins || typeof rec.plugins !== 'object') return false;\n const byMode = new Map(manifests.map((m) => [m.mode, m]));\n const stored = rec.plugins as Record<string, unknown>;\n const plugins: Record<string, unknown> = { ...stored };\n let changed = false;\n for (const mode of Object.keys(plugins)) {\n const m = byMode.get(mode);\n // 无声明(未注册,可能是外部插件或已卸载)→ 保守不清;external → 保留\n if (!m || m.external) continue;\n const section = plugins[mode];\n if (section === null || typeof section !== 'object') continue;\n const keys = Object.keys(section as Record<string, unknown>);\n if (!m.config || Object.keys(m.config).length === 0) {\n // 内置且未声明 config → 整段死键\n if (keys.length > 0) {\n delete plugins[mode];\n changed = true;\n }\n continue;\n }\n // 键级收敛:仅保留 manifest.config 声明的键\n const kept: Record<string, unknown> = {};\n for (const key of Object.keys(m.config)) {\n if (key in (section as Record<string, unknown>)) kept[key] = (section as Record<string, unknown>)[key];\n }\n if (Object.keys(kept).length !== keys.length) {\n if (Object.keys(kept).length === 0) delete plugins[mode];\n else plugins[mode] = kept;\n changed = true;\n }\n }\n if (!changed) return false;\n writePluginsConfig(root, plugins as Record<string, Record<string, unknown>>); // tmp+rename 原子写\n return true;\n } catch {\n return false; // 记录缺失/损坏:跳过清理,不阻塞启动\n }\n}\n\nexport function clearRecord(root: string): void {\n try {\n // 属主校验:记录若已指向别的实例(并发双启落败者),不得误删胜者记录\n const rec = readRecord(root);\n if (rec && rec.pid !== process.pid) return;\n fs.unlinkSync(recordPath(root));\n } catch {\n // best-effort\n }\n}\n\nexport function isAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code === 'ESRCH') return false;\n // EPERM or other → process exists, we just can't signal it\n return true;\n }\n}\n\nasync function fetchWithTimeout(url: string): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), VERIFY_TIMEOUT_MS);\n try {\n return await fetch(url, { signal: controller.signal });\n } finally {\n clearTimeout(timer);\n }\n}\n\n/** 活实例核验结果:reusable = 存活且 root 匹配;version 为该实例实时版本(供旧版检测) */\nexport interface VerifyResult {\n reusable: boolean;\n version?: string;\n}\n\nexport async function verifyRoot(port: number, root: string): Promise<VerifyResult> {\n try {\n const res = await fetchWithTimeout(`http://127.0.0.1:${port}/__config`);\n if (res.status !== 200) return { reusable: false };\n const body = await res.json();\n if (typeof body.root !== 'string') return { reusable: false };\n return {\n reusable: body.root === root,\n version: typeof body.version === 'string' ? body.version : undefined,\n };\n } catch {\n return { reusable: false };\n }\n}\n\n/**\n * 可复用实例发现:\n * - reuse → 存活 + root 匹配 + 版本一致,直接复用;\n * - stale-version → 存活 + root 匹配但版本落后(调用方决定提示或自动升级接管);\n * - null → 无可复用实例(无记录/进程死亡/端口被无关进程占用)。\n */\nexport async function findReusable(\n root: string,\n currentVersion: string,\n): Promise<{ status: 'reuse'; record: InstanceRecord } | { status: 'stale-version'; record: InstanceRecord; liveVersion?: string } | null> {\n const rec = readRecord(root);\n if (!rec) return null;\n if (!isAlive(rec.pid)) return null;\n const v = await verifyRoot(rec.port, root);\n if (!v.reusable) return null;\n if (v.version && v.version !== currentVersion) {\n return { status: 'stale-version', record: rec, liveVersion: v.version };\n }\n return { status: 'reuse', record: rec };\n}\n\nexport async function stopInstance(record: InstanceRecord): Promise<void> {\n try {\n process.kill(record.pid, 'SIGTERM');\n } catch {\n return;\n }\n\n const deadline = Date.now() + STOP_POLL_MS;\n while (Date.now() < deadline) {\n if (!isAlive(record.pid)) return;\n await new Promise((r) => setTimeout(r, STOP_POLL_INTERVAL_MS));\n }\n\n // still alive → SIGKILL\n try {\n process.kill(record.pid, 'SIGKILL');\n } catch {\n // ignore\n }\n await new Promise((r) => setTimeout(r, STOP_FINAL_WAIT_MS));\n}\n","import { exec, execFile } from 'node:child_process';\n\n/** 跨平台打开浏览器(macOS open / Windows start / Linux xdg-open) */\nexport function openUrl(url: string): void {\n const cmd =\n process.platform === 'darwin' ? 'open' :\n process.platform === 'win32' ? 'start' :\n 'xdg-open';\n // win32 `start` 是 shell 内建命令,只能走 shell;其他平台直接用 execFile\n if (process.platform === 'win32') {\n exec(`start \"\" \"${url}\"`);\n } else {\n execFile(cmd, [url]);\n }\n}\n","import fs from 'node:fs';\nimport http from 'node:http';\nimport { Service } from 'cordis';\nimport type { Context } from 'cordis';\n\ndeclare module 'cordis' {\n interface Context {\n reload: ReloadService;\n }\n}\n\nconst WATCH_DEBOUNCE_MS = 300;\n\n/** 忽略目录(recursive watch 相对路径前缀)与编辑器/系统/日志噪音文件 */\nconst IGNORED_DIR_RE = /^(?:\\.git|node_modules|dist|\\.pnpm)(?:[/\\\\]|$)/;\nconst IGNORED_FILE_RE = /\\.(?:swp|tmp|log)$|~$|^\\.DS_Store$|^Thumbs\\.db$/i;\n\n/** filename 是否应被 watcher 忽略;null(平台未提供文件名)放行,行为不变 */\nexport function isIgnoredPath(filename: string | null): boolean {\n if (!filename) return false;\n return IGNORED_DIR_RE.test(filename) || IGNORED_FILE_RE.test(filename);\n}\n\nexport class ReloadService extends Service {\n static inject = ['server'];\n private clients = new Set<http.ServerResponse>();\n private watcher?: fs.FSWatcher;\n private timer?: NodeJS.Timeout;\n\n constructor(ctx: Context, config: { root: string }) {\n super(ctx, 'reload');\n this.ctx.effect(() => () => this.dispose());\n\n this.ctx.server.sse('/__reload', (res) => {\n this.clients.add(res);\n return () => this.clients.delete(res);\n });\n\n try {\n this.watcher = fs.watch(config.root, { recursive: true }, (eventType, filename) => {\n if (isIgnoredPath(filename)) return;\n if (this.timer) clearTimeout(this.timer);\n this.timer = setTimeout(() => {\n this.ctx.server.refreshGitInfo();\n this.broadcast('reload');\n this.broadcast('files');\n this.timer = undefined;\n }, WATCH_DEBOUNCE_MS);\n });\n } catch {\n // watch unavailable - static only\n }\n }\n\n broadcast(ev: string, data: unknown = '') {\n const payload = `event: ${ev}\\ndata: ${JSON.stringify(data == null ? '' : data)}\\n\\n`;\n for (const c of this.clients) {\n try { c.write(payload); } catch {}\n }\n }\n\n /** 插件专用频道:plugin:<mode>:<event>,客户端 usePluginData subscribe 消费 */\n broadcastPlugin(mode: string, event: string, data: unknown = '') {\n this.broadcast(`plugin:${mode}:${event}`, data);\n }\n\n dispose() {\n if (this.watcher) { try { this.watcher.close(); } catch {} }\n if (this.timer) { clearTimeout(this.timer); }\n for (const c of this.clients) { try { c.end(); } catch {} }\n this.clients.clear();\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { walkDir } from './walk.js';\n\nexport type NodeKind = 'file' | 'dir' | 'log';\nexport interface TreeNode {\n name: string;\n kind: NodeKind;\n path?: string;\n defaultCollapsed?: boolean;\n children?: TreeNode[];\n}\n\nfunction buildTree(paths: string[], defaultExpandDepth = 2): TreeNode[] {\n const root: TreeNode[] = [];\n const map = new Map<string, TreeNode>();\n\n for (const p of paths) {\n const parts = p.split('/');\n let current = '';\n let parent = root;\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n current = current ? `${current}/${part}` : part;\n const isLast = i === parts.length - 1;\n const depth = i;\n\n if (!map.has(current)) {\n const isDir = !isLast;\n const collapsed = isDir && typeof defaultExpandDepth === 'number' && depth > defaultExpandDepth;\n const node: TreeNode = {\n name: part,\n kind: isLast ? 'file' : 'dir',\n ...(collapsed ? { defaultCollapsed: true } : {}),\n ...(isLast ? { path: p } : { children: [] }),\n };\n map.set(current, node);\n parent.push(node);\n }\n\n if (!isLast) {\n parent = map.get(current)!.children!;\n }\n }\n }\n\n const sortNodes = (nodes: TreeNode[]) => {\n nodes.sort((a, b) => (a.kind === b.kind ? a.name.localeCompare(b.name) : a.kind === 'dir' ? -1 : 1));\n for (const n of nodes) {\n if (n.children) sortNodes(n.children);\n }\n };\n\n sortNodes(root);\n return root;\n}\n\nexport interface ScanTreeOptions {\n defaultExpandDepth?: number;\n /** 允许点前缀的 scanDirs(如 .zdev/apply):声明后才扫描,且 walk 放行其内点前缀子目录;未声明的点前缀目录整组跳过 */\n dotDirs?: string[];\n}\n\nfunction prefixPaths(nodes: TreeNode[], prefix: string): TreeNode[] {\n return nodes.map((n) => {\n if (n.kind === 'file' && n.path) {\n return { ...n, path: `${prefix}/${n.path}` };\n }\n if (n.children) {\n return { ...n, children: prefixPaths(n.children, prefix) };\n }\n return n;\n });\n}\n\n/** 方案模式树形扫描:按 scanDirs 白名单扫描 */\nexport function scanTree(root: string, scanDirs: string[], opts?: ScanTreeOptions): TreeNode[] {\n const tree: TreeNode[] = [];\n const defaultExpandDepth = typeof opts?.defaultExpandDepth === 'number' ? opts.defaultExpandDepth : 2;\n const dotDeclared = new Set(Array.isArray(opts?.dotDirs) ? opts.dotDirs : []);\n const dirs = Array.isArray(scanDirs) ? scanDirs.filter((d) => typeof d === 'string' && d) : [];\n for (const dir of dirs) {\n // 点前缀目录须显式列入 dotDirs 才可扫(最小例外);未声明整组跳过\n if (dir.startsWith('.') && !dotDeclared.has(dir)) continue;\n const dirPath = path.join(root, dir);\n if (!fs.existsSync(dirPath)) continue;\n const paths: string[] = [];\n walkDir(dirPath, { maxDepth: 4, allowDotDirs: dotDeclared.has(dir), onFile: (_, rel) => paths.push(rel) });\n const prefix = dir;\n const children = prefixPaths(buildTree(paths, defaultExpandDepth), prefix);\n if (children.length) {\n tree.push({ name: `${dir} (${children.length})`, kind: 'dir', children });\n }\n }\n return tree;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nexport interface WalkOptions {\n skip?: Set<string>;\n maxDepth?: number;\n /** true 时点前缀「目录」不跳过(供显式列入 dotDirs 的扫描目录使用);点前缀「文件」仍恒跳过 */\n allowDotDirs?: boolean;\n onFile?: (abs: string, rel: string) => void;\n onDir?: (abs: string, rel: string) => void;\n}\n\nexport function walkDir(root: string, opts: WalkOptions = {}): void {\n const { skip = new Set(), maxDepth, allowDotDirs = false, onFile, onDir } = opts;\n\n function walk(dir: string, rel: string, depth: number) {\n if (typeof maxDepth === 'number' && depth > maxDepth) return;\n let ents: fs.Dirent[];\n try { ents = fs.readdirSync(dir, { withFileTypes: true }); } catch { return; }\n for (const ent of ents) {\n // 点前缀最小例外:仅目录可经 allowDotDirs 放行,文件一律跳过\n if (ent.name.startsWith('.') && !(allowDotDirs && ent.isDirectory())) continue;\n if (skip.has(ent.name)) continue;\n const abs = path.join(dir, ent.name);\n const r = rel ? `${rel}/${ent.name}` : ent.name;\n if (ent.isDirectory()) {\n onDir?.(abs, r);\n walk(abs, r, depth + 1);\n } else if (onFile) {\n onFile(abs, r);\n }\n }\n }\n\n walk(root, '', 0);\n}\n","import type { Context } from 'cordis';\nimport { scanTree } from '../server/spec-scan.js';\n\n/** 生态约定:项目根/worktree 根下的固定扫描目录,非用户可配;.zdev/apply 为点前缀目录,经 dotDirs 显式放行 */\nconst CONVENTION_SCAN_DIRS = ['openspec', 'docs', '.zdev/apply', '.zdev/scenario'] as const;\n/** 点前缀扫描目录子集:scanTree 须声明才可扫(walkDir 点前缀最小例外) */\nconst CONVENTION_DOT_DIRS = CONVENTION_SCAN_DIRS.filter((d) => d.startsWith('.'));\n\nexport const apply = {\n inject: ['server'] as const,\n apply(ctx: Context, config: { root: string }) {\n const server = ctx.server;\n if (server?.route) {\n // /__files 仅返回目录树;探测位已由独立轻量接口 /__detect 承担,不再搭车\n server.route('/__files', async (req, res) => {\n try {\n const url = new URL(req.url || '/', 'http://localhost');\n const wt = url.searchParams.get('wt');\n const scanRoot = wt ? decodeURIComponent(wt) : config.root;\n const tree = scanTree(scanRoot, [...CONVENTION_SCAN_DIRS], { dotDirs: [...CONVENTION_DOT_DIRS] });\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify({ tree }));\n } catch {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify({ tree: [] }));\n }\n });\n }\n },\n};\n","import { execFile } from 'node:child_process';\nimport type { Context } from 'cordis';\n\nexport interface WorktreeInfo {\n path: string;\n name: string;\n branch: string;\n head: string;\n dirty: boolean;\n}\n\nconst GIT_TIMEOUT_MS = 5_000;\nconst ZWORKTREE_SEGMENT = '.zworktree/';\n\nfunction runGit(args: string[], cwd: string): Promise<string> {\n return new Promise((resolve) => {\n execFile('git', args, { cwd, timeout: GIT_TIMEOUT_MS }, (err, stdout) => {\n if (err) return resolve('');\n resolve(stdout);\n });\n });\n}\n\nexport async function listWorktrees(root: string): Promise<WorktreeInfo[]> {\n const raw = await runGit(['worktree', 'list', '--porcelain'], root);\n if (!raw) return [];\n\n const entries: WorktreeInfo[] = [];\n const lines = raw.split('\\n');\n let current: Partial<WorktreeInfo> = {};\n\n for (const line of lines) {\n const m = line.match(/^(worktree|HEAD|branch|detached)\\s+(.+)$/);\n if (!m) continue;\n const [, key, val] = m;\n if (key === 'worktree') {\n if (current.path && current.path.includes(ZWORKTREE_SEGMENT)) {\n entries.push({\n path: current.path,\n name: current.path.split(ZWORKTREE_SEGMENT).pop() ?? '',\n branch: current.branch ?? '',\n head: current.head ?? '',\n dirty: false,\n });\n }\n current = { path: val, head: '', branch: '' };\n } else if (key === 'HEAD') {\n current.head = val;\n } else if (key === 'branch') {\n current.branch = val.replace(/^refs\\/heads\\//, '');\n }\n }\n\n // flush last entry\n if (current.path && current.path.includes(ZWORKTREE_SEGMENT)) {\n entries.push({\n path: current.path,\n name: current.path.split(ZWORKTREE_SEGMENT).pop() ?? '',\n branch: current.branch ?? '',\n head: current.head ?? '',\n dirty: false,\n });\n }\n\n // dirty detection: git status --porcelain 非空即 dirty(失败默认 false)\n await Promise.all(\n entries.map(async (entry) => {\n try {\n const statusOut = await runGit(['status', '--porcelain'], entry.path);\n entry.dirty = statusOut.trim().length > 0;\n } catch {\n entry.dirty = false;\n }\n })\n );\n\n return entries;\n}\n\nexport const apply = {\n inject: ['server'] as const,\n apply(ctx: Context, config: { root: string }) {\n const server = ctx.server;\n if (!server?.route) return;\n\n server.route('/__worktrees', async (_req, res) => {\n try {\n const entries = await listWorktrees(config.root);\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(entries));\n } catch {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify([]));\n }\n });\n },\n};\n","import { Service } from 'cordis';\nimport type { Context } from 'cordis';\nimport { readBody } from './read-body.js';\n\ndeclare module 'cordis' {\n interface Context {\n dashboard: DashboardService;\n }\n}\n\nexport interface PluginManifest {\n mode: string;\n label: string;\n icon: string;\n description?: string;\n viewerUrl?: string; // 同源 URL,前端 iframe 渲染\n external?: boolean;\n order?: number; // 排序权重(小在前);缺省按字母序\n config?: Record<string, ConfigField>;\n}\n\nexport interface ConfigField {\n type: 'string' | 'text' | 'number' | 'boolean' | 'string[]' | 'select' | 'multiselect';\n label: string;\n default?: unknown;\n placeholder?: string;\n options?: { value: string; label: string }[];\n min?: number;\n max?: number;\n}\n\nexport class DashboardService extends Service {\n static inject = ['server', 'reload'];\n private plugins = new Map<string, PluginManifest>();\n private reloadRef: any;\n\n constructor(ctx: Context) {\n super(ctx, 'dashboard');\n this.ctx.effect(() => () => this.plugins.clear());\n this.reloadRef = ctx.reload;\n\n this.ctx.server.route('/__plugins', (_req, res) => {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify({ plugins: Array.from(this.plugins.values()) }));\n });\n\n this.ctx.server.route('/__plugins/config', async (req, res) => {\n const out: Record<string, Record<string, unknown>> = {};\n if (req.method === 'GET') {\n for (const m of this.plugins.values()) {\n const stored = this.ctx.server.getPluginConfig(m.mode);\n const schema = m.config ?? {};\n const merged: Record<string, unknown> = {};\n for (const [key, field] of Object.entries(schema)) {\n merged[key] = key in stored ? stored[key] : (field as ConfigField).default ?? '';\n }\n if (Object.keys(merged).length) out[m.mode] = merged;\n }\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(out));\n return;\n }\n if (req.method === 'POST') {\n if (req.headers['x-stop-token'] !== this.ctx.server.stopToken) {\n res.writeHead(403);\n res.end('forbidden');\n return;\n }\n try {\n const body = JSON.parse(await readBody(req));\n const merged: Record<string, Record<string, unknown>> = {};\n for (const mode of Object.keys(body)) {\n merged[mode] = body[mode] ?? {};\n }\n this.ctx.server.savePluginConfig(merged);\n for (const mode of Object.keys(body)) {\n try { this.reloadRef.broadcast('config', { plugin: mode }); } catch { /* ignore */ }\n }\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end('{\"ok\":true}');\n } catch (e) {\n console.error('[config] POST error', e);\n res.writeHead(400);\n res.end('{\"error\":\"bad request\"}');\n }\n return;\n }\n res.writeHead(405);\n res.end('{\"error\":\"method not allowed\"}');\n });\n }\n\n register(manifest: PluginManifest) {\n this.plugins.set(manifest.mode, manifest);\n this.ctx.effect(() => () => this.plugins.delete(manifest.mode));\n }\n\n list() {\n return Array.from(this.plugins.values());\n }\n\n get(mode: string): PluginManifest | undefined {\n return this.plugins.get(mode);\n }\n\n getConfig(mode: string): Record<string, unknown> {\n return this.ctx.server.getPluginConfig(mode);\n }\n}\n","import http from 'node:http';\n\n/**\n * Read the full body of an IncomingMessage.\n * Listens for 'error' to prevent a hanging promise when the client aborts mid-stream.\n */\nexport async function readBody(req: http.IncomingMessage): Promise<string> {\n return new Promise((resolve) => {\n let data = '';\n req.on('data', (chunk: string | Buffer) => { data += chunk; });\n req.on('end', () => resolve(data));\n req.on('error', () => resolve('')); // client abort → settle with empty string\n });\n}\n","/**\n * just server 侧:definePlugin 接入(manifest 单源)。\n *\n * JustRunner 并发核实结论(T5):src/server/just-runner.ts 已是多任务并发 runner ——\n * tasks Map 每 recipe 独立子进程/日志缓冲/状态,事件载荷自带 recipe(=taskId),\n * 无需 runner 池改造。plugin:just:log 等频道广播按事件原样携带 taskId。\n *\n * start/restart/stop/clear 走 guardedRoute(x-stop-token);\n * /__just/tasks 为任务列表提供只读路由。\n */\nimport type http from 'node:http';\nimport { execFile } from 'node:child_process';\nimport { JustRunner } from '../../server/just-runner.js';\nimport { pickStringArgs } from '../../server/just-recipe-params.js';\nimport { readBody } from '../../core/read-body.js';\nimport { defineBuiltin } from '../builtin.js';\nimport { manifest } from './manifest.js';\nimport type { RouteHandler } from '../../sdk/server.js';\n\nexport const apply = defineBuiltin({\n manifest,\n setup(ctx, root) {\n const runner = new JustRunner(root);\n ctx.onDispose(() => runner.stop());\n\n ctx.route('/__just/recipes', async () => {\n try {\n return await runner.recipesWithParams();\n } catch {\n return [];\n }\n });\n\n ctx.route('/__just/tasks', async () => runner.list());\n\n // just 环境探测(空态三态文案依据):未装(ENOENT)/ 无 justfile(其他失败)/ 可用(成功)\n ctx.route('/__just/status', async () => {\n return await new Promise<{ installed: boolean; hasJustfile: boolean }>((resolve) => {\n execFile('just', ['--list', '--unsorted'], { cwd: root, maxBuffer: 1 << 20, timeout: 8000 }, (err) => {\n if (!err) return resolve({ installed: true, hasJustfile: true });\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return resolve({ installed: false, hasJustfile: false });\n resolve({ installed: true, hasJustfile: false });\n });\n });\n });\n\n ctx.sse('/__just/logs', (res) => {\n const unsub = runner.subscribe((ev) => {\n // 插件频道镜像:type 即事件名(log/clear/state),载荷携带 taskId(recipe)\n try { ctx.broadcast(ev.type, ev); } catch { /* reload 未就绪 */ }\n res.write(`data: ${JSON.stringify(ev)}\\n\\n`);\n });\n return unsub;\n });\n\n /** start/restart 须带合法 recipe(同名 start 即重启,可选 args 参数表);stop 可带单个 recipe 或省略(停全部);clear 清日志 */\n const handleAction = async (req: http.IncomingMessage, res: http.ServerResponse, act: 'start' | 'stop' | 'restart' | 'clear') => {\n const body = await readBody(req);\n let recipe: string | undefined;\n let rawArgs: unknown;\n try {\n const parsed = JSON.parse(body || '{}') as { recipe?: string; args?: unknown };\n recipe = parsed.recipe;\n rawArgs = parsed.args;\n } catch { /* ignore */ }\n if (act === 'clear') {\n if (recipe) runner.clear(recipe);\n return { ok: true };\n }\n if (act !== 'stop') {\n if (!recipe) {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end('{\"error\":\"no recipe\"}');\n return undefined;\n }\n const recipes = await runner.recipes();\n if (!recipes.some((r) => r.name === recipe)) {\n res.writeHead(403, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end('{\"error\":\"unknown recipe\"}');\n return undefined;\n }\n runner.start(recipe, pickStringArgs(rawArgs));\n } else {\n runner.stop(recipe || undefined);\n }\n return runner.list();\n };\n\n const routeAction = (name: 'start' | 'stop' | 'restart' | 'clear') => {\n ctx.guardedRoute(`/__just/${name}`, ((req, res) => handleAction(req, res, name)) satisfies RouteHandler);\n };\n routeAction('start');\n routeAction('stop');\n routeAction('restart');\n routeAction('clear');\n },\n});\n","import { spawn, execFile, type ChildProcess } from 'node:child_process';\nimport iconv from 'iconv-lite';\nimport { parseRecipeSignature, buildJustArgv } from './just-recipe-params.js';\n\nexport interface Recipe { name: string; description: string; }\nexport interface RecipeWithParams extends Recipe { params: string[] }\nexport type TaskStatus = 'running' | 'exited';\nexport interface TaskInfo { recipe: string; state: TaskStatus; code: number | null; startedAt: number; signal?: string }\n\nexport type JustEvent =\n | { type: 'log'; recipe: string; text: string }\n | { type: 'clear'; recipe: string }\n | { type: 'state'; recipe: string; state: TaskStatus; code: number | null; startedAt?: number; signal?: string };\n\ninterface Task {\n recipe: string;\n child: ChildProcess | null;\n state: TaskStatus;\n code: number | null;\n signal?: string;\n startedAt: number;\n buffer: string[];\n pending: Buffer; // 字节级行缓冲:块缓冲输出会在行中间断开,攒到 \\n(0x0A)才切行——多字节字符不会跨行界,解码只发生在完整行上\n}\n\nconst MAX_BUFFER = 1000;\n\nconst utf8Strict = new TextDecoder('utf-8', { fatal: true });\n\n/**\n * 逐行解码:先 UTF-8 严格解码,失败回退 GBK(Windows 码页输出)。\n * 行界按 0x0A 字节切分是安全的:UTF-8 续字节 ≥ 0x80、GBK 尾字节 0x40–0xFE,均不含 0x0A。\n */\nfunction decodeLine(buf: Buffer): string {\n try {\n return utf8Strict.decode(buf);\n } catch {\n return iconv.decode(buf, 'gbk');\n }\n}\n\n/** 多任务并发 runner:每个 recipe 独立进程/日志/状态,同名 start 即重启,互不影响 */\nexport class JustRunner {\n private cwd: string;\n private tasks = new Map<string, Task>();\n private clients = new Set<(ev: JustEvent) => void>();\n private recipesCache: Recipe[] | null = null;\n /** recipe 参数清单进程内缓存(含失败空数组),避免反复 just --show 探测 */\n private paramsCache = new Map<string, string[]>();\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 /** 懒解析单 recipe 参数:just --show 输出中首个可解析签名行(跳过 recipe 上方注释/空行)→ 参数名;失败记空数组并缓存 */\n recipeParams(name: string): Promise<string[]> {\n const hit = this.paramsCache.get(name);\n if (hit) return Promise.resolve(hit);\n return new Promise((resolve) => {\n execFile('just', ['--show', name], { cwd: this.cwd, maxBuffer: 1 << 20, timeout: 8000 }, (err, stdout) => {\n const sig = err ? null : stdout.split(/\\r?\\n/).map(l => parseRecipeSignature(l)).find(Boolean) ?? null;\n const params = sig?.params ?? [];\n this.paramsCache.set(name, params);\n resolve(params);\n });\n });\n }\n\n /** recipes 列表附参数清单(参数探测逐 recipe 并发,进程内缓存后零开销) */\n async recipesWithParams(): Promise<RecipeWithParams[]> {\n const list = await this.recipes();\n return Promise.all(list.map(async (r) => ({ ...r, params: await this.recipeParams(r.name) })));\n }\n\n subscribe(fn: (ev: JustEvent) => void): () => void {\n this.clients.add(fn);\n // 连上即重放:全部任务的日志与状态\n for (const t of this.tasks.values()) {\n for (const text of t.buffer) fn({ type: 'log', recipe: t.recipe, text });\n fn({ type: 'state', recipe: t.recipe, state: t.state, code: t.code, startedAt: t.startedAt });\n }\n return () => this.clients.delete(fn);\n }\n\n private emit(ev: JustEvent) { for (const fn of this.clients) fn(ev); }\n\n list(): TaskInfo[] {\n return Array.from(this.tasks.values(), (t) => ({ recipe: t.recipe, state: t.state, code: t.code, startedAt: t.startedAt }));\n }\n\n /** 启动 recipe:同名先停旧进程(重启语义),不影响其他任务;调用方须先用 recipes() 校验名字;\n * args 为可选参数表,spawn 数组 argv 追加 k=v(不经 shell,特殊字符安全) */\n start(recipe: string, args?: Record<string, string>) {\n this.killOne(recipe);\n const task: Task = { recipe, child: null, state: 'running', code: null, startedAt: Date.now(), buffer: [], pending: Buffer.alloc(0) };\n this.tasks.set(recipe, task);\n this.emit({ type: 'clear', recipe }); // 广播清屏:同步清掉该任务上一轮残留日志\n this.emit({ type: 'state', recipe, state: 'running', code: null, startedAt: task.startedAt });\n const child = spawn('just', buildJustArgv(recipe, args), {\n cwd: this.cwd,\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 task.child = child;\n // 身份守卫:同名重启后旧进程的迟到输出/退出不得污染新任务(闭包 task 是旧对象时静默丢弃)\n const isStale = () => this.tasks.get(recipe) !== task;\n const push = (d: Buffer) => {\n if (isStale()) return;\n task.pending = Buffer.concat([task.pending, d]);\n let idx: number;\n while ((idx = task.pending.indexOf(0x0a)) >= 0) { // 字节级切行:行界 0x0A 不会落在多字节字符内部\n const line = task.pending.subarray(0, idx + 1);\n task.pending = task.pending.subarray(idx + 1);\n this.pushLine(task, decodeLine(line));\n }\n // 无 \\n 的尾巴留在字节缓冲,等下个 chunk(块缓冲输出会在行中断开,不能当独立行;半个多字节字符也在此安全等待)\n };\n child.stdout?.on('data', push);\n child.stderr?.on('data', push);\n child.on('error', (err) => { this.pushLine(task, `[zdashboard] spawn error: ${err.message}\\n`); });\n child.on('exit', (code, signal) => {\n if (task.pending.length > 0 && !isStale()) { this.pushLine(task, decodeLine(task.pending) + '\\n'); } // flush 末尾无换行的残留(空 Buffer 为 truthy,须按 length 判)\n task.pending = Buffer.alloc(0);\n task.child = null;\n task.state = 'exited';\n task.code = code ?? 0;\n task.signal = signal ?? undefined; // 用户主动 stop 时 code=null+SIGTERM,与成功退出区分\n if (isStale()) return; // 迟到的旧进程退出,不打扰新任务状态\n this.emit({ type: 'state', recipe, state: 'exited', code: task.code, startedAt: task.startedAt, signal: task.signal });\n });\n }\n\n /** 行推送:行内 \\r 再切分为多段独立行(进度条输出降级为分段渲染);\n * \\r 空段丢弃,但整行全空仍推送一条空行(空行是日志内容,不静默丢弃) */\n private pushLine(task: Task, line: string) {\n const body = line.endsWith('\\n') ? line.slice(0, -1) : line;\n const segs = body.split('\\r').filter(Boolean);\n if (segs.length === 0) {\n this.pushSegment(task, '');\n return;\n }\n for (const seg of segs) this.pushSegment(task, seg);\n }\n\n private pushSegment(task: Task, seg: string) {\n const text = seg + '\\n';\n task.buffer.push(text);\n if (task.buffer.length > MAX_BUFFER) task.buffer.shift();\n this.emit({ type: 'log', recipe: task.recipe, text });\n }\n\n /** 停单个任务;不传 recipe 停全部 */\n stop(recipe?: string) {\n if (recipe === undefined) { for (const t of this.tasks.values()) this.killOne(t.recipe); }\n else this.killOne(recipe);\n }\n\n restart(recipe: string) {\n if (this.tasks.has(recipe)) this.start(recipe);\n }\n\n /** 清空某任务的日志缓冲并广播(真源清除,重连重放不会复活) */\n clear(recipe: string) {\n const task = this.tasks.get(recipe);\n if (!task) return;\n task.buffer = [];\n task.pending = Buffer.alloc(0);\n this.emit({ type: 'clear', recipe });\n }\n\n private killOne(recipe: string) {\n const task = this.tasks.get(recipe);\n const child = task?.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 if (task) { task.child = null; }\n }\n}\n","/**\n * just recipe 参数纯函数:签名解析(just --show 首行)与 spawn argv 拼装。\n *\n * 解析器为字符级扫描(非空白切分):默认值可含空格(`a=\"x y\"`),引号内内容不参与结构解析。\n * argv 拼装契约:数组原样传值,调用方 spawn 不得开 shell——值含空格/引号/& 时保持单元素,\n * 不经 shell 拼接即天然免疫注入与串位。\n */\n\nexport interface RecipeSignature { name: string; params: string[] }\n\nconst NAME_RE = /^[A-Za-z_][A-Za-z0-9_-]*/;\n\n/** 解析 recipe 签名行(`hello msg=\"world\":`);无冒号收尾等非法输入 → null */\nexport function parseRecipeSignature(line: string): RecipeSignature | null {\n let s = line.trim();\n if (s.startsWith('@')) s = s.slice(1).trimStart(); // private recipe 前缀\n const nameMatch = NAME_RE.exec(s);\n if (!nameMatch) return null;\n const name = nameMatch[0];\n const params: string[] = [];\n let i = name.length;\n while (true) {\n while (i < s.length && /\\s/.test(s[i])) i++;\n if (i >= s.length) return null; // 没等到收尾冒号\n if (s[i] === ':') {\n const rest = s.slice(i + 1).trim();\n if (rest === '' || rest.startsWith('#')) return { name, params };\n return null;\n }\n // 参数 token:可选 +/$ 前缀 + 参数名 + 可选 =默认值(引号内可有空格)\n let j = i;\n if (s[j] === '+' || s[j] === '$') j++;\n const pm = NAME_RE.exec(s.slice(j));\n if (!pm) return null;\n j += pm[0].length;\n if (s[j] === '=') {\n j++;\n if (s[j] === '\"' || s[j] === \"'\") {\n const quote = s[j];\n j++;\n while (j < s.length && s[j] !== quote) j++;\n if (j >= s.length) return null; // 引号未闭合\n j++;\n } else {\n while (j < s.length && !/\\s/.test(s[j]) && s[j] !== ':') j++;\n }\n }\n params.push(pm[0]);\n i = j;\n }\n}\n\n/** spawn argv:[recipe, ...k=v];args 为空/undefined 时不追加,与无参调用同形 */\nexport function buildJustArgv(recipe: string, args?: Record<string, string>): string[] {\n if (!args) return [recipe];\n return [recipe, ...Object.entries(args).map(([k, v]) => `${k}=${v}`)];\n}\n\n/** start args 白名单化:仅保留 string 值;剔除后为空或输入非对象 → undefined(请求体不携带 args) */\nexport function pickStringArgs(args: unknown): Record<string, string> | undefined {\n if (typeof args !== 'object' || args === null) return undefined;\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(args)) {\n if (typeof v === 'string') out[k] = v;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n","/**\n * 插件 SDK(server 侧):definePlugin 是插件接入宿主的唯一姿势。\n *\n * 内部自动完成 dashboard.register(manifest) 与 effect 清理注册,\n * 插件作者只面对 PluginContext 的七个通道;四种 cordis 手写姿势由此消亡。\n */\nimport type http from 'node:http';\nimport { json, guarded } from '../core/server.js';\nimport type { Context } from 'cordis';\nimport type { PluginManifest } from '../core/manifest.js';\n\n/** handler 返回非 undefined 值时由 SDK 包装为 json 响应;自行写响应则返回 undefined */\nexport type RouteHandler = (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n) => unknown | Promise<unknown>;\n\nexport type SseHandler = (res: http.ServerResponse) => (() => void) | void;\n\nexport interface PluginContext {\n /** manifest.mode 的只读镜像 */\n readonly mode: string;\n /** manifest.config 默认值合并 .zdev/dashboard.json 存储值(存储优先) */\n config<T extends Record<string, unknown> = Record<string, unknown>>(): T;\n /** 注册路由;handler 返回值自动 json 包装(200 + application/json) */\n route(path: string, handler: RouteHandler): void;\n /** 校验 x-stop-token 后执行 route 语义;缺/错 token 直接 403 */\n guardedRoute(path: string, handler: RouteHandler): void;\n sse(path: string, handler: SseHandler): void;\n static(prefix: string, dir: string): void;\n /** 广播到 SSE 频道 plugin:<mode>:<event>,客户端 usePluginData subscribe 消费 */\n broadcast(event: string, data?: unknown): void;\n onDispose(fn: () => void): void;\n}\n\ninterface CordisPluginApply {\n inject?: readonly string[];\n apply(ctx: Context, config: unknown): unknown;\n}\n\n/**\n * 定义内置/外部插件的 server 侧入口。\n * @param def.manifest 与 client defineWebPlugin 共享的同一份常量(SSOT)\n * @param def.setup 在 server/dashboard 服务就绪的上下文中执行\n */\nexport function definePlugin(def: {\n manifest: PluginManifest;\n setup(ctx: PluginContext): void;\n}): CordisPluginApply & { inject: readonly string[] } {\n const { manifest, setup } = def;\n\n return {\n inject: ['server', 'dashboard', 'reload'] as const,\n apply(this: void, ctx: Context) {\n const disposers: Array<() => void> = [];\n ctx.effect(() => () => {\n for (const fn of disposers.splice(0)) {\n try { fn(); } catch (e) {\n console.error(`[zdashboard] plugin ${manifest.mode} dispose error:`, e);\n }\n }\n });\n\n ctx.dashboard.register(manifest);\n\n /** json 包装语义与错误兜底;guardedRoute 不经此重注册路径 */\n const respondWith = (handler: RouteHandler) => async (req: http.IncomingMessage, res: http.ServerResponse) => {\n if (res.headersSent) return;\n try {\n const data = await handler(req, res);\n if (data !== undefined && !res.writableEnded) json(res, data);\n } catch (e) {\n console.error(`[zdashboard] plugin ${manifest.mode} route error:`, e);\n if (!res.headersSent) json(res, { error: 'internal' }, 500);\n }\n };\n\n const pctx: PluginContext = {\n mode: manifest.mode,\n config<T extends Record<string, unknown> = Record<string, unknown>>(): T {\n const schema = manifest.config ?? {};\n const stored = ctx.server.getPluginConfig(manifest.mode) ?? {};\n const defaults = Object.fromEntries(\n Object.entries(schema).map(([key, field]) => [key, field.default]),\n );\n return { ...defaults, ...stored } as T;\n },\n route(path: string, handler: RouteHandler): void {\n ctx.server.route(path, respondWith(handler));\n },\n guardedRoute(path: string, handler: RouteHandler): void {\n const token = () => ctx.server.stopToken;\n ctx.server.route(path, (req, res) => {\n if (!guarded(req, res, token())) return;\n void respondWith(handler)(req, res);\n });\n },\n sse(path: string, handler: SseHandler): void {\n ctx.server.sse(path, handler);\n },\n static(prefix: string, dir: string): void {\n ctx.server.static(prefix, dir);\n },\n broadcast(event: string, data?: unknown): void {\n ctx.reload?.broadcast(`plugin:${manifest.mode}:${event}`, data ?? '');\n },\n onDispose(fn: () => void): void {\n disposers.push(fn);\n },\n };\n\n setup(pctx);\n },\n };\n}\n","/**\n * 内置插件 root 注入壳(插件侧适配,不动 SDK 公共契约):\n *\n * SDK definePlugin 的 apply(ctx) 不向 setup 转发 cordis 插件 config,\n * 而六个内置插件都需要 cli 注入的 { root }。此壳在插件层捕获 config.root\n * 再调用 SDK 产出的 apply,setup 以第二参拿到 root。\n * 若 SDK 未来转发 config,此文件可整体删除。\n */\nimport type { Context } from 'cordis';\nimport { definePlugin, type PluginContext } from '../sdk/server.js';\nimport type { PluginManifest } from '../core/manifest.js';\n\nexport function defineBuiltin(def: {\n manifest: PluginManifest;\n setup(ctx: PluginContext, root: string): void;\n}) {\n let currentRoot = '';\n const inner = definePlugin({\n manifest: def.manifest,\n setup(pctx) { def.setup(pctx, currentRoot); },\n });\n\n return {\n inject: inner.inject,\n manifest: def.manifest, // cli 启动期死键剥离按 manifest 判定(config 声明/external)\n apply(ctx: Context, config: { root?: string }) {\n currentRoot = config?.root ?? '';\n inner.apply(ctx, config);\n },\n };\n}\n","/** just 插件单源:server definePlugin 与 web defineWebPlugin 共享 */\nimport type { PluginManifest } from '../../core/manifest.js';\nimport type { ParamSchema } from '../../sdk/shared.js';\n\nexport const manifest: PluginManifest = {\n mode: 'just',\n label: 'Just Runner',\n icon: '📜',\n description: 'Just 任务日志与执行',\n order: 50,\n};\n\n/** recipe:选中 recipe;task:活跃任务 id(与 recipe 同名空间) */\nexport const params: ParamSchema = [\n { name: 'recipe', label: 'Recipe', type: 'string', description: '选中的 recipe 名' },\n { name: 'task', label: '任务', type: 'string', description: '活跃任务 id' },\n];\n","/**\n * design server 侧:definePlugin 接入(约定化扫描)。\n * 恒扫 <root>/.zdev/design(zdesign 等 skill 统一产出目录,walkDir 跳过点目录扫根看不见);\n * 目录缺失 → emptyScan() 全组空数组。/__design/assets 响应形状(ScanResult)保持不变。\n * 另供只读代理 /__design/asset?path=<rel-to-.zdev/design>,viewers 由此加载资产(直取根路径必 404)。\n */\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport { MIME } from '../../core/server.js';\nimport { scanAssets, type ScanResult, type AssetType } from '../../server/design-assets.js';\nimport { defineBuiltin } from '../builtin.js';\nimport { manifest } from './manifest.js';\n\nconst ASSET_KEYS: AssetType[] = ['page', 'component', 'icon', 'token', 'md', 'video', 'audio', 'pdf', 'font', 'diagram'];\n\nfunction emptyScan(): ScanResult {\n const out = {} as ScanResult;\n for (const k of ASSET_KEYS) out[k] = [];\n return out;\n}\n\nexport const apply = defineBuiltin({\n manifest,\n setup(ctx, root) {\n ctx.route('/__design/assets', async () => {\n const designRoot = path.join(root, '.zdev', 'design');\n return fs.existsSync(designRoot) ? scanAssets(designRoot) : emptyScan();\n });\n\n // 只读资产代理:三重防御钉死任意读(字符拒绝 → join 归一化 → 前缀校验),先例 /__file-content\n ctx.route('/__design/asset', async (req, res) => {\n const rel = new URL(req.url || '/', 'http://localhost').searchParams.get('path') ?? '';\n if (!rel || rel.includes('..') || rel.includes('\\\\') || path.isAbsolute(rel)) {\n res.writeHead(400);\n res.end('bad path');\n return;\n }\n const designRoot = path.join(root, '.zdev', 'design');\n const filePath = path.join(designRoot, rel);\n if (!filePath.startsWith(designRoot + path.sep)) {\n res.writeHead(400);\n res.end('bad path');\n return;\n }\n fs.stat(filePath, (err) => {\n if (err) { res.writeHead(404); return res.end('Not found'); }\n const ct = MIME[path.extname(filePath).toLowerCase()] ?? 'application/octet-stream';\n res.writeHead(200, { 'Content-Type': ct, 'Cache-Control': 'no-cache' });\n // stat 通过后文件仍可能被删,流错误无人接会崩进程(与 core/server serveFile 同款兜底)\n const stream = fs.createReadStream(filePath);\n stream.on('error', () => { try { res.destroy(); } catch { /* 已断 */ } });\n stream.pipe(res);\n });\n });\n },\n});\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { walkDir } from './walk.js';\n\nexport type AssetType = 'page' | 'component' | 'icon' | 'token' | 'md' | 'video' | 'audio' | 'pdf' | 'font' | 'diagram';\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', '.cjs', '.mts', '.cts', '.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 | null {\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 // 图表:置于 CODE 判断前(.drawio 虽非 CODE_EXTS,显式前置防未来扩展名表收编)\n if (ext === '.excalidraw' || ext === '.drawio') return 'diagram';\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)) {\n if (TOKEN_RE.test(rel) && (ext === '.css' || ext === '.json')) return 'token';\n return null;\n }\n return null;\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, subDir = ''): ScanResult {\n const out: ScanResult = {} as ScanResult;\n const keys: AssetType[] = ['page','component','icon','token','md','video','audio','pdf','font','diagram'];\n for (const k of keys) out[k] = [];\n const SKIP = new Set(['node_modules', '.git', 'dist', 'build', 'coverage', '.next', '.cache']);\n const scanRoot = subDir ? path.join(root, subDir) : root;\n walkDir(scanRoot, { skip: SKIP, onFile: (abs, rel) => {\n const ext = path.extname(abs).toLowerCase();\n const t = categorize(rel, ext);\n if (t) out[t].push({ path: rel, name: path.basename(abs), ext, type: t });\n }});\n return out;\n}\n","/** design 插件单源:server definePlugin 与 web defineWebPlugin 共享 */\nimport type { PluginManifest } from '../../core/manifest.js';\nimport type { ParamSchema } from '../../sdk/shared.js';\n\nexport const manifest: PluginManifest = {\n mode: 'design',\n label: '设计资产',\n icon: '🎨',\n description: '设计资产分类浏览 · zdesign',\n order: 30,\n};\n\n/** type:资产类型;asset:选中资产路径;folder:资产路径过滤展示 */\nexport const params: ParamSchema = [\n { name: 'type', label: '资产类型', type: 'string', description: 'page/component/icon/token/md/video/audio/pdf/font' },\n { name: 'asset', label: '选中资产', type: 'string', description: '资产相对路径' },\n { name: 'folder', label: '当前文件夹', type: 'string', description: '限定展示的资产路径前缀' },\n];\n","/** view 插件单源:server definePlugin 与 web defineWebPlugin 共享 */\nimport type { PluginManifest } from '../../core/manifest.js';\nimport type { ParamSchema } from '../../sdk/shared.js';\n\nexport const manifest: PluginManifest = {\n mode: 'view',\n label: '项目浏览',\n icon: '👁️',\n description: 'openspec / docs / 文档预览',\n order: 20,\n};\n\n/** wt:worktree 绝对路径;file:文件相对路径;filter:树过滤词 */\nexport const params: ParamSchema = [\n { name: 'wt', label: 'Worktree 路径', type: 'string', description: 'worktree 绝对路径' },\n { name: 'file', label: '文件路径', type: 'string', description: '预览文件相对路径' },\n { name: 'filter', label: '过滤词', type: 'string', description: '文件树过滤词' },\n];\n","/**\n * view server 侧:definePlugin 接入(manifest 单源)。\n * 文件树路由 /__files 由 core/tree.ts 宿主服务提供(约定目录 ['openspec','docs'],非配置),此处仅注册 manifest。\n */\nimport { defineBuiltin } from '../builtin.js';\nimport { manifest } from './manifest.js';\n\nexport const apply = defineBuiltin({\n manifest,\n setup() { /* 路由由 core/tree.ts 承载 */ },\n});\n","/**\n * stats server 侧:definePlugin 接入(manifest 单源)。\n * /__stats/data 响应形状与迁移前保持一致。\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { execFile } from 'node:child_process';\nimport { walkDir } from '../../server/walk.js';\nimport { listWorktrees } from '../../core/worktrees.js';\nimport { defineBuiltin } from '../builtin.js';\nimport { manifest } from './manifest.js';\n\ninterface Stats {\n root: string;\n files: number;\n dirs: number;\n totalSize: number;\n byExt: { ext: string; count: number }[];\n markdown: number;\n openspec: { active: number; archived: number };\n hasJust: boolean;\n worktrees: number;\n branch?: string;\n dirty?: number;\n}\n\nconst SKIP_DIRS = new Set(['node_modules', '.git', 'dist', 'build', '.next', '.cache']);\n\nfunction execFilePromise(file: string, args: string[], opts: { cwd: string }): Promise<string> {\n return new Promise((resolve) => {\n execFile(file, args, opts, (err, stdout) => resolve(err ? '' : stdout));\n });\n}\n\nfunction scan(root: string): Stats {\n const stats: Stats = {\n root: path.basename(root),\n files: 0,\n dirs: 0,\n totalSize: 0,\n byExt: [],\n markdown: 0,\n openspec: { active: 0, archived: 0 },\n hasJust: fs.existsSync(path.join(root, 'justfile')),\n worktrees: 0,\n };\n const extMap = new Map<string, number>();\n\n const walk = (dir: string) => {\n walkDir(dir, { skip: SKIP_DIRS, onDir: () => { stats.dirs++; }, onFile: (abs) => {\n stats.files++;\n try { stats.totalSize += fs.statSync(abs).size; } catch {}\n const ext = path.extname(abs).toLowerCase() || '(无扩展名)';\n extMap.set(ext, (extMap.get(ext) ?? 0) + 1);\n if (ext === '.md' || ext === '.markdown') stats.markdown++;\n }});\n };\n walk(root);\n\n const changesDir = path.join(root, 'openspec', 'changes');\n if (fs.existsSync(changesDir)) {\n for (const ent of fs.readdirSync(changesDir, { withFileTypes: true })) {\n if (!ent.isDirectory() || ent.name.startsWith('.')) continue;\n if (ent.name === 'archive') {\n try {\n stats.openspec.archived = fs.readdirSync(path.join(changesDir, 'archive'), { withFileTypes: true })\n .filter(e => e.isDirectory() && !e.name.startsWith('.')).length;\n } catch { /* ignore */ }\n } else stats.openspec.active++;\n }\n }\n\n stats.byExt = Array.from(extMap.entries())\n .map(([ext, count]) => ({ ext, count }))\n .sort((a, b) => b.count - a.count)\n .slice(0, 10);\n return stats;\n}\n\nexport const apply = defineBuiltin({\n manifest,\n setup(ctx, root) {\n ctx.route('/__stats/data', async () => {\n const stats = scan(root);\n try {\n const wts = await listWorktrees(root);\n stats.worktrees = wts.length;\n } catch {\n stats.worktrees = 0;\n }\n try {\n const branchOut = await execFilePromise('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { cwd: root });\n stats.branch = branchOut.trim() || undefined;\n } catch { /* ignore */ }\n try {\n const statusOut = await execFilePromise('git', ['status', '--porcelain'], { cwd: root });\n stats.dirty = statusOut.trim() ? statusOut.trim().split('\\n').length : 0;\n } catch { /* ignore */ }\n return stats;\n });\n },\n});\n","/** stats 插件单源:server definePlugin 与 web defineWebPlugin 共享 */\nimport type { PluginManifest } from '../../core/manifest.js';\nimport type { ParamSchema } from '../../sdk/shared.js';\n\nexport const manifest: PluginManifest = {\n mode: 'stats',\n label: '项目统计',\n icon: '📊',\n description: '项目文件统计 · 扫描生成',\n order: 10,\n};\n\n/** card:钻取来源(worktree/dirty),view 侧读取后高亮 */\nexport const params: ParamSchema = [\n { name: 'card', label: '钻取来源', type: 'string', description: '钻取来源(worktree/dirty),view 侧读取后高亮' },\n];\n"],"mappings":";;;AAAA,OAAOA,WAAU;AACjB,OAAOC,SAAQ;AACf,SAAS,iBAAAC,sBAAqB;AAC9B,SAAS,QAAQ,eAAe;;;ACHhC;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,MAAQ;AAAA,IACR,WAAa;AAAA,IACb,iBAAiB;AAAA,IACjB,SAAW;AAAA,EACb;AAAA,EACA,cAAgB;AAAA,IACd,0BAA0B;AAAA,IAC1B,qBAAqB;AAAA,IACrB,yBAAyB;AAAA,IACzB,iCAAiC;AAAA,IACjC,+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,QAAU;AAAA,IACV,UAAY;AAAA,IACZ,YAAY;AAAA,IACZ,UAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,OAAS;AAAA,IACT,IAAM;AAAA,IACN,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,eAAiB;AAAA,IACjB,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,KAAO;AAAA,IACP,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,uBAAuB;AAAA,IACvB,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;;;ADtFA,SAAS,aAAa,qBAAqB;;;AEN3C,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,gBAAgB;AASzB,IAAM,wBAAwB;AAE9B,IAAM,2BAA2B;AAEjC,SAAS,cAAc,KAA+B;AAEpD,QAAM,QAAQ,CAAC,MAAgB,YAAoB,IAAI,QAAiB,CAAC,YAAY;AACnF,UAAM,QAAQ,SAAS,QAAQ,MAAM,EAAE,KAAK,QAAQ,GAAG,CAAC,QAAQ,QAAQ,CAAC,GAAG,CAAC;AAC7E,QAAI,MAAM,OAAQ,SAAQ,KAAK;AAAA,EACjC,CAAC;AAGD,SAAO,MAAM,CAAC,UAAU,eAAe,GAAG,qBAAqB,EAC5D,KAAK,CAAC,OAAQ,KAAK,OAAO,MAAM,CAAC,WAAW,GAAG,wBAAwB,CAAE;AAC9E;AAEA,eAAsB,OAAO,MAAqC;AAChE,QAAM,cAAc,GAAG,WAAW,KAAK,KAAK,MAAM,UAAU,CAAC;AAC7D,QAAM,UAAU,GAAG,WAAW,KAAK,KAAK,MAAM,MAAM,CAAC;AACrD,QAAM,UAAU,MAAM,cAAc,IAAI;AACxC,SAAO,EAAE,aAAa,SAAS,QAAQ;AACzC;AAMA,eAAsB,gBAAgB,MAAuC;AAC3E,SAAO,OAAO,IAAI;AACpB;;;AF/BA,SAAS,eAAwB;;;AGTjC,OAAO,UAAU;AACjB,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,OAAO,YAAY;AACnB,SAAS,qBAAqB;AAM9B,SAAS,eAAe;;;ACVxB,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAGjB,IAAM,kBAA0B,gBAAI;AAY7B,IAAM,cAAc;AACpB,IAAM,oBAAoB;AAC1B,IAAM,eAAe;AACrB,IAAM,wBAAwB;AAC9B,IAAM,qBAAqB;AAElC,SAAS,WAAW,MAAsB;AACxC,SAAOC,MAAK,KAAK,MAAM,WAAW;AACpC;AAEO,SAAS,WAAW,MAAqC;AAC9D,MAAI;AACF,UAAM,KAAK,WAAW,IAAI;AAC1B,UAAM,MAAMC,IAAG,aAAa,IAAI,OAAO;AACvC,UAAM,MAAM,KAAK,MAAM,GAAG;AAC1B,QACE,OAAO,IAAI,QAAQ,YACnB,OAAO,IAAI,SAAS,YACpB,OAAO,IAAI,SAAS,YACpB,OAAO,IAAI,cAAc,UACzB;AACA,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,YAAY,MAAc,MAAoB;AAC5D,QAAM,KAAK,WAAW,IAAI;AAC1B,EAAAA,IAAG,UAAUD,MAAK,QAAQ,EAAE,GAAG,EAAE,WAAW,KAAK,CAAC;AAGlD,QAAM,MAAM,WAAW,IAAI;AAC3B,QAAM,MAAsB;AAAA,IAC1B,KAAK,QAAQ;AAAA,IACb;AAAA,IACA;AAAA,IACA,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,SAAS;AAAA,EACX;AACA,MAAI,KAAK,WAAW,OAAO,IAAI,YAAY,UAAU;AACnD,QAAI,UAAU,IAAI;AAAA,EACpB;AAEA,QAAM,MAAM,KAAK;AACjB,EAAAC,IAAG,cAAc,KAAK,KAAK,UAAU,KAAK,MAAM,CAAC,IAAI,IAAI;AACzD,EAAAA,IAAG,WAAW,KAAK,EAAE;AACvB;AAEO,SAAS,kBAAkB,MAAuD;AACvF,MAAI;AACF,UAAM,MAAM,WAAW,IAAI;AAC3B,QAAI,KAAK,WAAW,OAAO,IAAI,YAAY,UAAU;AACnD,aAAO,IAAI;AAAA,IACb;AAAA,EACF,QAAQ;AAAA,EAAe;AACvB,SAAO,CAAC;AACV;AAEO,SAAS,mBAAmB,MAAc,SAAwD;AACvG,QAAM,KAAK,WAAW,IAAI;AAC1B,MAAI;AACJ,MAAI;AACF,UAAM,MAAMA,IAAG,aAAa,IAAI,OAAO;AACvC,UAAM,KAAK,MAAM,GAAG;AAAA,EACtB,QAAQ;AACN,UAAM,EAAE,KAAK,QAAQ,KAAK,MAAM,GAAG,MAAM,YAAW,oBAAI,KAAK,GAAE,YAAY,EAAE;AAAA,EAC/E;AACA,MAAI,UAAU;AACd,QAAM,MAAM,KAAK;AACjB,EAAAA,IAAG,cAAc,KAAK,KAAK,UAAU,KAAK,MAAM,CAAC,IAAI,IAAI;AACzD,EAAAA,IAAG,WAAW,KAAK,EAAE;AACvB;AAiBO,SAAS,sBAAsB,MAAc,WAAiD;AACnG,MAAI;AACF,UAAM,MAAM,WAAW,IAAI;AAC3B,QAAI,CAAC,KAAK,WAAW,OAAO,IAAI,YAAY,SAAU,QAAO;AAC7D,UAAM,SAAS,IAAI,IAAI,UAAU,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AACxD,UAAM,SAAS,IAAI;AACnB,UAAM,UAAmC,EAAE,GAAG,OAAO;AACrD,QAAI,UAAU;AACd,eAAW,QAAQ,OAAO,KAAK,OAAO,GAAG;AACvC,YAAM,IAAI,OAAO,IAAI,IAAI;AAEzB,UAAI,CAAC,KAAK,EAAE,SAAU;AACtB,YAAM,UAAU,QAAQ,IAAI;AAC5B,UAAI,YAAY,QAAQ,OAAO,YAAY,SAAU;AACrD,YAAM,OAAO,OAAO,KAAK,OAAkC;AAC3D,UAAI,CAAC,EAAE,UAAU,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,GAAG;AAEnD,YAAI,KAAK,SAAS,GAAG;AACnB,iBAAO,QAAQ,IAAI;AACnB,oBAAU;AAAA,QACZ;AACA;AAAA,MACF;AAEA,YAAM,OAAgC,CAAC;AACvC,iBAAW,OAAO,OAAO,KAAK,EAAE,MAAM,GAAG;AACvC,YAAI,OAAQ,QAAqC,MAAK,GAAG,IAAK,QAAoC,GAAG;AAAA,MACvG;AACA,UAAI,OAAO,KAAK,IAAI,EAAE,WAAW,KAAK,QAAQ;AAC5C,YAAI,OAAO,KAAK,IAAI,EAAE,WAAW,EAAG,QAAO,QAAQ,IAAI;AAAA,YAClD,SAAQ,IAAI,IAAI;AACrB,kBAAU;AAAA,MACZ;AAAA,IACF;AACA,QAAI,CAAC,QAAS,QAAO;AACrB,uBAAmB,MAAM,OAAkD;AAC3E,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,YAAY,MAAoB;AAC9C,MAAI;AAEF,UAAM,MAAM,WAAW,IAAI;AAC3B,QAAI,OAAO,IAAI,QAAQ,QAAQ,IAAK;AACpC,IAAAA,IAAG,WAAW,WAAW,IAAI,CAAC;AAAA,EAChC,QAAQ;AAAA,EAER;AACF;AAEO,SAAS,QAAQ,KAAsB;AAC5C,MAAI;AACF,YAAQ,KAAK,KAAK,CAAC;AACnB,WAAO;AAAA,EACT,SAAS,GAAG;AACV,QAAK,EAA4B,SAAS,QAAS,QAAO;AAE1D,WAAO;AAAA,EACT;AACF;AAEA,eAAe,iBAAiB,KAAgC;AAC9D,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,QAAQ,WAAW,MAAM,WAAW,MAAM,GAAG,iBAAiB;AACpE,MAAI;AACF,WAAO,MAAM,MAAM,KAAK,EAAE,QAAQ,WAAW,OAAO,CAAC;AAAA,EACvD,UAAE;AACA,iBAAa,KAAK;AAAA,EACpB;AACF;AAQA,eAAsB,WAAW,MAAc,MAAqC;AAClF,MAAI;AACF,UAAM,MAAM,MAAM,iBAAiB,oBAAoB,IAAI,WAAW;AACtE,QAAI,IAAI,WAAW,IAAK,QAAO,EAAE,UAAU,MAAM;AACjD,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,QAAI,OAAO,KAAK,SAAS,SAAU,QAAO,EAAE,UAAU,MAAM;AAC5D,WAAO;AAAA,MACL,UAAU,KAAK,SAAS;AAAA,MACxB,SAAS,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU;AAAA,IAC7D;AAAA,EACF,QAAQ;AACN,WAAO,EAAE,UAAU,MAAM;AAAA,EAC3B;AACF;AAQA,eAAsB,aACpB,MACA,gBACyI;AACzI,QAAM,MAAM,WAAW,IAAI;AAC3B,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,CAAC,QAAQ,IAAI,GAAG,EAAG,QAAO;AAC9B,QAAM,IAAI,MAAM,WAAW,IAAI,MAAM,IAAI;AACzC,MAAI,CAAC,EAAE,SAAU,QAAO;AACxB,MAAI,EAAE,WAAW,EAAE,YAAY,gBAAgB;AAC7C,WAAO,EAAE,QAAQ,iBAAiB,QAAQ,KAAK,aAAa,EAAE,QAAQ;AAAA,EACxE;AACA,SAAO,EAAE,QAAQ,SAAS,QAAQ,IAAI;AACxC;AAEA,eAAsB,aAAa,QAAuC;AACxE,MAAI;AACF,YAAQ,KAAK,OAAO,KAAK,SAAS;AAAA,EACpC,QAAQ;AACN;AAAA,EACF;AAEA,QAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,SAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,QAAI,CAAC,QAAQ,OAAO,GAAG,EAAG;AAC1B,UAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,qBAAqB,CAAC;AAAA,EAC/D;AAGA,MAAI;AACF,YAAQ,KAAK,OAAO,KAAK,SAAS;AAAA,EACpC,QAAQ;AAAA,EAER;AACA,QAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,kBAAkB,CAAC;AAC5D;;;ACnPA,SAAS,MAAM,YAAAC,iBAAgB;AAGxB,SAAS,QAAQ,KAAmB;AACzC,QAAM,MACJ,QAAQ,aAAa,WAAW,SAChC,QAAQ,aAAa,UAAU,UAC/B;AAEF,MAAI,QAAQ,aAAa,SAAS;AAChC,SAAK,aAAa,GAAG,GAAG;AAAA,EAC1B,OAAO;AACL,IAAAA,UAAS,KAAK,CAAC,GAAG,CAAC;AAAA,EACrB;AACF;;;AFAA,SAAS,YAAAC,iBAAgB;AAEzB,IAAM,UAAU,gBAAI;AACpB,IAAM,YAAYC,MAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAoBtD,IAAM,OAA+B;AAAA,EAC1C,SAAS;AAAA,EAA4B,QAAQ;AAAA,EAC7C,QAAQ;AAAA,EACR,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,SAAS;AAAA,EACT,OAAO;AAAA,EAAgC,QAAQ;AAAA,EAC/C,QAAQ;AAAA,EAA6B,QAAQ;AAAA,EAC7C,QAAQ;AAAA,EAA6B,SAAS;AAAA,EAC9C,QAAQ;AAAA,EAA4B,QAAQ;AAAA,EAC5C,OAAO;AAAA,EAA6B,OAAO;AAAA,EAC3C,SAAS;AAAA,EAA6B,OAAO;AAAA,EAC7C,OAAO;AAAA,EAA6B,OAAO;AAAA,EAC3C,QAAQ;AAAA,EAA6B,MAAM;AAAA,EAC3C,QAAQ;AAAA,EAA6B,MAAM;AAAA,EAC3C,OAAO;AAAA,EAA6B,UAAU;AAAA,EAC9C,OAAO;AAAA,EAA6B,UAAU;AAAA,EAC9C,OAAO;AAAA,EAA6B,SAAS;AAAA,EAC7C,QAAQ;AAAA,EAA6B,SAAS;AAAA,EAC9C,QAAQ;AAAA,EAA6B,cAAc;AAAA,EACnD,eAAe;AAAA,EACf,QAAQ;AAAA,EAAa,SAAS;AAAA,EAAc,QAAQ;AAAA,EACpD,QAAQ;AAAA,EAAa,QAAQ;AAAA,EAC7B,SAAS;AAAA,EAAa,UAAU;AAAA,EAAc,QAAQ;AAAA,EACtD,QAAQ;AACV;AAKA,IAAM,SAAS;AAER,IAAM,uBAAuB;AAG7B,SAAS,KAAK,KAA0B,MAAe,SAAS,KAAW;AAChF,MAAI,UAAU,QAAQ,EAAE,gBAAgB,mCAAmC,iBAAiB,WAAW,CAAC;AACxG,MAAI,IAAI,KAAK,UAAU,IAAI,CAAC;AAC9B;AAGA,IAAM,kBAA0C;AAAA,EAC9C,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AACP;AAMO,SAAS,cAAc,KAA0B,MAAoB;AAC1E,MAAI,IAAI,aAAa;AAEnB,QAAI;AAAE,UAAI,QAAQ;AAAA,IAAG,QAAQ;AAAA,IAAW;AACxC;AAAA,EACF;AACA,QAAM,OAAO,gBAAgB,IAAI,KAAK;AACtC,MAAI,UAAU,MAAM,EAAE,gBAAgB,2BAA2B,CAAC;AAClE,MAAI;AAAA,IACF,wEACU,IAAI,IAAI,IAAI,4CACT,IAAI,SAAM,IAAI;AAAA,EAE7B;AACF;AAGO,SAAS,QAAQ,KAA2B,KAA0B,OAAwB;AACnG,MAAI,IAAI,QAAQ,cAAc,MAAM,OAAO;AACzC,QAAI,UAAU,GAAG;AACjB,QAAI,IAAI,WAAW;AACnB,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,IAAM,gBAAN,cAA4B,QAAQ;AAAA,EACzC;AAAA,EACQ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS,oBAAI,IAA2E;AAAA,EACxF,OAAO,oBAAI,IAA+D;AAAA,EAC1E,eAAe,oBAAI,IAAoB;AAAA,EACvC;AAAA,EACA;AAAA,EAER,YAAY,KAAc,QAAuB;AAC/C,UAAM,KAAK,QAAQ;AACnB,SAAK,YAAY,OAAO,YAAY,EAAE,EAAE,SAAS,KAAK;AACtD,SAAK,OAAO,OAAO;AACnB,SAAK,SAAS,OAAO;AACrB,SAAK,OAAO,OAAO;AACnB,SAAK,OAAO,OAAO;AACnB,SAAK,MAAM,OAAO;AAClB,SAAK,UAAU,OAAO;AACtB,SAAK,WAAW,OAAO;AACvB,QAAI,OAAO,MAAM,MAAM,KAAK,QAAQ,CAAC;AAErC,SAAK,eAAe;AACpB,SAAK,MAAM,aAAa,CAAC,MAAM,QAAQ;AACrC,WAAK,KAAK,EAAE,WAAW,KAAK,WAAW,SAAS,SAAS,MAAM,KAAK,MAAM,GAAG,KAAK,QAAQ,CAAC;AAAA,IAC7F,CAAC;AAGD,SAAK,MAAM,aAAa,OAAO,MAAM,QAAQ;AAC3C,YAAM,QAAwB,MAAM,gBAAgB,KAAK,IAAI;AAC7D,WAAK,KAAK,KAAK;AAAA,IACjB,CAAC;AAGD,SAAK,MAAM,gBAAgB,CAAC,KAAK,QAAQ;AACvC,WAAK,UAAUA,MAAK,KAAK,KAAK,QAAQ,aAAa,GAAG,KAAK,KAAK,KAAK;AAAA,IACvE,CAAC;AAED,SAAK,MAAM,mBAAmB,OAAO,KAAK,QAAQ;AAChD,YAAM,MAAM,IAAI,IAAI,IAAI,OAAO,KAAK,kBAAkB;AACtD,YAAM,UAAU,IAAI,SAAS,QAAQ,wBAAwB,EAAE;AAC/D,UAAI,CAAC,WAAW,YAAY,KAAK;AAC/B,YAAI,UAAU,GAAG;AACjB,YAAI,IAAI,cAAc;AACtB;AAAA,MACF;AACA,YAAM,WAAWA,MAAK,KAAK,KAAK,MAAM,mBAAmB,OAAO,CAAC;AACjE,UAAI,CAAC,SAAS,WAAW,KAAK,OAAOA,MAAK,GAAG,KAAK,aAAa,KAAK,MAAM;AACxE,YAAI,UAAU,GAAG;AACjB,YAAI,IAAI,WAAW;AACnB;AAAA,MACF;AACA,MAAAC,IAAG,KAAK,UAAU,CAAC,QAAQ;AACzB,YAAI,KAAK;AAAE,cAAI,UAAU,GAAG;AAAG,iBAAO,IAAI,IAAI,WAAW;AAAA,QAAG;AAC5D,cAAM,MAAMD,MAAK,QAAQ,QAAQ,EAAE,YAAY;AAC/C,cAAM,KAAK,KAAK,GAAG,KAAK;AACxB,YAAI,UAAU,KAAK,EAAE,gBAAgB,IAAI,iBAAiB,WAAW,CAAC;AACtE,QAAAC,IAAG,iBAAiB,QAAQ,EAAE,KAAK,GAAG;AAAA,MACxC,CAAC;AAAA,IACH,CAAC;AAED,SAAK,MAAM,WAAW,OAAO,KAAK,QAAQ;AACxC,UAAI,CAAC,QAAQ,KAAK,KAAK,KAAK,SAAS,EAAG;AACxC,WAAK,KAAK,EAAE,IAAI,KAAK,CAAC;AACtB,WAAK,KAAK;AAAA,IACZ,CAAC;AAED,SAAK,MAAM,OAAO,IAAI;AAAA,EACxB;AAAA,EAEA,MAAMD,QAAc,SAAwE;AAC1F,SAAK,OAAO,IAAIA,QAAM,OAAO;AAC7B,SAAK,IAAI,OAAO,MAAM,MAAM,KAAK,OAAO,OAAOA,MAAI,CAAC;AAAA,EACtD;AAAA,EAEA,IAAIA,QAAc,WAA8D;AAC9E,SAAK,KAAK,IAAIA,QAAM,SAAS;AAC7B,SAAK,IAAI,OAAO,MAAM,MAAM,KAAK,KAAK,OAAOA,MAAI,CAAC;AAAA,EACpD;AAAA,EAEA,OAAO,QAAgB,KAAa;AAClC,SAAK,aAAa,IAAI,QAAQ,GAAG;AACjC,SAAK,IAAI,OAAO,MAAM,MAAM,KAAK,aAAa,OAAO,MAAM,CAAC;AAAA,EAC9D;AAAA,EAEQ,gBAAyD,CAAC;AAAA,EAElE,gBAAgB,MAAuC;AACrD,WAAO,KAAK,cAAc,IAAI,KAAK,CAAC;AAAA,EACtC;AAAA,EAEA,uBAAuB;AACrB,SAAK,gBAAgB,kBAAkB,KAAK,IAAI;AAAA,EAClD;AAAA,EAEA,iBAAiB,QAAiD;AAChE,SAAK,gBAAgB;AACrB,uBAAmB,KAAK,MAAM,MAAM;AAAA,EACtC;AAAA,EAEQ,UAAU,UAAkB,KAA2B,KAA0B,YAAqB;AAE5G,UAAM,WAAW,IAAI,OAAO,IAAI,WAAW,KAAK;AAChD,IAAAC,IAAG,KAAK,UAAU,CAAC,KAAK,SAAS;AAC/B,UAAI,KAAK;AACP,YAAI,SAAS;AAAE,cAAI,UAAU,GAAG;AAAG,iBAAO,IAAI,IAAI,WAAW;AAAA,QAAG;AAChE,eAAO,cAAc,KAAK,GAAG;AAAA,MAC/B;AACA,YAAM,MAAMD,MAAK,QAAQ,QAAQ,EAAE,YAAY;AAC/C,YAAM,KAAK,KAAK,GAAG,KAAK;AAGxB,YAAM,cAAe,IAAI,QAAQ,OAAO;AACxC,UAAI,QAA+C;AACnD,UAAI,aAAa;AACf,cAAM,IAAI,YAAY,MAAM,qBAAqB;AACjD,YAAI,GAAG;AACL,gBAAM,QAAQ,OAAO,EAAE,CAAC,CAAC;AACzB,gBAAM,MAAQ,EAAE,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC,CAAC,IAAI,KAAK,OAAO;AACvD,cAAI,CAAC,OAAO,MAAM,KAAK,KAAK,CAAC,OAAO,MAAM,GAAG,KAAK,SAAS,OAAO,QAAQ,KAAK,MAAM;AACnF,oBAAQ,EAAE,OAAO,KAAK,KAAK,IAAI,KAAK,KAAK,OAAO,CAAC,EAAE;AAAA,UACrD;AAAA,QAEF;AAAA,MAEF;AAEA,UAAI,OAAO;AACT,cAAM,EAAE,OAAO,IAAI,IAAI;AACvB,cAAM,YAAY,MAAM,QAAQ;AAChC,YAAI,UAAU,KAAK;AAAA,UACjB,gBAAgB;AAAA,UAChB,kBAAkB,OAAO,SAAS;AAAA,UAClC,iBAAiB,SAAS,KAAK,IAAI,GAAG,IAAI,KAAK,IAAI;AAAA,UACnD,iBAAiB;AAAA,UACjB,iBAAiB;AAAA,QACnB,CAAC;AAED,cAAM,SAASC,IAAG,iBAAiB,UAAU,EAAE,OAAO,IAAI,CAAC;AAC3D,eAAO,GAAG,SAAS,MAAM;AAAE,cAAI;AAAE,gBAAI,QAAQ;AAAA,UAAG,QAAQ;AAAA,UAAW;AAAA,QAAE,CAAC;AACtE,eAAO,KAAK,GAAG;AACf;AAAA,MACF;AAGA,MAAAA,IAAG,SAAS,UAAU,CAACC,MAAK,SAAS;AACnC,YAAIA,MAAK;AACP,cAAI,SAAS;AAAE,gBAAI,UAAU,GAAG;AAAG,mBAAO,IAAI,IAAI,WAAW;AAAA,UAAG;AAChE,iBAAO,cAAc,KAAK,GAAG;AAAA,QAC/B;AACA,YAAI,OAAwB;AAC5B,YAAI,cAAc,QAAQ,SAAS;AACjC,gBAAM,IAAI,KAAK,SAAS,MAAM;AAC9B,iBAAO,OAAO,KAAK,EAAE,QAAQ,SAAS,KAAK,IAAI,EAAE,QAAQ,WAAW,SAAS,SAAS,IAAI,IAAI,MAAM;AAAA,QACtG;AACA,YAAI,UAAU,KAAK,EAAE,gBAAgB,IAAI,iBAAiB,SAAS,iBAAiB,WAAW,CAAC;AAChG,YAAI,IAAI,IAAI;AAAA,MACd,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEQ,YAAY,KAAa,KAA2B,KAAmC;AAC7F,eAAW,CAAC,QAAQ,GAAG,KAAK,KAAK,cAAc;AAC7C,UAAI,IAAI,QAAQ,MAAM,MAAM,GAAG;AAC7B,YAAI,MAAM,KAAK,WAAW,IAAI,MAAM,OAAO,MAAM,CAAC;AAClD,YAAI,CAAC,OAAO,QAAQ,OAAO,CAACF,MAAK,QAAQ,GAAG,EAAG,OAAMA,MAAK,KAAK,OAAO,IAAI,YAAY;AACtF,cAAM,KAAKA,MAAK,KAAK,KAAK,GAAG;AAC7B,YAAI,GAAG,QAAQ,MAAMA,MAAK,GAAG,MAAM,GAAG;AAAE,cAAI,UAAU,GAAG;AAAG,cAAI,IAAI,WAAW;AAAG,iBAAO;AAAA,QAAO;AAChG,aAAK,UAAU,IAAI,KAAK,KAAK,IAAI;AACjC,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,WAAW,KAAqB;AACtC,QAAI;AAAE,aAAO,mBAAmB,GAAG;AAAA,IAAG,QAAQ;AAAE,aAAO;AAAA,IAAK;AAAA,EAC9D;AAAA,EAEQ,UAAU,CAAC,KAA2B,QAA6B;AACzE,QAAI;AACF,YAAM,SAAS,IAAI,OAAO;AAC1B,YAAM,MAAM,OAAO,MAAM,GAAG,EAAE,CAAC;AAEjC,YAAM,KAAK,KAAK,OAAO,IAAI,GAAG;AAC9B,UAAI,IAAI;AAAE,WAAG,KAAK,GAAG;AAAG;AAAA,MAAQ;AAChC,iBAAW,CAAC,IAAI,GAAG,KAAK,KAAK,QAAQ;AACnC,YAAI,IAAI,WAAW,KAAK,GAAG,GAAG;AAAE,cAAI,KAAK,GAAG;AAAG;AAAA,QAAQ;AAAA,MACzD;AACA,YAAM,KAAK,KAAK,KAAK,IAAI,GAAG;AAC1B,UAAI,IAAI;AACN,YAAI,UAAU,KAAK,EAAE,gBAAgB,qBAAqB,iBAAiB,YAAY,YAAY,aAAa,CAAC;AACjH,YAAI,MAAM,iBAAiB;AAC3B,cAAM,UAAU,GAAG,GAAG;AACtB,YAAI,GAAG,SAAS,MAAM;AAAE,oBAAU;AAAA,QAAG,CAAC;AACtC;AAAA,MACF;AAEA,UAAI,KAAK,YAAY,KAAK,KAAK,GAAG,EAAG;AAErC,UAAI,QAAQ,OAAO,IAAI,QAAQ,SAAS,MAAM,KAAK,IAAI,QAAQ,UAAU,MAAM,GAAG;AAChF,YAAIG,MAAK,KAAK;AACd,YAAI,QAAQ,IAAK,CAAAA,MAAKH,MAAK,KAAK,KAAK,QAAQ,KAAK,WAAW,GAAG,CAAC;AACjE,YAAI,IAAI,QAAQ,SAAS,MAAM,EAAG,CAAAG,MAAKH,MAAK,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,CAAC;AAC1E,YAAIG,QAAO,KAAK,UAAUA,IAAG,QAAQ,KAAK,SAASH,MAAK,GAAG,MAAM,GAAG;AAAE,iBAAO,cAAc,KAAK,GAAG;AAAA,QAAG;AACtG,YAAI,QAAQ,IAAK,CAAAG,MAAKH,MAAK,KAAK,KAAK,QAAQ,YAAY;AACzD,eAAO,KAAK,UAAUG,KAAI,KAAK,KAAK,KAAK;AAAA,MAC3C;AAEA,YAAM,KAAKH,MAAK,KAAK,KAAK,MAAM,KAAK,WAAW,GAAG,CAAC;AACpD,UAAI,OAAO,KAAK,QAAQ,GAAG,QAAQ,KAAK,OAAOA,MAAK,GAAG,MAAM,GAAG;AAE9D,aAAK,IAAI,OAAO,IAAI,WAAW,KAAK,GAAG;AAAE,cAAI,UAAU,GAAG;AAAG,iBAAO,IAAI,IAAI,WAAW;AAAA,QAAG;AAC1F,eAAO,cAAc,KAAK,GAAG;AAAA,MAC/B;AACA,aAAO,KAAK,UAAU,IAAI,KAAK,KAAK,IAAI;AAAA,IAC1C,SAAS,GAAG;AAEV,UAAI;AACF,aAAK,IAAI,OAAO,IAAI,WAAW,KAAK,GAAG;AAAE,cAAI,UAAU,GAAG;AAAG,cAAI,IAAI,aAAa;AAAA,QAAG,MAChF,eAAc,KAAK,GAAG;AAAA,MAC7B,QAAQ;AAAA,MAAW;AACnB,cAAQ,MAAM,8BAA8B,CAAC;AAAA,IAC/C;AAAA,EACF;AAAA,EAEA,MAAM,MAAc;AAClB,SAAK,SAAS,KAAK,aAAa,KAAK,OAAO;AAG5C,SAAK,OAAO,mBAAmB;AAC/B,SAAK,OAAO,iBAAiB;AAC7B,SAAK,OAAO,GAAG,SAAS,CAAC,QAA+B;AACtD,UAAI,IAAI,SAAS,cAAc;AAC7B,gBAAQ,IAAI,qBAAqB,IAAI,iBAAiB,OAAO,CAAC,EAAE;AAChE,aAAK,MAAM,OAAO,CAAC;AAAA,MACrB,MAAO,OAAM;AAAA,IACf,CAAC;AACD,SAAK,OAAO,OAAO,MAAM,aAAa,MAAM;AAE1C,YAAM,OAAO,KAAK,QAAQ,QAAQ;AAClC,YAAM,QAAQ,OAAO,SAAS,YAAY,OAAO,KAAK,OAAO;AAC7D,YAAM,IAAI,oBAAoB,KAAK;AACnC,YAAM,SAAS,KAAK,OAAO,GAAG,CAAC,IAAI,KAAK,IAAI,KAAK;AACjD,cAAQ,IAAI,iBAAiB,OAAO,iBAAiB,CAAC,EAAE;AACxD,cAAQ,IAAI,6BAA6B,KAAK,IAAI,EAAE;AACpD,cAAQ,IAAI,sCAAsC,KAAK,IAAI,WAAW,SAAS,KAAK,IAAI,OAAO,SAAS,KAAK,IAAI,OAAO,EAAE;AAC1H,UAAI,KAAK,QAAS,SAAQ,IAAI,6BAA6B,KAAK,OAAO,EAAE;AACzE,UAAI,KAAK,KAAM,SAAQ,MAAM;AAC7B,WAAK,WAAW,KAAK;AAAA,IACvB,CAAC;AAAA,EACH;AAAA;AAAA,EAGQ,UAA+C,CAAC;AAAA,EAExD,iBAAiB;AACf,UAAM,MAAM,CAAC,SAAmB,IAAI,QAAgB,CAAC,YAAY;AAC/D,MAAAD,UAAS,OAAO,MAAM,EAAE,KAAK,KAAK,MAAM,SAAS,IAAK,GAAG,CAAC,KAAK,WAAW,QAAQ,MAAM,KAAK,MAAM,CAAC;AAAA,IACtG,CAAC;AACD,UAAM,YAAY;AAChB,YAAM,CAAC,QAAQ,MAAM,IAAI,MAAM,QAAQ,IAAI;AAAA,QACzC,IAAI,CAAC,aAAa,gBAAgB,MAAM,CAAC;AAAA,QACzC,IAAI,CAAC,UAAU,aAAa,CAAC;AAAA,MAC/B,CAAC;AACD,YAAM,IAAI,OAAO,KAAK;AACtB,WAAK,UAAU,IAAI,EAAE,QAAQ,GAAG,OAAO,SAAS,OAAO,MAAM,IAAI,EAAE,OAAO,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC;AAAA,IACrG,GAAG;AAAA,EACL;AAAA,EAEA,OAAO;AACL,QAAI,KAAK,QAAQ;AAAE,UAAI;AAAE,aAAK,OAAO,MAAM;AAAA,MAAG,QAAQ;AAAA,MAAC;AAAA,IAAE;AACzD,QAAI;AAAE,kBAAY,KAAK,IAAI;AAAA,IAAG,QAAQ;AAAA,IAAC;AACvC,eAAW,MAAM;AACf,UAAI;AAAE,aAAK,IAAI,KAAK,MAAM,QAAQ;AAAA,MAAG,QAAQ;AAAA,MAAC;AAC9C,cAAQ,KAAK,CAAC;AAAA,IAChB,GAAG,EAAE;AAAA,EACP;AAAA,EAEA,UAAU;AACR,QAAI,KAAK,QAAQ;AAAE,UAAI;AAAE,aAAK,OAAO,MAAM;AAAA,MAAG,QAAQ;AAAA,MAAC;AAAA,IAAE;AACzD,QAAI;AAAE,kBAAY,KAAK,IAAI;AAAA,IAAG,QAAQ;AAAA,IAAC;AAAA,EACzC;AACF;;;AGnZA,OAAOK,SAAQ;AAEf,SAAS,WAAAC,gBAAe;AASxB,IAAM,oBAAoB;AAG1B,IAAM,iBAAiB;AACvB,IAAM,kBAAkB;AAGjB,SAAS,cAAc,UAAkC;AAC9D,MAAI,CAAC,SAAU,QAAO;AACtB,SAAO,eAAe,KAAK,QAAQ,KAAK,gBAAgB,KAAK,QAAQ;AACvE;AAEO,IAAM,gBAAN,cAA4BA,SAAQ;AAAA,EACzC,OAAO,SAAS,CAAC,QAAQ;AAAA,EACjB,UAAU,oBAAI,IAAyB;AAAA,EACvC;AAAA,EACA;AAAA,EAER,YAAY,KAAc,QAA0B;AAClD,UAAM,KAAK,QAAQ;AACnB,SAAK,IAAI,OAAO,MAAM,MAAM,KAAK,QAAQ,CAAC;AAE1C,SAAK,IAAI,OAAO,IAAI,aAAa,CAAC,QAAQ;AACxC,WAAK,QAAQ,IAAI,GAAG;AACpB,aAAO,MAAM,KAAK,QAAQ,OAAO,GAAG;AAAA,IACtC,CAAC;AAED,QAAI;AACF,WAAK,UAAUD,IAAG,MAAM,OAAO,MAAM,EAAE,WAAW,KAAK,GAAG,CAAC,WAAW,aAAa;AACjF,YAAI,cAAc,QAAQ,EAAG;AAC7B,YAAI,KAAK,MAAO,cAAa,KAAK,KAAK;AACvC,aAAK,QAAQ,WAAW,MAAM;AAC5B,eAAK,IAAI,OAAO,eAAe;AAC/B,eAAK,UAAU,QAAQ;AACvB,eAAK,UAAU,OAAO;AACtB,eAAK,QAAQ;AAAA,QACf,GAAG,iBAAiB;AAAA,MACtB,CAAC;AAAA,IACH,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,UAAU,IAAY,OAAgB,IAAI;AACxC,UAAM,UAAU,UAAU,EAAE;AAAA,QAAW,KAAK,UAAU,QAAQ,OAAO,KAAK,IAAI,CAAC;AAAA;AAAA;AAC/E,eAAW,KAAK,KAAK,SAAS;AAC5B,UAAI;AAAE,UAAE,MAAM,OAAO;AAAA,MAAG,QAAQ;AAAA,MAAC;AAAA,IACnC;AAAA,EACF;AAAA;AAAA,EAGA,gBAAgB,MAAc,OAAe,OAAgB,IAAI;AAC/D,SAAK,UAAU,UAAU,IAAI,IAAI,KAAK,IAAI,IAAI;AAAA,EAChD;AAAA,EAEA,UAAU;AACR,QAAI,KAAK,SAAS;AAAE,UAAI;AAAE,aAAK,QAAQ,MAAM;AAAA,MAAG,QAAQ;AAAA,MAAC;AAAA,IAAE;AAC3D,QAAI,KAAK,OAAO;AAAE,mBAAa,KAAK,KAAK;AAAA,IAAG;AAC5C,eAAW,KAAK,KAAK,SAAS;AAAE,UAAI;AAAE,UAAE,IAAI;AAAA,MAAG,QAAQ;AAAA,MAAC;AAAA,IAAE;AAC1D,SAAK,QAAQ,MAAM;AAAA,EACrB;AACF;;;ACxEA,OAAOE,SAAQ;AACf,OAAOC,WAAU;;;ACDjB,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAWV,SAAS,QAAQ,MAAc,OAAoB,CAAC,GAAS;AAClE,QAAM,EAAE,OAAO,oBAAI,IAAI,GAAG,UAAU,eAAe,OAAO,QAAQ,MAAM,IAAI;AAE5E,WAAS,KAAK,KAAa,KAAa,OAAe;AACrD,QAAI,OAAO,aAAa,YAAY,QAAQ,SAAU;AACtD,QAAI;AACJ,QAAI;AAAE,aAAOD,IAAG,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC;AAAA,IAAG,QAAQ;AAAE;AAAA,IAAQ;AAC7E,eAAW,OAAO,MAAM;AAEtB,UAAI,IAAI,KAAK,WAAW,GAAG,KAAK,EAAE,gBAAgB,IAAI,YAAY,GAAI;AACtE,UAAI,KAAK,IAAI,IAAI,IAAI,EAAG;AACxB,YAAM,MAAMC,MAAK,KAAK,KAAK,IAAI,IAAI;AACnC,YAAM,IAAI,MAAM,GAAG,GAAG,IAAI,IAAI,IAAI,KAAK,IAAI;AAC3C,UAAI,IAAI,YAAY,GAAG;AACrB,gBAAQ,KAAK,CAAC;AACd,aAAK,KAAK,GAAG,QAAQ,CAAC;AAAA,MACxB,WAAW,QAAQ;AACjB,eAAO,KAAK,CAAC;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAEA,OAAK,MAAM,IAAI,CAAC;AAClB;;;ADtBA,SAAS,UAAU,OAAiB,qBAAqB,GAAe;AACtE,QAAM,OAAmB,CAAC;AAC1B,QAAM,MAAM,oBAAI,IAAsB;AAEtC,aAAW,KAAK,OAAO;AACrB,UAAM,QAAQ,EAAE,MAAM,GAAG;AACzB,QAAI,UAAU;AACd,QAAI,SAAS;AAEb,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAM,OAAO,MAAM,CAAC;AACpB,gBAAU,UAAU,GAAG,OAAO,IAAI,IAAI,KAAK;AAC3C,YAAM,SAAS,MAAM,MAAM,SAAS;AACpC,YAAM,QAAQ;AAEd,UAAI,CAAC,IAAI,IAAI,OAAO,GAAG;AACrB,cAAM,QAAQ,CAAC;AACf,cAAM,YAAY,SAAS,OAAO,uBAAuB,YAAY,QAAQ;AAC7E,cAAM,OAAiB;AAAA,UACrB,MAAM;AAAA,UACN,MAAM,SAAS,SAAS;AAAA,UACxB,GAAI,YAAY,EAAE,kBAAkB,KAAK,IAAI,CAAC;AAAA,UAC9C,GAAI,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE;AAAA,QAC5C;AACA,YAAI,IAAI,SAAS,IAAI;AACrB,eAAO,KAAK,IAAI;AAAA,MAClB;AAEA,UAAI,CAAC,QAAQ;AACX,iBAAS,IAAI,IAAI,OAAO,EAAG;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AAEA,QAAM,YAAY,CAAC,UAAsB;AACvC,UAAM,KAAK,CAAC,GAAG,MAAO,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,IAAI,IAAI,EAAE,SAAS,QAAQ,KAAK,CAAE;AACnG,eAAW,KAAK,OAAO;AACrB,UAAI,EAAE,SAAU,WAAU,EAAE,QAAQ;AAAA,IACtC;AAAA,EACF;AAEA,YAAU,IAAI;AACd,SAAO;AACT;AAQA,SAAS,YAAY,OAAmB,QAA4B;AAClE,SAAO,MAAM,IAAI,CAAC,MAAM;AACtB,QAAI,EAAE,SAAS,UAAU,EAAE,MAAM;AAC/B,aAAO,EAAE,GAAG,GAAG,MAAM,GAAG,MAAM,IAAI,EAAE,IAAI,GAAG;AAAA,IAC7C;AACA,QAAI,EAAE,UAAU;AACd,aAAO,EAAE,GAAG,GAAG,UAAU,YAAY,EAAE,UAAU,MAAM,EAAE;AAAA,IAC3D;AACA,WAAO;AAAA,EACT,CAAC;AACH;AAGO,SAAS,SAAS,MAAc,UAAoB,MAAoC;AAC7F,QAAM,OAAmB,CAAC;AAC1B,QAAM,qBAAqB,OAAO,MAAM,uBAAuB,WAAW,KAAK,qBAAqB;AACpG,QAAM,cAAc,IAAI,IAAI,MAAM,QAAQ,MAAM,OAAO,IAAI,KAAK,UAAU,CAAC,CAAC;AAC5E,QAAM,OAAO,MAAM,QAAQ,QAAQ,IAAI,SAAS,OAAO,CAAC,MAAM,OAAO,MAAM,YAAY,CAAC,IAAI,CAAC;AAC7F,aAAW,OAAO,MAAM;AAEtB,QAAI,IAAI,WAAW,GAAG,KAAK,CAAC,YAAY,IAAI,GAAG,EAAG;AAClD,UAAM,UAAUC,MAAK,KAAK,MAAM,GAAG;AACnC,QAAI,CAACC,IAAG,WAAW,OAAO,EAAG;AAC7B,UAAM,QAAkB,CAAC;AACzB,YAAQ,SAAS,EAAE,UAAU,GAAG,cAAc,YAAY,IAAI,GAAG,GAAG,QAAQ,CAAC,GAAG,QAAQ,MAAM,KAAK,GAAG,EAAE,CAAC;AACzG,UAAM,SAAS;AACf,UAAM,WAAW,YAAY,UAAU,OAAO,kBAAkB,GAAG,MAAM;AACzE,QAAI,SAAS,QAAQ;AACnB,WAAK,KAAK,EAAE,MAAM,GAAG,GAAG,KAAK,SAAS,MAAM,KAAK,MAAM,OAAO,SAAS,CAAC;AAAA,IAC1E;AAAA,EACF;AACA,SAAO;AACT;;;AE5FA,IAAM,uBAAuB,CAAC,YAAY,QAAQ,eAAe,gBAAgB;AAEjF,IAAM,sBAAsB,qBAAqB,OAAO,CAAC,MAAM,EAAE,WAAW,GAAG,CAAC;AAEzE,IAAM,QAAQ;AAAA,EACnB,QAAQ,CAAC,QAAQ;AAAA,EACjB,MAAM,KAAc,QAA0B;AAC5C,UAAM,SAAS,IAAI;AACnB,QAAI,QAAQ,OAAO;AAEjB,aAAO,MAAM,YAAY,OAAO,KAAK,QAAQ;AAC3C,YAAI;AACF,gBAAM,MAAM,IAAI,IAAI,IAAI,OAAO,KAAK,kBAAkB;AACtD,gBAAM,KAAK,IAAI,aAAa,IAAI,IAAI;AACpC,gBAAM,WAAW,KAAK,mBAAmB,EAAE,IAAI,OAAO;AACtD,gBAAM,OAAO,SAAS,UAAU,CAAC,GAAG,oBAAoB,GAAG,EAAE,SAAS,CAAC,GAAG,mBAAmB,EAAE,CAAC;AAChG,cAAI,UAAU,KAAK,EAAE,gBAAgB,mCAAmC,iBAAiB,WAAW,CAAC;AACrG,cAAI,IAAI,KAAK,UAAU,EAAE,KAAK,CAAC,CAAC;AAAA,QAClC,QAAQ;AACN,cAAI,UAAU,KAAK,EAAE,gBAAgB,mCAAmC,iBAAiB,WAAW,CAAC;AACrG,cAAI,IAAI,KAAK,UAAU,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;AAAA,QACtC;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;AC7BA,SAAS,YAAAC,iBAAgB;AAWzB,IAAM,iBAAiB;AACvB,IAAM,oBAAoB;AAE1B,SAAS,OAAO,MAAgB,KAA8B;AAC5D,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,IAAAA,UAAS,OAAO,MAAM,EAAE,KAAK,SAAS,eAAe,GAAG,CAAC,KAAK,WAAW;AACvE,UAAI,IAAK,QAAO,QAAQ,EAAE;AAC1B,cAAQ,MAAM;AAAA,IAChB,CAAC;AAAA,EACH,CAAC;AACH;AAEA,eAAsB,cAAc,MAAuC;AACzE,QAAM,MAAM,MAAM,OAAO,CAAC,YAAY,QAAQ,aAAa,GAAG,IAAI;AAClE,MAAI,CAAC,IAAK,QAAO,CAAC;AAElB,QAAM,UAA0B,CAAC;AACjC,QAAM,QAAQ,IAAI,MAAM,IAAI;AAC5B,MAAI,UAAiC,CAAC;AAEtC,aAAW,QAAQ,OAAO;AACxB,UAAM,IAAI,KAAK,MAAM,0CAA0C;AAC/D,QAAI,CAAC,EAAG;AACR,UAAM,CAAC,EAAE,KAAK,GAAG,IAAI;AACrB,QAAI,QAAQ,YAAY;AACtB,UAAI,QAAQ,QAAQ,QAAQ,KAAK,SAAS,iBAAiB,GAAG;AAC5D,gBAAQ,KAAK;AAAA,UACX,MAAM,QAAQ;AAAA,UACd,MAAM,QAAQ,KAAK,MAAM,iBAAiB,EAAE,IAAI,KAAK;AAAA,UACrD,QAAQ,QAAQ,UAAU;AAAA,UAC1B,MAAM,QAAQ,QAAQ;AAAA,UACtB,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AACA,gBAAU,EAAE,MAAM,KAAK,MAAM,IAAI,QAAQ,GAAG;AAAA,IAC9C,WAAW,QAAQ,QAAQ;AACzB,cAAQ,OAAO;AAAA,IACjB,WAAW,QAAQ,UAAU;AAC3B,cAAQ,SAAS,IAAI,QAAQ,kBAAkB,EAAE;AAAA,IACnD;AAAA,EACF;AAGA,MAAI,QAAQ,QAAQ,QAAQ,KAAK,SAAS,iBAAiB,GAAG;AAC5D,YAAQ,KAAK;AAAA,MACX,MAAM,QAAQ;AAAA,MACd,MAAM,QAAQ,KAAK,MAAM,iBAAiB,EAAE,IAAI,KAAK;AAAA,MACrD,QAAQ,QAAQ,UAAU;AAAA,MAC1B,MAAM,QAAQ,QAAQ;AAAA,MACtB,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAGA,QAAM,QAAQ;AAAA,IACZ,QAAQ,IAAI,OAAO,UAAU;AAC3B,UAAI;AACF,cAAM,YAAY,MAAM,OAAO,CAAC,UAAU,aAAa,GAAG,MAAM,IAAI;AACpE,cAAM,QAAQ,UAAU,KAAK,EAAE,SAAS;AAAA,MAC1C,QAAQ;AACN,cAAM,QAAQ;AAAA,MAChB;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEO,IAAMC,SAAQ;AAAA,EACnB,QAAQ,CAAC,QAAQ;AAAA,EACjB,MAAM,KAAc,QAA0B;AAC5C,UAAM,SAAS,IAAI;AACnB,QAAI,CAAC,QAAQ,MAAO;AAEpB,WAAO,MAAM,gBAAgB,OAAO,MAAM,QAAQ;AAChD,UAAI;AACF,cAAM,UAAU,MAAM,cAAc,OAAO,IAAI;AAC/C,YAAI,UAAU,KAAK,EAAE,gBAAgB,mCAAmC,iBAAiB,WAAW,CAAC;AACrG,YAAI,IAAI,KAAK,UAAU,OAAO,CAAC;AAAA,MACjC,QAAQ;AACN,YAAI,UAAU,KAAK,EAAE,gBAAgB,mCAAmC,iBAAiB,WAAW,CAAC;AACrG,YAAI,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC;AAAA,MAC5B;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AChGA,SAAS,WAAAC,gBAAe;;;ACMxB,eAAsB,SAAS,KAA4C;AACzE,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,QAAI,OAAO;AACX,QAAI,GAAG,QAAQ,CAAC,UAA2B;AAAE,cAAQ;AAAA,IAAO,CAAC;AAC7D,QAAI,GAAG,OAAO,MAAM,QAAQ,IAAI,CAAC;AACjC,QAAI,GAAG,SAAS,MAAM,QAAQ,EAAE,CAAC;AAAA,EACnC,CAAC;AACH;;;ADkBO,IAAM,mBAAN,cAA+BC,SAAQ;AAAA,EAC5C,OAAO,SAAS,CAAC,UAAU,QAAQ;AAAA,EAC3B,UAAU,oBAAI,IAA4B;AAAA,EAC1C;AAAA,EAER,YAAY,KAAc;AACxB,UAAM,KAAK,WAAW;AACtB,SAAK,IAAI,OAAO,MAAM,MAAM,KAAK,QAAQ,MAAM,CAAC;AAChD,SAAK,YAAY,IAAI;AAErB,SAAK,IAAI,OAAO,MAAM,cAAc,CAAC,MAAM,QAAQ;AACjD,UAAI,UAAU,KAAK,EAAE,gBAAgB,mCAAmC,iBAAiB,WAAW,CAAC;AACrG,UAAI,IAAI,KAAK,UAAU,EAAE,SAAS,MAAM,KAAK,KAAK,QAAQ,OAAO,CAAC,EAAE,CAAC,CAAC;AAAA,IACxE,CAAC;AAED,SAAK,IAAI,OAAO,MAAM,qBAAqB,OAAO,KAAK,QAAQ;AAC7D,YAAM,MAA+C,CAAC;AACtD,UAAI,IAAI,WAAW,OAAO;AACxB,mBAAW,KAAK,KAAK,QAAQ,OAAO,GAAG;AACrC,gBAAM,SAAS,KAAK,IAAI,OAAO,gBAAgB,EAAE,IAAI;AACrD,gBAAM,SAAS,EAAE,UAAU,CAAC;AAC5B,gBAAM,SAAkC,CAAC;AACzC,qBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,mBAAO,GAAG,IAAI,OAAO,SAAS,OAAO,GAAG,IAAK,MAAsB,WAAW;AAAA,UAChF;AACA,cAAI,OAAO,KAAK,MAAM,EAAE,OAAQ,KAAI,EAAE,IAAI,IAAI;AAAA,QAChD;AACA,YAAI,UAAU,KAAK,EAAE,gBAAgB,mCAAmC,iBAAiB,WAAW,CAAC;AACrG,YAAI,IAAI,KAAK,UAAU,GAAG,CAAC;AAC3B;AAAA,MACF;AACA,UAAI,IAAI,WAAW,QAAQ;AACzB,YAAI,IAAI,QAAQ,cAAc,MAAM,KAAK,IAAI,OAAO,WAAW;AAC7D,cAAI,UAAU,GAAG;AACjB,cAAI,IAAI,WAAW;AACnB;AAAA,QACF;AACA,YAAI;AACF,gBAAM,OAAO,KAAK,MAAM,MAAM,SAAS,GAAG,CAAC;AAC3C,gBAAM,SAAkD,CAAC;AACzD,qBAAW,QAAQ,OAAO,KAAK,IAAI,GAAG;AACpC,mBAAO,IAAI,IAAI,KAAK,IAAI,KAAK,CAAC;AAAA,UAChC;AACA,eAAK,IAAI,OAAO,iBAAiB,MAAM;AACvC,qBAAW,QAAQ,OAAO,KAAK,IAAI,GAAG;AACpC,gBAAI;AAAE,mBAAK,UAAU,UAAU,UAAU,EAAE,QAAQ,KAAK,CAAC;AAAA,YAAG,QAAQ;AAAA,YAAe;AAAA,UACrF;AACA,cAAI,UAAU,KAAK,EAAE,gBAAgB,kCAAkC,CAAC;AACxE,cAAI,IAAI,aAAa;AAAA,QACvB,SAAS,GAAG;AACV,kBAAQ,MAAM,uBAAuB,CAAC;AACtC,cAAI,UAAU,GAAG;AACjB,cAAI,IAAI,yBAAyB;AAAA,QACnC;AACA;AAAA,MACF;AACA,UAAI,UAAU,GAAG;AACjB,UAAI,IAAI,gCAAgC;AAAA,IAC1C,CAAC;AAAA,EACH;AAAA,EAEA,SAASC,WAA0B;AACjC,SAAK,QAAQ,IAAIA,UAAS,MAAMA,SAAQ;AACxC,SAAK,IAAI,OAAO,MAAM,MAAM,KAAK,QAAQ,OAAOA,UAAS,IAAI,CAAC;AAAA,EAChE;AAAA,EAEA,OAAO;AACL,WAAO,MAAM,KAAK,KAAK,QAAQ,OAAO,CAAC;AAAA,EACzC;AAAA,EAEA,IAAI,MAA0C;AAC5C,WAAO,KAAK,QAAQ,IAAI,IAAI;AAAA,EAC9B;AAAA,EAEA,UAAU,MAAuC;AAC/C,WAAO,KAAK,IAAI,OAAO,gBAAgB,IAAI;AAAA,EAC7C;AACF;;;AEjGA,SAAS,YAAAC,iBAAgB;;;ACXzB,SAAS,OAAO,YAAAC,iBAAmC;AACnD,OAAO,WAAW;;;ACSlB,IAAM,UAAU;AAGT,SAAS,qBAAqB,MAAsC;AACzE,MAAI,IAAI,KAAK,KAAK;AAClB,MAAI,EAAE,WAAW,GAAG,EAAG,KAAI,EAAE,MAAM,CAAC,EAAE,UAAU;AAChD,QAAM,YAAY,QAAQ,KAAK,CAAC;AAChC,MAAI,CAAC,UAAW,QAAO;AACvB,QAAM,OAAO,UAAU,CAAC;AACxB,QAAM,SAAmB,CAAC;AAC1B,MAAI,IAAI,KAAK;AACb,SAAO,MAAM;AACX,WAAO,IAAI,EAAE,UAAU,KAAK,KAAK,EAAE,CAAC,CAAC,EAAG;AACxC,QAAI,KAAK,EAAE,OAAQ,QAAO;AAC1B,QAAI,EAAE,CAAC,MAAM,KAAK;AAChB,YAAM,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,KAAK;AACjC,UAAI,SAAS,MAAM,KAAK,WAAW,GAAG,EAAG,QAAO,EAAE,MAAM,OAAO;AAC/D,aAAO;AAAA,IACT;AAEA,QAAI,IAAI;AACR,QAAI,EAAE,CAAC,MAAM,OAAO,EAAE,CAAC,MAAM,IAAK;AAClC,UAAM,KAAK,QAAQ,KAAK,EAAE,MAAM,CAAC,CAAC;AAClC,QAAI,CAAC,GAAI,QAAO;AAChB,SAAK,GAAG,CAAC,EAAE;AACX,QAAI,EAAE,CAAC,MAAM,KAAK;AAChB;AACA,UAAI,EAAE,CAAC,MAAM,OAAO,EAAE,CAAC,MAAM,KAAK;AAChC,cAAM,QAAQ,EAAE,CAAC;AACjB;AACA,eAAO,IAAI,EAAE,UAAU,EAAE,CAAC,MAAM,MAAO;AACvC,YAAI,KAAK,EAAE,OAAQ,QAAO;AAC1B;AAAA,MACF,OAAO;AACL,eAAO,IAAI,EAAE,UAAU,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,MAAM,IAAK;AAAA,MAC3D;AAAA,IACF;AACA,WAAO,KAAK,GAAG,CAAC,CAAC;AACjB,QAAI;AAAA,EACN;AACF;AAGO,SAAS,cAAc,QAAgB,MAAyC;AACrF,MAAI,CAAC,KAAM,QAAO,CAAC,MAAM;AACzB,SAAO,CAAC,QAAQ,GAAG,OAAO,QAAQ,IAAI,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;AACtE;AAGO,SAAS,eAAe,MAAmD;AAChF,MAAI,OAAO,SAAS,YAAY,SAAS,KAAM,QAAO;AACtD,QAAM,MAA8B,CAAC;AACrC,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,IAAI,GAAG;AACzC,QAAI,OAAO,MAAM,SAAU,KAAI,CAAC,IAAI;AAAA,EACtC;AACA,SAAO,OAAO,KAAK,GAAG,EAAE,SAAS,IAAI,MAAM;AAC7C;;;ADzCA,IAAM,aAAa;AAEnB,IAAM,aAAa,IAAI,YAAY,SAAS,EAAE,OAAO,KAAK,CAAC;AAM3D,SAAS,WAAW,KAAqB;AACvC,MAAI;AACF,WAAO,WAAW,OAAO,GAAG;AAAA,EAC9B,QAAQ;AACN,WAAO,MAAM,OAAO,KAAK,KAAK;AAAA,EAChC;AACF;AAGO,IAAM,aAAN,MAAiB;AAAA,EACd;AAAA,EACA,QAAQ,oBAAI,IAAkB;AAAA,EAC9B,UAAU,oBAAI,IAA6B;AAAA,EAC3C,eAAgC;AAAA;AAAA,EAEhC,cAAc,oBAAI,IAAsB;AAAA,EAEhD,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,MAAAC,UAAS,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;AAAA,EAGA,aAAa,MAAiC;AAC5C,UAAM,MAAM,KAAK,YAAY,IAAI,IAAI;AACrC,QAAI,IAAK,QAAO,QAAQ,QAAQ,GAAG;AACnC,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,MAAAA,UAAS,QAAQ,CAAC,UAAU,IAAI,GAAG,EAAE,KAAK,KAAK,KAAK,WAAW,KAAK,IAAI,SAAS,IAAK,GAAG,CAAC,KAAK,WAAW;AACxG,cAAM,MAAM,MAAM,OAAO,OAAO,MAAM,OAAO,EAAE,IAAI,OAAK,qBAAqB,CAAC,CAAC,EAAE,KAAK,OAAO,KAAK;AAClG,cAAM,SAAS,KAAK,UAAU,CAAC;AAC/B,aAAK,YAAY,IAAI,MAAM,MAAM;AACjC,gBAAQ,MAAM;AAAA,MAChB,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,oBAAiD;AACrD,UAAM,OAAO,MAAM,KAAK,QAAQ;AAChC,WAAO,QAAQ,IAAI,KAAK,IAAI,OAAO,OAAO,EAAE,GAAG,GAAG,QAAQ,MAAM,KAAK,aAAa,EAAE,IAAI,EAAE,EAAE,CAAC;AAAA,EAC/F;AAAA,EAEA,UAAU,IAAyC;AACjD,SAAK,QAAQ,IAAI,EAAE;AAEnB,eAAW,KAAK,KAAK,MAAM,OAAO,GAAG;AACnC,iBAAW,QAAQ,EAAE,OAAQ,IAAG,EAAE,MAAM,OAAO,QAAQ,EAAE,QAAQ,KAAK,CAAC;AACvE,SAAG,EAAE,MAAM,SAAS,QAAQ,EAAE,QAAQ,OAAO,EAAE,OAAO,MAAM,EAAE,MAAM,WAAW,EAAE,UAAU,CAAC;AAAA,IAC9F;AACA,WAAO,MAAM,KAAK,QAAQ,OAAO,EAAE;AAAA,EACrC;AAAA,EAEQ,KAAK,IAAe;AAAE,eAAW,MAAM,KAAK,QAAS,IAAG,EAAE;AAAA,EAAG;AAAA,EAErE,OAAmB;AACjB,WAAO,MAAM,KAAK,KAAK,MAAM,OAAO,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,OAAO,EAAE,OAAO,MAAM,EAAE,MAAM,WAAW,EAAE,UAAU,EAAE;AAAA,EAC5H;AAAA;AAAA;AAAA,EAIA,MAAM,QAAgB,MAA+B;AACnD,SAAK,QAAQ,MAAM;AACnB,UAAM,OAAa,EAAE,QAAQ,OAAO,MAAM,OAAO,WAAW,MAAM,MAAM,WAAW,KAAK,IAAI,GAAG,QAAQ,CAAC,GAAG,SAAS,OAAO,MAAM,CAAC,EAAE;AACpI,SAAK,MAAM,IAAI,QAAQ,IAAI;AAC3B,SAAK,KAAK,EAAE,MAAM,SAAS,OAAO,CAAC;AACnC,SAAK,KAAK,EAAE,MAAM,SAAS,QAAQ,OAAO,WAAW,MAAM,MAAM,WAAW,KAAK,UAAU,CAAC;AAC5F,UAAM,QAAQ,MAAM,QAAQ,cAAc,QAAQ,IAAI,GAAG;AAAA,MACvD,KAAK,KAAK;AAAA,MACV,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;AAEb,UAAM,UAAU,MAAM,KAAK,MAAM,IAAI,MAAM,MAAM;AACjD,UAAM,OAAO,CAAC,MAAc;AAC1B,UAAI,QAAQ,EAAG;AACf,WAAK,UAAU,OAAO,OAAO,CAAC,KAAK,SAAS,CAAC,CAAC;AAC9C,UAAI;AACJ,cAAQ,MAAM,KAAK,QAAQ,QAAQ,EAAI,MAAM,GAAG;AAC9C,cAAM,OAAO,KAAK,QAAQ,SAAS,GAAG,MAAM,CAAC;AAC7C,aAAK,UAAU,KAAK,QAAQ,SAAS,MAAM,CAAC;AAC5C,aAAK,SAAS,MAAM,WAAW,IAAI,CAAC;AAAA,MACtC;AAAA,IAEF;AACA,UAAM,QAAQ,GAAG,QAAQ,IAAI;AAC7B,UAAM,QAAQ,GAAG,QAAQ,IAAI;AAC7B,UAAM,GAAG,SAAS,CAAC,QAAQ;AAAE,WAAK,SAAS,MAAM,6BAA6B,IAAI,OAAO;AAAA,CAAI;AAAA,IAAG,CAAC;AACjG,UAAM,GAAG,QAAQ,CAAC,MAAM,WAAW;AACjC,UAAI,KAAK,QAAQ,SAAS,KAAK,CAAC,QAAQ,GAAG;AAAE,aAAK,SAAS,MAAM,WAAW,KAAK,OAAO,IAAI,IAAI;AAAA,MAAG;AACnG,WAAK,UAAU,OAAO,MAAM,CAAC;AAC7B,WAAK,QAAQ;AACb,WAAK,QAAQ;AACb,WAAK,OAAO,QAAQ;AACpB,WAAK,SAAS,UAAU;AACxB,UAAI,QAAQ,EAAG;AACf,WAAK,KAAK,EAAE,MAAM,SAAS,QAAQ,OAAO,UAAU,MAAM,KAAK,MAAM,WAAW,KAAK,WAAW,QAAQ,KAAK,OAAO,CAAC;AAAA,IACvH,CAAC;AAAA,EACH;AAAA;AAAA;AAAA,EAIQ,SAAS,MAAY,MAAc;AACzC,UAAM,OAAO,KAAK,SAAS,IAAI,IAAI,KAAK,MAAM,GAAG,EAAE,IAAI;AACvD,UAAM,OAAO,KAAK,MAAM,IAAI,EAAE,OAAO,OAAO;AAC5C,QAAI,KAAK,WAAW,GAAG;AACrB,WAAK,YAAY,MAAM,EAAE;AACzB;AAAA,IACF;AACA,eAAW,OAAO,KAAM,MAAK,YAAY,MAAM,GAAG;AAAA,EACpD;AAAA,EAEQ,YAAY,MAAY,KAAa;AAC3C,UAAM,OAAO,MAAM;AACnB,SAAK,OAAO,KAAK,IAAI;AACrB,QAAI,KAAK,OAAO,SAAS,WAAY,MAAK,OAAO,MAAM;AACvD,SAAK,KAAK,EAAE,MAAM,OAAO,QAAQ,KAAK,QAAQ,KAAK,CAAC;AAAA,EACtD;AAAA;AAAA,EAGA,KAAK,QAAiB;AACpB,QAAI,WAAW,QAAW;AAAE,iBAAW,KAAK,KAAK,MAAM,OAAO,EAAG,MAAK,QAAQ,EAAE,MAAM;AAAA,IAAG,MACpF,MAAK,QAAQ,MAAM;AAAA,EAC1B;AAAA,EAEA,QAAQ,QAAgB;AACtB,QAAI,KAAK,MAAM,IAAI,MAAM,EAAG,MAAK,MAAM,MAAM;AAAA,EAC/C;AAAA;AAAA,EAGA,MAAM,QAAgB;AACpB,UAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,QAAI,CAAC,KAAM;AACX,SAAK,SAAS,CAAC;AACf,SAAK,UAAU,OAAO,MAAM,CAAC;AAC7B,SAAK,KAAK,EAAE,MAAM,SAAS,OAAO,CAAC;AAAA,EACrC;AAAA,EAEQ,QAAQ,QAAgB;AAC9B,UAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,UAAM,QAAQ,MAAM;AACpB,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,QAAI,MAAM;AAAE,WAAK,QAAQ;AAAA,IAAM;AAAA,EACjC;AACF;;;AEnKO,SAAS,aAAa,KAGyB;AACpD,QAAM,EAAE,UAAAC,WAAU,MAAM,IAAI;AAE5B,SAAO;AAAA,IACL,QAAQ,CAAC,UAAU,aAAa,QAAQ;AAAA,IACxC,MAAkB,KAAc;AAC9B,YAAM,YAA+B,CAAC;AACtC,UAAI,OAAO,MAAM,MAAM;AACrB,mBAAW,MAAM,UAAU,OAAO,CAAC,GAAG;AACpC,cAAI;AAAE,eAAG;AAAA,UAAG,SAAS,GAAG;AACtB,oBAAQ,MAAM,uBAAuBA,UAAS,IAAI,mBAAmB,CAAC;AAAA,UACxE;AAAA,QACF;AAAA,MACF,CAAC;AAED,UAAI,UAAU,SAASA,SAAQ;AAG/B,YAAM,cAAc,CAAC,YAA0B,OAAO,KAA2B,QAA6B;AAC5G,YAAI,IAAI,YAAa;AACrB,YAAI;AACF,gBAAM,OAAO,MAAM,QAAQ,KAAK,GAAG;AACnC,cAAI,SAAS,UAAa,CAAC,IAAI,cAAe,MAAK,KAAK,IAAI;AAAA,QAC9D,SAAS,GAAG;AACV,kBAAQ,MAAM,uBAAuBA,UAAS,IAAI,iBAAiB,CAAC;AACpE,cAAI,CAAC,IAAI,YAAa,MAAK,KAAK,EAAE,OAAO,WAAW,GAAG,GAAG;AAAA,QAC5D;AAAA,MACF;AAEA,YAAM,OAAsB;AAAA,QAC1B,MAAMA,UAAS;AAAA,QACf,SAAyE;AACvE,gBAAM,SAASA,UAAS,UAAU,CAAC;AACnC,gBAAM,SAAS,IAAI,OAAO,gBAAgBA,UAAS,IAAI,KAAK,CAAC;AAC7D,gBAAM,WAAW,OAAO;AAAA,YACtB,OAAO,QAAQ,MAAM,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,MAAM,OAAO,CAAC;AAAA,UACnE;AACA,iBAAO,EAAE,GAAG,UAAU,GAAG,OAAO;AAAA,QAClC;AAAA,QACA,MAAMC,QAAc,SAA6B;AAC/C,cAAI,OAAO,MAAMA,QAAM,YAAY,OAAO,CAAC;AAAA,QAC7C;AAAA,QACA,aAAaA,QAAc,SAA6B;AACtD,gBAAM,QAAQ,MAAM,IAAI,OAAO;AAC/B,cAAI,OAAO,MAAMA,QAAM,CAAC,KAAK,QAAQ;AACnC,gBAAI,CAAC,QAAQ,KAAK,KAAK,MAAM,CAAC,EAAG;AACjC,iBAAK,YAAY,OAAO,EAAE,KAAK,GAAG;AAAA,UACpC,CAAC;AAAA,QACH;AAAA,QACA,IAAIA,QAAc,SAA2B;AAC3C,cAAI,OAAO,IAAIA,QAAM,OAAO;AAAA,QAC9B;AAAA,QACA,OAAO,QAAgB,KAAmB;AACxC,cAAI,OAAO,OAAO,QAAQ,GAAG;AAAA,QAC/B;AAAA,QACA,UAAU,OAAe,MAAsB;AAC7C,cAAI,QAAQ,UAAU,UAAUD,UAAS,IAAI,IAAI,KAAK,IAAI,QAAQ,EAAE;AAAA,QACtE;AAAA,QACA,UAAU,IAAsB;AAC9B,oBAAU,KAAK,EAAE;AAAA,QACnB;AAAA,MACF;AAEA,YAAM,IAAI;AAAA,IACZ;AAAA,EACF;AACF;;;ACtGO,SAAS,cAAc,KAG3B;AACD,MAAI,cAAc;AAClB,QAAM,QAAQ,aAAa;AAAA,IACzB,UAAU,IAAI;AAAA,IACd,MAAM,MAAM;AAAE,UAAI,MAAM,MAAM,WAAW;AAAA,IAAG;AAAA,EAC9C,CAAC;AAED,SAAO;AAAA,IACL,QAAQ,MAAM;AAAA,IACd,UAAU,IAAI;AAAA;AAAA,IACd,MAAM,KAAc,QAA2B;AAC7C,oBAAc,QAAQ,QAAQ;AAC9B,YAAM,MAAM,KAAK,MAAM;AAAA,IACzB;AAAA,EACF;AACF;;;AC1BO,IAAM,WAA2B;AAAA,EACtC,MAAM;AAAA,EACN,OAAO;AAAA,EACP,MAAM;AAAA,EACN,aAAa;AAAA,EACb,OAAO;AACT;;;ALSO,IAAME,SAAQ,cAAc;AAAA,EACjC;AAAA,EACA,MAAM,KAAK,MAAM;AACf,UAAM,SAAS,IAAI,WAAW,IAAI;AAClC,QAAI,UAAU,MAAM,OAAO,KAAK,CAAC;AAEjC,QAAI,MAAM,mBAAmB,YAAY;AACvC,UAAI;AACF,eAAO,MAAM,OAAO,kBAAkB;AAAA,MACxC,QAAQ;AACN,eAAO,CAAC;AAAA,MACV;AAAA,IACF,CAAC;AAED,QAAI,MAAM,iBAAiB,YAAY,OAAO,KAAK,CAAC;AAGpD,QAAI,MAAM,kBAAkB,YAAY;AACtC,aAAO,MAAM,IAAI,QAAsD,CAAC,YAAY;AAClF,QAAAC,UAAS,QAAQ,CAAC,UAAU,YAAY,GAAG,EAAE,KAAK,MAAM,WAAW,KAAK,IAAI,SAAS,IAAK,GAAG,CAAC,QAAQ;AACpG,cAAI,CAAC,IAAK,QAAO,QAAQ,EAAE,WAAW,MAAM,aAAa,KAAK,CAAC;AAC/D,cAAK,IAA8B,SAAS,SAAU,QAAO,QAAQ,EAAE,WAAW,OAAO,aAAa,MAAM,CAAC;AAC7G,kBAAQ,EAAE,WAAW,MAAM,aAAa,MAAM,CAAC;AAAA,QACjD,CAAC;AAAA,MACH,CAAC;AAAA,IACH,CAAC;AAED,QAAI,IAAI,gBAAgB,CAAC,QAAQ;AAC/B,YAAM,QAAQ,OAAO,UAAU,CAAC,OAAO;AAErC,YAAI;AAAE,cAAI,UAAU,GAAG,MAAM,EAAE;AAAA,QAAG,QAAQ;AAAA,QAAmB;AAC7D,YAAI,MAAM,SAAS,KAAK,UAAU,EAAE,CAAC;AAAA;AAAA,CAAM;AAAA,MAC7C,CAAC;AACD,aAAO;AAAA,IACT,CAAC;AAGD,UAAM,eAAe,OAAO,KAA2B,KAA0B,QAAgD;AAC/H,YAAM,OAAO,MAAM,SAAS,GAAG;AAC/B,UAAI;AACJ,UAAI;AACJ,UAAI;AACF,cAAM,SAAS,KAAK,MAAM,QAAQ,IAAI;AACtC,iBAAS,OAAO;AAChB,kBAAU,OAAO;AAAA,MACnB,QAAQ;AAAA,MAAe;AACvB,UAAI,QAAQ,SAAS;AACnB,YAAI,OAAQ,QAAO,MAAM,MAAM;AAC/B,eAAO,EAAE,IAAI,KAAK;AAAA,MACpB;AACA,UAAI,QAAQ,QAAQ;AAClB,YAAI,CAAC,QAAQ;AACX,cAAI,UAAU,KAAK,EAAE,gBAAgB,kCAAkC,CAAC;AACxE,cAAI,IAAI,uBAAuB;AAC/B,iBAAO;AAAA,QACT;AACA,cAAM,UAAU,MAAM,OAAO,QAAQ;AACrC,YAAI,CAAC,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,GAAG;AAC3C,cAAI,UAAU,KAAK,EAAE,gBAAgB,kCAAkC,CAAC;AACxE,cAAI,IAAI,4BAA4B;AACpC,iBAAO;AAAA,QACT;AACA,eAAO,MAAM,QAAQ,eAAe,OAAO,CAAC;AAAA,MAC9C,OAAO;AACL,eAAO,KAAK,UAAU,MAAS;AAAA,MACjC;AACA,aAAO,OAAO,KAAK;AAAA,IACrB;AAEA,UAAM,cAAc,CAAC,SAAiD;AACpE,UAAI,aAAa,WAAW,IAAI,KAAK,CAAC,KAAK,QAAQ,aAAa,KAAK,KAAK,IAAI,EAAyB;AAAA,IACzG;AACA,gBAAY,OAAO;AACnB,gBAAY,MAAM;AAClB,gBAAY,SAAS;AACrB,gBAAY,OAAO;AAAA,EACrB;AACF,CAAC;;;AM1FD,OAAOC,WAAU;AACjB,OAAOC,SAAQ;;;ACNf,OAAOC,WAAU;AAKjB,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,QAAQ,QAAQ,QAAQ,OAAO,QAAQ,QAAQ,QAAQ,SAAS,QAAQ,QAAQ,QAAQ,SAAS,OAAO,KAAK;AAC/I,IAAM,YAAY,CAAC,SAAS,UAAU,QAAQ,MAAM;AACpD,IAAM,WAAW;AAEV,SAAS,WAAW,KAAa,KAA+B;AACrE,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;AAE1B,MAAI,QAAQ,iBAAiB,QAAQ,UAAW,QAAO;AACvD,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,GAAG;AAC3B,QAAI,SAAS,KAAK,GAAG,MAAM,QAAQ,UAAU,QAAQ,SAAU,QAAO;AACtE,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAKO,SAAS,WAAW,MAAc,SAAS,IAAgB;AAChE,QAAM,MAAkB,CAAC;AACzB,QAAM,OAAoB,CAAC,QAAO,aAAY,QAAO,SAAQ,MAAK,SAAQ,SAAQ,OAAM,QAAO,SAAS;AACxG,aAAW,KAAK,KAAM,KAAI,CAAC,IAAI,CAAC;AAChC,QAAM,OAAO,oBAAI,IAAI,CAAC,gBAAgB,QAAQ,QAAQ,SAAS,YAAY,SAAS,QAAQ,CAAC;AAC7F,QAAM,WAAW,SAASC,MAAK,KAAK,MAAM,MAAM,IAAI;AACpD,UAAQ,UAAU,EAAE,MAAM,MAAM,QAAQ,CAAC,KAAK,QAAQ;AACpD,UAAM,MAAMA,MAAK,QAAQ,GAAG,EAAE,YAAY;AAC1C,UAAM,IAAI,WAAW,KAAK,GAAG;AAC7B,QAAI,EAAG,KAAI,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAMA,MAAK,SAAS,GAAG,GAAG,KAAK,MAAM,EAAE,CAAC;AAAA,EAC1E,EAAC,CAAC;AACF,SAAO;AACT;;;AC3CO,IAAMC,YAA2B;AAAA,EACtC,MAAM;AAAA,EACN,OAAO;AAAA,EACP,MAAM;AAAA,EACN,aAAa;AAAA,EACb,OAAO;AACT;;;AFGA,IAAM,aAA0B,CAAC,QAAQ,aAAa,QAAQ,SAAS,MAAM,SAAS,SAAS,OAAO,QAAQ,SAAS;AAEvH,SAAS,YAAwB;AAC/B,QAAM,MAAM,CAAC;AACb,aAAW,KAAK,WAAY,KAAI,CAAC,IAAI,CAAC;AACtC,SAAO;AACT;AAEO,IAAMC,SAAQ,cAAc;AAAA,EACjC,UAAAC;AAAA,EACA,MAAM,KAAK,MAAM;AACf,QAAI,MAAM,oBAAoB,YAAY;AACxC,YAAM,aAAaC,MAAK,KAAK,MAAM,SAAS,QAAQ;AACpD,aAAOC,IAAG,WAAW,UAAU,IAAI,WAAW,UAAU,IAAI,UAAU;AAAA,IACxE,CAAC;AAGD,QAAI,MAAM,mBAAmB,OAAO,KAAK,QAAQ;AAC/C,YAAM,MAAM,IAAI,IAAI,IAAI,OAAO,KAAK,kBAAkB,EAAE,aAAa,IAAI,MAAM,KAAK;AACpF,UAAI,CAAC,OAAO,IAAI,SAAS,IAAI,KAAK,IAAI,SAAS,IAAI,KAAKD,MAAK,WAAW,GAAG,GAAG;AAC5E,YAAI,UAAU,GAAG;AACjB,YAAI,IAAI,UAAU;AAClB;AAAA,MACF;AACA,YAAM,aAAaA,MAAK,KAAK,MAAM,SAAS,QAAQ;AACpD,YAAM,WAAWA,MAAK,KAAK,YAAY,GAAG;AAC1C,UAAI,CAAC,SAAS,WAAW,aAAaA,MAAK,GAAG,GAAG;AAC/C,YAAI,UAAU,GAAG;AACjB,YAAI,IAAI,UAAU;AAClB;AAAA,MACF;AACA,MAAAC,IAAG,KAAK,UAAU,CAAC,QAAQ;AACzB,YAAI,KAAK;AAAE,cAAI,UAAU,GAAG;AAAG,iBAAO,IAAI,IAAI,WAAW;AAAA,QAAG;AAC5D,cAAM,KAAK,KAAKD,MAAK,QAAQ,QAAQ,EAAE,YAAY,CAAC,KAAK;AACzD,YAAI,UAAU,KAAK,EAAE,gBAAgB,IAAI,iBAAiB,WAAW,CAAC;AAEtE,cAAM,SAASC,IAAG,iBAAiB,QAAQ;AAC3C,eAAO,GAAG,SAAS,MAAM;AAAE,cAAI;AAAE,gBAAI,QAAQ;AAAA,UAAG,QAAQ;AAAA,UAAW;AAAA,QAAE,CAAC;AACtE,eAAO,KAAK,GAAG;AAAA,MACjB,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AACF,CAAC;;;AGnDM,IAAMC,YAA2B;AAAA,EACtC,MAAM;AAAA,EACN,OAAO;AAAA,EACP,MAAM;AAAA,EACN,aAAa;AAAA,EACb,OAAO;AACT;;;ACHO,IAAMC,SAAQ,cAAc;AAAA,EACjC,UAAAC;AAAA,EACA,QAAQ;AAAA,EAA4B;AACtC,CAAC;;;ACND,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,YAAAC,iBAAgB;;;ACFlB,IAAMC,YAA2B;AAAA,EACtC,MAAM;AAAA,EACN,OAAO;AAAA,EACP,MAAM;AAAA,EACN,aAAa;AAAA,EACb,OAAO;AACT;;;ADgBA,IAAM,YAAY,oBAAI,IAAI,CAAC,gBAAgB,QAAQ,QAAQ,SAAS,SAAS,QAAQ,CAAC;AAEtF,SAAS,gBAAgB,MAAc,MAAgB,MAAwC;AAC7F,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,IAAAC,UAAS,MAAM,MAAM,MAAM,CAAC,KAAK,WAAW,QAAQ,MAAM,KAAK,MAAM,CAAC;AAAA,EACxE,CAAC;AACH;AAEA,SAAS,KAAK,MAAqB;AACjC,QAAM,QAAe;AAAA,IACnB,MAAMC,MAAK,SAAS,IAAI;AAAA,IACxB,OAAO;AAAA,IACP,MAAM;AAAA,IACN,WAAW;AAAA,IACX,OAAO,CAAC;AAAA,IACR,UAAU;AAAA,IACV,UAAU,EAAE,QAAQ,GAAG,UAAU,EAAE;AAAA,IACnC,SAASC,IAAG,WAAWD,MAAK,KAAK,MAAM,UAAU,CAAC;AAAA,IAClD,WAAW;AAAA,EACb;AACA,QAAM,SAAS,oBAAI,IAAoB;AAEvC,QAAM,OAAO,CAAC,QAAgB;AAC5B,YAAQ,KAAK,EAAE,MAAM,WAAW,OAAO,MAAM;AAAE,YAAM;AAAA,IAAQ,GAAG,QAAQ,CAAC,QAAQ;AAC/E,YAAM;AACN,UAAI;AAAE,cAAM,aAAaC,IAAG,SAAS,GAAG,EAAE;AAAA,MAAM,QAAQ;AAAA,MAAC;AACzD,YAAM,MAAMD,MAAK,QAAQ,GAAG,EAAE,YAAY,KAAK;AAC/C,aAAO,IAAI,MAAM,OAAO,IAAI,GAAG,KAAK,KAAK,CAAC;AAC1C,UAAI,QAAQ,SAAS,QAAQ,YAAa,OAAM;AAAA,IAClD,EAAC,CAAC;AAAA,EACJ;AACA,OAAK,IAAI;AAET,QAAM,aAAaA,MAAK,KAAK,MAAM,YAAY,SAAS;AACxD,MAAIC,IAAG,WAAW,UAAU,GAAG;AAC7B,eAAW,OAAOA,IAAG,YAAY,YAAY,EAAE,eAAe,KAAK,CAAC,GAAG;AACrE,UAAI,CAAC,IAAI,YAAY,KAAK,IAAI,KAAK,WAAW,GAAG,EAAG;AACpD,UAAI,IAAI,SAAS,WAAW;AAC1B,YAAI;AACF,gBAAM,SAAS,WAAWA,IAAG,YAAYD,MAAK,KAAK,YAAY,SAAS,GAAG,EAAE,eAAe,KAAK,CAAC,EAC/F,OAAO,OAAK,EAAE,YAAY,KAAK,CAAC,EAAE,KAAK,WAAW,GAAG,CAAC,EAAE;AAAA,QAC7D,QAAQ;AAAA,QAAe;AAAA,MACzB,MAAO,OAAM,SAAS;AAAA,IACxB;AAAA,EACF;AAEA,QAAM,QAAQ,MAAM,KAAK,OAAO,QAAQ,CAAC,EACtC,IAAI,CAAC,CAAC,KAAK,KAAK,OAAO,EAAE,KAAK,MAAM,EAAE,EACtC,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,EAChC,MAAM,GAAG,EAAE;AACd,SAAO;AACT;AAEO,IAAME,SAAQ,cAAc;AAAA,EACjC,UAAAC;AAAA,EACA,MAAM,KAAK,MAAM;AACf,QAAI,MAAM,iBAAiB,YAAY;AACrC,YAAM,QAAQ,KAAK,IAAI;AACvB,UAAI;AACF,cAAM,MAAM,MAAM,cAAc,IAAI;AACpC,cAAM,YAAY,IAAI;AAAA,MACxB,QAAQ;AACN,cAAM,YAAY;AAAA,MACpB;AACA,UAAI;AACF,cAAM,YAAY,MAAM,gBAAgB,OAAO,CAAC,aAAa,gBAAgB,MAAM,GAAG,EAAE,KAAK,KAAK,CAAC;AACnG,cAAM,SAAS,UAAU,KAAK,KAAK;AAAA,MACrC,QAAQ;AAAA,MAAe;AACvB,UAAI;AACF,cAAM,YAAY,MAAM,gBAAgB,OAAO,CAAC,UAAU,aAAa,GAAG,EAAE,KAAK,KAAK,CAAC;AACvF,cAAM,QAAQ,UAAU,KAAK,IAAI,UAAU,KAAK,EAAE,MAAM,IAAI,EAAE,SAAS;AAAA,MACzE,QAAQ;AAAA,MAAe;AACvB,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AACF,CAAC;;;AxBzED,IAAMC,aAAYC,MAAK,QAAQC,eAAc,YAAY,GAAG,CAAC;AAE7D,IAAM,eAAe;AAErB,SAAS,YAAY;AACnB,QAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AACjC,QAAM,EAAE,OAAO,IAAI,cAAc;AAAA,IAC/B,SAAS;AAAA,MACP,KAAK,EAAE,MAAM,SAAS;AAAA,MACtB,MAAM,EAAE,MAAM,SAAS;AAAA,MACvB,MAAM,EAAE,MAAM,WAAW,SAAS,MAAM;AAAA,MACxC,MAAM,EAAE,MAAM,SAAS;AAAA,MACvB,SAAS,EAAE,MAAM,WAAW,SAAS,MAAM;AAAA,MAC3C,SAAS,EAAE,MAAM,SAAS;AAAA,IAC5B;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,kBAAkB;AAAA,EACpB,CAAC;AACD,SAAO;AAAA,IACL,KAAK,OAAO,OAAO,QAAQ,WAAW,OAAO,MAAM,QAAQ,IAAI;AAAA,IAC/D,MAAM,OAAO,OAAO,SAAS,WAAW,OAAO,OAAO,IAAI,IAAI;AAAA,IAC9D,cAAc,KAAK,KAAK,OAAK,MAAM,YAAY,EAAE,WAAW,SAAS,CAAC;AAAA,IACtE,MAAM,CAAC,CAAC,OAAO;AAAA,IACf,MAAM,OAAO,OAAO,SAAS,WAAW,OAAO,OAAO;AAAA,IACtD,SAAS,CAAC,CAAC,OAAO;AAAA,IAClB,SAAS,OAAO,OAAO,YAAY,WAAW,OAAO,UAAU;AAAA,EACjE;AACF;AAEA,eAAe,WAAW,GAA6B;AACrD,MAAI;AAAE,UAAM,OAAO,CAAC;AAAG,WAAO;AAAA,EAAM,QAAQ;AAAE,WAAO;AAAA,EAAO;AAC9D;AAEA,eAAe,aAAa,KAAc,KAAa,MAAc;AACnE,MAAI,CAAC,IAAK;AACV,MAAI,YAAY;AAChB,MAAI;AACF,UAAM,EAAE,SAAS,IAAI,MAAM,OAAO,aAAa;AAC/C,aAAS;AACT,gBAAY;AAAA,EACd,QAAQ;AAAA,EAER;AAEA,MAAI;AACF,UAAM,UAAU,MAAM,WAAW,GAAG,IAAI,MAAM,QAAQ,KAAK,EAAE,eAAe,KAAK,CAAC,IAAI,CAAC;AACvF,eAAW,OAAO,SAAS;AACzB,UAAI,CAAC,IAAI,YAAY,EAAG;AACxB,YAAM,aAAa,YAAY,CAAC,YAAY,YAAY,WAAW,IAAI,CAAC,YAAY,WAAW;AAC/F,iBAAW,QAAQ,YAAY;AAC7B,cAAM,IAAID,MAAK,KAAK,KAAK,IAAI,MAAM,IAAI;AACvC,YAAI,MAAM,WAAW,CAAC,GAAG;AACvB,cAAI;AACF,kBAAM,MAAM,MAAM,OAAO;AACzB,kBAAM,SAAS,IAAI,WAAW;AAC9B,gBAAI,QAAQ,OAAO;AACjB,kBAAI;AACF,sBAAM,IAAI,OAAO,QAAQ,EAAE,KAAK,CAAC;AAAA,cACnC,SAAS,GAAG;AACV,wBAAQ,MAAM,uCAAuC,IAAI,IAAI,KAAK,CAAC;AACnE;AAAA,cACF;AAEA,oBAAM,IAAI,IAAI,UAAU,IAAI,IAAI,IAAI;AACpC,kBAAI,KAAK,EAAE,SAAS,IAAI,MAAM;AAC5B,sBAAM,QAAiC,EAAE,UAAU,KAAK;AACxD,sBAAM,SAASA,MAAK,KAAK,KAAK,IAAI,MAAM,KAAK;AAC7C,oBAAI,MAAM,WAAWA,MAAK,KAAK,QAAQ,YAAY,CAAC,GAAG;AACrD,sBAAI,OAAO,OAAO,GAAG,oBAAoB,GAAG,IAAI,IAAI,KAAK,MAAM;AAC/D,sBAAI,CAAC,EAAE,UAAW,OAAM,YAAY,GAAG,oBAAoB,GAAG,IAAI,IAAI;AAAA,gBACxE;AACA,oBAAI,UAAU,SAAS,EAAE,GAAG,GAAG,GAAG,MAAM,CAAC;AAAA,cAC3C;AAAA,YACF;AAAA,UACF,SAAS,GAAG;AACV,oBAAQ,MAAM,sCAAsC,IAAI,IAAI,KAAK,CAAC;AAAA,UACpE;AACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AAEA,eAAe,OAAO;AACpB,QAAM,OAAO,UAAU;AACvB,QAAM,OAAOA,MAAK,QAAQ,KAAK,GAAG;AAIlC,QAAM,QAAQ,MAAM,aAAa,MAAM,gBAAI,OAAO;AAClD,QAAM,WAAW,OAAO,UAAU;AAClC,QAAM,cAAc,OAAO,WAAW;AACtC,MAAI,YAAY,CAAC,KAAK,WAAW,CAAC,aAAa;AAC7C,UAAM,IAAI,oBAAoB,SAAS,IAAI,MAAM,KAAK,OAAO,IAAI,KAAK,IAAI,KAAK;AAC/E,QAAI,KAAK,KAAM,SAAQ,CAAC;AACxB,YAAQ,IAAI,+CAAsB,CAAC,sDAAmB;AAEtD,UAAM,IAAI,QAAc,CAAC,YAAY,QAAQ,OAAO,MAAM,IAAI,MAAM,QAAQ,CAAC,CAAC;AAC9E,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,YAAY,aAAa,KAAK,WAAW,eAAe,WAAW;AACzE,MAAI,WAAW;AACb,QAAI,aAAa;AACf,cAAQ;AAAA,QACN,kEAA0B,MAAO,eAAe,SAAS,yCAAW,gBAAI,OAAO,4CAAc,UAAU,GAAG;AAAA,MAC5G;AAAA,IACF,OAAO;AACL,cAAQ,IAAI,kEAAoC,UAAU,GAAG,EAAE;AAAA,IACjE;AACA,UAAM,aAAa,SAAS;AAAA,EAC9B;AAEA,QAAM,SAASA,MAAK,QAAQD,YAAW,KAAK;AAG5C,QAAM,kBAAkB,CAACG,QAAYA,QAAWA,QAAaA,MAAS;AAGtE,MAAI,sBAAsB,MAAM,gBAAgB,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG;AACvE,YAAQ,IAAI,mHAA6C;AAAA,EAC3D;AAGA,QAAM,YAAY,aAAa,CAAC,KAAK,eAAe,UAAU,OAAO,KAAK;AAG1E,QAAM,UAAUF,MAAK,KAAK,MAAM,OAAO;AACvC,QAAM,UAAUG,IAAG,WAAW,OAAO,IAAI,WAAW;AAEpD,QAAM,MAAM,MAAM,OAAO,IAAI;AAE7B,QAAM,MAAM,IAAI,QAAQ;AAGxB,MAAI,OAAO,eAAe;AAAA,IACxB;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,MAAM,KAAK;AAAA,IACX,QAAQ;AAAA,IACR,MAAM,KAAK;AAAA,IACX,SAAS,WAAW;AAAA,IACpB,UAAU,CAAC,SAAiB,YAAY,MAAM,IAAI;AAAA,EACpD,CAAC;AACD,MAAI,OAAO,eAAe,EAAE,KAAK,CAAC;AAClC,MAAI,OAAO,OAAW,EAAE,KAAK,CAAC;AAC9B,MAAI,OAAOD,QAAgB,EAAE,KAAK,CAAC;AACnC,MAAI,OAAO,gBAAgB;AAE3B,aAAWA,UAAS,iBAAiB;AACnC,QAAI;AACF,UAAI,OAAOA,QAAO,EAAE,KAAK,CAAC;AAAA,IAC5B,SAAS,GAAG;AACV,cAAQ,MAAM,uCAAuC,CAAC;AAAA,IACxD;AAAA,EACF;AAGA,MAAI,KAAK,SAAS;AAChB,UAAM,aAAa,KAAKF,MAAK,QAAQ,KAAK,OAAO,GAAG,IAAI;AAAA,EAC1D;AAGA,QAAM,WAAW,MAAM;AACrB,QAAI;AAAE,kBAAY,IAAI;AAAA,IAAG,QAAQ;AAAA,IAAC;AAClC,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,UAAQ,GAAG,WAAW,QAAQ;AAC9B,UAAQ,GAAG,UAAU,QAAQ;AAE7B,SAAO;AACT;AAEA,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM;AACxB,UAAQ,MAAM,CAAC;AACf,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["path","fs","fileURLToPath","fs","path","fs","path","path","fs","execFile","execFile","path","fs","err","fp","fs","Service","fs","path","fs","path","path","fs","execFile","apply","Service","Service","manifest","execFile","execFile","execFile","manifest","path","apply","execFile","path","fs","path","path","manifest","apply","manifest","path","fs","manifest","apply","manifest","fs","path","execFile","manifest","execFile","path","fs","apply","manifest","__dirname","path","fileURLToPath","apply","fs"]}
1
+ {"version":3,"sources":["../src/cli.ts","../package.json","../src/server/detect.ts","../src/core/server.ts","../src/core/instance.ts","../src/core/open-url.ts","../src/core/reload.ts","../src/server/spec-scan.ts","../src/server/walk.ts","../src/core/tree.ts","../src/core/worktrees.ts","../src/core/manifest.ts","../src/core/read-body.ts","../src/plugins/just/index.ts","../src/server/just-runner.ts","../src/server/just-recipe-params.ts","../src/sdk/server.ts","../src/plugins/builtin.ts","../src/plugins/just/manifest.ts","../src/plugins/design/index.ts","../src/server/design-assets.ts","../src/plugins/design/manifest.ts","../src/plugins/view/manifest.ts","../src/plugins/view/index.ts","../src/plugins/stats/index.ts","../src/plugins/stats/manifest.ts"],"sourcesContent":["import path from 'node:path';\nimport fs from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport { access, readdir } from 'node:fs/promises';\nimport { exec } from 'node:child_process';\nimport pkg from '../package.json' with { type: 'json' };\nimport { parseArgs as utilParseArgs } from 'node:util';\nimport { detect } from './server/detect.js';\nimport type { DetectResult } from './server/detect.js';\nimport { Context, Service } from 'cordis';\nimport { ServerService, PLUGIN_STATIC_PREFIX } from './core/server.js';\nimport { ReloadService } from './core/reload.js';\nimport { apply as treeApply } from './core/tree.js';\nimport { apply as worktreesApply } from './core/worktrees.js';\nimport { DashboardService } from './core/manifest.js';\nimport {\n findReusable,\n stopInstance,\n writeRecord,\n clearRecord,\n stripDeadPluginConfig,\n} from './core/instance.js';\nimport { openUrl } from './core/open-url.js';\nimport { apply as justApply } from './plugins/just/index.js';\nimport { apply as designApply } from './plugins/design/index.js';\nimport { apply as viewApply } from './plugins/view/index.js';\nimport { apply as statsApply } from './plugins/stats/index.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nconst DEFAULT_PORT = 4190;\n\nfunction parseArgs() {\n const args = process.argv.slice(2);\n const { values } = utilParseArgs({\n options: {\n dir: { type: 'string' },\n port: { type: 'string' },\n open: { type: 'boolean', default: false },\n page: { type: 'string' },\n restart: { type: 'boolean', default: false },\n plugins: { type: 'string' },\n },\n args,\n strict: false,\n allowPositionals: false,\n });\n return {\n dir: typeof values.dir === 'string' ? values.dir : process.cwd(),\n port: typeof values.port === 'string' ? Number(values.port) : DEFAULT_PORT,\n portExplicit: args.some(a => a === '--port' || a.startsWith('--port=')),\n open: !!values.open,\n page: typeof values.page === 'string' ? values.page : null,\n restart: !!values.restart,\n plugins: typeof values.plugins === 'string' ? values.plugins : null,\n };\n}\n\nasync function pathExists(p: string): Promise<boolean> {\n try { await access(p); return true; } catch { return false; }\n}\n\nasync function loadExternal(ctx: Context, dir: string, root: string) {\n if (!dir) return;\n let tsxLoaded = false;\n try {\n const { register } = await import('tsx/esm/api');\n register();\n tsxLoaded = true;\n } catch {\n // tsx not available\n }\n\n try {\n const entries = await pathExists(dir) ? await readdir(dir, { withFileTypes: true }) : [];\n for (const ent of entries) {\n if (!ent.isDirectory()) continue;\n const candidates = tsxLoaded ? ['index.ts', 'index.js', 'index.mjs'] : ['index.js', 'index.mjs'];\n for (const name of candidates) {\n const p = path.join(dir, ent.name, name);\n if (await pathExists(p)) {\n try {\n const mod = await import(p);\n const plugin = mod.default ?? mod;\n if (plugin?.apply) {\n try {\n await ctx.plugin(plugin, { root });\n } catch (e) {\n console.error(`[zdashboard] failed to apply plugin ${ent.name}:`, e);\n break;\n }\n // 自动接线约定:mode === 目录名时补 external 标记与 viewerUrl\n const m = ctx.dashboard.get(ent.name);\n if (m && m.mode === ent.name) {\n const patch: Record<string, unknown> = { external: true };\n const webDir = path.join(dir, ent.name, 'web');\n if (await pathExists(path.join(webDir, 'index.html'))) {\n ctx.server.static(`${PLUGIN_STATIC_PREFIX}${ent.name}/`, webDir);\n if (!m.viewerUrl) patch.viewerUrl = `${PLUGIN_STATIC_PREFIX}${ent.name}/`;\n }\n ctx.dashboard.register({ ...m, ...patch });\n }\n }\n } catch (e) {\n console.error(`[zdashboard] failed to load plugin ${ent.name}:`, e);\n }\n break;\n }\n }\n }\n } catch {\n // ignore\n }\n}\n\nasync function main() {\n const args = parseArgs();\n const root = path.resolve(args.dir);\n\n // --- instance reuse (before creating Context) ---\n // 版本比对:活实例版本落后当前 CLI → 自动停旧接管(零操作升级);--restart 仍为强制重开\n const found = await findReusable(root, pkg.version);\n const existing = found?.record ?? null;\n const autoUpgrade = found?.status === 'stale-version';\n if (existing && !args.restart && !autoUpgrade) {\n const u = `http://localhost:${existing.port}` + (args.page ? `#${args.page}` : '');\n if (args.open) openUrl(u);\n console.log(`[zdashboard] 已复用实例 ${u}(--restart 可强制重开)`);\n // 管道场景下 stdout 是异步写,显式等 flush 再 exit,避免日志被截断\n await new Promise<void>((resolve) => process.stdout.write('', () => resolve()));\n process.exit(0);\n }\n // 记录旧端口(--restart/自动升级时用于端口继承;stopInstance 会清 record)\n const oldRecord = existing && (args.restart || autoUpgrade) ? existing : null;\n if (oldRecord) {\n if (autoUpgrade) {\n console.log(\n `[zdashboard] 检测到旧版本实例 v${found!.liveVersion ?? 'unknown'},自动升级到 v${pkg.version}(停止旧实例 pid=${oldRecord.pid})`,\n );\n } else {\n console.log(`[zdashboard] --restart:停止旧实例 pid=${oldRecord.pid}`);\n }\n await stopInstance(oldRecord);\n }\n\n const appDir = path.resolve(__dirname, 'web');\n\n // built-in plugins:统一数组注册(未来迁移为 definePlugin 产出后无需改动此处)\n const BUILTIN_PLUGINS = [statsApply, justApply, designApply, viewApply];\n\n // 约定化扫描:启动一次性剥离 dashboard.json 里内置插件的死配置键(未声明 config 即清,external/未知保留)\n if (stripDeadPluginConfig(root, BUILTIN_PLUGINS.map((p) => p.manifest))) {\n console.log('[zdashboard] 已清理 dashboard.json 中内置插件的过时配置键');\n }\n\n // P2: restart 且有旧记录时,起始端口用 record.port(用户显式 --port 则尊重)\n const startPort = oldRecord && !args.portExplicit ? oldRecord.port : args.port;\n\n // P0: 数据目录检测(.zdev/ 存在则优先)\n const zdevDir = path.join(root, '.zdev');\n const dataDir = fs.existsSync(zdevDir) ? '.zdev/' : '';\n\n const det = await detect(root);\n\n const ctx = new Context();\n\n // core services\n ctx.plugin(ServerService, {\n root,\n appDir,\n port: startPort,\n open: args.open,\n detect: det,\n page: args.page,\n dataDir: dataDir || undefined,\n onListen: (port: number) => writeRecord(root, port),\n });\n ctx.plugin(ReloadService, { root });\n ctx.plugin(treeApply, { root });\n ctx.plugin(worktreesApply, { root });\n ctx.plugin(DashboardService);\n\n for (const apply of BUILTIN_PLUGINS) {\n try {\n ctx.plugin(apply, { root });\n } catch (e) {\n console.error('[zdashboard] builtin plugin failed:', e);\n }\n }\n\n // external plugins\n if (args.plugins) {\n await loadExternal(ctx, path.resolve(args.plugins), root);\n }\n\n // graceful shutdown: clear .zdev record on SIGTERM / SIGINT\n const shutdown = () => {\n try { clearRecord(root); } catch {}\n process.exit(0);\n };\n process.on('SIGTERM', shutdown);\n process.on('SIGINT', shutdown);\n\n return ctx;\n}\n\nawait main().catch((e) => {\n console.error(e);\n process.exit(1);\n});\n","{\n \"name\": \"zdashboard\",\n \"version\": \"2.13.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 && node scripts/check-excalidraw-lazy.mjs\",\n \"build:web\": \"vite build\",\n \"build:node\": \"tsup\",\n \"start\": \"node dist/cli.js\",\n \"test\": \"vitest run\",\n \"typecheck\": \"tsc --noEmit\",\n \"test:coverage\": \"vitest run --coverage\",\n \"preview\": \"vite preview\"\n },\n \"dependencies\": {\n \"@excalidraw/excalidraw\": \"0.18.1\",\n \"@fontsource/vt323\": \"^5.3.0\",\n \"@phosphor-icons/react\": \"^2.1.10\",\n \"@radix-ui/react-dropdown-menu\": \"^2.1.24\",\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 \"cordis\": \"4.0.0-rc.8\",\n \"cosmokit\": \"^1.8.1\",\n \"date-fns\": \"^3.6.0\",\n \"filesize\": \"^11.0.0\",\n \"highlight.js\": \"^11.11.1\",\n \"iconv-lite\": \"0.7.3\",\n \"katex\": \"^0.16.11\",\n \"ky\": \"^1.7.0\",\n \"lodash-es\": \"^4.17.21\",\n \"lucide-react\": \"^0.460.0\",\n \"pixelarticons\": \"^2.4.1\",\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 \"tsx\": \"^4.7.0\",\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 \"@vitest/coverage-v8\": \"1.6.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}\n\n/** --list 主探测超时(与迁移前一致) */\nconst JUST_PROBE_TIMEOUT_MS = 5000;\n/** --version 兜底探测超时(快失败:二进制存在性检查无需长等) */\nconst JUST_FALLBACK_TIMEOUT_MS = 3000;\n\nfunction justAvailable(cwd: string): Promise<boolean> {\n /** 探测一次:进程正常退出即视为可用 */\n const probe = (args: string[], timeout: number) => new Promise<boolean>((resolve) => {\n const child = execFile('just', args, { cwd, timeout }, (err) => resolve(!err));\n if (child.killed) resolve(false);\n });\n // 旧版以 --list --unsupported 判定;新版 just 移除该旗标会报错(hasJust 恒 false),\n // 回退 --version 探测二进制本身可用\n return probe(['--list', '--unsupported'], JUST_PROBE_TIMEOUT_MS)\n .then((ok) => (ok ? true : probe(['--version'], JUST_FALLBACK_TIMEOUT_MS)));\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 return { hasOpenspec, hasDocs, hasJust };\n}\n\n/** /__detect 的响应形状:与 DetectResult 同形(bugs 期兼容字段已随清理 change 摘除) */\nexport type DetectResponse = DetectResult;\n\n/** 现场探测(每次请求重新跑),供 /__detect 独立路由使用 */\nexport async function detectLiveShape(root: string): Promise<DetectResponse> {\n return detect(root);\n}\n","import http from 'node:http';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport crypto from 'node:crypto';\nimport { fileURLToPath } from 'node:url';\nimport pkg from '../../package.json' with { type: 'json' };\nimport type { Context } from 'cordis';\nimport type { DetectResult, DetectResponse } from '../server/detect.js';\nimport { detectLiveShape } from '../server/detect.js';\nimport type { PluginManifest, ConfigField } from '../core/manifest.js';\nimport { Service } from 'cordis';\nimport { clearRecord, readPluginsConfig, writePluginsConfig } from './instance.js';\nimport { openUrl } from './open-url.js';\nimport { readBody } from './read-body.js';\nimport { execFile } from 'node:child_process';\n\nconst VERSION = pkg.version;\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface ServerOptions {\n root: string;\n appDir: string;\n port: number;\n open: boolean;\n page: string | null;\n detect: DetectResult;\n dataDir?: string;\n onListen?: (port: number) => void;\n}\n\ndeclare module 'cordis' {\n interface Context {\n server: ServerService;\n }\n}\n\n/** 扩展名 → Content-Type 表(SDK 插件路由等复用,勿在他处复制) */\nexport const MIME: Record<string, string> = {\n '.html': 'text/html; charset=utf-8', '.htm': 'text/html; charset=utf-8',\n '.pdf': 'application/pdf',\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 '.avif': 'image/avif',\n '.md': 'text/markdown; charset=utf-8', '.txt': 'text/plain; charset=utf-8',\n '.sql': 'text/plain; charset=utf-8', '.csv': 'text/plain; charset=utf-8',\n '.tsv': 'text/plain; charset=utf-8', '.yaml': 'text/yaml; charset=utf-8',\n '.yml': 'text/yaml; charset=utf-8', '.xml': 'application/xml; charset=utf-8',\n '.py': 'text/plain; charset=utf-8', '.ts': 'text/plain; charset=utf-8',\n '.java': 'text/plain; charset=utf-8', '.go': 'text/plain; charset=utf-8',\n '.rs': 'text/plain; charset=utf-8', '.rb': 'text/plain; charset=utf-8',\n '.php': 'text/plain; charset=utf-8', '.c': 'text/plain; charset=utf-8',\n '.cpp': 'text/plain; charset=utf-8', '.h': 'text/plain; charset=utf-8',\n '.cs': 'text/plain; charset=utf-8', '.swift': 'text/plain; charset=utf-8',\n '.kt': 'text/plain; charset=utf-8', '.scala': 'text/plain; charset=utf-8',\n '.sh': 'text/plain; charset=utf-8', '.bash': 'text/plain; charset=utf-8',\n '.zsh': 'text/plain; charset=utf-8', '.fish': 'text/plain; charset=utf-8',\n '.env': 'text/plain; charset=utf-8', '.gitignore': 'text/plain; charset=utf-8',\n '.dockerfile': 'text/plain; charset=utf-8',\n '.mp4': 'video/mp4', '.webm': 'video/webm', '.mov': 'video/quicktime',\n '.m4a': 'audio/mp4', '.aac': 'audio/aac',\n '.woff': 'font/woff', '.woff2': 'font/woff2', '.ttf': 'font/woff',\n '.map': 'application/json; charset=utf-8',\n};\n\n// 静态 HTML 注入脚本:仅保留 _self 链接补丁(文件预览页内跳转留在当前窗口)。\n// 旧 EventSource('/__reload') 注入已随沙箱收紧移除——sandbox=allow-scripts 下 iframe\n// 为不透明源,/__reload 属跨域请求,只会制造 console error 且其处理器本已为空。\nconst INJECT = `<script>(function(){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\nexport const PLUGIN_STATIC_PREFIX = '/__plugin/';\n\n/** json 响应助手:统一 Content-Type/缓存头与序列化,消灭 writeHead 样板 */\nexport function json(res: http.ServerResponse, data: unknown, status = 200): void {\n res.writeHead(status, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(data));\n}\n\n/** 错误码 → 中文说明(极简错误页单源) */\nconst ERROR_PAGE_TEXT: Record<number, string> = {\n 400: '请求无效',\n 403: '没有访问权限',\n 404: '页面不存在',\n};\n\n/**\n * 极简 HTML 错误页:标题/说明/返回首页链接,零外部资源(离线可用)。\n * 页面类路径(项目文件/静态资源)404/403 专用;`/__` 前缀 API 路径保持 JSON/原文不变。\n */\nexport function sendErrorPage(res: http.ServerResponse, code: number): void {\n if (res.headersSent) {\n // 头已发出(响应中途出错):不能再改状态码,只断开连接防悬挂\n try { res.destroy(); } catch { /* 已断 */ }\n return;\n }\n const text = ERROR_PAGE_TEXT[code] ?? '出错了';\n res.writeHead(code, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(\n `<!doctype html><html lang=\"zh-CN\"><head><meta charset=\"utf-8\">` +\n `<title>${code} ${text} · zdashboard</title></head>` +\n `<body><h1>${code} · ${text}</h1><p>请求的资源不可用或已被移动。</p>` +\n `<p><a href=\"/\">返回首页</a></p></body></html>`,\n );\n}\n\n/** x-stop-token 鉴权助手:通过返回 true;未通过时已写 403 响应并返回 false */\nexport function guarded(req: http.IncomingMessage, res: http.ServerResponse, token: string): boolean {\n if (req.headers['x-stop-token'] !== token) {\n res.writeHead(403);\n res.end('forbidden');\n return false;\n }\n return true;\n}\n\nexport class ServerService extends Service {\n stopToken: string;\n private root: string;\n private appDir: string;\n private open: boolean;\n private page: string | null;\n private det: DetectResult;\n private dataDir?: string;\n private routes = new Map<string, (req: http.IncomingMessage, res: http.ServerResponse) => void>();\n private sses = new Map<string, (res: http.ServerResponse) => (() => void) | void>();\n private prefixStatic = new Map<string, string>();\n private server?: http.Server;\n private onListen?: (port: number) => void;\n\n constructor(ctx: Context, config: ServerOptions) {\n super(ctx, 'server');\n this.stopToken = crypto.randomBytes(12).toString('hex');\n this.root = config.root;\n this.appDir = config.appDir;\n this.open = config.open;\n this.page = config.page;\n this.det = config.detect;\n this.dataDir = config.dataDir;\n this.onListen = config.onListen;\n ctx.effect(() => () => this.dispose());\n\n this.refreshGitInfo();\n this.route('/__config', (_req, res) => {\n json(res, { stopToken: this.stopToken, version: VERSION, root: this.root, ...this.gitInfo });\n });\n\n // 独立探测接口(轻量,替代 HomeGrid 借道 /__files 全量树)\n this.route('/__detect', async (_req, res) => {\n const shape: DetectResponse = await detectLiveShape(this.root);\n json(res, shape);\n });\n\n // 应用级静态文件(index.html 引用但不在 /assets/ 下),避免落到项目目录 404\n this.route('/favicon.svg', (req, res) => {\n this.serveFile(path.join(this.appDir, 'favicon.svg'), req, res, false);\n });\n\n this.route('/__file-content', async (req, res) => {\n const url = new URL(req.url || '/', 'http://localhost');\n const rawPath = url.pathname.replace(/^\\/__file-content\\/?/, '');\n if (!rawPath || rawPath === '/') {\n res.writeHead(400);\n res.end('missing path');\n return;\n }\n const filePath = path.join(this.root, decodeURIComponent(rawPath));\n if (!filePath.startsWith(this.root + path.sep) && filePath !== this.root) {\n res.writeHead(403);\n res.end('Forbidden');\n return;\n }\n fs.stat(filePath, (err) => {\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 res.writeHead(200, { 'Content-Type': ct, 'Cache-Control': 'no-cache' });\n fs.createReadStream(filePath).pipe(res);\n });\n });\n\n this.route('/__stop', async (req, res) => {\n if (!guarded(req, res, this.stopToken)) return;\n json(res, { ok: true });\n this.stop();\n });\n\n this.start(config.port);\n }\n\n route(path: string, handler: (req: http.IncomingMessage, res: http.ServerResponse) => void) {\n this.routes.set(path, handler);\n this.ctx.effect(() => () => this.routes.delete(path));\n }\n\n sse(path: string, onConnect: (res: http.ServerResponse) => (() => void) | void) {\n this.sses.set(path, onConnect);\n this.ctx.effect(() => () => this.sses.delete(path));\n }\n\n static(prefix: string, dir: string) {\n this.prefixStatic.set(prefix, dir);\n this.ctx.effect(() => () => this.prefixStatic.delete(prefix));\n }\n\n private pluginsConfig: Record<string, Record<string, unknown>> = {};\n\n getPluginConfig(mode: string): Record<string, unknown> {\n return this.pluginsConfig[mode] ?? {};\n }\n\n refreshPluginsConfig() {\n this.pluginsConfig = readPluginsConfig(this.root);\n }\n\n savePluginConfig(merged: Record<string, Record<string, unknown>>) {\n this.pluginsConfig = merged;\n writePluginsConfig(this.root, merged);\n }\n\n private serveFile(filePath: string, req: http.IncomingMessage, res: http.ServerResponse, injectHtml: boolean) {\n // `/__` 前缀为 API/插件资源路径:错误保持原样(不换 HTML 错误页)\n const apiPath = (req.url || '').startsWith('/__');\n fs.stat(filePath, (err, stat) => {\n if (err) {\n if (apiPath) { res.writeHead(404); return res.end('Not found'); }\n return sendErrorPage(res, 404);\n }\n const ext = path.extname(filePath).toLowerCase();\n const ct = MIME[ext] ?? 'application/octet-stream';\n\n // ---- HTTP Range support ----\n const rangeHeader = (req.headers['range'] as string | undefined);\n let range: { start: number; end: number } | null = null;\n if (rangeHeader) {\n const m = rangeHeader.match(/^bytes=(\\d+)-(\\d*)$/);\n if (m) {\n const start = Number(m[1]);\n const end = m[2] !== '' ? Number(m[2]) : stat.size - 1;\n if (!Number.isNaN(start) && !Number.isNaN(end) && start <= end && start < stat.size) {\n range = { start, end: Math.min(end, stat.size - 1) };\n }\n // malformed range → fall through to 200 full response\n }\n // unparseable range header → fall through to 200 full response\n }\n\n if (range) {\n const { start, end } = range;\n const chunkSize = end - start + 1;\n res.writeHead(206, {\n 'Content-Type': ct,\n 'Content-Length': String(chunkSize),\n 'Content-Range': `bytes ${start}-${end}/${stat.size}`,\n 'Accept-Ranges': 'bytes',\n 'Cache-Control': 'no-cache',\n });\n // stat 成功后文件仍可能在 open 前被删/换(高频增删的工作区),流错误无人接会崩进程\n const stream = fs.createReadStream(filePath, { start, end });\n stream.on('error', () => { try { res.destroy(); } catch { /* 已断 */ } });\n stream.pipe(res);\n return;\n }\n\n // Full response\n fs.readFile(filePath, (err, data) => {\n if (err) {\n if (apiPath) { res.writeHead(404); return res.end('Not found'); }\n return sendErrorPage(res, 404);\n }\n let body: string | Buffer = 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, 'Accept-Ranges': 'bytes', 'Cache-Control': 'no-cache' });\n res.end(body);\n });\n });\n }\n\n private servePrefix(url: string, req: http.IncomingMessage, res: http.ServerResponse): boolean {\n for (const [prefix, dir] of this.prefixStatic) {\n if (url.indexOf(prefix) === 0) {\n let rel = this.safeDecode(url.slice(prefix.length));\n if (!rel || rel === '/' || !path.extname(rel)) rel = path.join(rel || '', 'index.html');\n const fp = path.join(dir, rel);\n if (fp.indexOf(dir + path.sep) !== 0) { res.writeHead(403); res.end('Forbidden'); return false; }\n this.serveFile(fp, req, res, true);\n return true;\n }\n }\n return false;\n }\n\n private safeDecode(raw: string): string {\n try { return decodeURIComponent(raw); } catch { return raw; }\n }\n\n private handler = (req: http.IncomingMessage, res: http.ServerResponse) => {\n try {\n const rawUrl = req.url || '/';\n const url = rawUrl.split('?')[0];\n\n const rh = this.routes.get(url);\n if (rh) { rh(req, res); return; }\n for (const [rp, rh2] of this.routes) {\n if (url.startsWith(rp + '/')) { rh2(req, res); return; }\n }\n const sh = this.sses.get(url);\n if (sh) {\n res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', Connection: 'keep-alive' });\n res.write(': connected\\n\\n');\n const cleanup = sh(res);\n req.on('close', () => { cleanup?.(); });\n return;\n }\n\n if (this.servePrefix(url, req, res)) return;\n\n if (url === '/' || url.indexOf('/__app/') === 0 || url.indexOf('/assets/') === 0) {\n let fp = this.appDir;\n if (url !== '/') fp = path.join(this.appDir, this.safeDecode(url));\n if (url.indexOf('/__app/') === 0) fp = path.join(this.appDir, url.slice(7));\n if (fp !== this.appDir && fp.indexOf(this.appDir + path.sep) !== 0) { return sendErrorPage(res, 403); }\n if (url === '/') fp = path.join(this.appDir, 'index.html');\n return this.serveFile(fp, req, res, false);\n }\n\n const fp = path.join(this.root, this.safeDecode(url));\n if (fp !== this.root && fp.indexOf(this.root + path.sep) !== 0) {\n // `/__` 前缀 API 路径错误保持原文(S2);页面类路径走 HTML 错误页\n if ((req.url || '').startsWith('/__')) { res.writeHead(403); return res.end('Forbidden'); }\n return sendErrorPage(res, 403);\n }\n return this.serveFile(fp, req, res, true);\n } catch (e) {\n // 兜底错误:API 路径保持原文(S2),页面类 400 错误页;头已发出时 sendErrorPage 仅断连\n try {\n if ((req.url || '').startsWith('/__')) { res.writeHead(400); res.end('bad request'); }\n else sendErrorPage(res, 400);\n } catch { /* 已断 */ }\n console.error('[zdashboard] handler error', e);\n }\n };\n\n start(port: number) {\n this.server = http.createServer(this.handler);\n // 浏览器复用空闲 keep-alive 连接时若已被服务端关闭,请求会石沉大海(点击无响应)。\n // 拉长 keep-alive 使其远大于浏览器侧空闲窗口\n this.server.keepAliveTimeout = 65_000;\n this.server.headersTimeout = 66_000;\n this.server.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n console.log(`[zdashboard] port ${port} busy, trying ${port + 1}`);\n this.start(port + 1);\n } else throw err;\n });\n this.server.listen(port, '127.0.0.1', () => {\n // port=0(测试/随机端口)时上报实际绑定端口\n const addr = this.server?.address();\n const bound = typeof addr === 'object' && addr ? addr.port : port;\n const u = `http://localhost:${bound}`;\n const target = this.page ? `${u}#${this.page}` : u;\n console.log(`[zdashboard] v${VERSION} dashboard -> ${u}`);\n console.log(`[zdashboard] project -> ${this.root}`);\n console.log(`[zdashboard] detect -> openspec:${this.det.hasOpenspec} docs:${this.det.hasDocs} just:${this.det.hasJust}`);\n if (this.dataDir) console.log(`[zdashboard] data -> ${this.dataDir}`);\n if (this.open) openUrl(target);\n this.onListen?.(bound);\n });\n }\n\n /** 项目 git 信息(分支/脏文件数),启动探测一次,文件变更时刷新 */\n private gitInfo: { branch?: string; dirty?: number } = {};\n\n refreshGitInfo() {\n const run = (args: string[]) => new Promise<string>((resolve) => {\n execFile('git', args, { cwd: this.root, timeout: 3000 }, (err, stdout) => resolve(err ? '' : stdout));\n });\n void (async () => {\n const [branch, status] = await Promise.all([\n run(['rev-parse', '--abbrev-ref', 'HEAD']),\n run(['status', '--porcelain']),\n ]);\n const b = branch.trim();\n this.gitInfo = b ? { branch: b, dirty: status ? status.split('\\n').filter(Boolean).length : 0 } : {};\n })();\n }\n\n stop() {\n if (this.server) { try { this.server.close(); } catch {} }\n try { clearRecord(this.root); } catch {}\n setTimeout(() => {\n try { this.ctx.root.fiber.dispose(); } catch {}\n process.exit(0);\n }, 50);\n }\n\n dispose() {\n if (this.server) { try { this.server.close(); } catch {} }\n try { clearRecord(this.root); } catch {}\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport pkg from '../../package.json' with { type: 'json' };\n\nconst CURRENT_VERSION: string = pkg.version;\n\nexport interface InstanceRecord {\n pid: number;\n port: number;\n root: string;\n startedAt: string;\n /** 写入该记录的实例版本(信息用途;活实例版本以 /__config 实时值为准) */\n version?: string;\n plugins?: Record<string, Record<string, unknown>>;\n}\n\nexport const RECORD_FILE = '.zdev/dashboard.json';\nexport const VERIFY_TIMEOUT_MS = 1500;\nexport const STOP_POLL_MS = 2000;\nexport const STOP_POLL_INTERVAL_MS = 100;\nexport const STOP_FINAL_WAIT_MS = 100;\n\nfunction recordPath(root: string): string {\n return path.join(root, RECORD_FILE);\n}\n\nexport function readRecord(root: string): InstanceRecord | null {\n try {\n const fp = recordPath(root);\n const raw = fs.readFileSync(fp, 'utf-8');\n const rec = JSON.parse(raw) as Partial<InstanceRecord>;\n if (\n typeof rec.pid === 'number' &&\n typeof rec.port === 'number' &&\n typeof rec.root === 'string' &&\n typeof rec.startedAt === 'string'\n ) {\n return rec as InstanceRecord;\n }\n return null;\n } catch {\n return null;\n }\n}\n\nexport function writeRecord(root: string, port: number): void {\n const fp = recordPath(root);\n fs.mkdirSync(path.dirname(fp), { recursive: true });\n // 读改写:onListen 每次启动都会调 writeRecord,需沿用旧记录的 plugins 段,\n // 只更新运行字段(pid/port/root/startedAt),否则插件配置跨重启清零。\n const old = readRecord(root); // 记录缺失/损坏 → null,兜底最小记录\n const rec: InstanceRecord = {\n pid: process.pid,\n port,\n root,\n startedAt: new Date().toISOString(),\n version: CURRENT_VERSION,\n };\n if (old?.plugins && typeof old.plugins === 'object') {\n rec.plugins = old.plugins;\n }\n // tmp+rename 原子写(对齐 writePluginsConfig),避免半写状态被读到\n const tmp = fp + '.tmp';\n fs.writeFileSync(tmp, JSON.stringify(rec, null, 2) + '\\n');\n fs.renameSync(tmp, fp);\n}\n\nexport function readPluginsConfig(root: string): Record<string, Record<string, unknown>> {\n try {\n const rec = readRecord(root);\n if (rec?.plugins && typeof rec.plugins === 'object') {\n return rec.plugins as Record<string, Record<string, unknown>>;\n }\n } catch { /* ignore */ }\n return {};\n}\n\nexport function writePluginsConfig(root: string, plugins: Record<string, Record<string, unknown>>): void {\n const fp = recordPath(root);\n let rec: InstanceRecord;\n try {\n const raw = fs.readFileSync(fp, 'utf-8');\n rec = JSON.parse(raw) as InstanceRecord;\n } catch {\n rec = { pid: process.pid, port: 0, root, startedAt: new Date().toISOString() };\n }\n rec.plugins = plugins;\n const tmp = fp + '.tmp';\n fs.writeFileSync(tmp, JSON.stringify(rec, null, 2) + '\\n');\n fs.renameSync(tmp, fp);\n}\n\n/** 死键剥离判定所需的最小 manifest 投影(PluginManifest 结构兼容) */\nexport interface ConfigSchemaInfo {\n mode: string;\n external?: boolean;\n /** manifest.config 声明:缺省或空对象表示该内置插件无配置面 */\n config?: Record<string, unknown>;\n}\n\n/**\n * 启动一次性:剥离 dashboard.json 里内置插件的死配置键(通用规则,收敛自 view/design 约定化扫描)。\n * - 内置(非 external)未声明 config → 整段死键,清除;\n * - 内置已声明 config → 仅保留声明键(键级收敛);\n * - external 插件键保留;存储中无 manifest 声明的键(未知/未加载插件)保守保留。\n * 无变更/无记录时不写盘。返回是否发生了剥离。记录缺失/损坏跳过清理,不阻塞启动。\n */\nexport function stripDeadPluginConfig(root: string, manifests: readonly ConfigSchemaInfo[]): boolean {\n try {\n const rec = readRecord(root);\n if (!rec?.plugins || typeof rec.plugins !== 'object') return false;\n const byMode = new Map(manifests.map((m) => [m.mode, m]));\n const stored = rec.plugins as Record<string, unknown>;\n const plugins: Record<string, unknown> = { ...stored };\n let changed = false;\n for (const mode of Object.keys(plugins)) {\n const m = byMode.get(mode);\n // 无声明(未注册,可能是外部插件或已卸载)→ 保守不清;external → 保留\n if (!m || m.external) continue;\n const section = plugins[mode];\n if (section === null || typeof section !== 'object') continue;\n const keys = Object.keys(section as Record<string, unknown>);\n if (!m.config || Object.keys(m.config).length === 0) {\n // 内置且未声明 config → 整段死键\n if (keys.length > 0) {\n delete plugins[mode];\n changed = true;\n }\n continue;\n }\n // 键级收敛:仅保留 manifest.config 声明的键\n const kept: Record<string, unknown> = {};\n for (const key of Object.keys(m.config)) {\n if (key in (section as Record<string, unknown>)) kept[key] = (section as Record<string, unknown>)[key];\n }\n if (Object.keys(kept).length !== keys.length) {\n if (Object.keys(kept).length === 0) delete plugins[mode];\n else plugins[mode] = kept;\n changed = true;\n }\n }\n if (!changed) return false;\n writePluginsConfig(root, plugins as Record<string, Record<string, unknown>>); // tmp+rename 原子写\n return true;\n } catch {\n return false; // 记录缺失/损坏:跳过清理,不阻塞启动\n }\n}\n\nexport function clearRecord(root: string): void {\n try {\n // 属主校验:记录若已指向别的实例(并发双启落败者),不得误删胜者记录\n const rec = readRecord(root);\n if (rec && rec.pid !== process.pid) return;\n fs.unlinkSync(recordPath(root));\n } catch {\n // best-effort\n }\n}\n\nexport function isAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code === 'ESRCH') return false;\n // EPERM or other → process exists, we just can't signal it\n return true;\n }\n}\n\nasync function fetchWithTimeout(url: string): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), VERIFY_TIMEOUT_MS);\n try {\n return await fetch(url, { signal: controller.signal });\n } finally {\n clearTimeout(timer);\n }\n}\n\n/** 活实例核验结果:reusable = 存活且 root 匹配;version 为该实例实时版本(供旧版检测) */\nexport interface VerifyResult {\n reusable: boolean;\n version?: string;\n}\n\nexport async function verifyRoot(port: number, root: string): Promise<VerifyResult> {\n try {\n const res = await fetchWithTimeout(`http://127.0.0.1:${port}/__config`);\n if (res.status !== 200) return { reusable: false };\n const body = await res.json();\n if (typeof body.root !== 'string') return { reusable: false };\n return {\n reusable: body.root === root,\n version: typeof body.version === 'string' ? body.version : undefined,\n };\n } catch {\n return { reusable: false };\n }\n}\n\n/**\n * 可复用实例发现:\n * - reuse → 存活 + root 匹配 + 版本一致,直接复用;\n * - stale-version → 存活 + root 匹配但版本落后(调用方决定提示或自动升级接管);\n * - null → 无可复用实例(无记录/进程死亡/端口被无关进程占用)。\n */\nexport async function findReusable(\n root: string,\n currentVersion: string,\n): Promise<{ status: 'reuse'; record: InstanceRecord } | { status: 'stale-version'; record: InstanceRecord; liveVersion?: string } | null> {\n const rec = readRecord(root);\n if (!rec) return null;\n if (!isAlive(rec.pid)) return null;\n const v = await verifyRoot(rec.port, root);\n if (!v.reusable) return null;\n if (v.version && v.version !== currentVersion) {\n return { status: 'stale-version', record: rec, liveVersion: v.version };\n }\n return { status: 'reuse', record: rec };\n}\n\nexport async function stopInstance(record: InstanceRecord): Promise<void> {\n try {\n process.kill(record.pid, 'SIGTERM');\n } catch {\n return;\n }\n\n const deadline = Date.now() + STOP_POLL_MS;\n while (Date.now() < deadline) {\n if (!isAlive(record.pid)) return;\n await new Promise((r) => setTimeout(r, STOP_POLL_INTERVAL_MS));\n }\n\n // still alive → SIGKILL\n try {\n process.kill(record.pid, 'SIGKILL');\n } catch {\n // ignore\n }\n await new Promise((r) => setTimeout(r, STOP_FINAL_WAIT_MS));\n}\n","import { exec, execFile } from 'node:child_process';\n\n/** 跨平台打开浏览器(macOS open / Windows start / Linux xdg-open) */\nexport function openUrl(url: string): void {\n const cmd =\n process.platform === 'darwin' ? 'open' :\n process.platform === 'win32' ? 'start' :\n 'xdg-open';\n // win32 `start` 是 shell 内建命令,只能走 shell;其他平台直接用 execFile\n if (process.platform === 'win32') {\n exec(`start \"\" \"${url}\"`);\n } else {\n execFile(cmd, [url]);\n }\n}\n","import fs from 'node:fs';\nimport http from 'node:http';\nimport { Service } from 'cordis';\nimport type { Context } from 'cordis';\n\ndeclare module 'cordis' {\n interface Context {\n reload: ReloadService;\n }\n}\n\nconst WATCH_DEBOUNCE_MS = 300;\n\n/** 忽略目录(recursive watch 相对路径前缀)与编辑器/系统/日志噪音文件 */\nconst IGNORED_DIR_RE = /^(?:\\.git|node_modules|dist|\\.pnpm)(?:[/\\\\]|$)/;\nconst IGNORED_FILE_RE = /\\.(?:swp|tmp|log)$|~$|^\\.DS_Store$|^Thumbs\\.db$/i;\n\n/** filename 是否应被 watcher 忽略;null(平台未提供文件名)放行,行为不变 */\nexport function isIgnoredPath(filename: string | null): boolean {\n if (!filename) return false;\n return IGNORED_DIR_RE.test(filename) || IGNORED_FILE_RE.test(filename);\n}\n\nexport class ReloadService extends Service {\n static inject = ['server'];\n private clients = new Set<http.ServerResponse>();\n private watcher?: fs.FSWatcher;\n private timer?: NodeJS.Timeout;\n\n constructor(ctx: Context, config: { root: string }) {\n super(ctx, 'reload');\n this.ctx.effect(() => () => this.dispose());\n\n this.ctx.server.sse('/__reload', (res) => {\n this.clients.add(res);\n return () => this.clients.delete(res);\n });\n\n try {\n this.watcher = fs.watch(config.root, { recursive: true }, (eventType, filename) => {\n if (isIgnoredPath(filename)) return;\n if (this.timer) clearTimeout(this.timer);\n this.timer = setTimeout(() => {\n this.ctx.server.refreshGitInfo();\n this.broadcast('reload');\n this.broadcast('files');\n this.timer = undefined;\n }, WATCH_DEBOUNCE_MS);\n });\n } catch {\n // watch unavailable - static only\n }\n }\n\n broadcast(ev: string, data: unknown = '') {\n const payload = `event: ${ev}\\ndata: ${JSON.stringify(data == null ? '' : data)}\\n\\n`;\n for (const c of this.clients) {\n try { c.write(payload); } catch {}\n }\n }\n\n /** 插件专用频道:plugin:<mode>:<event>,客户端 usePluginData subscribe 消费 */\n broadcastPlugin(mode: string, event: string, data: unknown = '') {\n this.broadcast(`plugin:${mode}:${event}`, data);\n }\n\n dispose() {\n if (this.watcher) { try { this.watcher.close(); } catch {} }\n if (this.timer) { clearTimeout(this.timer); }\n for (const c of this.clients) { try { c.end(); } catch {} }\n this.clients.clear();\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { walkDir } from './walk.js';\n\nexport type NodeKind = 'file' | 'dir' | 'log';\nexport interface TreeNode {\n name: string;\n kind: NodeKind;\n path?: string;\n defaultCollapsed?: boolean;\n children?: TreeNode[];\n}\n\nfunction buildTree(paths: string[], defaultExpandDepth = 2): TreeNode[] {\n const root: TreeNode[] = [];\n const map = new Map<string, TreeNode>();\n\n for (const p of paths) {\n const parts = p.split('/');\n let current = '';\n let parent = root;\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n current = current ? `${current}/${part}` : part;\n const isLast = i === parts.length - 1;\n const depth = i;\n\n if (!map.has(current)) {\n const isDir = !isLast;\n const collapsed = isDir && typeof defaultExpandDepth === 'number' && depth > defaultExpandDepth;\n const node: TreeNode = {\n name: part,\n kind: isLast ? 'file' : 'dir',\n ...(collapsed ? { defaultCollapsed: true } : {}),\n ...(isLast ? { path: p } : { children: [] }),\n };\n map.set(current, node);\n parent.push(node);\n }\n\n if (!isLast) {\n parent = map.get(current)!.children!;\n }\n }\n }\n\n const sortNodes = (nodes: TreeNode[]) => {\n nodes.sort((a, b) => (a.kind === b.kind ? a.name.localeCompare(b.name) : a.kind === 'dir' ? -1 : 1));\n for (const n of nodes) {\n if (n.children) sortNodes(n.children);\n }\n };\n\n sortNodes(root);\n return root;\n}\n\nexport interface ScanTreeOptions {\n defaultExpandDepth?: number;\n /** 允许点前缀的 scanDirs(如 .zdev/apply):声明后才扫描,且 walk 放行其内点前缀子目录;未声明的点前缀目录整组跳过 */\n dotDirs?: string[];\n}\n\nfunction prefixPaths(nodes: TreeNode[], prefix: string): TreeNode[] {\n return nodes.map((n) => {\n if (n.kind === 'file' && n.path) {\n return { ...n, path: `${prefix}/${n.path}` };\n }\n if (n.children) {\n return { ...n, children: prefixPaths(n.children, prefix) };\n }\n return n;\n });\n}\n\n/** 方案模式树形扫描:按 scanDirs 白名单扫描 */\nexport function scanTree(root: string, scanDirs: string[], opts?: ScanTreeOptions): TreeNode[] {\n const tree: TreeNode[] = [];\n const defaultExpandDepth = typeof opts?.defaultExpandDepth === 'number' ? opts.defaultExpandDepth : 2;\n const dotDeclared = new Set(Array.isArray(opts?.dotDirs) ? opts.dotDirs : []);\n const dirs = Array.isArray(scanDirs) ? scanDirs.filter((d) => typeof d === 'string' && d) : [];\n for (const dir of dirs) {\n // 点前缀目录须显式列入 dotDirs 才可扫(最小例外);未声明整组跳过\n if (dir.startsWith('.') && !dotDeclared.has(dir)) continue;\n const dirPath = path.join(root, dir);\n if (!fs.existsSync(dirPath)) continue;\n const paths: string[] = [];\n walkDir(dirPath, { maxDepth: 4, allowDotDirs: dotDeclared.has(dir), onFile: (_, rel) => paths.push(rel) });\n const prefix = dir;\n const children = prefixPaths(buildTree(paths, defaultExpandDepth), prefix);\n if (children.length) {\n tree.push({ name: `${dir} (${children.length})`, kind: 'dir', children });\n }\n }\n return tree;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nexport interface WalkOptions {\n skip?: Set<string>;\n maxDepth?: number;\n /** true 时点前缀「目录」不跳过(供显式列入 dotDirs 的扫描目录使用);点前缀「文件」仍恒跳过 */\n allowDotDirs?: boolean;\n onFile?: (abs: string, rel: string) => void;\n onDir?: (abs: string, rel: string) => void;\n}\n\nexport function walkDir(root: string, opts: WalkOptions = {}): void {\n const { skip = new Set(), maxDepth, allowDotDirs = false, onFile, onDir } = opts;\n\n function walk(dir: string, rel: string, depth: number) {\n if (typeof maxDepth === 'number' && depth > maxDepth) return;\n let ents: fs.Dirent[];\n try { ents = fs.readdirSync(dir, { withFileTypes: true }); } catch { return; }\n for (const ent of ents) {\n // 点前缀最小例外:仅目录可经 allowDotDirs 放行,文件一律跳过\n if (ent.name.startsWith('.') && !(allowDotDirs && ent.isDirectory())) continue;\n if (skip.has(ent.name)) continue;\n const abs = path.join(dir, ent.name);\n const r = rel ? `${rel}/${ent.name}` : ent.name;\n if (ent.isDirectory()) {\n onDir?.(abs, r);\n walk(abs, r, depth + 1);\n } else if (onFile) {\n onFile(abs, r);\n }\n }\n }\n\n walk(root, '', 0);\n}\n","import type { Context } from 'cordis';\nimport { scanTree } from '../server/spec-scan.js';\n\n/** 生态约定:项目根/worktree 根下的固定扫描目录,非用户可配;.zdev/apply 为点前缀目录,经 dotDirs 显式放行 */\nconst CONVENTION_SCAN_DIRS = ['openspec', 'docs', '.zdev/apply', '.zdev/scenario'] as const;\n/** 点前缀扫描目录子集:scanTree 须声明才可扫(walkDir 点前缀最小例外) */\nconst CONVENTION_DOT_DIRS = CONVENTION_SCAN_DIRS.filter((d) => d.startsWith('.'));\n\nexport const apply = {\n inject: ['server'] as const,\n apply(ctx: Context, config: { root: string }) {\n const server = ctx.server;\n if (server?.route) {\n // /__files 仅返回目录树;探测位已由独立轻量接口 /__detect 承担,不再搭车\n server.route('/__files', async (req, res) => {\n try {\n const url = new URL(req.url || '/', 'http://localhost');\n const wt = url.searchParams.get('wt');\n const scanRoot = wt ? decodeURIComponent(wt) : config.root;\n const tree = scanTree(scanRoot, [...CONVENTION_SCAN_DIRS], { dotDirs: [...CONVENTION_DOT_DIRS] });\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify({ tree }));\n } catch {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify({ tree: [] }));\n }\n });\n }\n },\n};\n","import { execFile } from 'node:child_process';\nimport type { Context } from 'cordis';\n\nexport interface WorktreeInfo {\n path: string;\n name: string;\n branch: string;\n head: string;\n dirty: boolean;\n}\n\nconst GIT_TIMEOUT_MS = 5_000;\nconst ZWORKTREE_SEGMENT = '.zworktree/';\n\nfunction runGit(args: string[], cwd: string): Promise<string> {\n return new Promise((resolve) => {\n execFile('git', args, { cwd, timeout: GIT_TIMEOUT_MS }, (err, stdout) => {\n if (err) return resolve('');\n resolve(stdout);\n });\n });\n}\n\nexport async function listWorktrees(root: string): Promise<WorktreeInfo[]> {\n const raw = await runGit(['worktree', 'list', '--porcelain'], root);\n if (!raw) return [];\n\n const entries: WorktreeInfo[] = [];\n const lines = raw.split('\\n');\n let current: Partial<WorktreeInfo> = {};\n\n for (const line of lines) {\n const m = line.match(/^(worktree|HEAD|branch|detached)\\s+(.+)$/);\n if (!m) continue;\n const [, key, val] = m;\n if (key === 'worktree') {\n if (current.path && current.path.includes(ZWORKTREE_SEGMENT)) {\n entries.push({\n path: current.path,\n name: current.path.split(ZWORKTREE_SEGMENT).pop() ?? '',\n branch: current.branch ?? '',\n head: current.head ?? '',\n dirty: false,\n });\n }\n current = { path: val, head: '', branch: '' };\n } else if (key === 'HEAD') {\n current.head = val;\n } else if (key === 'branch') {\n current.branch = val.replace(/^refs\\/heads\\//, '');\n }\n }\n\n // flush last entry\n if (current.path && current.path.includes(ZWORKTREE_SEGMENT)) {\n entries.push({\n path: current.path,\n name: current.path.split(ZWORKTREE_SEGMENT).pop() ?? '',\n branch: current.branch ?? '',\n head: current.head ?? '',\n dirty: false,\n });\n }\n\n // dirty detection: git status --porcelain 非空即 dirty(失败默认 false)\n await Promise.all(\n entries.map(async (entry) => {\n try {\n const statusOut = await runGit(['status', '--porcelain'], entry.path);\n entry.dirty = statusOut.trim().length > 0;\n } catch {\n entry.dirty = false;\n }\n })\n );\n\n return entries;\n}\n\nexport const apply = {\n inject: ['server'] as const,\n apply(ctx: Context, config: { root: string }) {\n const server = ctx.server;\n if (!server?.route) return;\n\n server.route('/__worktrees', async (_req, res) => {\n try {\n const entries = await listWorktrees(config.root);\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(entries));\n } catch {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify([]));\n }\n });\n },\n};\n","import { Service } from 'cordis';\nimport type { Context } from 'cordis';\nimport { readBody } from './read-body.js';\n\ndeclare module 'cordis' {\n interface Context {\n dashboard: DashboardService;\n }\n}\n\nexport interface PluginManifest {\n mode: string;\n label: string;\n icon: string;\n description?: string;\n viewerUrl?: string; // 同源 URL,前端 iframe 渲染\n external?: boolean;\n order?: number; // 排序权重(小在前);缺省按字母序\n config?: Record<string, ConfigField>;\n}\n\nexport interface ConfigField {\n type: 'string' | 'text' | 'number' | 'boolean' | 'string[]' | 'select' | 'multiselect';\n label: string;\n default?: unknown;\n placeholder?: string;\n options?: { value: string; label: string }[];\n min?: number;\n max?: number;\n}\n\nexport class DashboardService extends Service {\n static inject = ['server', 'reload'];\n private plugins = new Map<string, PluginManifest>();\n private reloadRef: any;\n\n constructor(ctx: Context) {\n super(ctx, 'dashboard');\n this.ctx.effect(() => () => this.plugins.clear());\n this.reloadRef = ctx.reload;\n\n this.ctx.server.route('/__plugins', (_req, res) => {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify({ plugins: Array.from(this.plugins.values()) }));\n });\n\n this.ctx.server.route('/__plugins/config', async (req, res) => {\n const out: Record<string, Record<string, unknown>> = {};\n if (req.method === 'GET') {\n for (const m of this.plugins.values()) {\n const stored = this.ctx.server.getPluginConfig(m.mode);\n const schema = m.config ?? {};\n const merged: Record<string, unknown> = {};\n for (const [key, field] of Object.entries(schema)) {\n merged[key] = key in stored ? stored[key] : (field as ConfigField).default ?? '';\n }\n if (Object.keys(merged).length) out[m.mode] = merged;\n }\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(out));\n return;\n }\n if (req.method === 'POST') {\n if (req.headers['x-stop-token'] !== this.ctx.server.stopToken) {\n res.writeHead(403);\n res.end('forbidden');\n return;\n }\n try {\n const body = JSON.parse(await readBody(req));\n const merged: Record<string, Record<string, unknown>> = {};\n for (const mode of Object.keys(body)) {\n merged[mode] = body[mode] ?? {};\n }\n this.ctx.server.savePluginConfig(merged);\n for (const mode of Object.keys(body)) {\n try { this.reloadRef.broadcast('config', { plugin: mode }); } catch { /* ignore */ }\n }\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end('{\"ok\":true}');\n } catch (e) {\n console.error('[config] POST error', e);\n res.writeHead(400);\n res.end('{\"error\":\"bad request\"}');\n }\n return;\n }\n res.writeHead(405);\n res.end('{\"error\":\"method not allowed\"}');\n });\n }\n\n register(manifest: PluginManifest) {\n this.plugins.set(manifest.mode, manifest);\n this.ctx.effect(() => () => this.plugins.delete(manifest.mode));\n }\n\n list() {\n return Array.from(this.plugins.values());\n }\n\n get(mode: string): PluginManifest | undefined {\n return this.plugins.get(mode);\n }\n\n getConfig(mode: string): Record<string, unknown> {\n return this.ctx.server.getPluginConfig(mode);\n }\n}\n","import http from 'node:http';\n\n/**\n * Read the full body of an IncomingMessage.\n * Listens for 'error' to prevent a hanging promise when the client aborts mid-stream.\n */\nexport async function readBody(req: http.IncomingMessage): Promise<string> {\n return new Promise((resolve) => {\n let data = '';\n req.on('data', (chunk: string | Buffer) => { data += chunk; });\n req.on('end', () => resolve(data));\n req.on('error', () => resolve('')); // client abort → settle with empty string\n });\n}\n","/**\n * just server 侧:definePlugin 接入(manifest 单源)。\n *\n * JustRunner 并发核实结论(T5):src/server/just-runner.ts 已是多任务并发 runner ——\n * tasks Map 每 recipe 独立子进程/日志缓冲/状态,事件载荷自带 recipe(=taskId),\n * 无需 runner 池改造。plugin:just:log 等频道广播按事件原样携带 taskId。\n *\n * start/restart/stop/clear 走 guardedRoute(x-stop-token);\n * /__just/tasks 为任务列表提供只读路由。\n */\nimport type http from 'node:http';\nimport { execFile } from 'node:child_process';\nimport { JustRunner } from '../../server/just-runner.js';\nimport { pickStringArgs } from '../../server/just-recipe-params.js';\nimport { readBody } from '../../core/read-body.js';\nimport { defineBuiltin } from '../builtin.js';\nimport { manifest } from './manifest.js';\nimport type { RouteHandler } from '../../sdk/server.js';\n\nexport const apply = defineBuiltin({\n manifest,\n setup(ctx, root) {\n const runner = new JustRunner(root);\n ctx.onDispose(() => runner.stop());\n\n ctx.route('/__just/recipes', async () => {\n try {\n return await runner.recipesWithParams();\n } catch {\n return [];\n }\n });\n\n ctx.route('/__just/tasks', async () => runner.list());\n\n // just 环境探测(空态三态文案依据):未装(ENOENT)/ 无 justfile(其他失败)/ 可用(成功)\n ctx.route('/__just/status', async () => {\n return await new Promise<{ installed: boolean; hasJustfile: boolean }>((resolve) => {\n execFile('just', ['--list', '--unsorted'], { cwd: root, maxBuffer: 1 << 20, timeout: 8000 }, (err) => {\n if (!err) return resolve({ installed: true, hasJustfile: true });\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return resolve({ installed: false, hasJustfile: false });\n resolve({ installed: true, hasJustfile: false });\n });\n });\n });\n\n ctx.sse('/__just/logs', (res) => {\n const unsub = runner.subscribe((ev) => {\n // 插件频道镜像:type 即事件名(log/clear/state),载荷携带 taskId(recipe)\n try { ctx.broadcast(ev.type, ev); } catch { /* reload 未就绪 */ }\n res.write(`data: ${JSON.stringify(ev)}\\n\\n`);\n });\n return unsub;\n });\n\n /** start/restart 须带合法 recipe(同名 start 即重启,可选 args 参数表);stop 可带单个 recipe 或省略(停全部);clear 清日志 */\n const handleAction = async (req: http.IncomingMessage, res: http.ServerResponse, act: 'start' | 'stop' | 'restart' | 'clear') => {\n const body = await readBody(req);\n let recipe: string | undefined;\n let rawArgs: unknown;\n try {\n const parsed = JSON.parse(body || '{}') as { recipe?: string; args?: unknown };\n recipe = parsed.recipe;\n rawArgs = parsed.args;\n } catch { /* ignore */ }\n if (act === 'clear') {\n if (recipe) runner.clear(recipe);\n return { ok: true };\n }\n if (act !== 'stop') {\n if (!recipe) {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end('{\"error\":\"no recipe\"}');\n return undefined;\n }\n const recipes = await runner.recipes();\n if (!recipes.some((r) => r.name === recipe)) {\n res.writeHead(403, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end('{\"error\":\"unknown recipe\"}');\n return undefined;\n }\n runner.start(recipe, pickStringArgs(rawArgs));\n } else {\n runner.stop(recipe || undefined);\n }\n return runner.list();\n };\n\n const routeAction = (name: 'start' | 'stop' | 'restart' | 'clear') => {\n ctx.guardedRoute(`/__just/${name}`, ((req, res) => handleAction(req, res, name)) satisfies RouteHandler);\n };\n routeAction('start');\n routeAction('stop');\n routeAction('restart');\n routeAction('clear');\n },\n});\n","import { spawn, execFile, type ChildProcess } from 'node:child_process';\nimport iconv from 'iconv-lite';\nimport { parseRecipeSignature, buildJustArgv } from './just-recipe-params.js';\n\nexport interface Recipe { name: string; description: string; }\nexport interface RecipeWithParams extends Recipe { params: string[] }\nexport type TaskStatus = 'running' | 'exited';\nexport interface TaskInfo { recipe: string; state: TaskStatus; code: number | null; startedAt: number; signal?: string }\n\nexport type JustEvent =\n | { type: 'log'; recipe: string; text: string }\n | { type: 'clear'; recipe: string }\n | { type: 'state'; recipe: string; state: TaskStatus; code: number | null; startedAt?: number; signal?: string };\n\ninterface Task {\n recipe: string;\n child: ChildProcess | null;\n state: TaskStatus;\n code: number | null;\n signal?: string;\n startedAt: number;\n buffer: string[];\n pending: Buffer; // 字节级行缓冲:块缓冲输出会在行中间断开,攒到 \\n(0x0A)才切行——多字节字符不会跨行界,解码只发生在完整行上\n}\n\nconst MAX_BUFFER = 1000;\n\nconst utf8Strict = new TextDecoder('utf-8', { fatal: true });\n\n/**\n * 逐行解码:先 UTF-8 严格解码,失败回退 GBK(Windows 码页输出)。\n * 行界按 0x0A 字节切分是安全的:UTF-8 续字节 ≥ 0x80、GBK 尾字节 0x40–0xFE,均不含 0x0A。\n */\nfunction decodeLine(buf: Buffer): string {\n try {\n return utf8Strict.decode(buf);\n } catch {\n return iconv.decode(buf, 'gbk');\n }\n}\n\n/** 多任务并发 runner:每个 recipe 独立进程/日志/状态,同名 start 即重启,互不影响 */\nexport class JustRunner {\n private cwd: string;\n private tasks = new Map<string, Task>();\n private clients = new Set<(ev: JustEvent) => void>();\n private recipesCache: Recipe[] | null = null;\n /** recipe 参数清单进程内缓存(含失败空数组),避免反复 just --show 探测 */\n private paramsCache = new Map<string, string[]>();\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 /** 懒解析单 recipe 参数:just --show 输出中首个可解析签名行(跳过 recipe 上方注释/空行)→ 参数名;失败记空数组并缓存 */\n recipeParams(name: string): Promise<string[]> {\n const hit = this.paramsCache.get(name);\n if (hit) return Promise.resolve(hit);\n return new Promise((resolve) => {\n execFile('just', ['--show', name], { cwd: this.cwd, maxBuffer: 1 << 20, timeout: 8000 }, (err, stdout) => {\n const sig = err ? null : stdout.split(/\\r?\\n/).map(l => parseRecipeSignature(l)).find(Boolean) ?? null;\n const params = sig?.params ?? [];\n this.paramsCache.set(name, params);\n resolve(params);\n });\n });\n }\n\n /** recipes 列表附参数清单(参数探测逐 recipe 并发,进程内缓存后零开销) */\n async recipesWithParams(): Promise<RecipeWithParams[]> {\n const list = await this.recipes();\n return Promise.all(list.map(async (r) => ({ ...r, params: await this.recipeParams(r.name) })));\n }\n\n subscribe(fn: (ev: JustEvent) => void): () => void {\n this.clients.add(fn);\n // 连上即重放:全部任务的日志与状态\n for (const t of this.tasks.values()) {\n for (const text of t.buffer) fn({ type: 'log', recipe: t.recipe, text });\n fn({ type: 'state', recipe: t.recipe, state: t.state, code: t.code, startedAt: t.startedAt });\n }\n return () => this.clients.delete(fn);\n }\n\n private emit(ev: JustEvent) { for (const fn of this.clients) fn(ev); }\n\n list(): TaskInfo[] {\n return Array.from(this.tasks.values(), (t) => ({ recipe: t.recipe, state: t.state, code: t.code, startedAt: t.startedAt }));\n }\n\n /** 启动 recipe:同名先停旧进程(重启语义),不影响其他任务;调用方须先用 recipes() 校验名字;\n * args 为可选参数表,spawn 数组 argv 追加 k=v(不经 shell,特殊字符安全) */\n start(recipe: string, args?: Record<string, string>) {\n this.killOne(recipe);\n const task: Task = { recipe, child: null, state: 'running', code: null, startedAt: Date.now(), buffer: [], pending: Buffer.alloc(0) };\n this.tasks.set(recipe, task);\n this.emit({ type: 'clear', recipe }); // 广播清屏:同步清掉该任务上一轮残留日志\n this.emit({ type: 'state', recipe, state: 'running', code: null, startedAt: task.startedAt });\n const child = spawn('just', buildJustArgv(recipe, args), {\n cwd: this.cwd,\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 task.child = child;\n // 身份守卫:同名重启后旧进程的迟到输出/退出不得污染新任务(闭包 task 是旧对象时静默丢弃)\n const isStale = () => this.tasks.get(recipe) !== task;\n const push = (d: Buffer) => {\n if (isStale()) return;\n task.pending = Buffer.concat([task.pending, d]);\n let idx: number;\n while ((idx = task.pending.indexOf(0x0a)) >= 0) { // 字节级切行:行界 0x0A 不会落在多字节字符内部\n const line = task.pending.subarray(0, idx + 1);\n task.pending = task.pending.subarray(idx + 1);\n this.pushLine(task, decodeLine(line));\n }\n // 无 \\n 的尾巴留在字节缓冲,等下个 chunk(块缓冲输出会在行中断开,不能当独立行;半个多字节字符也在此安全等待)\n };\n child.stdout?.on('data', push);\n child.stderr?.on('data', push);\n child.on('error', (err) => { this.pushLine(task, `[zdashboard] spawn error: ${err.message}\\n`); });\n child.on('exit', (code, signal) => {\n if (task.pending.length > 0 && !isStale()) { this.pushLine(task, decodeLine(task.pending) + '\\n'); } // flush 末尾无换行的残留(空 Buffer 为 truthy,须按 length 判)\n task.pending = Buffer.alloc(0);\n task.child = null;\n task.state = 'exited';\n task.code = code ?? 0;\n task.signal = signal ?? undefined; // 用户主动 stop 时 code=null+SIGTERM,与成功退出区分\n if (isStale()) return; // 迟到的旧进程退出,不打扰新任务状态\n this.emit({ type: 'state', recipe, state: 'exited', code: task.code, startedAt: task.startedAt, signal: task.signal });\n });\n }\n\n /** 行推送:行内 \\r 再切分为多段独立行(进度条输出降级为分段渲染);\n * \\r 空段丢弃,但整行全空仍推送一条空行(空行是日志内容,不静默丢弃) */\n private pushLine(task: Task, line: string) {\n const body = line.endsWith('\\n') ? line.slice(0, -1) : line;\n const segs = body.split('\\r').filter(Boolean);\n if (segs.length === 0) {\n this.pushSegment(task, '');\n return;\n }\n for (const seg of segs) this.pushSegment(task, seg);\n }\n\n private pushSegment(task: Task, seg: string) {\n const text = seg + '\\n';\n task.buffer.push(text);\n if (task.buffer.length > MAX_BUFFER) task.buffer.shift();\n this.emit({ type: 'log', recipe: task.recipe, text });\n }\n\n /** 停单个任务;不传 recipe 停全部 */\n stop(recipe?: string) {\n if (recipe === undefined) { for (const t of this.tasks.values()) this.killOne(t.recipe); }\n else this.killOne(recipe);\n }\n\n restart(recipe: string) {\n if (this.tasks.has(recipe)) this.start(recipe);\n }\n\n /** 清空某任务的日志缓冲并广播(真源清除,重连重放不会复活) */\n clear(recipe: string) {\n const task = this.tasks.get(recipe);\n if (!task) return;\n task.buffer = [];\n task.pending = Buffer.alloc(0);\n this.emit({ type: 'clear', recipe });\n }\n\n private killOne(recipe: string) {\n const task = this.tasks.get(recipe);\n const child = task?.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 if (task) { task.child = null; }\n }\n}\n","/**\n * just recipe 参数纯函数:签名解析(just --show 首行)与 spawn argv 拼装。\n *\n * 解析器为字符级扫描(非空白切分):默认值可含空格(`a=\"x y\"`),引号内内容不参与结构解析。\n * argv 拼装契约:数组原样传值,调用方 spawn 不得开 shell——值含空格/引号/& 时保持单元素,\n * 不经 shell 拼接即天然免疫注入与串位。\n */\n\nexport interface RecipeSignature { name: string; params: string[] }\n\nconst NAME_RE = /^[A-Za-z_][A-Za-z0-9_-]*/;\n\n/** 解析 recipe 签名行(`hello msg=\"world\":`);无冒号收尾等非法输入 → null */\nexport function parseRecipeSignature(line: string): RecipeSignature | null {\n let s = line.trim();\n if (s.startsWith('@')) s = s.slice(1).trimStart(); // private recipe 前缀\n const nameMatch = NAME_RE.exec(s);\n if (!nameMatch) return null;\n const name = nameMatch[0];\n const params: string[] = [];\n let i = name.length;\n while (true) {\n while (i < s.length && /\\s/.test(s[i])) i++;\n if (i >= s.length) return null; // 没等到收尾冒号\n if (s[i] === ':') {\n const rest = s.slice(i + 1).trim();\n if (rest === '' || rest.startsWith('#')) return { name, params };\n return null;\n }\n // 参数 token:可选 +/$ 前缀 + 参数名 + 可选 =默认值(引号内可有空格)\n let j = i;\n if (s[j] === '+' || s[j] === '$') j++;\n const pm = NAME_RE.exec(s.slice(j));\n if (!pm) return null;\n j += pm[0].length;\n if (s[j] === '=') {\n j++;\n if (s[j] === '\"' || s[j] === \"'\") {\n const quote = s[j];\n j++;\n while (j < s.length && s[j] !== quote) j++;\n if (j >= s.length) return null; // 引号未闭合\n j++;\n } else {\n while (j < s.length && !/\\s/.test(s[j]) && s[j] !== ':') j++;\n }\n }\n params.push(pm[0]);\n i = j;\n }\n}\n\n/** spawn argv:[recipe, ...k=v];args 为空/undefined 时不追加,与无参调用同形 */\nexport function buildJustArgv(recipe: string, args?: Record<string, string>): string[] {\n if (!args) return [recipe];\n return [recipe, ...Object.entries(args).map(([k, v]) => `${k}=${v}`)];\n}\n\n/** start args 白名单化:仅保留 string 值;剔除后为空或输入非对象 → undefined(请求体不携带 args) */\nexport function pickStringArgs(args: unknown): Record<string, string> | undefined {\n if (typeof args !== 'object' || args === null) return undefined;\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(args)) {\n if (typeof v === 'string') out[k] = v;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n","/**\n * 插件 SDK(server 侧):definePlugin 是插件接入宿主的唯一姿势。\n *\n * 内部自动完成 dashboard.register(manifest) 与 effect 清理注册,\n * 插件作者只面对 PluginContext 的七个通道;四种 cordis 手写姿势由此消亡。\n */\nimport type http from 'node:http';\nimport { json, guarded } from '../core/server.js';\nimport type { Context } from 'cordis';\nimport type { PluginManifest } from '../core/manifest.js';\n\n/** handler 返回非 undefined 值时由 SDK 包装为 json 响应;自行写响应则返回 undefined */\nexport type RouteHandler = (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n) => unknown | Promise<unknown>;\n\nexport type SseHandler = (res: http.ServerResponse) => (() => void) | void;\n\nexport interface PluginContext {\n /** manifest.mode 的只读镜像 */\n readonly mode: string;\n /** manifest.config 默认值合并 .zdev/dashboard.json 存储值(存储优先) */\n config<T extends Record<string, unknown> = Record<string, unknown>>(): T;\n /** 注册路由;handler 返回值自动 json 包装(200 + application/json) */\n route(path: string, handler: RouteHandler): void;\n /** 校验 x-stop-token 后执行 route 语义;缺/错 token 直接 403 */\n guardedRoute(path: string, handler: RouteHandler): void;\n sse(path: string, handler: SseHandler): void;\n static(prefix: string, dir: string): void;\n /** 广播到 SSE 频道 plugin:<mode>:<event>,客户端 usePluginData subscribe 消费 */\n broadcast(event: string, data?: unknown): void;\n onDispose(fn: () => void): void;\n}\n\ninterface CordisPluginApply {\n inject?: readonly string[];\n apply(ctx: Context, config: unknown): unknown;\n}\n\n/**\n * 定义内置/外部插件的 server 侧入口。\n * @param def.manifest 与 client defineWebPlugin 共享的同一份常量(SSOT)\n * @param def.setup 在 server/dashboard 服务就绪的上下文中执行\n */\nexport function definePlugin(def: {\n manifest: PluginManifest;\n setup(ctx: PluginContext): void;\n}): CordisPluginApply & { inject: readonly string[] } {\n const { manifest, setup } = def;\n\n return {\n inject: ['server', 'dashboard', 'reload'] as const,\n apply(this: void, ctx: Context) {\n const disposers: Array<() => void> = [];\n ctx.effect(() => () => {\n for (const fn of disposers.splice(0)) {\n try { fn(); } catch (e) {\n console.error(`[zdashboard] plugin ${manifest.mode} dispose error:`, e);\n }\n }\n });\n\n ctx.dashboard.register(manifest);\n\n /** json 包装语义与错误兜底;guardedRoute 不经此重注册路径 */\n const respondWith = (handler: RouteHandler) => async (req: http.IncomingMessage, res: http.ServerResponse) => {\n if (res.headersSent) return;\n try {\n const data = await handler(req, res);\n if (data !== undefined && !res.writableEnded) json(res, data);\n } catch (e) {\n console.error(`[zdashboard] plugin ${manifest.mode} route error:`, e);\n if (!res.headersSent) json(res, { error: 'internal' }, 500);\n }\n };\n\n const pctx: PluginContext = {\n mode: manifest.mode,\n config<T extends Record<string, unknown> = Record<string, unknown>>(): T {\n const schema = manifest.config ?? {};\n const stored = ctx.server.getPluginConfig(manifest.mode) ?? {};\n const defaults = Object.fromEntries(\n Object.entries(schema).map(([key, field]) => [key, field.default]),\n );\n return { ...defaults, ...stored } as T;\n },\n route(path: string, handler: RouteHandler): void {\n ctx.server.route(path, respondWith(handler));\n },\n guardedRoute(path: string, handler: RouteHandler): void {\n const token = () => ctx.server.stopToken;\n ctx.server.route(path, (req, res) => {\n if (!guarded(req, res, token())) return;\n void respondWith(handler)(req, res);\n });\n },\n sse(path: string, handler: SseHandler): void {\n ctx.server.sse(path, handler);\n },\n static(prefix: string, dir: string): void {\n ctx.server.static(prefix, dir);\n },\n broadcast(event: string, data?: unknown): void {\n ctx.reload?.broadcast(`plugin:${manifest.mode}:${event}`, data ?? '');\n },\n onDispose(fn: () => void): void {\n disposers.push(fn);\n },\n };\n\n setup(pctx);\n },\n };\n}\n","/**\n * 内置插件 root 注入壳(插件侧适配,不动 SDK 公共契约):\n *\n * SDK definePlugin 的 apply(ctx) 不向 setup 转发 cordis 插件 config,\n * 而六个内置插件都需要 cli 注入的 { root }。此壳在插件层捕获 config.root\n * 再调用 SDK 产出的 apply,setup 以第二参拿到 root。\n * 若 SDK 未来转发 config,此文件可整体删除。\n */\nimport type { Context } from 'cordis';\nimport { definePlugin, type PluginContext } from '../sdk/server.js';\nimport type { PluginManifest } from '../core/manifest.js';\n\nexport function defineBuiltin(def: {\n manifest: PluginManifest;\n setup(ctx: PluginContext, root: string): void;\n}) {\n let currentRoot = '';\n const inner = definePlugin({\n manifest: def.manifest,\n setup(pctx) { def.setup(pctx, currentRoot); },\n });\n\n return {\n inject: inner.inject,\n manifest: def.manifest, // cli 启动期死键剥离按 manifest 判定(config 声明/external)\n apply(ctx: Context, config: { root?: string }) {\n currentRoot = config?.root ?? '';\n inner.apply(ctx, config);\n },\n };\n}\n","/** just 插件单源:server definePlugin 与 web defineWebPlugin 共享 */\nimport type { PluginManifest } from '../../core/manifest.js';\nimport type { ParamSchema } from '../../sdk/shared.js';\n\nexport const manifest: PluginManifest = {\n mode: 'just',\n label: 'Just Runner',\n icon: '📜',\n description: 'Just 任务日志与执行',\n order: 50,\n};\n\n/** recipe:选中 recipe;task:活跃任务 id(与 recipe 同名空间) */\nexport const params: ParamSchema = [\n { name: 'recipe', label: 'Recipe', type: 'string', description: '选中的 recipe 名' },\n { name: 'task', label: '任务', type: 'string', description: '活跃任务 id' },\n];\n","/**\n * design server 侧:definePlugin 接入(约定化扫描)。\n * 恒扫 <root>/.zdev/design(zdesign 等 skill 统一产出目录,walkDir 跳过点目录扫根看不见);\n * 目录缺失 → emptyScan() 全组空数组。/__design/assets 响应形状(ScanResult)保持不变。\n * 另供只读代理 /__design/asset?path=<rel-to-.zdev/design>,viewers 由此加载资产(直取根路径必 404)。\n */\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport { MIME } from '../../core/server.js';\nimport { scanAssets, type ScanResult, type AssetType } from '../../server/design-assets.js';\nimport { defineBuiltin } from '../builtin.js';\nimport { manifest } from './manifest.js';\n\nconst ASSET_KEYS: AssetType[] = ['page', 'component', 'icon', 'token', 'md', 'video', 'audio', 'pdf', 'font', 'diagram'];\n\nfunction emptyScan(): ScanResult {\n const out = {} as ScanResult;\n for (const k of ASSET_KEYS) out[k] = [];\n return out;\n}\n\nexport const apply = defineBuiltin({\n manifest,\n setup(ctx, root) {\n ctx.route('/__design/assets', async () => {\n const designRoot = path.join(root, '.zdev', 'design');\n return fs.existsSync(designRoot) ? scanAssets(designRoot) : emptyScan();\n });\n\n // 只读资产代理:三重防御钉死任意读(字符拒绝 → join 归一化 → 前缀校验),先例 /__file-content\n ctx.route('/__design/asset', async (req, res) => {\n const rel = new URL(req.url || '/', 'http://localhost').searchParams.get('path') ?? '';\n if (!rel || rel.includes('..') || rel.includes('\\\\') || path.isAbsolute(rel)) {\n res.writeHead(400);\n res.end('bad path');\n return;\n }\n const designRoot = path.join(root, '.zdev', 'design');\n const filePath = path.join(designRoot, rel);\n if (!filePath.startsWith(designRoot + path.sep)) {\n res.writeHead(400);\n res.end('bad path');\n return;\n }\n fs.stat(filePath, (err) => {\n if (err) { res.writeHead(404); return res.end('Not found'); }\n const ct = MIME[path.extname(filePath).toLowerCase()] ?? 'application/octet-stream';\n res.writeHead(200, { 'Content-Type': ct, 'Cache-Control': 'no-cache' });\n // stat 通过后文件仍可能被删,流错误无人接会崩进程(与 core/server serveFile 同款兜底)\n const stream = fs.createReadStream(filePath);\n stream.on('error', () => { try { res.destroy(); } catch { /* 已断 */ } });\n stream.pipe(res);\n });\n });\n },\n});\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { walkDir } from './walk.js';\n\nexport type AssetType = 'page' | 'component' | 'icon' | 'token' | 'md' | 'video' | 'audio' | 'pdf' | 'font' | 'diagram';\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', '.cjs', '.mts', '.cts', '.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 | null {\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 // 图表:置于 CODE 判断前(.drawio 虽非 CODE_EXTS,显式前置防未来扩展名表收编)\n if (ext === '.excalidraw' || ext === '.drawio') return 'diagram';\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)) {\n if (TOKEN_RE.test(rel) && (ext === '.css' || ext === '.json')) return 'token';\n return null;\n }\n return null;\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, subDir = ''): ScanResult {\n const out: ScanResult = {} as ScanResult;\n const keys: AssetType[] = ['page','component','icon','token','md','video','audio','pdf','font','diagram'];\n for (const k of keys) out[k] = [];\n const SKIP = new Set(['node_modules', '.git', 'dist', 'build', 'coverage', '.next', '.cache']);\n const scanRoot = subDir ? path.join(root, subDir) : root;\n walkDir(scanRoot, { skip: SKIP, onFile: (abs, rel) => {\n const ext = path.extname(abs).toLowerCase();\n const t = categorize(rel, ext);\n if (t) out[t].push({ path: rel, name: path.basename(abs), ext, type: t });\n }});\n return out;\n}\n","/** design 插件单源:server definePlugin 与 web defineWebPlugin 共享 */\nimport type { PluginManifest } from '../../core/manifest.js';\nimport type { ParamSchema } from '../../sdk/shared.js';\n\nexport const manifest: PluginManifest = {\n mode: 'design',\n label: '设计资产',\n icon: '🎨',\n description: '设计资产分类浏览 · zdesign',\n order: 30,\n};\n\n/** type:资产类型;asset:选中资产路径;folder:资产路径过滤展示 */\nexport const params: ParamSchema = [\n { name: 'type', label: '资产类型', type: 'string', description: 'page/component/icon/token/md/video/audio/pdf/font' },\n { name: 'asset', label: '选中资产', type: 'string', description: '资产相对路径' },\n { name: 'folder', label: '当前文件夹', type: 'string', description: '限定展示的资产路径前缀' },\n];\n","/** view 插件单源:server definePlugin 与 web defineWebPlugin 共享 */\nimport type { PluginManifest } from '../../core/manifest.js';\nimport type { ParamSchema } from '../../sdk/shared.js';\n\nexport const manifest: PluginManifest = {\n mode: 'view',\n label: '项目浏览',\n icon: '👁️',\n description: 'openspec / docs / 文档预览',\n order: 20,\n};\n\n/** wt:worktree 绝对路径;file:文件相对路径;filter:树过滤词 */\nexport const params: ParamSchema = [\n { name: 'wt', label: 'Worktree 路径', type: 'string', description: 'worktree 绝对路径' },\n { name: 'file', label: '文件路径', type: 'string', description: '预览文件相对路径' },\n { name: 'filter', label: '过滤词', type: 'string', description: '文件树过滤词' },\n];\n","/**\n * view server 侧:definePlugin 接入(manifest 单源)。\n * 文件树路由 /__files 由 core/tree.ts 宿主服务提供(约定目录 ['openspec','docs'],非配置),此处仅注册 manifest。\n */\nimport { defineBuiltin } from '../builtin.js';\nimport { manifest } from './manifest.js';\n\nexport const apply = defineBuiltin({\n manifest,\n setup() { /* 路由由 core/tree.ts 承载 */ },\n});\n","/**\n * stats server 侧:definePlugin 接入(manifest 单源)。\n * /__stats/data 响应形状与迁移前保持一致。\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { execFile } from 'node:child_process';\nimport { walkDir } from '../../server/walk.js';\nimport { listWorktrees } from '../../core/worktrees.js';\nimport { defineBuiltin } from '../builtin.js';\nimport { manifest } from './manifest.js';\n\ninterface Stats {\n root: string;\n files: number;\n dirs: number;\n totalSize: number;\n byExt: { ext: string; count: number }[];\n markdown: number;\n openspec: { active: number; archived: number };\n hasJust: boolean;\n worktrees: number;\n branch?: string;\n dirty?: number;\n}\n\nconst SKIP_DIRS = new Set(['node_modules', '.git', 'dist', 'build', '.next', '.cache']);\n\nfunction execFilePromise(file: string, args: string[], opts: { cwd: string }): Promise<string> {\n return new Promise((resolve) => {\n execFile(file, args, opts, (err, stdout) => resolve(err ? '' : stdout));\n });\n}\n\nfunction scan(root: string): Stats {\n const stats: Stats = {\n root: path.basename(root),\n files: 0,\n dirs: 0,\n totalSize: 0,\n byExt: [],\n markdown: 0,\n openspec: { active: 0, archived: 0 },\n hasJust: fs.existsSync(path.join(root, 'justfile')),\n worktrees: 0,\n };\n const extMap = new Map<string, number>();\n\n const walk = (dir: string) => {\n walkDir(dir, { skip: SKIP_DIRS, onDir: () => { stats.dirs++; }, onFile: (abs) => {\n stats.files++;\n try { stats.totalSize += fs.statSync(abs).size; } catch {}\n const ext = path.extname(abs).toLowerCase() || '(无扩展名)';\n extMap.set(ext, (extMap.get(ext) ?? 0) + 1);\n if (ext === '.md' || ext === '.markdown') stats.markdown++;\n }});\n };\n walk(root);\n\n const changesDir = path.join(root, 'openspec', 'changes');\n if (fs.existsSync(changesDir)) {\n for (const ent of fs.readdirSync(changesDir, { withFileTypes: true })) {\n if (!ent.isDirectory() || ent.name.startsWith('.')) continue;\n if (ent.name === 'archive') {\n try {\n stats.openspec.archived = fs.readdirSync(path.join(changesDir, 'archive'), { withFileTypes: true })\n .filter(e => e.isDirectory() && !e.name.startsWith('.')).length;\n } catch { /* ignore */ }\n } else stats.openspec.active++;\n }\n }\n\n stats.byExt = Array.from(extMap.entries())\n .map(([ext, count]) => ({ ext, count }))\n .sort((a, b) => b.count - a.count)\n .slice(0, 10);\n return stats;\n}\n\nexport const apply = defineBuiltin({\n manifest,\n setup(ctx, root) {\n ctx.route('/__stats/data', async () => {\n const stats = scan(root);\n try {\n const wts = await listWorktrees(root);\n stats.worktrees = wts.length;\n } catch {\n stats.worktrees = 0;\n }\n try {\n const branchOut = await execFilePromise('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { cwd: root });\n stats.branch = branchOut.trim() || undefined;\n } catch { /* ignore */ }\n try {\n const statusOut = await execFilePromise('git', ['status', '--porcelain'], { cwd: root });\n stats.dirty = statusOut.trim() ? statusOut.trim().split('\\n').length : 0;\n } catch { /* ignore */ }\n return stats;\n });\n },\n});\n","/** stats 插件单源:server definePlugin 与 web defineWebPlugin 共享 */\nimport type { PluginManifest } from '../../core/manifest.js';\nimport type { ParamSchema } from '../../sdk/shared.js';\n\nexport const manifest: PluginManifest = {\n mode: 'stats',\n label: '项目统计',\n icon: '📊',\n description: '项目文件统计 · 扫描生成',\n order: 10,\n};\n\n/** card:钻取来源(worktree/dirty),view 侧读取后高亮 */\nexport const params: ParamSchema = [\n { name: 'card', label: '钻取来源', type: 'string', description: '钻取来源(worktree/dirty),view 侧读取后高亮' },\n];\n"],"mappings":"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","names":["path","fs","fileURLToPath","fs","path","fs","path","path","fs","execFile","execFile","path","fs","err","fp","fs","Service","fs","path","fs","path","path","fs","execFile","apply","Service","Service","manifest","execFile","execFile","execFile","manifest","path","apply","execFile","path","fs","path","path","manifest","apply","manifest","path","fs","manifest","apply","manifest","fs","path","execFile","manifest","execFile","path","fs","apply","manifest","__dirname","path","fileURLToPath","apply","fs"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zdashboard",
3
- "version": "2.12.2",
3
+ "version": "2.13.0",
4
4
  "description": "ZCode skill dashboard platform — pluggable viewers for zdesign/zview/zreview/zgoal",
5
5
  "type": "module",
6
6
  "bin": {