zdashboard 2.8.4 → 2.8.6

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.
Files changed (38) hide show
  1. package/dist/cli.js +520 -292
  2. package/dist/cli.js.map +1 -1
  3. package/dist/web/assets/CodeViewer-_jAxbWVL.js +10 -0
  4. package/dist/web/assets/{FileIcon-1KBdrfw3.js → FileIcon-68etP2t6.js} +1 -1
  5. package/dist/web/assets/{FilterPills-CCubROoX.js → FilterPills-DGfzMpn_.js} +1 -1
  6. package/dist/web/assets/ImageViewer-ChZdzYPf.js +298 -0
  7. package/dist/web/assets/{Sidebar-DE0UBp9b.js → Sidebar-D83uLTNy.js} +1 -1
  8. package/dist/web/assets/{Sidebar-D4sJtPI_.js → Sidebar-N0HiMJRK.js} +1 -1
  9. package/dist/web/assets/Workspace-BE7p2hNz.js +1 -0
  10. package/dist/web/assets/Workspace-BpSq60xh.js +1 -0
  11. package/dist/web/assets/{Workspace-CvG5lIPT.js → Workspace-DW8xX3Tg.js} +1 -1
  12. package/dist/web/assets/Workspace-DjL1fdji.js +2 -0
  13. package/dist/web/assets/Workspace-DrN9--Je.js +1 -0
  14. package/dist/web/assets/index-DH1Mqw-g.css +1 -0
  15. package/dist/web/assets/{index-Co7MWSFf.js → index-D_uh-zkI.js} +3 -3
  16. package/dist/web/assets/{usePluginData-IoRqReIJ.js → usePluginData-Bk2M7LNj.js} +1 -1
  17. package/dist/web/assets/{web-BZSTgldm.js → web-BZukfmmT.js} +2 -2
  18. package/dist/web/assets/{web-DOEmlI8d.js → web-CEB9kTEr.js} +2 -2
  19. package/dist/web/assets/web-CGvrDSNo.js +2 -0
  20. package/dist/web/assets/{web-DxbVzGf3.js → web-CLKkH6eO.js} +2 -2
  21. package/dist/web/assets/web-CbW9uGDV.js +2 -0
  22. package/dist/web/index.html +2 -2
  23. package/package.json +1 -1
  24. package/dist/web/assets/BatchView-pClKtVa8.js +0 -2
  25. package/dist/web/assets/CheckpointViewer-CAbXbMti.js +0 -1
  26. package/dist/web/assets/CodeViewer-Cs0mG1h6.js +0 -279
  27. package/dist/web/assets/DependencyGraph-Czdg00AM.js +0 -1
  28. package/dist/web/assets/ProgressBar-DVfldtzq.js +0 -1
  29. package/dist/web/assets/SingleChangeView-BYcaGOyR.js +0 -1
  30. package/dist/web/assets/ViewHeader-DPfbaJmK.js +0 -1
  31. package/dist/web/assets/Workspace-B7MhdnwY.js +0 -2
  32. package/dist/web/assets/Workspace-CAcrVL-m.js +0 -1
  33. package/dist/web/assets/Workspace-DWHHR42N.js +0 -1
  34. package/dist/web/assets/Workspace-cXLWoMNL.js +0 -1
  35. package/dist/web/assets/index-CwS-KyOV.css +0 -1
  36. package/dist/web/assets/index-D6EJRHBV.js +0 -29
  37. package/dist/web/assets/web-CX1FEFxC.js +0 -2
  38. package/dist/web/assets/web-DLwxO4fO.js +0 -2
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/server/detect.ts","../src/core/server.ts","../package.json","../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/server/just-runner.ts","../src/sdk/server.ts","../src/plugins/builtin.ts","../src/plugins/just/manifest.ts","../src/plugins/just/index.ts","../src/plugins/apply/scan.ts","../src/plugins/apply/parse-tasks.ts","../src/plugins/apply/batch.ts","../src/plugins/apply/manifest.ts","../src/plugins/apply/index.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 { 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 applyApply } from './plugins/apply/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 const existing = await findReusable(root);\n if (existing && !args.restart) {\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 ? existing : null;\n if (oldRecord) {\n console.log(`[zdashboard] --restart:停止旧实例 pid=${oldRecord.pid}`);\n await stopInstance(oldRecord);\n }\n\n const appDir = path.resolve(__dirname, 'web');\n\n // built-in plugins:统一数组注册(未来迁移为 definePlugin 产出后无需改动此处)\n // apply-batch 已并入 apply(mode apply,view=batch Tab 只读驾驶舱),见 2026-08-28-apply-merge-progress\n const BUILTIN_PLUGINS = [statsApply, justApply, applyApply, 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","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 '.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/** 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 fs.stat(filePath, (err, stat) => {\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\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) { res.writeHead(404); return res.end('Not found'); }\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) { res.writeHead(403); return res.end('Forbidden'); }\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) { res.writeHead(403); return res.end('Forbidden'); }\n return this.serveFile(fp, req, res, true);\n } catch (e) {\n try { res.writeHead(400); res.end('bad request'); } 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","{\n \"name\": \"zdashboard\",\n \"version\": \"2.8.4\",\n \"description\": \"ZCode skill dashboard platform — pluggable viewers for zdesign/zview/zreview/zgoal\",\n \"type\": \"module\",\n \"bin\": {\n \"zdashboard\": \"./dist/cli.js\"\n },\n \"files\": [\n \"dist\"\n ],\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"dev\": \"vite\",\n \"build\": \"tsup && vite build\",\n \"build:web\": \"vite build\",\n \"build:node\": \"tsup\",\n \"start\": \"node dist/cli.js\",\n \"test\": \"vitest run\",\n \"typecheck\": \"tsc --noEmit\",\n \"test:coverage\": \"vitest run --coverage\",\n \"preview\": \"vite preview\"\n },\n \"dependencies\": {\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';\n\nexport interface InstanceRecord {\n pid: number;\n port: number;\n root: string;\n startedAt: 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 };\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\nexport async function verifyRoot(port: number, root: string): Promise<boolean> {\n try {\n const res = await fetchWithTimeout(`http://127.0.0.1:${port}/__config`);\n if (res.status !== 200) return false;\n const body = await res.json();\n if (typeof body.root !== 'string') return false;\n return body.root === root;\n } catch {\n return false;\n }\n}\n\nexport async function findReusable(root: string): Promise<InstanceRecord | null> {\n const rec = readRecord(root);\n if (!rec) return null;\n if (!isAlive(rec.pid)) return null;\n if (!(await verifyRoot(rec.port, root))) return null;\n return 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}\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 dirs = Array.isArray(scanDirs) ? scanDirs.filter((d) => typeof d === 'string' && d) : [];\n for (const dir of dirs) {\n const dirPath = path.join(root, dir);\n if (!fs.existsSync(dirPath)) continue;\n const paths: string[] = [];\n walkDir(dirPath, { maxDepth: 4, 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 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, 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 if (ent.name.startsWith('.')) 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 根下的固定扫描目录,非用户可配 */\nconst CONVENTION_SCAN_DIRS = ['openspec', 'docs'] as const;\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]);\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","import { spawn, execFile, type ChildProcess } from 'node:child_process';\nimport iconv from 'iconv-lite';\n\nexport interface Recipe { name: string; description: 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\n constructor(cwd: string) { this.cwd = cwd; }\n\n recipes(): Promise<Recipe[]> {\n if (this.recipesCache) return Promise.resolve(this.recipesCache);\n return new Promise((resolve) => {\n execFile('just', ['--list', '--unsorted'], { cwd: this.cwd, maxBuffer: 1 << 20, timeout: 8000 }, (err, stdout) => {\n if (err) { resolve([]); return; }\n const out: Recipe[] = [];\n const seen = new Set<string>();\n for (const line of stdout.split(/\\r?\\n/).slice(1)) { // 跳过 \"Available recipes:\"\n const trimmed = line.trim();\n if (!trimmed) continue;\n const hashIdx = trimmed.indexOf('#');\n const sig = (hashIdx >= 0 ? trimmed.slice(0, hashIdx) : trimmed).trim();\n if (!sig) continue;\n const name = sig.split(/\\s+/)[0]; // \"hello msg=...\" -> \"hello\"\n if (seen.has(name)) continue;\n seen.add(name);\n out.push({ name, description: hashIdx >= 0 ? trimmed.slice(hashIdx + 1).trim() : '' });\n }\n this.recipesCache = out;\n resolve(out);\n });\n });\n }\n\n subscribe(fn: (ev: JustEvent) => void): () => void {\n this.clients.add(fn);\n // 连上即重放:全部任务的日志与状态\n for (const 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 start(recipe: 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', [recipe], {\n cwd: this.cwd,\n shell: true,\n env: {\n ...process.env,\n FORCE_COLOR: '1', // node 生态(chalk 等)\n // maven 检测非 tty 会关颜色;经 MAVEN_OPTS 强制开(保留用户已有值)\n MAVEN_OPTS: `${process.env.MAVEN_OPTS ?? ''} -Dstyle.color=always`.trim(),\n CI: '',\n },\n });\n 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 private pushLine(task: Task, line: string) {\n task.buffer.push(line);\n if (task.buffer.length > MAX_BUFFER) task.buffer.shift();\n this.emit({ type: 'log', recipe: task.recipe, text: line });\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 * 插件 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 * 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 { JustRunner } from '../../server/just-runner.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.recipes();\n } catch {\n return [];\n }\n });\n\n ctx.route('/__just/tasks', async () => runner.list());\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 即重启);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 try { recipe = JSON.parse(body || '{}').recipe; } 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);\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 fs from 'node:fs';\nimport path from 'node:path';\nimport { countTasks } from './parse-tasks.js';\n\nexport interface ChangeSummary {\n name: string;\n path: string;\n total: number;\n done: number;\n hasProposal: boolean;\n hasDesign: boolean;\n inWorktree: boolean;\n}\n\nexport interface ChangeDetail extends ChangeSummary {\n proposal?: string;\n design?: string;\n tasks: string;\n dependsOn: string[];\n hasTestStrategy: boolean;\n}\n\nfunction readText(p: string): string {\n try { return fs.readFileSync(p, 'utf8'); } catch { return ''; }\n}\n\nfunction worktreeDir(root: string, name: string): string {\n return path.join(root, '.zworktree', name);\n}\n\nfunction changeDir(root: string, name: string): string {\n return path.join(root, 'openspec', 'changes', name);\n}\n\nfunction parseDependsOn(proposal: string): string[] {\n const deps: string[] = [];\n // 提取 \"## 依赖\" 节:紧跟该标题的列表行\n const m = proposal.match(/^##\\s+依赖\\s*\\n([\\s\\S]*?)(?:\\n#{1,6}\\s|\\n---\\s*\\n|$)/i);\n if (!m) return deps;\n for (const line of m[1].split('\\n')) {\n // 仅收集零缩进的一级条目(/^-/),子级列表(缩进 -)不算依赖名\n if (!/^-\\s+/.test(line)) continue;\n const name = line.replace(/^-\\s+/, '').trim();\n if (name) deps.push(name);\n }\n return deps;\n}\n\nexport function scanApplyChanges(root: string): ChangeSummary[] {\n const changesDir = path.join(root, 'openspec', 'changes');\n if (!fs.existsSync(changesDir)) return [];\n const out: ChangeSummary[] = [];\n for (const ent of fs.readdirSync(changesDir, { withFileTypes: true })) {\n if (!ent.isDirectory() || ent.name.startsWith('.') || ent.name === 'archive') continue;\n const wt = worktreeDir(root, ent.name);\n const tasks = readText(path.join(wt, 'openspec', 'changes', ent.name, 'tasks.md'));\n if (!tasks) {\n const fallback = readText(path.join(changesDir, ent.name, 'tasks.md'));\n if (fallback) {\n const { total, done } = countTasks(fallback);\n const wtChange = path.join(wt, 'openspec', 'changes', ent.name);\n const mainChange = path.join(changesDir, ent.name);\n out.push({\n name: ent.name,\n path: `openspec/changes/${ent.name}`,\n total,\n done,\n hasProposal: fs.existsSync(path.join(wtChange, 'proposal.md')) || fs.existsSync(path.join(mainChange, 'proposal.md')),\n hasDesign: fs.existsSync(path.join(wtChange, 'design.md')) || fs.existsSync(path.join(mainChange, 'design.md')),\n // worktree 目录存在即算执行中(tasks.md 可能尚未落盘)\n inWorktree: fs.existsSync(wtChange),\n });\n }\n } else {\n const { total, done } = countTasks(tasks);\n const wtChange = path.join(wt, 'openspec', 'changes', ent.name);\n const mainChange = path.join(changesDir, ent.name);\n out.push({\n name: ent.name,\n path: `openspec/changes/${ent.name}`,\n total,\n done,\n // 任一侧存在即算(详情读取是 worktree 优先、主目录兜底,列表标记保持一致)\n hasProposal: fs.existsSync(path.join(wtChange, 'proposal.md')) || fs.existsSync(path.join(mainChange, 'proposal.md')),\n hasDesign: fs.existsSync(path.join(wtChange, 'design.md')) || fs.existsSync(path.join(mainChange, 'design.md')),\n inWorktree: true,\n });\n }\n }\n out.sort((a, b) => a.name.localeCompare(b.name));\n return out;\n}\n\nexport function readApplyChange(root: string, name: string): ChangeDetail {\n const wt = worktreeDir(root, name);\n const mainChangeDir = changeDir(root, name);\n\n // 优先 worktree 内;回退主目录\n const proposalFrom = fs.existsSync(path.join(wt, 'openspec', 'changes', name, 'proposal.md'))\n ? path.join(wt, 'openspec', 'changes', name, 'proposal.md')\n : path.join(mainChangeDir, 'proposal.md');\n const designFrom = fs.existsSync(path.join(wt, 'openspec', 'changes', name, 'design.md'))\n ? path.join(wt, 'openspec', 'changes', name, 'design.md')\n : path.join(mainChangeDir, 'design.md');\n const tasksFrom = fs.existsSync(path.join(wt, 'openspec', 'changes', name, 'tasks.md'))\n ? path.join(wt, 'openspec', 'changes', name, 'tasks.md')\n : path.join(mainChangeDir, 'tasks.md');\n\n const proposal = readText(proposalFrom);\n const design = readText(designFrom);\n const tasks = readText(tasksFrom);\n const { total, done } = countTasks(tasks);\n const inWorktree = fs.existsSync(path.join(wt, 'openspec', 'changes', name));\n const dependsOn = parseDependsOn(proposal);\n const hasTestStrategy = /^##\\s+测试策略\\s*$/m.test(design);\n\n return {\n name,\n path: `openspec/changes/${name}`,\n total,\n done,\n hasProposal: !!proposal,\n hasDesign: !!design,\n inWorktree,\n proposal,\n design,\n tasks,\n dependsOn,\n hasTestStrategy,\n };\n}\n","const TASK_RE = /^\\s*-\\s*\\[([ xX])\\]\\s*(.*)$/;\n\n/** zskills/zapply 约定:任务行首的 🔧[人工] 前缀标记(人工项不计完成度) */\nconst MANUAL_PREFIX = '🔧[人工]';\n\nexport interface ParsedTask {\n text: string\n checked: boolean\n /** 行首 🔧[人工] 标记的人工条目 */\n manual?: boolean\n}\n\nexport function parseTasks(md: string): ParsedTask[] {\n // 按可选 \\r 拆行:CRLF 文件(\\r 是正则行终止符,$ 无法锚定其前)否则全量失配\n return md\n .split(/\\r?\\n/)\n .filter((l) => TASK_RE.test(l))\n .map((l) => {\n const m = l.match(TASK_RE);\n const text = (m?.[2] ?? l).trim();\n return { text, checked: m?.[1] !== ' ', manual: text.startsWith(MANUAL_PREFIX) };\n });\n}\n\nexport function countTasks(md: string): { total: number; done: number; manual: number } {\n const tasks = parseTasks(md);\n const normal = tasks.filter((t) => !t.manual);\n return {\n total: normal.length,\n done: normal.filter((t) => t.checked).length,\n manual: tasks.length - normal.length,\n };\n}\n","/**\n * 批量执行只读读取器(zapply 新约定):读 `.zdev/apply/CURRENT` 指针 →\n * `.zdev/apply/runs/<runId>/state.json` 快照。无状态投影,不持缓存——\n * state.json 由 zapply skill 外部写入,文件小、读廉价,缓存失效复杂度不值得。\n *\n * 空态语义(design.md 契约):无 CURRENT / runId 非法 → { run: null, state: null };\n * CURRENT 有效但 state.json 缺失或 JSON 损坏 → { run: { id }, state: null },前端空态引导。\n * BatchState 接口形状与旧 ApplyBatchStore(.zapply/batch-state.json 时代)完全一致。\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nexport interface BatchChange {\n name: string;\n path: string;\n status: 'pending' | 'running' | 'completed' | 'failed' | 'parked' | 'skipped';\n priority: number;\n risk: 'low' | 'medium' | 'high' | 'unknown';\n dependencies: string[];\n estimatedDuration: number;\n batchIndex: number;\n checkpoint?: {\n currentTaskIndex: number;\n totalTasks: number;\n completedTasks: number;\n currentTask: string;\n };\n error?: string;\n retryCount: number;\n startedAt?: string;\n completedAt?: string;\n}\n\nexport interface BatchLog {\n timestamp: string;\n level: 'info' | 'warn' | 'error' | 'success';\n message: string;\n changeName?: string;\n}\n\nexport interface BatchConflict {\n changeA: string;\n changeB: string;\n files: string[];\n resolution: 'serialize' | 'merge' | 'ignore';\n}\n\nexport interface BatchState {\n version: string;\n status: 'idle' | 'analyzing' | 'pending-approval' | 'running' | 'paused' | 'completed' | 'failed';\n changes: BatchChange[];\n batches: {\n index: number;\n changeNames: string[];\n status: 'pending' | 'running' | 'completed' | 'failed';\n startedAt?: string;\n completedAt?: string;\n }[];\n currentBatchIndex: number;\n parallelism: number;\n logs: BatchLog[];\n conflicts: BatchConflict[];\n /** 战线别名(zskills 0.6.0 可选字段,并行战线时标识本 run;缺失/空则前端不展示) */\n front?: string;\n createdAt: string;\n updatedAt: string;\n}\n\n/** 活动 run 指针(只读快照引用) */\nexport interface BatchRunRef {\n id: string;\n}\n\n/** GET /__apply/batch 响应形状 */\nexport interface BatchSnapshot {\n run: BatchRunRef | null;\n state: BatchState | null;\n}\n\n/** GET /__apply/batch/graph 响应形状(与旧 /__apply-batch/graph 一致) */\nexport interface BatchGraph {\n changes: Array<Pick<BatchChange, 'name' | 'status' | 'dependencies' | 'batchIndex'>>;\n batches: BatchState['batches'];\n conflicts: BatchConflict[];\n}\n\n/** runId 仅允许字母/数字/连字符(同时阻断路径穿越);与 zapply 生成约定一致 */\nconst RUN_ID_PATTERN = /^[A-Za-z0-9-]+$/;\n\n/** BatchState 必须是普通对象:数组/原始值放行会让投影层 state.changes.map 抛 TypeError */\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\n\nfunction readText(p: string): string | null {\n try {\n return fs.readFileSync(p, 'utf8');\n } catch {\n return null;\n }\n}\n\n/** 读活动 run 指针与状态快照;任何缺失/非法分支均降级为空态而非抛错。\n * explicitRun(多战线寻址):先过同一 RUN_ID_PATTERN,非法则忽略回退 CURRENT;\n * 合法则跳过 CURRENT 直接读 runs/<runId>/state.json(缺失/损坏 → { run: { id }, state: null })。 */\nexport function readBatchState(root: string, explicitRun?: string): BatchSnapshot {\n const applyDir = path.join(root, '.zdev', 'apply');\n const requested = explicitRun?.trim() ?? '';\n const runId = requested && RUN_ID_PATTERN.test(requested)\n ? requested\n : (readText(path.join(applyDir, 'CURRENT'))?.trim() ?? '');\n if (!runId || !RUN_ID_PATTERN.test(runId)) {\n return { run: null, state: null };\n }\n const parsed: unknown = (() => {\n const text = readText(path.join(applyDir, 'runs', runId, 'state.json'));\n if (text == null) return null;\n try {\n return JSON.parse(text);\n } catch {\n return null;\n }\n })();\n if (!isPlainObject(parsed)) {\n return { run: { id: runId }, state: null };\n }\n // 形状守卫已确认普通对象;字段级结构由消费方容忍(外部写入,无 schema 校验层)\n return { run: { id: runId }, state: parsed as unknown as BatchState };\n}\n\n/** batch state → 依赖图投影;state 缺失时给三数组空投影(前端空态直接消费) */\nexport function projectGraph(state: BatchState | null): BatchGraph {\n if (!state) {\n return { changes: [], batches: [], conflicts: [] };\n }\n // 字段容忍:state 由 zapply skill 外部写入、无 schema 校验层(zskills 0.6.0 中 conflicts 非必填),\n // changes/batches/conflicts 及 change.dependencies 缺失/非数组一律投影为空数组而非抛错。\n const rawChanges: unknown = state.changes;\n const rawBatches: unknown = state.batches;\n const rawConflicts: unknown = state.conflicts;\n return {\n changes: (Array.isArray(rawChanges) ? rawChanges : []).map((c: BatchChange) => ({\n name: c.name,\n status: c.status,\n dependencies: Array.isArray(c?.dependencies) ? c.dependencies : [],\n batchIndex: c.batchIndex,\n })),\n batches: Array.isArray(rawBatches) ? rawBatches : [],\n conflicts: Array.isArray(rawConflicts) ? rawConflicts : [],\n };\n}\n\n/** 日志尾窗口:GET /__apply/batch/logs 只回最近 N 条(与旧行为一致) */\nexport const BATCH_LOGS_TAIL = 100;\n\nexport function tailLogs(state: BatchState | null): BatchLog[] {\n const logs = state?.logs;\n return (Array.isArray(logs) ? logs : []).slice(-BATCH_LOGS_TAIL);\n}\n\n/** 读活动 run 的 plan.md 文本;缺失返回 null(路由层转 404,前端空态承接) */\nexport function readBatchPlan(root: string, runId: string): string | null {\n return readText(path.join(root, '.zdev', 'apply', 'runs', runId, 'plan.md'));\n}\n","/** apply 插件单源: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: 'apply',\n label: '执行进度',\n icon: '⚙️',\n description: 'OpenSpec 执行进度 · zapply 单 change 与批量',\n order: 40,\n};\n\n/** change:单 change 视图选中的 change 名;view:single/batch Tab;sel:批量视图选中 change 名;\n * run:批量驾驶舱显式 runId(多战线寻址,缺省读 CURRENT) */\nexport const params: ParamSchema = [\n { name: 'change', label: 'Change', type: 'string', description: 'openspec change 名' },\n { name: 'view', label: '视图', type: 'string', description: 'single/batch(缺省 single)' },\n { name: 'sel', label: '选中 change', type: 'string', description: '批量驾驶舱选中的 change 名' },\n { name: 'run', label: 'Run ID', type: 'string', description: '显式 runId(多战线时寻址),缺省读 CURRENT' },\n];\n","/**\n * apply server 侧:definePlugin 接入(manifest 单源)。\n * 单 change 读路由(/__apply、/__apply/change)与批量只读路由(/__apply/batch*)。\n * 批量只读:状态文件由 zapply skill 写入,dashboard 不提供任何写路由(避免双写冲突)。\n * 响应形状:错误手写 400/404 + {error},不经 SDK 500 兜底(与既有契约一致)。\n */\nimport type http from 'node:http';\nimport { scanApplyChanges, readApplyChange } from './scan.js';\nimport { readBatchState, projectGraph, tailLogs, readBatchPlan } from './batch.js';\nimport { defineBuiltin } from '../builtin.js';\nimport { manifest } from './manifest.js';\n\n/** 错误响应:写状态码 + {error: 具体信息},返回 undefined 短路 SDK json 包装 */\nfunction errorResponse(res: http.ServerResponse, status: number, msg: string): undefined {\n res.writeHead(status, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: msg }));\n return undefined;\n}\n\nexport const apply = defineBuiltin({\n manifest,\n setup(ctx, root) {\n ctx.route('/__apply', async () => scanApplyChanges(root));\n\n ctx.route('/__apply/change', async (req, res) => {\n const url = new URL(req.url || '', 'http://x');\n const name = url.searchParams.get('name');\n const bad = (msg: string) => errorResponse(res, 400, msg);\n if (!name) return bad('missing name');\n if (name.includes('..') || name.includes('/') || name.includes('\\\\')) return bad('invalid name');\n try {\n return readApplyChange(root, name);\n } catch (e) {\n return bad(e instanceof Error ? e.message : 'unknown error');\n }\n });\n\n // ── 批量驾驶舱只读路由(数据源 .zdev/apply/runs/<runId>/) ──\n // run query 显式寻址(多战线):透传给 readBatchState,非法/缺省回退 CURRENT\n const queryRun = (req: http.IncomingMessage): string | undefined =>\n new URL(req.url || '', 'http://x').searchParams.get('run') ?? undefined;\n\n ctx.route('/__apply/batch', async (req) => readBatchState(root, queryRun(req)));\n\n ctx.route('/__apply/batch/graph', async (req) => projectGraph(readBatchState(root, queryRun(req)).state));\n\n ctx.route('/__apply/batch/logs', async (req) => tailLogs(readBatchState(root, queryRun(req)).state));\n\n ctx.route('/__apply/batch/plan', async (req, res) => {\n const snap = readBatchState(root, queryRun(req));\n const plan = snap.run ? readBatchPlan(root, snap.run.id) : null;\n if (plan == null) return errorResponse(res, 404, 'plan not found');\n return { plan };\n });\n },\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'];\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';\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 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'];\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","execFile","execFile","path","fs","err","fp","fs","Service","fs","path","fs","path","path","fs","execFile","apply","Service","Service","manifest","execFile","manifest","path","apply","fs","path","fs","path","fs","path","readText","manifest","apply","manifest","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","../src/server/detect.ts","../src/core/server.ts","../package.json","../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/server/just-runner.ts","../src/sdk/server.ts","../src/plugins/builtin.ts","../src/plugins/just/manifest.ts","../src/plugins/just/index.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","../src/plugins/market/manifest.ts","../src/plugins/market/sources/logotypes.ts","../src/plugins/market/sources/motions.ts","../src/plugins/market/sources/inspirations.ts","../src/plugins/market/sources/index.ts","../src/plugins/market/index.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 { 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';\nimport { apply as marketApply } from './plugins/market/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 const existing = await findReusable(root);\n if (existing && !args.restart) {\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 ? existing : null;\n if (oldRecord) {\n console.log(`[zdashboard] --restart:停止旧实例 pid=${oldRecord.pid}`);\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, marketApply];\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","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 '.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/** 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 fs.stat(filePath, (err, stat) => {\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\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) { res.writeHead(404); return res.end('Not found'); }\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) { res.writeHead(403); return res.end('Forbidden'); }\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) { res.writeHead(403); return res.end('Forbidden'); }\n return this.serveFile(fp, req, res, true);\n } catch (e) {\n try { res.writeHead(400); res.end('bad request'); } 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","{\n \"name\": \"zdashboard\",\n \"version\": \"2.8.6\",\n \"description\": \"ZCode skill dashboard platform — pluggable viewers for zdesign/zview/zreview/zgoal\",\n \"type\": \"module\",\n \"bin\": {\n \"zdashboard\": \"./dist/cli.js\"\n },\n \"files\": [\n \"dist\"\n ],\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"dev\": \"vite\",\n \"build\": \"tsup && vite build\",\n \"build:web\": \"vite build\",\n \"build:node\": \"tsup\",\n \"start\": \"node dist/cli.js\",\n \"test\": \"vitest run\",\n \"typecheck\": \"tsc --noEmit\",\n \"test:coverage\": \"vitest run --coverage\",\n \"preview\": \"vite preview\"\n },\n \"dependencies\": {\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';\n\nexport interface InstanceRecord {\n pid: number;\n port: number;\n root: string;\n startedAt: 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 };\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\nexport async function verifyRoot(port: number, root: string): Promise<boolean> {\n try {\n const res = await fetchWithTimeout(`http://127.0.0.1:${port}/__config`);\n if (res.status !== 200) return false;\n const body = await res.json();\n if (typeof body.root !== 'string') return false;\n return body.root === root;\n } catch {\n return false;\n }\n}\n\nexport async function findReusable(root: string): Promise<InstanceRecord | null> {\n const rec = readRecord(root);\n if (!rec) return null;\n if (!isAlive(rec.pid)) return null;\n if (!(await verifyRoot(rec.port, root))) return null;\n return 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'] 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","import { spawn, execFile, type ChildProcess } from 'node:child_process';\nimport iconv from 'iconv-lite';\n\nexport interface Recipe { name: string; description: 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\n constructor(cwd: string) { this.cwd = cwd; }\n\n recipes(): Promise<Recipe[]> {\n if (this.recipesCache) return Promise.resolve(this.recipesCache);\n return new Promise((resolve) => {\n execFile('just', ['--list', '--unsorted'], { cwd: this.cwd, maxBuffer: 1 << 20, timeout: 8000 }, (err, stdout) => {\n if (err) { resolve([]); return; }\n const out: Recipe[] = [];\n const seen = new Set<string>();\n for (const line of stdout.split(/\\r?\\n/).slice(1)) { // 跳过 \"Available recipes:\"\n const trimmed = line.trim();\n if (!trimmed) continue;\n const hashIdx = trimmed.indexOf('#');\n const sig = (hashIdx >= 0 ? trimmed.slice(0, hashIdx) : trimmed).trim();\n if (!sig) continue;\n const name = sig.split(/\\s+/)[0]; // \"hello msg=...\" -> \"hello\"\n if (seen.has(name)) continue;\n seen.add(name);\n out.push({ name, description: hashIdx >= 0 ? trimmed.slice(hashIdx + 1).trim() : '' });\n }\n this.recipesCache = out;\n resolve(out);\n });\n });\n }\n\n subscribe(fn: (ev: JustEvent) => void): () => void {\n this.clients.add(fn);\n // 连上即重放:全部任务的日志与状态\n for (const 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 start(recipe: 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', [recipe], {\n cwd: this.cwd,\n shell: true,\n env: {\n ...process.env,\n FORCE_COLOR: '1', // node 生态(chalk 等)\n // maven 检测非 tty 会关颜色;经 MAVEN_OPTS 强制开(保留用户已有值)\n MAVEN_OPTS: `${process.env.MAVEN_OPTS ?? ''} -Dstyle.color=always`.trim(),\n CI: '',\n },\n });\n 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 private pushLine(task: Task, line: string) {\n task.buffer.push(line);\n if (task.buffer.length > MAX_BUFFER) task.buffer.shift();\n this.emit({ type: 'log', recipe: task.recipe, text: line });\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 * 插件 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 * 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 { JustRunner } from '../../server/just-runner.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.recipes();\n } catch {\n return [];\n }\n });\n\n ctx.route('/__just/tasks', async () => runner.list());\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 即重启);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 try { recipe = JSON.parse(body || '{}').recipe; } 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);\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","/**\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'];\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';\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 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'];\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","/** market 插件单源: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: 'market',\n label: '灵感市场',\n icon: '✨',\n description: 'Logo / 动效 / 设计灵感浏览 · 转提示词闭环',\n order: 40,\n};\n\n/** tab:当前市场;entry:选中目录项(深链接);q:搜索词 */\nexport const params: ParamSchema = [\n { name: 'tab', label: '当前市场', type: 'string', description: 'logos/motions/inspirations' },\n { name: 'q', label: '搜索词', type: 'string', description: '当前市场内搜索/过滤' },\n { name: 'entry', label: '选中条目', type: 'string', description: '目录项 id,直达详情' },\n];\n","/**\n * Logo 目录:simple-icons slug 精选(v1 ~200 常用品牌,按类别分组)。\n * id 即 simple-icons slug,经 /__market/proxy 取 https://cdn.jsdelivr.net/npm/simple-icons@13/icons/<slug>.svg。\n * slug 真实性:T6 冒烟对 pinned CDN 全量校验。\n */\nexport interface LogotypeEntry {\n /** simple-icons slug(如 react) */\n id: string;\n name: string;\n category: 'tech' | 'social' | 'dev' | 'cloud' | 'finance' | 'media' | 'gaming' | 'design' | 'shopping' | 'productivity' | 'ai';\n}\n\nexport const LOGOTYPES: LogotypeEntry[] = [\n // ---- tech 消费与硬件 ----\n { id: 'apple', name: 'Apple', category: 'tech' },\n { id: 'google', name: 'Google', category: 'tech' },\n { id: 'samsung', name: 'Samsung', category: 'tech' },\n { id: 'huawei', name: 'Huawei', category: 'tech' },\n { id: 'xiaomi', name: 'Xiaomi', category: 'tech' },\n { id: 'sony', name: 'Sony', category: 'tech' },\n { id: 'panasonic', name: 'Panasonic', category: 'tech' },\n { id: 'lg', name: 'LG', category: 'tech' },\n { id: 'nvidia', name: 'NVIDIA', category: 'tech' },\n { id: 'amd', name: 'AMD', category: 'tech' },\n { id: 'intel', name: 'Intel', category: 'tech' },\n { id: 'oracle', name: 'Oracle', category: 'tech' },\n { id: 'dell', name: 'Dell', category: 'tech' },\n { id: 'asus', name: 'ASUS', category: 'tech' },\n { id: 'lenovo', name: 'Lenovo', category: 'tech' },\n { id: 'razer', name: 'Razer', category: 'tech' },\n { id: 'logitech', name: 'Logitech', category: 'tech' },\n { id: 'nikon', name: 'Nikon', category: 'tech' },\n { id: 'tesla', name: 'Tesla', category: 'tech' },\n { id: 'nokia', name: 'Nokia', category: 'tech' },\n { id: 'oneplus', name: 'OnePlus', category: 'tech' },\n { id: 'oppo', name: 'OPPO', category: 'tech' },\n\n // ---- social 社交内容 ----\n { id: 'facebook', name: 'Facebook', category: 'social' },\n { id: 'instagram', name: 'Instagram', category: 'social' },\n { id: 'whatsapp', name: 'WhatsApp', category: 'social' },\n { id: 'signal', name: 'Signal', category: 'social' },\n { id: 'telegram', name: 'Telegram', category: 'social' },\n { id: 'discord', name: 'Discord', category: 'social' },\n { id: 'slack', name: 'Slack', category: 'social' },\n { id: 'x', name: 'X', category: 'social' },\n { id: 'threads', name: 'Threads', category: 'social' },\n { id: 'bluesky', name: 'Bluesky', category: 'social' },\n { id: 'mastodon', name: 'Mastodon', category: 'social' },\n { id: 'reddit', name: 'Reddit', category: 'social' },\n { id: 'pinterest', name: 'Pinterest', category: 'social' },\n { id: 'tiktok', name: 'TikTok', category: 'social' },\n { id: 'youtube', name: 'YouTube', category: 'social' },\n { id: 'twitch', name: 'Twitch', category: 'social' },\n { id: 'wechat', name: 'WeChat', category: 'social' },\n { id: 'sinaweibo', name: 'Sina Weibo', category: 'social' },\n { id: 'bilibili', name: 'bilibili', category: 'social' },\n { id: 'tencentqq', name: 'Tencent QQ', category: 'social' },\n\n // ---- dev 开发 ----\n { id: 'github', name: 'GitHub', category: 'dev' },\n { id: 'gitlab', name: 'GitLab', category: 'dev' },\n { id: 'bitbucket', name: 'Bitbucket', category: 'dev' },\n { id: 'git', name: 'Git', category: 'dev' },\n { id: 'githubactions', name: 'GitHub Actions', category: 'dev' },\n { id: 'react', name: 'React', category: 'dev' },\n { id: 'vuedotjs', name: 'Vue.js', category: 'dev' },\n { id: 'angular', name: 'Angular', category: 'dev' },\n { id: 'svelte', name: 'Svelte', category: 'dev' },\n { id: 'nextdotjs', name: 'Next.js', category: 'dev' },\n { id: 'nuxtdotjs', name: 'Nuxt', category: 'dev' },\n { id: 'astro', name: 'Astro', category: 'dev' },\n { id: 'typescript', name: 'TypeScript', category: 'dev' },\n { id: 'javascript', name: 'JavaScript', category: 'dev' },\n { id: 'nodedotjs', name: 'Node.js', category: 'dev' },\n { id: 'python', name: 'Python', category: 'dev' },\n { id: 'rust', name: 'Rust', category: 'dev' },\n { id: 'go', name: 'Go', category: 'dev' },\n { id: 'swift', name: 'Swift', category: 'dev' },\n { id: 'kotlin', name: 'Kotlin', category: 'dev' },\n { id: 'php', name: 'PHP', category: 'dev' },\n { id: 'laravel', name: 'Laravel', category: 'dev' },\n { id: 'ruby', name: 'Ruby', category: 'dev' },\n { id: 'rubyonrails', name: 'Ruby on Rails', category: 'dev' },\n { id: 'cplusplus', name: 'C++', category: 'dev' },\n { id: 'sass', name: 'Sass', category: 'dev' },\n { id: 'tailwindcss', name: 'Tailwind CSS', category: 'dev' },\n { id: 'pnpm', name: 'pnpm', category: 'dev' },\n { id: 'npm', name: 'npm', category: 'dev' },\n { id: 'yarn', name: 'Yarn', category: 'dev' },\n { id: 'vite', name: 'Vite', category: 'dev' },\n { id: 'vitest', name: 'Vitest', category: 'dev' },\n { id: 'storybook', name: 'Storybook', category: 'dev' },\n { id: 'docker', name: 'Docker', category: 'dev' },\n { id: 'kubernetes', name: 'Kubernetes', category: 'dev' },\n { id: 'terraform', name: 'Terraform', category: 'dev' },\n { id: 'ansible', name: 'Ansible', category: 'dev' },\n { id: 'jenkins', name: 'Jenkins', category: 'dev' },\n { id: 'nginx', name: 'NGINX', category: 'dev' },\n { id: 'postgresql', name: 'PostgreSQL', category: 'dev' },\n { id: 'mysql', name: 'MySQL', category: 'dev' },\n { id: 'mongodb', name: 'MongoDB', category: 'dev' },\n { id: 'redis', name: 'Redis', category: 'dev' },\n { id: 'sqlite', name: 'SQLite', category: 'dev' },\n { id: 'elasticsearch', name: 'Elasticsearch', category: 'dev' },\n { id: 'graphql', name: 'GraphQL', category: 'dev' },\n { id: 'firebase', name: 'Firebase', category: 'dev' },\n { id: 'linux', name: 'Linux', category: 'dev' },\n { id: 'ubuntu', name: 'Ubuntu', category: 'dev' },\n { id: 'archlinux', name: 'Arch Linux', category: 'dev' },\n { id: 'vim', name: 'Vim', category: 'dev' },\n { id: 'xcode', name: 'Xcode', category: 'dev' },\n { id: 'dotnet', name: '.NET', category: 'dev' },\n { id: 'sublimetext', name: 'Sublime Text', category: 'dev' },\n\n // ---- cloud 云服务 ----\n { id: 'googlecloud', name: 'Google Cloud', category: 'cloud' },\n { id: 'cloudflare', name: 'Cloudflare', category: 'cloud' },\n { id: 'vercel', name: 'Vercel', category: 'cloud' },\n { id: 'netlify', name: 'Netlify', category: 'cloud' },\n { id: 'heroku', name: 'Heroku', category: 'cloud' },\n { id: 'digitalocean', name: 'DigitalOcean', category: 'cloud' },\n { id: 'hetzner', name: 'Hetzner', category: 'cloud' },\n { id: 'fastly', name: 'Fastly', category: 'cloud' },\n { id: 'flydotio', name: 'Fly.io', category: 'cloud' },\n { id: 'render', name: 'Render', category: 'cloud' },\n { id: 'supabase', name: 'Supabase', category: 'cloud' },\n { id: 'alibabacloud', name: 'Alibaba Cloud', category: 'cloud' },\n { id: 'scaleway', name: 'Scaleway', category: 'cloud' },\n\n // ---- finance 金融支付 ----\n { id: 'visa', name: 'Visa', category: 'finance' },\n { id: 'mastercard', name: 'Mastercard', category: 'finance' },\n { id: 'paypal', name: 'PayPal', category: 'finance' },\n { id: 'stripe', name: 'Stripe', category: 'finance' },\n { id: 'wise', name: 'Wise', category: 'finance' },\n { id: 'square', name: 'Square', category: 'finance' },\n { id: 'applepay', name: 'Apple Pay', category: 'finance' },\n { id: 'googlepay', name: 'Google Pay', category: 'finance' },\n { id: 'alipay', name: 'Alipay', category: 'finance' },\n { id: 'bitcoin', name: 'Bitcoin', category: 'finance' },\n { id: 'ethereum', name: 'Ethereum', category: 'finance' },\n { id: 'binance', name: 'Binance', category: 'finance' },\n { id: 'coinbase', name: 'Coinbase', category: 'finance' },\n { id: 'americanexpress', name: 'American Express', category: 'finance' },\n\n // ---- media 媒体娱乐 ----\n { id: 'netflix', name: 'Netflix', category: 'media' },\n { id: 'spotify', name: 'Spotify', category: 'media' },\n { id: 'applemusic', name: 'Apple Music', category: 'media' },\n { id: 'soundcloud', name: 'SoundCloud', category: 'media' },\n { id: 'youtubemusic', name: 'YouTube Music', category: 'media' },\n { id: 'lastdotfm', name: 'Last.fm', category: 'media' },\n { id: 'primevideo', name: 'Prime Video', category: 'media' },\n { id: 'crunchyroll', name: 'Crunchyroll', category: 'media' },\n { id: 'vlcmediaplayer', name: 'VLC Media Player', category: 'media' },\n { id: 'unsplash', name: 'Unsplash', category: 'media' },\n { id: 'behance', name: 'Behance', category: 'media' },\n { id: 'dribbble', name: 'Dribbble', category: 'media' },\n { id: 'substack', name: 'Substack', category: 'media' },\n { id: 'pixiv', name: 'pixiv', category: 'media' },\n\n // ---- gaming 游戏 ----\n { id: 'steam', name: 'Steam', category: 'gaming' },\n { id: 'epicgames', name: 'Epic Games', category: 'gaming' },\n { id: 'playstation', name: 'PlayStation', category: 'gaming' },\n { id: 'nintendo', name: 'Nintendo', category: 'gaming' },\n { id: 'nintendoswitch', name: 'Nintendo Switch', category: 'gaming' },\n { id: 'roblox', name: 'Roblox', category: 'gaming' },\n { id: 'unity', name: 'Unity', category: 'gaming' },\n { id: 'unrealengine', name: 'Unreal Engine', category: 'gaming' },\n { id: 'godotengine', name: 'Godot Engine', category: 'gaming' },\n { id: 'itchdotio', name: 'itch.io', category: 'gaming' },\n { id: 'riotgames', name: 'Riot Games', category: 'gaming' },\n { id: 'dota2', name: 'Dota 2', category: 'gaming' },\n { id: 'ea', name: 'EA', category: 'gaming' },\n\n // ---- design 设计创作 ----\n { id: 'figma', name: 'Figma', category: 'design' },\n { id: 'sketch', name: 'Sketch', category: 'design' },\n { id: 'canva', name: 'Canva', category: 'design' },\n { id: 'adobe', name: 'Adobe', category: 'design' },\n { id: 'adobephotoshop', name: 'Adobe Photoshop', category: 'design' },\n { id: 'adobeillustrator', name: 'Adobe Illustrator', category: 'design' },\n { id: 'adobeaftereffects', name: 'Adobe After Effects', category: 'design' },\n { id: 'adobepremierepro', name: 'Adobe Premiere Pro', category: 'design' },\n { id: 'blender', name: 'Blender', category: 'design' },\n { id: 'affinitydesigner', name: 'Affinity Designer', category: 'design' },\n { id: 'framer', name: 'Framer', category: 'design' },\n { id: 'webflow', name: 'Webflow', category: 'design' },\n { id: 'wordpress', name: 'WordPress', category: 'design' },\n { id: 'penpot', name: 'Penpot', category: 'design' },\n { id: 'excalidraw', name: 'Excalidraw', category: 'design' },\n { id: 'miro', name: 'Miro', category: 'design' },\n\n // ---- shopping 电商零售 ----\n { id: 'shopify', name: 'Shopify', category: 'shopping' },\n { id: 'woocommerce', name: 'WooCommerce', category: 'shopping' },\n { id: 'magento', name: 'Magento', category: 'shopping' },\n { id: 'amazon', name: 'Amazon', category: 'shopping' },\n { id: 'ebay', name: 'eBay', category: 'shopping' },\n { id: 'etsy', name: 'Etsy', category: 'shopping' },\n { id: 'ikea', name: 'IKEA', category: 'shopping' },\n { id: 'target', name: 'Target', category: 'shopping' },\n { id: 'walmart', name: 'Walmart', category: 'shopping' },\n { id: 'zalando', name: 'Zalando', category: 'shopping' },\n\n // ---- productivity 效率办公 ----\n { id: 'notion', name: 'Notion', category: 'productivity' },\n { id: 'todoist', name: 'Todoist', category: 'productivity' },\n { id: 'asana', name: 'Asana', category: 'productivity' },\n { id: 'clickup', name: 'ClickUp', category: 'productivity' },\n { id: 'jira', name: 'Jira', category: 'productivity' },\n { id: 'confluence', name: 'Confluence', category: 'productivity' },\n { id: 'linear', name: 'Linear', category: 'productivity' },\n { id: 'zapier', name: 'Zapier', category: 'productivity' },\n { id: 'n8n', name: 'n8n', category: 'productivity' },\n { id: 'googledrive', name: 'Google Drive', category: 'productivity' },\n { id: 'googledocs', name: 'Google Docs', category: 'productivity' },\n { id: 'gmail', name: 'Gmail', category: 'productivity' },\n { id: 'dropbox', name: 'Dropbox', category: 'productivity' },\n { id: 'zoom', name: 'Zoom', category: 'productivity' },\n { id: 'googlemeet', name: 'Google Meet', category: 'productivity' },\n\n // ---- ai 人工智能 ----\n { id: 'openai', name: 'OpenAI', category: 'ai' },\n { id: 'anthropic', name: 'Anthropic', category: 'ai' },\n { id: 'huggingface', name: 'Hugging Face', category: 'ai' },\n { id: 'tensorflow', name: 'TensorFlow', category: 'ai' },\n { id: 'pytorch', name: 'PyTorch', category: 'ai' },\n { id: 'opencv', name: 'OpenCV', category: 'ai' },\n { id: 'scikitlearn', name: 'scikit-learn', category: 'ai' },\n { id: 'jupyter', name: 'Jupyter', category: 'ai' },\n { id: 'ollama', name: 'Ollama', category: 'ai' },\n { id: 'langchain', name: 'LangChain', category: 'ai' }, { id: 'googlegemini', name: 'Google Gemini', category: 'ai' },\n\n];\n","/**\n * 动效目录:animate.css v4 与 hover.css v2 精选(v1 ~60 项)。\n * cls 为库内动画类名(不含 animate__animated 基类,由视图按 lib 组装);\n * 库 css 经 /__market/proxy 拉取注入 <style>,类名真实性由 T6 冒烟对 pinned CDN 校验。\n */\nexport interface MotionEntry {\n id: string;\n name: string;\n desc: string;\n cls: string;\n lib: 'animate.css' | 'hover.css';\n}\n\nexport const MOTIONS: MotionEntry[] = [\n // ---- animate.css:attention seekers 吸睛 ----\n { id: 'animate-bounce', name: '弹跳', desc: '上下弹跳,常用于引导注意', cls: 'animate__bounce', lib: 'animate.css' },\n { id: 'animate-flash', name: '闪烁', desc: '透明度快速闪烁', cls: 'animate__flash', lib: 'animate.css' },\n { id: 'animate-pulse', name: '脉冲', desc: '缩放呼吸,常用于加载与直播状态', cls: 'animate__pulse', lib: 'animate.css' },\n { id: 'animate-rubberband', name: '橡皮筋', desc: '弹性拉伸,强调趣味反馈', cls: 'animate__rubberBand', lib: 'animate.css' },\n { id: 'animate-shakex', name: '横向抖动', desc: '左右抖动,常用于错误提示', cls: 'animate__shakeX', lib: 'animate.css' },\n { id: 'animate-shakey', name: '纵向抖动', desc: '上下抖动,表单校验反馈', cls: 'animate__shakeY', lib: 'animate.css' },\n { id: 'animate-headshake', name: '摇头', desc: '绕纵轴小幅摆头', cls: 'animate__headShake', lib: 'animate.css' },\n { id: 'animate-swing', name: '摆动', desc: '顶部悬挂式左右摆动', cls: 'animate__swing', lib: 'animate.css' },\n { id: 'animate-tada', name: '欢呼', desc: '缩放加旋转的组合强调', cls: 'animate__tada', lib: 'animate.css' },\n { id: 'animate-wobble', name: '摇晃', desc: '大幅左右摇晃', cls: 'animate__wobble', lib: 'animate.css' },\n { id: 'animate-jello', name: '果冻', desc: '倾斜加缩放的果冻感', cls: 'animate__jello', lib: 'animate.css' },\n { id: 'animate-heartbeat', name: '心跳', desc: '双击式心跳缩放', cls: 'animate__heartBeat', lib: 'animate.css' },\n\n // ---- animate.css:入场 ----\n { id: 'animate-flipinx', name: '翻转入场 X', desc: '绕 X 轴翻转入场', cls: 'animate__flipInX', lib: 'animate.css' },\n { id: 'animate-flipiny', name: '翻转入场 Y', desc: '绕 Y 轴翻转入场', cls: 'animate__flipInY', lib: 'animate.css' },\n { id: 'animate-fadein', name: '淡入', desc: '透明度渐入', cls: 'animate__fadeIn', lib: 'animate.css' },\n { id: 'animate-fadeindown', name: '淡入下移', desc: '自上而下淡入', cls: 'animate__fadeInDown', lib: 'animate.css' },\n { id: 'animate-fadeinleft', name: '淡入右移', desc: '自左向右淡入', cls: 'animate__fadeInLeft', lib: 'animate.css' },\n { id: 'animate-fadeinright', name: '淡入左移', desc: '自右向左淡入', cls: 'animate__fadeInRight', lib: 'animate.css' },\n { id: 'animate-fadeinup', name: '淡入上移', desc: '自下而上淡入,卡片列表常用', cls: 'animate__fadeInUp', lib: 'animate.css' },\n { id: 'animate-fadeinupbig', name: '大幅淡入上移', desc: '大距离自下而上淡入', cls: 'animate__fadeInUpBig', lib: 'animate.css' },\n { id: 'animate-zoomin', name: '放大入场', desc: '由小放大淡入', cls: 'animate__zoomIn', lib: 'animate.css' },\n { id: 'animate-zoomindown', name: '放大入场(下)', desc: '自上而下放大入场', cls: 'animate__zoomInDown', lib: 'animate.css' },\n { id: 'animate-slideindown', name: '滑入(下)', desc: '自上滑入,通知条常用', cls: 'animate__slideInDown', lib: 'animate.css' },\n { id: 'animate-slideinleft', name: '滑入(左)', desc: '自左滑入,侧栏抽屉常用', cls: 'animate__slideInLeft', lib: 'animate.css' },\n { id: 'animate-slideinright', name: '滑入(右)', desc: '自右滑入,侧栏抽屉常用', cls: 'animate__slideInRight', lib: 'animate.css' },\n { id: 'animate-slideinup', name: '滑入(上)', desc: '自下滑入,底部弹层常用', cls: 'animate__slideInUp', lib: 'animate.css' },\n { id: 'animate-backindown', name: '回弹入场(下)', desc: '带回弹曲线自上而下入场', cls: 'animate__backInDown', lib: 'animate.css' },\n { id: 'animate-backinleft', name: '回弹入场(左)', desc: '带回弹曲线自左入场', cls: 'animate__backInLeft', lib: 'animate.css' },\n { id: 'animate-backinup', name: '回弹入场(上)', desc: '带回弹曲线自下而上入场', cls: 'animate__backInUp', lib: 'animate.css' },\n { id: 'animate-bouncein', name: '弹跳入场', desc: '弹性弹跳入场', cls: 'animate__bounceIn', lib: 'animate.css' },\n { id: 'animate-bounceindown', name: '弹跳入场(下)', desc: '自上弹跳入场', cls: 'animate__bounceInDown', lib: 'animate.css' },\n { id: 'animate-bounceinup', name: '弹跳入场(上)', desc: '自下弹跳入场', cls: 'animate__bounceInUp', lib: 'animate.css' },\n { id: 'animate-rotatein', name: '旋转入场', desc: '旋转淡入', cls: 'animate__rotateIn', lib: 'animate.css' },\n { id: 'animate-rotateindownleft', name: '旋转入场(左下)', desc: '自左下角旋转淡入', cls: 'animate__rotateInDownLeft', lib: 'animate.css' },\n { id: 'animate-lightspeedinright', name: '光速入场', desc: '斜切加高速飞入', cls: 'animate__lightSpeedInRight', lib: 'animate.css' },\n { id: 'animate-rollin', name: '滚入', desc: '水平滚转入场', cls: 'animate__rollIn', lib: 'animate.css' },\n { id: 'animate-jackinthebox', name: '跳跳盒', desc: '弹出盒式趣味入场', cls: 'animate__jackInTheBox', lib: 'animate.css' },\n\n // ---- animate.css:退场 ----\n { id: 'animate-flipoutx', name: '翻转退场 X', desc: '绕 X 轴翻转退场', cls: 'animate__flipOutX', lib: 'animate.css' },\n { id: 'animate-fadeout', name: '淡出', desc: '透明度渐出', cls: 'animate__fadeOut', lib: 'animate.css' },\n { id: 'animate-fadeoutdown', name: '淡出下移', desc: '向下淡出,弹层关闭常用', cls: 'animate__fadeOutDown', lib: 'animate.css' },\n { id: 'animate-zoomout', name: '缩小退场', desc: '缩小淡出', cls: 'animate__zoomOut', lib: 'animate.css' },\n { id: 'animate-slideoutup', name: '滑出(上)', desc: '向上滑出,通知关闭常用', cls: 'animate__slideOutUp', lib: 'animate.css' },\n { id: 'animate-bounceout', name: '弹跳退场', desc: '弹性弹跳退场', cls: 'animate__bounceOut', lib: 'animate.css' },\n { id: 'animate-hinge', name: '铰链', desc: '悬挂摆动坠落,喜剧式退场', cls: 'animate__hinge', lib: 'animate.css' },\n\n // ---- hover.css:hover 反馈 ----\n { id: 'hover-grow', name: '放大', desc: 'hover 时轻微放大', cls: 'hvr-grow', lib: 'hover.css' },\n { id: 'hover-shrink', name: '缩小', desc: 'hover 时轻微缩小', cls: 'hvr-shrink', lib: 'hover.css' },\n { id: 'hover-pulse', name: '脉冲', desc: 'hover 期间缩放脉冲', cls: 'hvr-pulse', lib: 'hover.css' },\n { id: 'hover-push', name: '推挤', desc: 'hover 时压扁再回弹', cls: 'hvr-push', lib: 'hover.css' },\n { id: 'hover-pop', name: '弹出', desc: 'hover 时弹出放大', cls: 'hvr-pop', lib: 'hover.css' },\n { id: 'hover-bounce-in', name: '弹入', desc: 'hover 时弹性放大', cls: 'hvr-bounce-in', lib: 'hover.css' },\n { id: 'hover-bounce-out', name: '弹出', desc: 'hover 时弹性缩小', cls: 'hvr-bounce-out', lib: 'hover.css' },\n { id: 'hover-rotate', name: '旋转', desc: 'hover 时旋转 4 度', cls: 'hvr-rotate', lib: 'hover.css' },\n { id: 'hover-grow-rotate', name: '放大旋转', desc: 'hover 时放大并旋转', cls: 'hvr-grow-rotate', lib: 'hover.css' },\n { id: 'hover-float', name: '上浮', desc: 'hover 时上浮,按钮常用', cls: 'hvr-float', lib: 'hover.css' },\n { id: 'hover-sink', name: '下沉', desc: 'hover 时下沉按压感', cls: 'hvr-sink', lib: 'hover.css' },\n { id: 'hover-bob', name: '浮动', desc: 'hover 期间持续上下浮动', cls: 'hvr-bob', lib: 'hover.css' },\n { id: 'hover-hang', name: '悬挂', desc: 'hover 期间悬挂摆动', cls: 'hvr-hang', lib: 'hover.css' },\n { id: 'hover-skew', name: '斜切', desc: 'hover 时斜切变形', cls: 'hvr-skew', lib: 'hover.css' },\n { id: 'hover-wobble-horizontal', name: '横向摇摆', desc: 'hover 时水平摇摆', cls: 'hvr-wobble-horizontal', lib: 'hover.css' },\n { id: 'hover-wobble-vertical', name: '纵向摇摆', desc: 'hover 时垂直摇摆', cls: 'hvr-wobble-vertical', lib: 'hover.css' },\n { id: 'hover-buzz', name: '震动', desc: 'hover 时小幅高频震动', cls: 'hvr-buzz', lib: 'hover.css' },\n { id: 'hover-sweep-to-right', name: '背景右扫', desc: '背景色自左向右扫过', cls: 'hvr-sweep-to-right', lib: 'hover.css' },\n { id: 'hover-bounce-to-right', name: '弹性右填', desc: '背景弹性填满(向右)', cls: 'hvr-bounce-to-right', lib: 'hover.css' },\n { id: 'hover-radial-out', name: '径向扩散', desc: '背景自中心圆形扩散', cls: 'hvr-radial-out', lib: 'hover.css' },\n { id: 'hover-underline-from-left', name: '下划线滑入', desc: '下划线自左滑入', cls: 'hvr-underline-from-left', lib: 'hover.css' },\n { id: 'hover-glow', name: '发光', desc: 'hover 时外发光', cls: 'hvr-glow', lib: 'hover.css' },\n { id: 'hover-shadow', name: '阴影', desc: 'hover 时出现投影', cls: 'hvr-shadow', lib: 'hover.css' },\n { id: 'hover-grow-shadow', name: '放大投影', desc: 'hover 时放大并投影', cls: 'hvr-grow-shadow', lib: 'hover.css' },\n { id: 'hover-float-shadow', name: '上浮投影', desc: 'hover 时上浮并投影', cls: 'hvr-float-shadow', lib: 'hover.css' },\n];\n","/**\n * 灵感目录:真实开源站点/设计模式精选(v1 40 条)。\n * 仅元数据(name/desc/url/tags),详情新窗口打开原站,不做内嵌(第三方站点不可 iframe)。\n */\nexport interface InspirationEntry {\n id: string;\n name: string;\n desc: string;\n url: string;\n tags: string[];\n}\n\nexport const INSPIRATIONS: InspirationEntry[] = [\n { id: 'shadcn', name: 'shadcn/ui', desc: '可复制粘贴的 React 组件集,代码归你所有', url: 'https://ui.shadcn.com', tags: ['react', 'tailwind', '设计系统'] },\n { id: 'radix', name: 'Radix UI', desc: '无样式可访问性 React 基础组件', url: 'https://www.radix-ui.com', tags: ['react', '无障碍', '基础组件'] },\n { id: 'tailwindcss', name: 'Tailwind CSS', desc: '原子化 CSS 框架的官方站点', url: 'https://tailwindcss.com', tags: ['css', '原子化', '官网'] },\n { id: 'antd', name: 'Ant Design', desc: '企业级 React 设计系统与组件库', url: 'https://ant.design', tags: ['react', '设计系统', '企业级'] },\n { id: 'arco', name: 'Arco Design', desc: '字节跳动企业级设计系统', url: 'https://arco.design', tags: ['react', '设计系统', '企业级'] },\n { id: 'semi', name: 'Semi Design', desc: '抖音前端团队设计系统', url: 'https://semi.design', tags: ['react', '设计系统', '主题化'] },\n { id: 'chakra', name: 'Chakra UI', desc: '以无障碍和主题著称的 React 组件库', url: 'https://chakra-ui.com', tags: ['react', '无障碍', '主题'] },\n { id: 'mui', name: 'MUI', desc: 'Material Design 风格 React 组件库', url: 'https://mui.com', tags: ['react', 'material', '组件库'] },\n { id: 'mantine', name: 'Mantine', desc: '组件+hooks 齐全的 React 全家桶', url: 'https://mantine.dev', tags: ['react', '组件库', 'hooks'] },\n { id: 'naiveui', name: 'Naive UI', desc: 'Vue 3 全类型组件库,主题定制细', url: 'https://www.naiveui.com', tags: ['vue', '组件库', '主题'] },\n { id: 'element-plus', name: 'Element Plus', desc: 'Vue 3 老牌企业级组件库', url: 'https://element-plus.org', tags: ['vue', '组件库', '企业级'] },\n { id: 'daisyui', name: 'daisyUI', desc: 'Tailwind 语义化组件类与多主题', url: 'https://daisyui.com', tags: ['tailwind', 'css', '主题'] },\n { id: 'nextui', name: 'NextUI', desc: '美观优先的 React + Tailwind 组件库', url: 'https://nextui.org', tags: ['react', 'tailwind', '组件库'] },\n { id: 'headlessui', name: 'Headless UI', desc: '完全无样式、带行为的 React/Vue 组件', url: 'https://headlessui.com', tags: ['react', 'vue', '无样式'] },\n { id: 'carbon', name: 'Carbon Design System', desc: 'IBM 开源设计系统,token 体系教科书', url: 'https://carbondesignsystem.com', tags: ['设计系统', 'token', '文档'] },\n { id: 'polaris', name: 'Polaris', desc: 'Shopify 设计系统,电商后台范式', url: 'https://polaris.shopify.com', tags: ['设计系统', 'react', '电商'] },\n { id: 'material3', name: 'Material Design 3', desc: 'Google 动态取色与形变设计规范', url: 'https://m3.material.io', tags: ['google', '设计系统', '动效'] },\n { id: 'storybook', name: 'Storybook', desc: '组件工作台与文档的事实标准', url: 'https://storybook.js.org', tags: ['组件文档', '工作台', '协作'] },\n { id: 'geist', name: 'Geist', desc: 'Vercel 极简设计系统', url: 'https://vercel.com/geist', tags: ['设计系统', '极简', 'vercel'] },\n { id: 'openprops', name: 'Open Props', desc: '超实用 CSS 变量集合(动效/颜色/布局)', url: 'https://open-props.style', tags: ['css', '变量', '动效'] },\n { id: 'everylayout', name: 'Every Layout', desc: '用 CSS 原生能力解决布局问题', url: 'https://every-layout.dev', tags: ['css', '布局', '响应式'] },\n { id: 'animatecss', name: 'Animate.css', desc: '最流行的即用型 CSS 动画库官网', url: 'https://animate.style', tags: ['css', '动效', '库'] },\n { id: 'csstricks', name: 'CSS-Tricks', desc: 'CSS 技巧与模式的长青社区', url: 'https://css-tricks.com', tags: ['css', '教程', '模式'] },\n { id: 'webdev', name: 'web.dev', desc: 'Google Web 最佳实践与性能指南', url: 'https://web.dev', tags: ['性能', '最佳实践', 'google'] },\n { id: 'excalidraw', name: 'Excalidraw', desc: '手绘风协作白板,开源虚拟白板标杆', url: 'https://excalidraw.com', tags: ['白板', '手绘风', '协作'] },\n { id: 'tldraw', name: 'tldraw', desc: '无限画布 SDK 与精美白板', url: 'https://www.tldraw.com', tags: ['白板', '画布', 'sdk'] },\n { id: 'penpot', name: 'Penpot', desc: '开源 Figma 替代,设计开发同源', url: 'https://penpot.app', tags: ['设计工具', '开源', '协作'] },\n { id: 'cal', name: 'Cal.com', desc: '开源日程预约,产品站与交互范式', url: 'https://cal.com', tags: ['saas', '日程', '表单'] },\n { id: 'dub', name: 'Dub', desc: '开源短链平台,现代 SaaS 界面范本', url: 'https://dub.co', tags: ['saas', '短链', '分析'] },\n { id: 'twenty', name: 'Twenty', desc: '开源 Notion 风 CRM,表格交互教科书', url: 'https://twenty.com', tags: ['crm', '表格', 'saas'] },\n { id: 'umami', name: 'Umami', desc: '隐私友好的开源站点统计,仪表盘简洁', url: 'https://umami.is', tags: ['统计', '隐私', '仪表盘'] },\n { id: 'plausible', name: 'Plausible', desc: '极简开源分析,一屏仪表盘范式', url: 'https://plausible.io', tags: ['统计', '隐私', '极简'] },\n { id: 'outline', name: 'Outline', desc: '开源团队 wiki,排版与快捷键体验佳', url: 'https://www.getoutline.com', tags: ['文档', 'wiki', '团队'] },\n { id: 'plane', name: 'Plane', desc: '开源项目管理,issue/看板/周期', url: 'https://plane.so', tags: ['项目管理', '看板', 'issue'] },\n { id: 'huly', name: 'Huly', desc: '开源全栈项目管理,视觉华丽', url: 'https://huly.io', tags: ['项目管理', '视觉', '全栈'] },\n { id: 'uptime-kuma', name: 'Uptime Kuma', desc: '自托管监控与状态页', url: 'https://uptime.kuma.pet', tags: ['监控', '状态页', '自托管'] },\n { id: 'homepage', name: 'Homepage', desc: '现代化自托管导航仪表盘', url: 'https://gethomepage.dev', tags: ['仪表盘', '导航', '自托管'] },\n { id: 'nocodb', name: 'NocoDB', desc: '开源 Airtable 替代,数据库表格化', url: 'https://nocodb.com', tags: ['数据库', '表格', '低代码'] },\n { id: 'bruno', name: 'Bruno', desc: '离线优先开源 API 客户端', url: 'https://www.usebruno.com', tags: ['api', '离线优先', '开发工具'] },\n { id: 'grafana', name: 'Grafana', desc: '开源可视化监控面板标杆', url: 'https://grafana.com/oss/grafana/', tags: ['监控', '可视化', '仪表盘'] },\n];\n","/**\n * 目录注册表:market 名 → 内置条目(目录与取数分离,目录演进不动代理)。\n * 响应契约(design.md):{ entries: [{ id, name, ...市场字段 }] },logos 附带 slug(= id)。\n */\nimport { LOGOTYPES, type LogotypeEntry } from './logotypes.js';\nimport { MOTIONS, type MotionEntry } from './motions.js';\nimport { INSPIRATIONS, type InspirationEntry } from './inspirations.js';\n\nexport type { LogotypeEntry, MotionEntry, InspirationEntry };\n\nexport const MARKETS = ['logos', 'motions', 'inspirations'] as const;\nexport type MarketName = (typeof MARKETS)[number];\n\nexport interface CatalogResponse {\n entries: Array<Record<string, unknown>>;\n}\n\nexport function isMarketName(v: string): v is MarketName {\n return (MARKETS as readonly string[]).includes(v);\n}\n\nexport function catalogFor(market: string): CatalogResponse | null {\n switch (market) {\n case 'logos':\n return { entries: LOGOTYPES.map((e) => ({ ...e, slug: e.id })) };\n case 'motions':\n return { entries: MOTIONS.map((e) => ({ ...e })) };\n case 'inspirations':\n return { entries: INSPIRATIONS.map((e) => ({ ...e })) };\n default:\n return null;\n }\n}\n","/**\n * market server 侧:defineBuiltin 接入 + 代理/目录路由(目录与取数分离)。\n *\n * - GET /__market/proxy?url=<完整 URL>:host 白名单收敛 SSRF 面(design 安全红线);\n * 8s 超时降级 502;内存缓存 ≤200 条 TTL 10min,X-Market-Cache: hit|miss。\n * - GET /__market/catalog/<market>:内置目录 JSON,未知 market 404,零 IO 离线可浏览。\n */\nimport { defineBuiltin } from '../builtin.js';\nimport { manifest } from './manifest.js';\nimport { catalogFor, isMarketName } from './sources/index.js';\n\n/** 代理 allowlist:仅此双 host(任意外发 = 0,design 安全红线) */\nexport const ALLOWED_PROXY_HOSTS = ['cdn.jsdelivr.net', 'data.jsdelivr.com'] as const;\n\n/** 端口限定:仅缺省/80/443 放行,防 CDN 域名解析到固定 IP 后的非标端口探测 */\nconst ALLOWED_PROXY_PORTS = new Set(['', '80', '443']);\n\nconst PROXY_TIMEOUT_MS = 8_000; // 上游超时,超时降级 502\nconst PROXY_CACHE_MAX_ENTRIES = 200; // 内存缓存条目上限,超出淘汰最旧\nconst PROXY_CACHE_TTL_MS = 10 * 60 * 1000; // 缓存有效期 10min\nconst CATALOG_PREFIX = '/__market/catalog/';\n\ninterface ProxyCacheEntry {\n body: string;\n contentType: string;\n cachedAt: number;\n}\n\nexport const apply = defineBuiltin({\n manifest,\n setup(ctx) {\n // 缓存随插件 setup 生命周期(cordis 重载即重建,测试天然隔离)\n const cache = new Map<string, ProxyCacheEntry>();\n\n ctx.route('/__market/proxy', async (req, res) => {\n const raw = new URL(req.url || '/', 'http://localhost').searchParams.get('url');\n if (!raw) { res.writeHead(400); res.end('missing url'); return; }\n let target: URL;\n try { target = new URL(raw); } catch { res.writeHead(400); res.end('bad url'); return; }\n if (target.protocol !== 'https:' && target.protocol !== 'http:') { res.writeHead(403); res.end('scheme not allowed'); return; }\n if (!(ALLOWED_PROXY_HOSTS as readonly string[]).includes(target.hostname)) { res.writeHead(403); res.end('host not allowed'); return; }\n if (!ALLOWED_PROXY_PORTS.has(target.port)) { res.writeHead(403); res.end('port not allowed'); return; }\n\n // 缓存命中:未过 TTL 直接回源副本,零上游请求\n const hit = cache.get(raw);\n if (hit && Date.now() - hit.cachedAt < PROXY_CACHE_TTL_MS) {\n res.writeHead(200, { 'Content-Type': hit.contentType, 'X-Market-Cache': 'hit', 'Cache-Control': 'no-cache' });\n res.end(hit.body);\n return;\n }\n if (hit) cache.delete(raw); // 过期清除\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), PROXY_TIMEOUT_MS);\n try {\n // redirect: 'error' — jsdelivr 直链无跨域重定向需求,30x 跨 host 跳转不经 allowlist 复核,拒绝跟随\n const upstream = await fetch(raw, { signal: controller.signal, redirect: 'error' });\n if (!upstream.ok) { res.writeHead(502); res.end('upstream error'); return; }\n const body = await upstream.text();\n const contentType = upstream.headers.get('content-type') ?? 'application/octet-stream';\n cache.set(raw, { body, contentType, cachedAt: Date.now() });\n if (cache.size > PROXY_CACHE_MAX_ENTRIES) {\n // Map 迭代序 = 插入序,淘汰最旧一条回到上限\n const oldest = cache.keys().next().value;\n if (oldest !== undefined) cache.delete(oldest);\n }\n res.writeHead(200, { 'Content-Type': contentType, 'X-Market-Cache': 'miss', 'Cache-Control': 'no-cache' });\n res.end(body);\n } catch {\n // 上游断网/超时中止:统一 502,前端降级\n if (!res.headersSent) { res.writeHead(502); res.end('upstream failed'); }\n } finally {\n clearTimeout(timer);\n }\n });\n\n // 注册不带尾斜杠:core/server 前缀分发按 rp + '/' 命中 /__market/catalog/<market>\n ctx.route('/__market/catalog', async (req, res) => {\n // 命中方式为前缀匹配(/__market/catalog/logos),取首段为 market 名\n const pathname = new URL(req.url || '/', 'http://localhost').pathname;\n const market = pathname.startsWith(CATALOG_PREFIX)\n ? pathname.slice(CATALOG_PREFIX.length).split('/')[0]\n : '';\n if (!market || !isMarketName(market)) {\n res.writeHead(404);\n res.end('unknown market');\n return;\n }\n return catalogFor(market);\n });\n },\n});\n"],"mappings":"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","names":["path","fs","fileURLToPath","fs","path","fs","path","execFile","execFile","path","fs","err","fp","fs","Service","fs","path","fs","path","path","fs","execFile","apply","Service","Service","manifest","execFile","manifest","path","apply","path","fs","path","path","manifest","apply","manifest","path","fs","manifest","apply","manifest","fs","path","execFile","manifest","execFile","path","fs","apply","manifest","manifest","apply","manifest","__dirname","path","fileURLToPath","apply","fs"]}