zen-gitsync 2.12.8 → 2.12.9

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 (32) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/scripts/README_COLOR_CONVERTER.md +196 -196
  4. package/scripts/README_FONTSIZE_CONVERTER.md +278 -278
  5. package/scripts/README_SPACING_CONVERTER.md +126 -126
  6. package/scripts/README_STYLE_VARS.md +180 -180
  7. package/src/ui/public/assets/EditorView-C4DezJRA.js +0 -0
  8. package/src/ui/public/assets/SourceMapView-B521sL_k.js +3 -0
  9. package/src/ui/public/assets/WorkbenchView-75x9qygA.js +1 -0
  10. package/src/ui/public/assets/WorkbenchView-Dc9vThI8.css +1 -0
  11. package/src/ui/public/assets/{_plugin-vue_export-helper-opDPZuCO.js → _plugin-vue_export-helper-DMUTnP0C.js} +3 -3
  12. package/src/ui/public/assets/{css.worker-CvXBzhp8.js → css.worker-Wv5dxAWO.js} +1 -1
  13. package/src/ui/public/assets/{html.worker-BO6WuOEO.js → html.worker-CQP8QQsS.js} +1 -1
  14. package/src/ui/public/assets/index-BCIFnj7e.css +1 -0
  15. package/src/ui/public/assets/index-cS1g7H--.js +65 -0
  16. package/src/ui/public/assets/{json.worker-BkJRGcCJ.js → json.worker-DzV-CpCQ.js} +1 -1
  17. package/src/ui/public/assets/{ts.worker-B0J26iPs.js → ts.worker-Dth06zuC.js} +15 -15
  18. package/src/ui/public/assets/vendor-B2yudN8R.css +1 -0
  19. package/src/ui/public/assets/{vendor-A4IPqbyo.js → vendor-C1sPhIEb.js} +242 -249
  20. package/src/ui/public/favicon.svg +75 -75
  21. package/src/ui/public/index.html +23 -23
  22. package/src/ui/public/logo.svg +74 -74
  23. package/src/ui/server/routes/workbench.js +259 -64
  24. package/src/ui/public/assets/EditorView-DkH7PwMR.js +0 -0
  25. package/src/ui/public/assets/SourceMapView-BG6MIju7.js +0 -3
  26. package/src/ui/public/assets/WorkbenchView-CDKIBwuO.css +0 -1
  27. package/src/ui/public/assets/WorkbenchView-DgwZOvhW.js +0 -1
  28. package/src/ui/public/assets/index-DPihtJfT.js +0 -65
  29. package/src/ui/public/assets/index-tejX3YgJ.css +0 -1
  30. package/src/ui/public/assets/vendor-DpYOE9sy.css +0 -1
  31. /package/src/ui/public/assets/{editor.worker-Cn2oRESe.js → editor.worker-Bd9IXS8d.js} +0 -0
  32. /package/src/ui/public/assets/{rolldown-runtime-CMxvf4Kt.js → rolldown-runtime-BM3Ffeng.js} +0 -0
@@ -28,6 +28,35 @@ const DATA_DIR = path.join(os.homedir(), '.zen-gitsync');
28
28
  const PROMPTS_FILE = path.join(DATA_DIR, 'prompts.json');
29
29
  const TASKS_FILE = path.join(DATA_DIR, 'tasks.json');
30
30
  const IMAGES_DIR = path.join(DATA_DIR, 'workbench-images');
31
+ const INSTRUCTION_FILE = path.join(DATA_DIR, 'ai-instruction.json');
32
+
33
+ // 子项目识别 / 文件扫描时需要跳过的目录
34
+ const SKIP_DIRS = new Set([
35
+ 'node_modules', 'dist', 'build', '.next', '.nuxt', '__pycache__',
36
+ 'target', 'out', 'coverage', 'vendor', '.git', '.svn', '.hg',
37
+ '.idea', '.vscode', '.gradle', '.terraform', '.cache', '.parcel-cache',
38
+ '.turbo', '.svelte-kit', 'storybook-static'
39
+ ]);
40
+
41
+ // 默认生成指令:用户首次使用时作为可编辑指令的初始值
42
+ const DEFAULT_INSTRUCTION = `你是一名资深软件架构师。
43
+
44
+ 【探索步骤】
45
+ 1. 先识别项目结构:扫描根目录是否包含 .git 目录,以及 package.json / pyproject.toml / go.mod / Cargo.toml / pom.xml / build.gradle{,.kts} / composer.json / Gemfile / pubspec.yaml 这 9 种 manifest。
46
+ 2. 如果根目录含 manifest,就把整个根目录视为一个子项目。
47
+ 3. 如果根目录不含 manifest、但子目录(含一层 .git 或上述 manifest)形成多个子项目,对每个子项目分别探索。
48
+ 4. 对每个子项目,重点读取:
49
+ - 所有识别到的 manifest(限制单文件 20KB)
50
+ - README.md(限制 8KB)
51
+ - 入口文件:package.json 的 main / scripts / workspaces 字段;pyproject.toml 的 [project.scripts];go.mod 的 module;Cargo.toml 的 [[bin]];pom.xml 的 <modules>
52
+ - 2 层目录树(最多 200 行)
53
+
54
+ 【输出要求】
55
+ 1. 给出一段 400-800 字的中文「项目架构说明」,覆盖:项目整体定位、技术栈、模块划分、核心流程、关键设计决策。
56
+ 2. 必须引用子项目里实际存在的文件路径、目录名、依赖名,不要编造。
57
+ 3. 多个子项目时:先逐个说明,最后输出一段「整体架构」总结它们之间的关系。
58
+ 4. 语气专业、具体、面向接手这个项目的开发者。
59
+ 5. 只返回 JSON:{ "name": "项目名(10-20字)", "summary": "架构说明正文" }。`;
31
60
 
32
61
  // 单个附件最大 5MB;与 Anthropic Messages API 文档约束一致
33
62
  const MAX_IMAGE_BYTES = 5 * 1024 * 1024;
@@ -151,7 +180,8 @@ async function listDirTree(projectPath, maxDepth = 2, maxEntries = 400) {
151
180
  return lines.join('\n');
152
181
  }
153
182
 
154
- async function callLlmJson(model, prompt) {
183
+ async function callLlmJson(model, prompt, opts = {}) {
184
+ const { maxTokens = 1500, timeoutMs = 60000 } = opts;
155
185
  const { default: fetch } = await import('node-fetch').catch(() => ({ default: globalThis.fetch }));
156
186
  const url = `${String(model.baseURL || '').replace(/\/$/, '')}/chat/completions`;
157
187
  const headers = { 'Content-Type': 'application/json' };
@@ -160,14 +190,14 @@ async function callLlmJson(model, prompt) {
160
190
  const body = JSON.stringify({
161
191
  model: model.model,
162
192
  messages: [{ role: 'user', content: prompt }],
163
- max_tokens: 1500,
193
+ max_tokens: maxTokens,
164
194
  temperature: 0.4,
165
195
  response_format: { type: 'json_object' },
166
196
  stream: false,
167
197
  });
168
198
 
169
199
  const controller = new AbortController();
170
- const timer = setTimeout(() => controller.abort(), 60000);
200
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
171
201
  try {
172
202
  const resp = await fetch(url, { method: 'POST', headers, body, signal: controller.signal });
173
203
  const data = await resp.json().catch(() => ({}));
@@ -231,6 +261,108 @@ function interpolate(template, ctx) {
231
261
  const bus = new EventEmitter();
232
262
  const jobs = new Map(); // jobId -> { id, taskId, subId, status, pid, startedAt, endedAt, exitCode, error, prompt }
233
263
 
264
+ // ── 生成指令持久化(~/.zen-gitsync/ai-instruction.json) ────────────────────
265
+ async function readInstruction() {
266
+ try {
267
+ const buf = await fsp.readFile(INSTRUCTION_FILE, 'utf-8');
268
+ const obj = JSON.parse(buf);
269
+ if (obj && typeof obj.instruction === 'string' && obj.instruction.trim()) {
270
+ return obj.instruction;
271
+ }
272
+ } catch { /* 文件不存在或解析失败 */ }
273
+ return DEFAULT_INSTRUCTION;
274
+ }
275
+
276
+ async function writeInstruction(instruction) {
277
+ await ensureDataDir();
278
+ const text = String(instruction || '').trim() || DEFAULT_INSTRUCTION;
279
+ const tmp = `${INSTRUCTION_FILE}.tmp`;
280
+ await fsp.writeFile(tmp, JSON.stringify({ instruction: text, updatedAt: nowIso() }, null, 2), 'utf-8');
281
+ await fsp.rename(tmp, INSTRUCTION_FILE);
282
+ }
283
+
284
+ // ── 子项目识别:递归找 .git / manifest;A 是 B 的祖先时只保留 B ─────────────
285
+ async function findSubProjects(projectPath, opts = {}) {
286
+ const { maxDepth = 4 } = opts;
287
+ const candidates = [];
288
+
289
+ async function walk(dir, depth) {
290
+ if (depth > maxDepth) return;
291
+ let entries;
292
+ try { entries = await fsp.readdir(dir, { withFileTypes: true }); }
293
+ catch { return; }
294
+
295
+ let hasManifest = false;
296
+ let hasGit = false;
297
+ const subDirs = [];
298
+ for (const e of entries) {
299
+ if (!e.isDirectory() && !e.isFile()) continue;
300
+ if (e.name.startsWith('.')) {
301
+ if (e.name === '.git' && e.isDirectory()) hasGit = true;
302
+ continue;
303
+ }
304
+ if (e.isDirectory()) {
305
+ if (SKIP_DIRS.has(e.name)) continue;
306
+ subDirs.push(path.join(dir, e.name));
307
+ } else if (e.isFile() && MANIFEST_FILES.includes(e.name)) {
308
+ hasManifest = true;
309
+ }
310
+ }
311
+ if (hasManifest || hasGit) {
312
+ candidates.push(dir);
313
+ return; // 子目录里若还有 manifest,会被自己发现;这里不再下钻避免冗余
314
+ }
315
+ if (depth >= maxDepth) return;
316
+ for (const sub of subDirs) {
317
+ await walk(sub, depth + 1);
318
+ }
319
+ }
320
+
321
+ await walk(projectPath, 0);
322
+
323
+ // 去重:若 candidates 里 A 是 B 的祖先,只保留更深一级的 B
324
+ candidates.sort((a, b) => a.length - b.length);
325
+ const kept = [];
326
+ for (const c of candidates) {
327
+ let dominated = false;
328
+ for (const k of kept) {
329
+ if (c === k || c.startsWith(k + path.sep)) { dominated = true; break; }
330
+ }
331
+ if (!dominated) kept.push(c);
332
+ }
333
+
334
+ // 收集每个子项目的关键文件
335
+ const result = [];
336
+ for (const root of kept) {
337
+ const manifests = {};
338
+ for (const m of MANIFEST_FILES) {
339
+ const p = path.join(root, m);
340
+ try {
341
+ const stat = await fsp.stat(p);
342
+ if (stat.isFile()) {
343
+ manifests[m] = stat.size > 20000
344
+ ? await safeReadFile(p, 20000)
345
+ : await fsp.readFile(p, 'utf8');
346
+ }
347
+ } catch { /* 不存在就跳过 */ }
348
+ }
349
+ let readme = '';
350
+ try {
351
+ const stat = await fsp.stat(path.join(root, 'README.md'));
352
+ if (stat.isFile()) readme = await safeReadFile(path.join(root, 'README.md'), 8000);
353
+ } catch { /* 不存在就跳过 */ }
354
+ const dirTree = await listDirTree(root, 2, 200);
355
+ result.push({
356
+ root,
357
+ name: path.basename(root) || path.basename(projectPath),
358
+ manifests,
359
+ readme,
360
+ dirTree
361
+ });
362
+ }
363
+ return result;
364
+ }
365
+
234
366
  function publish(event, payload) {
235
367
  bus.emit('event', { event, payload, ts: nowIso() });
236
368
  }
@@ -449,112 +581,175 @@ export function registerWorkbenchRoutes({ app, getCurrentProjectPath, getProject
449
581
  return res.status(400).json({ success: false, error: '未配置 AI 模型,请先在通用设置中添加模型' });
450
582
  }
451
583
 
452
- // 收集项目上下文
453
- const dirTree = await listDirTree(projectPath, 2, 400);
454
- const manifest = await readProjectManifest(projectPath);
455
- const readme = await safeReadFile(path.join(projectPath, 'README.md'), 8000);
456
-
457
- const manifestBlock = Object.entries(manifest)
458
- .map(([name, content]) => `\n--- ${name} ---\n${content}`)
459
- .join('\n');
584
+ // 读取用户可编辑的生成指令;没存就用默认
585
+ const userInstruction = await readInstruction();
586
+
587
+ // 递归识别多子项目
588
+ const subProjects = await findSubProjects(projectPath);
589
+ if (subProjects.length === 0) {
590
+ // 没识别到任何子项目:回退到根目录本身
591
+ const fallbackTree = await listDirTree(projectPath, 2, 400);
592
+ const fallbackManifest = await readProjectManifest(projectPath);
593
+ const fallbackReadme = await safeReadFile(path.join(projectPath, 'README.md'), 8000);
594
+ subProjects.push({
595
+ root: projectPath,
596
+ name: path.basename(projectPath),
597
+ manifests: fallbackManifest,
598
+ readme: fallbackReadme,
599
+ dirTree: fallbackTree
600
+ });
601
+ }
460
602
 
461
603
  const projectName = path.basename(projectPath);
604
+ const LLM_OPTS = { maxTokens: 4000, timeoutMs: 1200000 };
462
605
 
463
- const userPayload = `项目根目录:${projectPath}
464
- 项目名称:${projectName}
606
+ // ── 第一阶段:基于可编辑指令 + 根目录概览,生成「可复用的提示词模板」 ──
607
+ const overviewBlock = subProjects.map(sp =>
608
+ `### 子项目 ${sp.name} (${sp.root})\n目录:\n${sp.dirTree || '(无)'}`
609
+ ).join('\n\n');
465
610
 
466
- ## 目录结构(前 2 层,截断)
467
- ${dirTree || '(无)'}
611
+ const firstPrompt = `${userInstruction}
468
612
 
469
- ## README.md
470
- ${readme || '(无)'}
613
+ ---
471
614
 
472
- ## 关键 manifest
473
- ${manifestBlock || '(无)'}`;
615
+ 以下是你需要分析的项目(请先生成「可复用的提示词模板」,不要直接给总结):
474
616
 
475
- // 第一阶段:让 LLM 写一段「可复用的提示词模板」
476
- const templateSystemPrompt = `你是一名资深软件架构师。任务:根据用户提供的项目目录结构、README、manifest 文件,输出一段**可复用的提示词模板**。
477
- 这段模板将作为指令注入到大模型的 system prompt 中,用来指导大模型对**当前项目**做「项目架构总结」。
617
+ 项目根目录:${projectPath}
618
+ 项目名称:${projectName}
619
+ 子项目数:${subProjects.length}
620
+
621
+ ## 子项目概览
622
+ ${overviewBlock || '(无)'}
478
623
 
479
- 要求:
480
- 1. 模板主体使用中文,语气专业、具体
481
- 2. 模板中必须明确使用 4 个变量占位符:
482
- - {{task.title}} - 任务标题
483
- - {{task.desc}} - 任务详细描述
484
- - {{sub.title}} - 子任务标题
485
- - {{sub.desc}} - 子任务详细描述
486
- 并向大模型说明:项目根目录是 {{repo.path}},当前 git 分支是 {{branch}}
487
- 3. 模板应指导大模型:阅读项目目录、识别语言与框架、找出入口文件、画出主要模块依赖关系、输出 200-400 字的中文总结
488
- 4. 模板长度控制在 300-600 字之间
489
- 5. 只返回 JSON,不要任何额外解释
624
+ ## 各子项目 manifest 与 README
625
+ ${subProjects.map(sp => {
626
+ const manifestBlock = Object.entries(sp.manifests)
627
+ .map(([n, c]) => `\n--- ${n} ---\n${c}`)
628
+ .join('\n');
629
+ return `\n### ${sp.name}\n${manifestBlock || '(无 manifest)'}\n\nREADME(前 8KB):\n${sp.readme || '(无)'}`;
630
+ }).join('\n')}
490
631
 
491
- 返回 JSON:
632
+ 只返回 JSON:
492
633
  {
493
- "name": "模板名称(10-20字)",
494
- "template": "模板正文"
634
+ "name": "项目名(10-20字)",
635
+ "template": "可复用的提示词模板(300-600字),应明确使用 {{task.title}} / {{task.desc}} / {{sub.title}} / {{sub.desc}} / {{repo.path}} / {{branch}} 这 6 个变量"
495
636
  }`;
496
637
 
497
- const first = await callLlmJson(model, `${templateSystemPrompt}\n\n${userPayload}`);
498
- const templateName = String(first.name || '').trim() || '项目架构总结';
638
+ const first = await callLlmJson(model, firstPrompt, LLM_OPTS);
639
+ const templateName = String(first.name || '').trim() || projectName || '项目架构说明';
499
640
  const template = String(first.template || '').trim();
500
- if (!template) {
501
- return res.status(500).json({ success: false, error: 'AI 未返回有效模板' });
502
- }
503
641
 
504
- // 第二阶段:以模板为指令,喂入项目上下文,跑一次实际生成
505
- const execPrompt = `${template}
642
+ // ── 第二阶段:为每个子项目分别生成总结(单子项目 = 现在的行为) ──
643
+ async function summarizeOneSub(sp) {
644
+ const manifestBlock = Object.entries(sp.manifests)
645
+ .map(([n, c]) => `\n--- ${n} ---\n${c}`)
646
+ .join('\n');
647
+ const subPrompt = `${template}
506
648
 
507
649
  ---
508
650
 
509
- 以下是你需要分析的项目实际数据(请直接基于这些数据输出最终结果):
651
+ 以下是你需要分析的一个子项目(请直接基于这些数据输出该子项目的架构说明):
510
652
 
511
- 项目根目录:${projectPath}
512
- 项目名称:${projectName}
653
+ 子项目根目录:${sp.root}
654
+ 子项目名称:${sp.name}
513
655
 
514
656
  ## 目录结构(前 2 层)
515
- ${dirTree || '(无)'}
516
-
517
- ## README.md
518
- ${readme || '(无)'}
657
+ ${sp.dirTree || '(无)'}
519
658
 
520
- ## 关键 manifest
659
+ ## manifest
521
660
  ${manifestBlock || '(无)'}
522
661
 
523
- 请输出一份 200-400 字的中文架构总结,包含:项目整体定位、技术栈、模块划分、核心流程、关键设计决策。只返回 JSON:
662
+ ## README
663
+ ${sp.readme || '(无)'}
524
664
 
665
+ 只返回 JSON:
525
666
  {
526
- "summary": "架构总结正文"
667
+ "summary": "该子项目的架构说明(300-600字)"
527
668
  }`;
669
+ const r = await callLlmJson(model, subPrompt, LLM_OPTS);
670
+ return { name: sp.name, root: sp.root, summary: String(r.summary || '').trim() };
671
+ }
672
+
673
+ const subSummaries = await Promise.all(subProjects.map(summarizeOneSub));
674
+
675
+ // ── 第三阶段:仅多子项目时合并(单子项目直接拿它的 summary) ──
676
+ let finalSummary = '';
677
+ let finalName = templateName;
678
+
679
+ if (subSummaries.length === 1) {
680
+ finalSummary = subSummaries[0].summary;
681
+ } else {
682
+ const mergePrompt = `你是项目架构师。下列是同一仓库下 N 个子项目的架构说明,请合并输出**单一**的「项目架构说明」(800-1500字),覆盖:项目整体定位、技术栈、模块划分、子项目间关系、核心流程、关键设计决策。
683
+ 子项目之间用清晰的小标题或编号分隔。最后输出一段「整体架构」总结它们如何协同。
684
+ 只引用实际出现的子项目名 / 文件路径 / 依赖名,不要编造。只返回 JSON:
685
+
686
+ {
687
+ "name": "项目名(10-20字)",
688
+ "summary": "合并后的架构说明"
689
+ }
528
690
 
529
- const second = await callLlmJson(model, execPrompt);
530
- const summary = String(second.summary || '').trim();
691
+ ## 子项目说明
692
+ ${subSummaries.map((s, i) => `\n### [${i + 1}] ${s.name} (${s.root})\n${s.summary || '(空)'}`).join('\n')}`;
531
693
 
532
- if (!summary) {
533
- // 兜底:仅返回模板,结果留空
694
+ const merged = await callLlmJson(model, mergePrompt, LLM_OPTS);
695
+ finalSummary = String(merged.summary || '').trim()
696
+ || subSummaries.map(s => `### ${s.name}\n${s.summary}`).join('\n\n');
697
+ finalName = String(merged.name || '').trim() || templateName;
698
+ }
699
+
700
+ if (!finalSummary) {
701
+ // 兜底:仅返回模板
534
702
  return res.json({
535
703
  success: true,
536
- name: templateName,
704
+ name: finalName,
537
705
  template,
538
706
  result: '',
539
707
  content: template
540
708
  });
541
709
  }
542
710
 
543
- // 把模板和实际结果拼到一起,作为预置提示词存进 prompts.json
544
- const content = `${template}\n\n## 当前项目架构总结(已生成于 ${nowIso()})\n\n${summary}`;
545
-
711
+ // 顶层 request 已经自带 20 分钟(1200s)超时;
712
+ // 这里在 express 处理器内部不再额外加整体超时。
546
713
  res.json({
547
714
  success: true,
548
- name: templateName,
715
+ name: finalName,
549
716
  template,
550
- result: summary,
551
- content
717
+ result: finalSummary,
718
+ content: finalSummary
552
719
  });
553
720
  } catch (err) {
554
721
  res.status(500).json({ success: false, error: err.message });
555
722
  }
556
723
  });
557
724
 
725
+ // ── 生成指令:读 / 写(用户可在弹窗里自定义) ───────────────────────
726
+ app.get('/api/workbench/prompts/ai-instruction', async (_req, res) => {
727
+ try {
728
+ const instruction = await readInstruction();
729
+ res.json({ success: true, instruction, isDefault: instruction === DEFAULT_INSTRUCTION });
730
+ } catch (err) {
731
+ res.status(500).json({ success: false, error: err.message });
732
+ }
733
+ });
734
+
735
+ app.put('/api/workbench/prompts/ai-instruction', async (req, res) => {
736
+ try {
737
+ const text = req.body && typeof req.body.instruction === 'string'
738
+ ? req.body.instruction.trim()
739
+ : '';
740
+ if (!text) {
741
+ return res.status(400).json({ success: false, error: '指令不能为空' });
742
+ }
743
+ if (text.length > 50000) {
744
+ return res.status(413).json({ success: false, error: '指令过长(最多 50000 字符)' });
745
+ }
746
+ await writeInstruction(text);
747
+ res.json({ success: true });
748
+ } catch (err) {
749
+ res.status(500).json({ success: false, error: err.message });
750
+ }
751
+ });
752
+
558
753
  // SSE 事件流
559
754
  app.get('/api/workbench/events', (req, res) => {
560
755
  res.set({
@@ -1,3 +0,0 @@
1
- import{o as e}from"./rolldown-runtime-CMxvf4Kt.js";import{$n as t,An as n,Cn as r,En as i,Fn as a,Hn as o,In as s,Jn as c,Kn as l,Ln as u,Mn as d,Nn as f,P as p,Qn as m,Sn as ee,Un as te,Wn as ne,_ as re,ar as h,c as g,cr as _,d as v,er as y,f as ie,g as ae,h as oe,ht as se,ir as ce,kn as b,m as le,or as x,p as ue,rr as S,sr as C,t as de,v as fe,wn as pe,y as me,zn as he}from"./vendor-A4IPqbyo.js";import{n as w,t as T}from"./_plugin-vue_export-helper-opDPZuCO.js";import{a as ge,r as _e}from"./index-DPihtJfT.js";var ve=e(v(),1),ye={class:`source-map-view`},be={class:`sm-toolbar`},xe={class:`sm-toolbar-left`},Se={class:`sm-title`},Ce={class:`sm-toolbar-center`},we=[`placeholder`,`disabled`],Te=[`disabled`],Ee={class:`sm-toolbar-right`},De={class:`sm-body`},Oe={class:`sm-panel-header sm-panel-header--tabs`},ke={key:0,class:`sm-badge`},Ae={class:`sm-panel-body sm-file-tree`},je=[`onClick`],Me={key:1,class:`sm-tree-arrow-spacer`},Ne={key:2,class:`sm-tree-icon mit-icon`,"aria-hidden":`true`},Pe=[`xlink:href`],Fe={key:3,class:`sm-tree-icon mit-icon`,"aria-hidden":`true`},Ie=[`xlink:href`],Le=[`title`],Re={key:1,class:`sm-tree-empty`},ze={class:`sm-panel-body sm-outline-body`},Be={class:`sm-badge`,style:{"margin-left":`auto`}},Ve=[`onClick`],He=[`title`],Ue={key:0,class:`sm-outline-desc`},We={key:1,class:`sm-tree-empty`},Ge={class:`sm-panel sm-panel-graph`},Ke={key:0,class:`sm-project-info`},qe={class:`sm-lang-badge`},Je={class:`sm-summary-text`},Ye={class:`sm-graph-container`},Xe={class:`sm-layout-btn-wrap`},Ze=[`disabled`],Qe=[`title`],$e={class:`sm-fn-label`},et={key:0,class:`sm-fn-desc`},tt={key:0,class:`sm-graph-empty`},nt={viewBox:`0 0 24 24`,width:`48`,height:`48`,fill:`none`,stroke:`currentColor`,"stroke-width":`1`,style:{opacity:`0.3`}},rt={key:1,class:`sm-graph-loading`},it={class:`sm-log-header`},at={key:0,class:`sm-log-indicator`},ot={class:`sm-log-body`,ref:`logBodyRef`},st={key:0,class:`sm-empty`},ct={class:`sm-panel-header`},lt={key:0,class:`sm-badge sm-badge-amber`},ut={key:0,class:`sm-node-detail`},dt={class:`sm-node-name`},ft={class:`sm-node-file`},pt={key:0},mt={key:0,class:`sm-node-desc`},ht={class:`sm-panel-body sm-source-body`},gt={key:0,class:`sm-source-overlay`},_t={key:1,class:`sm-source-overlay sm-source-placeholder`},E=T(he({__name:`SourceMapView`,setup(e){let v=S(document.documentElement.getAttribute(`data-theme`)===`dark`?`dark`:`light`);function he(){v.value=document.documentElement.getAttribute(`data-theme`)===`dark`?`dark`:`light`}let T=null,E=ge(),D=S(E.currentDirectory||``),O=S(`idle`),k=S([]),vt=0,A=S(null),j=S(null),M=S(`files`),N=S(``),P=S(``),F=S(!1),I=S([]),L=S(new Set),R=S({files:!0,graph:!0,source:!0}),z=S(!1),B=S(220),V=S(360),H=S(140),U=null,W=0,yt=0,G=0;function K(e,t){U=e,W=t.clientX,yt=t.clientY,G=e===`files`?B.value:e===`source`?V.value:H.value,document.addEventListener(`mousemove`,bt),document.addEventListener(`mouseup`,q),t.preventDefault()}function bt(e){U&&(U===`files`?B.value=Math.max(120,Math.min(480,G+e.clientX-W)):U===`source`?V.value=Math.max(200,Math.min(700,G+W-e.clientX)):H.value=Math.max(60,Math.min(500,G+yt-e.clientY)))}function q(){U=null,document.removeEventListener(`mousemove`,bt),document.removeEventListener(`mouseup`,q)}let J=S(null),Y=ce(null),{fitView:xt,setNodes:X,setEdges:St,getNodes:Ct,getEdges:wt,updateNodeInternals:Tt}=me(),Z=b(()=>O.value===`scanning`||O.value===`analyzing`),Et=b(()=>v.value===`dark`?`#334155`:`#cbd5e1`),Q=b(()=>A.value?.nodes.find(e=>e.id===j.value)??null),Dt=b(()=>{if(!A.value)return[];let e=new Map;for(let t of A.value.nodes){let n=t.subsystem??`__default__`;if(!e.has(n)){let r=A.value.subsystems?.find(e=>e.name===n);e.set(n,{displayName:r?.displayName||t.subsystem||w(`@SRCMAP:默认`),color:t.subsystemColor||kt[0],nodes:[]})}e.get(n).nodes.push(t)}return[...e.entries()].map(([,e])=>e)});function $(e,t=`info`){k.value.push({id:++vt,message:e,type:t,timestamp:Date.now()}),k.value.length>200&&k.value.splice(0,k.value.length-200)}function Ot(e){let t={name:``,path:``,kind:`dir`,children:[],childMap:new Map};for(let n of e){let e=n.trim().split(`/`).filter(Boolean),r=t,i=``;for(let t=0;t<e.length;t++){let n=e[t];i=i?`${i}/${n}`:n;let a=t===e.length-1,o=r.childMap.get(n);o||(o={name:n,path:i,kind:a?`file`:`dir`,children:[],childMap:new Map},r.childMap.set(n,o),r.children.push(o)),r=o}}let n=e=>{e.sort((e,t)=>e.kind===t.kind?e.name.localeCompare(t.name):e.kind===`dir`?-1:1),e.forEach(e=>{e.kind===`dir`&&n(e.children)})};return n(t.children),t.children}let kt=[`#f59e0b`,`#3b82f6`,`#10b981`,`#8b5cf6`];function At(e){return e.subsystemColor?e.subsystemColor:e.subsystemIndex===void 0?e.importance===`high`?`#f59e0b`:e.importance===`low`?`#94a3b8`:`#3b82f6`:kt[e.subsystemIndex%kt.length]}function jt(e){return{ts:`typescript`,tsx:`typescript`,js:`javascript`,mjs:`javascript`,cjs:`javascript`,jsx:`javascript`,vue:`html`,svelte:`html`,html:`html`,py:`python`,java:`java`,go:`go`,rs:`rust`,cpp:`cpp`,cc:`cpp`,cxx:`cpp`,c:`c`,h:`c`,hpp:`cpp`,cs:`csharp`,rb:`ruby`,php:`php`,swift:`swift`,kt:`kotlin`,sh:`shell`,bash:`shell`,json:`json`,yaml:`yaml`,yml:`yaml`,md:`markdown`,css:`css`,scss:`scss`,less:`less`,sql:`sql`}[e.split(`.`).pop()?.toLowerCase()||``]||`plaintext`}function Mt(){!J.value||Y.value||(Y.value=g.create(J.value,{value:``,language:`plaintext`,theme:v.value===`dark`?`vs-dark`:`vs`,readOnly:!0,fontSize:12,lineHeight:19,fontFamily:`'JetBrains Mono', 'Fira Code', Consolas, monospace`,minimap:{enabled:!1},scrollBeyondLastLine:!1,automaticLayout:!0,wordWrap:`off`,padding:{top:8,bottom:8},scrollbar:{verticalScrollbarSize:6,horizontalScrollbarSize:6}}))}m(v,e=>{Y.value&&g.setTheme(e===`dark`?`vs-dark`:`vs`)});function Nt(e,t){let n={};t.forEach(e=>{n[e.source]||(n[e.source]=[]),n[e.source].push(e.target)});let r=new Map;e.forEach(e=>{let t=e.subsystem??`__default`;r.has(t)||r.set(t,[]),r.get(t).push(e)});let i=[],a=0;for(let[,e]of r){let t=new Set(e.map(e=>e.id)),r={},o=e.length?[e[0].id]:[];for(o[0]&&(r[o[0]]=0);o.length;){let e=o.shift();(n[e]||[]).filter(e=>t.has(e)).forEach(t=>{r[t]===void 0&&(r[t]=(r[e]??0)+1,o.push(t))})}let s={};e.forEach(e=>{let t=r[e.id]??0;s[t]=(s[t]||0)+1});let c={};e.forEach(e=>{let t=r[e.id]??0;c[t]=(c[t]??-1)+1;let n=c[t],o=s[t]??1,l=a*600+n*220-(o-1)*220/2,u=t*110,d=At(e);i.push({id:e.id,type:`default`,position:{x:l,y:u},label:e.label,class:`sm-fn-node`,data:{...e,_accentColor:d},style:{"--node-accent":d}})}),a++}return{flowNodes:i,flowEdges:t.map((e,t)=>({id:`e_${t}_${e.source}_${e.target}`,source:e.source,target:e.target,type:`smoothstep`,animated:!1,class:`sm-fn-edge`,markerEnd:{type:oe.ArrowClosed}}))}}async function Pt(){let e=Ct.value,t=wt.value;if(e.length!==0){z.value=!0;try{await o(),await new Promise(e=>requestAnimationFrame(()=>e())),Tt(e.map(e=>e.id)),await new Promise(e=>requestAnimationFrame(()=>e()));let n=new Map;e.forEach(e=>{let t=e.data?.subsystem??`__default__`;n.has(t)||n.set(t,[]),n.get(t).push(e)});let r=new Map,i=0;for(let[,e]of n){let n=new ve.default.graphlib.Graph;n.setDefaultEdgeLabel(()=>({})),n.setGraph({rankdir:`TB`,nodesep:55,ranksep:75,marginx:40,marginy:40});let a=new Set(e.map(e=>e.id));e.forEach(e=>{let t=190,r=e.data?.description?68:48,i=document.querySelector(`.vue-flow__node[data-id="${e.id}"]`);i&&i.offsetWidth>0&&(t=i.offsetWidth,r=i.offsetHeight),n.setNode(e.id,{width:t,height:r})}),t.forEach(e=>{a.has(e.source)&&a.has(e.target)&&n.setEdge(e.source,e.target)}),ve.default.layout(n);let o=0;e.forEach(e=>{let t=n.node(e.id);t&&(r.set(e.id,{x:i+t.x-t.width/2,y:t.y-t.height/2}),o=Math.max(o,t.x+t.width/2))}),i+=o+120}X(e.map(e=>({...e,position:r.get(e.id)??e.position}))),await o(),xt({padding:.18})}finally{z.value=!1}}}async function Ft(){if(!D.value.trim()){p.warning(w(`@SRCMAP:请先输入项目路径`));return}if(!Z.value){k.value=[],A.value=null,j.value=null,N.value=``,P.value=``,X([]),St([]),O.value=`scanning`,$(w(`@SRCMAP:开始分析项目...`),`info`);try{let e=await fetch(`/api/code-analysis/analyze`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({path:D.value})});if(!e.ok){let t=await e.json().catch(()=>({error:`请求失败`}));throw Error(t.error||`HTTP ${e.status}`)}let t=e.body.getReader(),n=new TextDecoder,r=``;O.value=`analyzing`;let i=``,a=[];for(;;){let{done:e,value:o}=await t.read();if(e)break;r+=n.decode(o,{stream:!0});let s=r.split(`
2
- `);r=s.pop()??``;for(let e of s)if(e.startsWith(`event:`))i=e.slice(6).trim(),a=[];else if(e.startsWith(`data:`))a.push(e.slice(5).trim());else if(e===``){if(i&&a.length){let e=a.join(``);try{let t=JSON.parse(e);It(i,t)}catch{}}i=``,a=[]}}}catch(e){$(`${w(`@SRCMAP:分析失败`)}: ${e.message}`,`error`),O.value=`error`}}}function It(e,t){if(e===`log`)$(t.message,t.type||`info`);else if(e===`files`)I.value=Ot(t.files||[]),I.value.forEach(e=>{e.kind===`dir`&&L.value.add(e.path)});else if(e===`result`){A.value={language:t.language||``,entryFile:t.entryFile||``,entryFunction:t.entryFunction||``,nodes:Array.isArray(t.nodes)?t.nodes:[],edges:Array.isArray(t.edges)?t.edges:[],techStack:Array.isArray(t.techStack)?t.techStack:[],summary:t.summary||``,allFiles:Array.isArray(t.allFiles)?t.allFiles:[],codeFiles:Array.isArray(t.codeFiles)?t.codeFiles:[],subsystems:Array.isArray(t.subsystems)?t.subsystems:void 0};let{flowNodes:e,flowEdges:n}=Nt(A.value.nodes,A.value.edges);X(e),St(n),o(()=>Pt())}else e===`done`&&(t.error?($(`${w(`@SRCMAP:分析失败`)}: ${t.error}`,`error`),O.value=`error`):O.value=`done`)}async function Lt(e){if(!(!e||F.value)&&P.value!==e){F.value=!0,P.value=e,N.value=``;try{let t=await(await fetch(`/api/code-analysis/file-content?path=${encodeURIComponent(D.value)}&file=${encodeURIComponent(e)}`)).json();if(t.error)throw Error(t.error);N.value=t.content||``}catch(e){N.value=`// ${w(`@SRCMAP:加载失败`)}: ${e.message}`}finally{F.value=!1}}}function Rt(e){let t=e.node.data;j.value=t.id,t.file&&Lt(t.file)}function zt(e){L.value.has(e)?L.value.delete(e):L.value.add(e)}let Bt=b(()=>{let e=[];function t(n,r){for(let i of n){let n=L.value.has(i.path);e.push({name:i.name,path:i.path,kind:i.kind,depth:r,expanded:n}),i.kind===`dir`&&n&&t(i.children,r+1)}}return t(I.value,0),e});return m(()=>E.currentDirectory,e=>{e&&!D.value&&(D.value=e)}),m([N,P],([e,t])=>{let n=Y.value;if(!n)return;let r=jt(t||``),i=n.getModel(),a=g.createModel(e||``,r);n.setModel(a),i?.dispose(),n.setScrollPosition({scrollTop:0,scrollLeft:0})}),ne(()=>{Mt(),!D.value&&E.currentDirectory&&(D.value=E.currentDirectory),T=new MutationObserver(()=>he()),T.observe(document.documentElement,{attributes:!0,attributeFilter:[`data-theme`]})}),te(()=>{Y.value?.getModel()?.dispose(),Y.value?.dispose(),q(),T?.disconnect(),T=null}),(e,o)=>{let p=se;return l(),f(`div`,ye,[n(`div`,be,[n(`div`,xe,[o[9]||=n(`svg`,{viewBox:`0 0 24 24`,width:`18`,height:`18`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.8`,class:`sm-icon-map`},[n(`polygon`,{points:`3 6 9 3 15 6 21 3 21 18 15 21 9 18 3 21`}),n(`line`,{x1:`9`,y1:`3`,x2:`9`,y2:`18`}),n(`line`,{x1:`15`,y1:`6`,x2:`15`,y2:`21`})],-1),n(`span`,Se,_(h(w)(`@SRCMAP:源码地图`)),1)]),n(`div`,Ce,[y(n(`input`,{"onUpdate:modelValue":o[0]||=e=>D.value=e,class:`sm-path-input`,placeholder:h(w)(`@SRCMAP:输入项目目录路径`),disabled:Z.value,onKeydown:pe(Ft,[`enter`])},null,40,we),[[ee,D.value]]),n(`button`,{class:`sm-btn sm-btn-primary`,disabled:Z.value,onClick:Ft},[Z.value?(l(),f(i,{key:0},[o[10]||=n(`span`,{class:`sm-spinner`},null,-1),s(` `+_(h(w)(`@SRCMAP:分析中...`)),1)],64)):(l(),f(i,{key:1},[s(_(O.value===`done`?h(w)(`@SRCMAP:重新分析`):h(w)(`@SRCMAP:开始分析`)),1)],64))],8,Te)]),n(`div`,Ee,[u(p,{content:h(w)(`@SRCMAP:文件列表`),placement:`bottom`},{default:t(()=>[n(`button`,{class:x([`sm-panel-btn`,{active:R.value.files}]),onClick:o[1]||=e=>R.value.files=!R.value.files},[...o[11]||=[n(`svg`,{viewBox:`0 0 24 24`,width:`16`,height:`16`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.8`},[n(`path`,{d:`M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z`})],-1)]],2)]),_:1},8,[`content`]),u(p,{content:h(w)(`@SRCMAP:调用图`),placement:`bottom`},{default:t(()=>[n(`button`,{class:x([`sm-panel-btn`,{active:R.value.graph}]),onClick:o[2]||=e=>R.value.graph=!R.value.graph},[...o[12]||=[n(`svg`,{viewBox:`0 0 24 24`,width:`16`,height:`16`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.8`},[n(`circle`,{cx:`12`,cy:`12`,r:`3`}),n(`circle`,{cx:`3`,cy:`6`,r:`2`}),n(`circle`,{cx:`21`,cy:`6`,r:`2`}),n(`circle`,{cx:`3`,cy:`18`,r:`2`}),n(`circle`,{cx:`21`,cy:`18`,r:`2`}),n(`line`,{x1:`5`,y1:`6`,x2:`9`,y2:`11`}),n(`line`,{x1:`19`,y1:`6`,x2:`15`,y2:`11`}),n(`line`,{x1:`5`,y1:`18`,x2:`9`,y2:`13`}),n(`line`,{x1:`19`,y1:`18`,x2:`15`,y2:`13`})],-1)]],2)]),_:1},8,[`content`]),u(p,{content:h(w)(`@SRCMAP:源码面板`),placement:`bottom`},{default:t(()=>[n(`button`,{class:x([`sm-panel-btn`,{active:R.value.source}]),onClick:o[3]||=e=>R.value.source=!R.value.source},[...o[13]||=[n(`svg`,{viewBox:`0 0 24 24`,width:`16`,height:`16`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.8`},[n(`polyline`,{points:`16 18 22 12 16 6`}),n(`polyline`,{points:`8 6 2 12 8 18`})],-1)]],2)]),_:1},8,[`content`])])]),n(`div`,De,[y(n(`div`,{class:`sm-panel sm-panel-files`,style:C({width:B.value+`px`})},[n(`div`,Oe,[n(`button`,{class:x([`sm-tab-btn`,{active:M.value===`files`}]),onClick:o[4]||=e=>M.value=`files`},[o[14]||=n(`svg`,{viewBox:`0 0 24 24`,width:`12`,height:`12`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.8`},[n(`path`,{d:`M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z`})],-1),s(` `+_(h(w)(`@SRCMAP:文件列表`))+` `,1),A.value?(l(),f(`span`,ke,_(A.value.allFiles.length),1)):d(``,!0)],2),n(`button`,{class:x([`sm-tab-btn`,{active:M.value===`outline`}]),onClick:o[5]||=e=>M.value=`outline`},[o[15]||=a(`<svg viewBox="0 0 24 24" width="12" height="12" fill="none" stroke="currentColor" stroke-width="1.8" data-v-71d3569e><line x1="8" y1="6" x2="21" y2="6" data-v-71d3569e></line><line x1="8" y1="12" x2="21" y2="12" data-v-71d3569e></line><line x1="8" y1="18" x2="21" y2="18" data-v-71d3569e></line><line x1="3" y1="6" x2="3.01" y2="6" data-v-71d3569e></line><line x1="3" y1="12" x2="3.01" y2="12" data-v-71d3569e></line><line x1="3" y1="18" x2="3.01" y2="18" data-v-71d3569e></line></svg>`,1),s(` `+_(h(w)(`@SRCMAP:大纲`)),1)],2)]),y(n(`div`,Ae,[Bt.value.length>0?(l(!0),f(i,{key:0},c(Bt.value,e=>(l(),f(`div`,{key:e.path,class:x([`sm-tree-node`,{"sm-tree-node--dir":e.kind===`dir`,"sm-tree-node--active":e.kind===`file`&&P.value===e.path}]),style:C({paddingLeft:10+e.depth*14+`px`}),onClick:t=>e.kind===`dir`?zt(e.path):Lt(e.path)},[e.kind===`dir`?(l(),f(`span`,{key:0,class:x([`sm-tree-arrow`,{expanded:e.expanded}])},[...o[16]||=[n(`svg`,{viewBox:`0 0 24 24`,width:`10`,height:`10`,fill:`none`,stroke:`currentColor`,"stroke-width":`2.5`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[n(`polyline`,{points:`9 18 15 12 9 6`})],-1)]],2)):(l(),f(`span`,Me)),e.kind===`dir`?(l(),f(`svg`,Ne,[n(`use`,{"xlink:href":`#${h(_e)(e.name)||`icon-folder`}`},null,8,Pe)])):(l(),f(`svg`,Fe,[n(`use`,{"xlink:href":`#${h(_e)(e.name)}`},null,8,Ie)])),n(`span`,{class:`sm-tree-name`,title:e.path},_(e.name),9,Le)],14,je))),128)):(l(),f(`div`,Re,_(h(w)(`@SRCMAP:暂无文件,请先开始分析`)),1))],512),[[r,M.value===`files`]]),y(n(`div`,ze,[Dt.value.length>0?(l(!0),f(i,{key:0},c(Dt.value,e=>(l(),f(`div`,{key:e.displayName,class:`sm-outline-group`},[n(`div`,{class:`sm-outline-group-header`,style:C({color:e.color})},[o[17]||=n(`svg`,{viewBox:`0 0 24 24`,width:`8`,height:`8`,fill:`currentColor`},[n(`circle`,{cx:`12`,cy:`12`,r:`6`})],-1),s(` `+_(e.displayName)+` `,1),n(`span`,Be,_(e.nodes.length),1)],4),(l(!0),f(i,null,c(e.nodes,t=>(l(),f(`div`,{key:t.id,class:x([`sm-outline-node`,{"sm-outline-node--active":j.value===t.id}]),onClick:e=>{j.value=t.id,t.file&&Lt(t.file)}},[n(`span`,{class:`sm-outline-dot`,style:C({background:e.color})},null,4),n(`span`,{class:`sm-outline-label`,title:t.file||t.label},_(t.label),9,He),t.description?(l(),f(`span`,Ue,_(t.description.length>18?t.description.slice(0,18)+`…`:t.description),1)):d(``,!0)],10,Ve))),128))]))),128)):(l(),f(`div`,We,_(h(w)(`@SRCMAP:暂无分析结果`)),1))],512),[[r,M.value===`outline`]])],4),[[r,R.value.files]]),y(n(`div`,{class:`sm-resizer sm-resizer-v`,onMousedown:o[6]||=e=>K(`files`,e)},null,544),[[r,R.value.files&&R.value.graph]]),y(n(`div`,Ge,[A.value?(l(),f(`div`,Ke,[n(`span`,qe,_(A.value.language),1),A.value.subsystems&&A.value.subsystems.length>1?(l(!0),f(i,{key:0},c(A.value.subsystems,e=>(l(),f(`span`,{key:e.name,class:`sm-subsystem-tag`,style:C({borderColor:e.color,color:e.color})},`● `+_(e.displayName||e.name),5))),128)):(l(!0),f(i,{key:1},c(A.value.techStack.slice(0,4),e=>(l(),f(`span`,{key:e,class:`sm-tech-tag`},_(e),1))),128)),n(`span`,Je,_(A.value.summary),1)])):d(``,!0),n(`div`,Ye,[n(`div`,Xe,[n(`button`,{class:`sm-layout-btn`,disabled:z.value||!A.value,onClick:Pt},[o[18]||=a(`<svg viewBox="0 0 24 24" width="12" height="12" fill="none" stroke="currentColor" stroke-width="1.8" data-v-71d3569e><rect x="3" y="3" width="7" height="7" rx="1" data-v-71d3569e></rect><rect x="14" y="3" width="7" height="7" rx="1" data-v-71d3569e></rect><rect x="3" y="14" width="7" height="7" rx="1" data-v-71d3569e></rect><rect x="14" y="14" width="7" height="7" rx="1" data-v-71d3569e></rect></svg>`,1),s(` `+_(z.value?h(w)(`@SRCMAP:布局中...`):h(w)(`@SRCMAP:优化布局`)),1)],8,Ze)]),u(h(re),{class:`sm-vue-flow`,"default-viewport":{zoom:1},"min-zoom":.2,"max-zoom":4,"fit-view-on-init":``,onNodeClick:Rt},{"node-default":t(({data:e,label:t})=>[u(h(fe),{type:`target`,position:h(ae).Top},null,8,[`position`]),n(`div`,{class:`sm-fn-inner`,title:`${t}${e?.description?`
3
- `+e.description:``}`},[n(`div`,$e,_(t),1),e?.description?(l(),f(`div`,et,_(e.description.length>22?e.description.slice(0,22)+`…`:e.description),1)):d(``,!0)],8,Qe),u(h(fe),{type:`source`,position:h(ae).Bottom},null,8,[`position`])]),default:t(()=>[u(h(le),{variant:h(ue).Dots,gap:20,size:1,"pattern-color":Et.value},null,8,[`variant`,`pattern-color`]),u(h(ie)),u(h(de),{"node-color":`#3b82f6`,"mask-color":v.value===`dark`?`rgba(0,0,0,0.55)`:`rgba(15,23,42,0.06)`},null,8,[`mask-color`])]),_:1}),!A.value&&!Z.value?(l(),f(`div`,tt,[(l(),f(`svg`,nt,[...o[19]||=[n(`polygon`,{points:`3 6 9 3 15 6 21 3 21 18 15 21 9 18 3 21`},null,-1),n(`line`,{x1:`9`,y1:`3`,x2:`9`,y2:`18`},null,-1),n(`line`,{x1:`15`,y1:`6`,x2:`15`,y2:`21`},null,-1)]])),n(`p`,null,_(h(w)(`@SRCMAP:输入项目路径后点击开始分析`)),1)])):d(``,!0),Z.value&&!A.value?(l(),f(`div`,rt,[o[20]||=n(`span`,{class:`sm-spinner sm-spinner-lg`},null,-1),n(`p`,null,_(h(w)(`@SRCMAP:AI 正在分析项目结构...`)),1)])):d(``,!0)]),n(`div`,{class:`sm-resizer sm-resizer-h`,onMousedown:o[7]||=e=>K(`log`,e)},null,32),n(`div`,{class:`sm-log-panel`,style:C({height:H.value+`px`})},[n(`div`,it,[o[21]||=n(`svg`,{viewBox:`0 0 24 24`,width:`12`,height:`12`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.8`},[n(`polyline`,{points:`4 17 10 11 4 5`}),n(`line`,{x1:`12`,y1:`19`,x2:`20`,y2:`19`})],-1),s(` `+_(h(w)(`@SRCMAP:Agent 日志`))+` `,1),Z.value?(l(),f(`span`,at)):d(``,!0)]),n(`div`,ot,[(l(!0),f(i,null,c(k.value.slice(-50),e=>(l(),f(`div`,{key:e.id,class:x([`sm-log-entry`,`sm-log-entry--${e.type}`])},_(e.message),3))),128)),k.value.length===0?(l(),f(`div`,st,_(h(w)(`@SRCMAP:等待开始分析`)),1)):d(``,!0)],512)],4)],512),[[r,R.value.graph]]),y(n(`div`,{class:`sm-resizer sm-resizer-v`,onMousedown:o[8]||=e=>K(`source`,e)},null,544),[[r,R.value.graph&&R.value.source]]),y(n(`div`,{class:`sm-panel sm-panel-source`,style:C({width:V.value+`px`})},[n(`div`,ct,[o[22]||=n(`svg`,{viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.8`},[n(`polyline`,{points:`16 18 22 12 16 6`}),n(`polyline`,{points:`8 6 2 12 8 18`})],-1),s(` `+_(P.value||h(w)(`@SRCMAP:源码面板`))+` `,1),Q.value?(l(),f(`span`,lt,_(Q.value.label),1)):d(``,!0)]),Q.value?(l(),f(`div`,ut,[n(`div`,dt,_(Q.value.label),1),n(`div`,ft,[s(_(Q.value.file),1),Q.value.line?(l(),f(`span`,pt,` :`+_(Q.value.line),1)):d(``,!0)]),Q.value.description?(l(),f(`div`,mt,_(Q.value.description),1)):d(``,!0)])):d(``,!0),n(`div`,ht,[F.value?(l(),f(`div`,gt,[...o[23]||=[n(`span`,{class:`sm-spinner`},null,-1)]])):d(``,!0),!F.value&&!N.value?(l(),f(`div`,_t,_(h(w)(`@SRCMAP:点击调用图中的节点查看源码`)),1)):d(``,!0),n(`div`,{ref_key:`monacoContainerRef`,ref:J,class:`sm-monaco-container`},null,512)])],4),[[r,R.value.source]])])])}}}),[[`__scopeId`,`data-v-71d3569e`]]);export{E as default};
@@ -1 +0,0 @@
1
- .workbench[data-v-3d63d0a0]{background:var(--bg-container);height:100%;color:var(--text-primary);display:flex}.wb-sidebar[data-v-3d63d0a0]{border-right:1px solid var(--border-color);background:var(--bg-surface);flex-shrink:0;width:260px;padding:12px;overflow-y:auto}.wb-sidebar__header[data-v-3d63d0a0]{justify-content:space-between;align-items:center;margin-bottom:8px;display:flex}.wb-sidebar__header h3[data-v-3d63d0a0]{color:var(--text-secondary);text-transform:uppercase;letter-spacing:.5px;margin:0;font-size:13px;font-weight:600}.wb-sidebar__divider[data-v-3d63d0a0]{background:var(--border-color);height:1px;margin:16px 0}.wb-task-list[data-v-3d63d0a0],.wb-prompt-list[data-v-3d63d0a0]{margin:0;padding:0;list-style:none}.wb-task-item[data-v-3d63d0a0]{border-radius:var(--radius-md);cursor:pointer;border:1px solid #0000;margin-bottom:4px;padding:10px 12px;transition:background .15s,border-color .15s}.wb-task-item[data-v-3d63d0a0]:hover{background:var(--bg-hover)}.wb-task-item.active[data-v-3d63d0a0]{border-color:var(--color-primary);background:#3b82f61a}.wb-task-item__title[data-v-3d63d0a0]{margin-bottom:2px;font-size:13px;font-weight:500}.wb-task-item__meta[data-v-3d63d0a0]{color:var(--text-tertiary);justify-content:space-between;align-items:center;font-size:11px;display:flex}.wb-task-item__del[data-v-3d63d0a0],.wb-prompt-item__del[data-v-3d63d0a0],.wb-sub-item__del[data-v-3d63d0a0]{color:var(--text-tertiary);cursor:pointer;background:0 0;border:none;padding:0 4px;font-size:16px;line-height:1}.wb-task-item__del[data-v-3d63d0a0]:hover,.wb-prompt-item__del[data-v-3d63d0a0]:hover,.wb-sub-item__del[data-v-3d63d0a0]:hover{color:#ef4444}.wb-prompt-item[data-v-3d63d0a0]{border-radius:var(--radius-sm);justify-content:space-between;align-items:center;padding:6px 8px;font-size:12px;display:flex}.wb-prompt-item[data-v-3d63d0a0]:hover{background:var(--bg-hover)}.wb-prompt-item__name[data-v-3d63d0a0]{cursor:pointer;white-space:nowrap;text-overflow:ellipsis;flex:1;overflow:hidden}.wb-empty[data-v-3d63d0a0]{text-align:center;color:var(--text-tertiary);padding:16px 8px;font-size:12px}.wb-split[data-v-3d63d0a0]{flex-direction:column;flex:1;gap:12px;padding:16px 20px;display:flex;overflow-y:auto}.wb-placeholder[data-v-3d63d0a0]{color:var(--text-tertiary);flex:1;justify-content:center;align-items:center;font-size:13px;display:flex}.wb-split__header[data-v-3d63d0a0]{align-items:center;gap:8px;display:flex}.wb-input[data-v-3d63d0a0]{background:var(--bg-base);border:1px solid var(--border-color);color:var(--text-primary);border-radius:var(--radius-md);outline:none;padding:6px 10px;font-size:13px}.wb-input[data-v-3d63d0a0]:focus{border-color:var(--color-primary)}.wb-input--title[data-v-3d63d0a0]{flex:1;font-size:16px;font-weight:600}.wb-select[data-v-3d63d0a0]{background:var(--bg-base);border:1px solid var(--border-color);color:var(--text-primary);border-radius:var(--radius-md);padding:6px 8px;font-size:13px}.wb-textarea[data-v-3d63d0a0]{background:var(--bg-base);border:1px solid var(--border-color);color:var(--text-primary);border-radius:var(--radius-md);resize:vertical;box-sizing:border-box;outline:none;width:100%;padding:8px 10px;font-family:inherit;font-size:13px}.wb-textarea[data-v-3d63d0a0]:focus{border-color:var(--color-primary)}.wb-textarea--sm[data-v-3d63d0a0]{min-height:40px}.wb-split__sub-header[data-v-3d63d0a0]{justify-content:space-between;align-items:center;margin-top:8px;display:flex}.wb-split__sub-header h4[data-v-3d63d0a0]{color:var(--text-secondary);margin:0;font-size:13px;font-weight:600}.wb-sub-list[data-v-3d63d0a0]{flex-direction:column;gap:8px;margin:0;padding:0;list-style:none;display:flex}.wb-sub-item[data-v-3d63d0a0]{background:var(--bg-surface);border:1px solid var(--border-color);border-radius:var(--radius-md);padding:10px}.wb-sub-item__row[data-v-3d63d0a0]{align-items:center;gap:8px;margin-bottom:6px;display:flex}.wb-sub-item__status[data-v-3d63d0a0]{color:#fff;border-radius:10px;flex-shrink:0;padding:2px 8px;font-size:11px}.wb-sub-item__pid[data-v-3d63d0a0]{color:var(--text-tertiary);flex-shrink:0;font-family:ui-monospace,monospace;font-size:11px}.wb-sub-item__row .wb-input[data-v-3d63d0a0]{flex:1}.wb-log-details[data-v-3d63d0a0]{border:1px solid var(--border-color);border-radius:var(--radius-sm,4px);background:var(--bg-code);margin-top:6px;overflow:hidden}.wb-log-summary[data-v-3d63d0a0]{cursor:pointer;color:var(--text-secondary);-webkit-user-select:none;user-select:none;justify-content:space-between;align-items:center;gap:8px;padding:6px 10px;font-size:12px;list-style:none;display:flex}.wb-log-summary[data-v-3d63d0a0]::-webkit-details-marker{display:none}.wb-log-summary[data-v-3d63d0a0]:hover{background:#3b82f60f}.wb-log-summary__meta[data-v-3d63d0a0]{color:var(--text-tertiary);font-variant-numeric:tabular-nums;font-size:11px}.wb-log-pre[data-v-3d63d0a0]{max-height:240px;font-family:var(--font-mono,ui-monospace, monospace);color:var(--text-primary);background:var(--bg-code);white-space:pre-wrap;word-break:break-word;border-top:1px solid var(--border-color);margin:0;padding:8px 10px;font-size:12px;line-height:1.55;overflow:auto}.wb-attachments[data-v-3d63d0a0]{border:1px solid var(--border-color);border-radius:var(--radius-sm,4px);background:var(--bg-subtle,var(--bg-container));margin-top:6px;transition:border-color .15s,background .15s;overflow:hidden}.wb-attachments.is-paste-hover[data-v-3d63d0a0]{border-color:var(--color-primary);box-shadow:inset 0 0 0 1px var(--color-primary);background:#3b82f60f}.wb-attachments__paste-hint[data-v-3d63d0a0]{background:var(--color-primary);color:#fff;text-align:center;border-top:1px solid var(--border-color);padding:4px 10px;font-size:12px}.wb-attachments__head[data-v-3d63d0a0]{color:var(--text-secondary);border-bottom:1px solid var(--border-color);justify-content:space-between;align-items:center;padding:6px 10px;font-size:12px;display:flex}.wb-attachments__label[data-v-3d63d0a0]{align-items:center;gap:6px;display:inline-flex}.wb-attachments__count[data-v-3d63d0a0]{font-variant-numeric:tabular-nums;color:var(--text-tertiary);font-size:11px}.wb-attachments__add[data-v-3d63d0a0]{border:1px solid var(--border-color);background:var(--bg-container);color:var(--text-primary);border-radius:var(--radius-sm,4px);cursor:pointer;padding:3px 10px;font-size:12px;transition:background .15s}.wb-attachments__add[data-v-3d63d0a0]:hover:not(:disabled){border-color:var(--color-primary);color:var(--color-primary);background:#3b82f614}.wb-attachments__add[data-v-3d63d0a0]:disabled{opacity:.5;cursor:not-allowed}.wb-attachments__list[data-v-3d63d0a0]{flex-wrap:wrap;gap:4px;margin:0;padding:4px;list-style:none;display:flex}.wb-attachment[data-v-3d63d0a0]{border:1px solid var(--border-color);border-radius:var(--radius-sm,4px);background:var(--bg-container);align-items:center;gap:6px;min-width:0;max-width:240px;padding:4px 6px 4px 4px;display:flex}.wb-attachment__icon[data-v-3d63d0a0]{background:var(--bg-code);width:32px;height:32px;color:var(--text-tertiary);letter-spacing:.5px;border-radius:3px;flex-shrink:0;justify-content:center;align-items:center;font-size:10px;font-weight:600;display:flex;overflow:hidden}.wb-attachment__icon--img[data-v-3d63d0a0]{background:var(--bg-code)}.wb-attachment__icon img[data-v-3d63d0a0]{object-fit:cover;width:100%;height:100%}.wb-attachment__meta[data-v-3d63d0a0]{flex:1;min-width:0}.wb-attachment__name[data-v-3d63d0a0]{color:var(--text-primary);white-space:nowrap;text-overflow:ellipsis;font-size:12px;overflow:hidden}.wb-attachment__sub[data-v-3d63d0a0]{color:var(--text-tertiary);white-space:nowrap;text-overflow:ellipsis;font-size:10px;overflow:hidden}.wb-attachment__del[data-v-3d63d0a0]{color:var(--text-tertiary);cursor:pointer;background:0 0;border:none;border-radius:3px;flex-shrink:0;width:20px;height:20px;font-size:16px;line-height:1}.wb-attachment__del[data-v-3d63d0a0]:hover{color:#ef4444;background:#ef444414}
@@ -1 +0,0 @@
1
- import"./rolldown-runtime-CMxvf4Kt.js";import{$ as e,$n as t,An as n,En as r,Hn as ee,In as i,Jn as a,Kn as o,Ln as s,Mn as c,N as l,Nn as u,P as d,Qn as f,Sn as p,Tn as m,Un as h,Wn as g,_t as te,ar as _,cr as v,ct as ne,er as y,gt as re,jn as ie,kn as b,mt as ae,nr as x,or as S,rr as C,sr as oe,st as se,ut as ce,xn as le,zn as ue}from"./vendor-A4IPqbyo.js";import{n as w,t as T}from"./_plugin-vue_export-helper-opDPZuCO.js";import{t as de}from"./index-DPihtJfT.js";var fe={class:`workbench`},pe={class:`wb-sidebar`},me={class:`wb-sidebar__header`},he={class:`wb-task-list`},ge=[`onClick`],_e={class:`wb-task-item__title`},ve={class:`wb-task-item__meta`},ye=[`onClick`,`title`],be={key:0,class:`wb-empty`},xe={class:`wb-sidebar__header`},Se={class:`wb-prompt-list`},E=[`onClick`,`title`],D=[`onClick`],O={key:0,class:`wb-empty`},k={class:`wb-split`},A={key:0,class:`wb-placeholder`},j={class:`wb-split__header`},Ce=[`placeholder`],we={value:null},Te=[`value`],Ee=[`placeholder`],De={class:`wb-split__sub-header`},Oe={class:`wb-sub-list`},ke={class:`wb-sub-item__row`},Ae=[`onUpdate:modelValue`,`placeholder`,`onPaste`],je=[`title`],Me=[`onClick`],Ne=[`onUpdate:modelValue`,`placeholder`,`onPaste`],Pe=[`open`],Fe={class:`wb-log-summary`},Ie={key:0},Le={key:1},Re={key:2},ze={class:`wb-log-summary__meta`},Be=[`onPaste`,`onDragover`,`onDragenter`,`onDragleave`,`onDrop`],Ve={class:`wb-attachments__head`},He={class:`wb-attachments__label`},Ue={class:`wb-attachments__count`},We=[`disabled`,`onClick`],Ge={key:0,class:`wb-attachments__paste-hint`},Ke={key:1,class:`wb-attachments__list`},qe=[`src`,`alt`],Je={key:1},Ye={class:`wb-attachment__meta`},Xe=[`title`],Ze={class:`wb-attachment__sub`},Qe=[`onClick`,`title`],$e={key:0,class:`wb-empty`},et=64*1024,tt=`.png,.jpg,.jpeg,.gif,.webp,.bmp,.svg,.pdf,.txt,.md,.csv,.json,.log`,nt=5*1024*1024,M=T(ue({__name:`WorkbenchView`,setup(ue){let T=C([]),M=C([]),N=C([]),P=C(null),F=b(()=>M.value.find(e=>e.id===P.value)||null),I=x({visible:!1,editing:null,name:``,content:``,aiLoading:!1}),L=x({visible:!1,editing:null,title:``,desc:``,promptId:null}),R=null,rt=de();function z(){rt.setRunning(N.value.filter(e=>e.status===`running`).length)}function B(e){return N.value.find(t=>t.subId===e)||null}function it(e,t){if(e===`hello`){N.value=t.jobs||[],z();return}if(e===`job:update`){let e=t,n=N.value.findIndex(t=>t.id===e.id);n>=0?N.value[n]=e:N.value.push(e),z()}if(e===`sub:update`){let e=M.value.find(e=>e.id===t.taskId);if(e){let n=e.subtasks.findIndex(e=>e.id===t.sub.id);n>=0&&(e.subtasks[n]=t.sub)}}if(e===`task:update`){let e=M.value.findIndex(e=>e.id===t.id);e>=0&&(M.value[e]=t)}e===`task:error`&&d.error(t.error||w(`@WORKBENCH:执行出错`))}async function V(){T.value=(await fetch(`/api/workbench/prompts`).then(e=>e.json()).catch(()=>({prompts:[]}))).prompts||[]}async function H(){M.value=(await fetch(`/api/workbench/tasks`).then(e=>e.json()).catch(()=>({tasks:[]}))).tasks||[],!P.value&&M.value.length>0&&(P.value=M.value[0].id)}async function at(){N.value=(await fetch(`/api/workbench/jobs`).then(e=>e.json()).catch(()=>({jobs:[]}))).jobs||[],z()}function U(){R&&=(R.close(),null),R=new EventSource(`/api/workbench/events`),R.onmessage=e=>{try{let t=JSON.parse(e.data);it(t.event,t.payload)}catch{}},R.onerror=()=>{R&&=(R.close(),null),setTimeout(U,3e3)}}function ot(){I.editing=null,I.name=``,I.content=``,I.aiLoading=!1,I.visible=!0}function st(e){I.editing=e,I.name=e.name,I.content=e.content,I.aiLoading=!1,I.visible=!0}async function ct(){if(!I.aiLoading){I.aiLoading=!0;try{let e=await fetch(`/api/workbench/prompts/ai-generate`,{method:`POST`}).then(e=>e.json());if(e.success){let t=e.name||I.name,n=e.content||e.template||``;e.template&&e.result&&(n=`${e.template}\n\n## 当前项目架构总结\n\n${e.result}`),I.name=t,I.content=n,d.success(w(`@WORKBENCH:已生成,可继续编辑`))}else d.error(e.error||w(`@WORKBENCH:生成失败`))}catch(e){d.error(w(`@WORKBENCH:网络错误: `)+(e&&e.message||e))}finally{I.aiLoading=!1}}}async function lt(){if(!I.name.trim()||!I.content.trim()){d.warning(w(`@WORKBENCH:名称和内容不能为空`));return}let e={id:I.editing?.id,name:I.name.trim(),content:I.content},t=await fetch(`/api/workbench/prompts`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)}).then(e=>e.json());t.success?(d.success(w(`@WORKBENCH:已保存`)),I.visible=!1,V()):d.error(t.error||w(`@WORKBENCH:保存失败`))}async function ut(e){await l.confirm(w(`@WORKBENCH:删除提示词「{name}」?`,{name:e.name}),w(`@WORKBENCH:确认`),{type:`warning`}),await fetch(`/api/workbench/prompts/${e.id}`,{method:`DELETE`}),V();for(let t of M.value)t.promptId===e.id&&(t.promptId=null,await fetch(`/api/workbench/tasks`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)}));H()}function dt(){L.editing=null,L.title=``,L.desc=``,L.promptId=null,L.visible=!0}async function ft(){if(!L.title.trim()){d.warning(w(`@WORKBENCH:标题必填`));return}let e={id:L.editing?.id,title:L.title.trim(),desc:L.desc,promptId:L.promptId,subtasks:L.editing?.subtasks||[]},t=await fetch(`/api/workbench/tasks`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)}).then(e=>e.json());t.success?(d.success(w(`@WORKBENCH:已保存`)),L.visible=!1,H(),P.value||=t.task.id):d.error(t.error||w(`@WORKBENCH:保存失败`))}async function pt(e){await l.confirm(w(`@WORKBENCH:删除任务「{title}」及其所有子任务?`,{title:e.title}),w(`@WORKBENCH:确认`),{type:`warning`}),await fetch(`/api/workbench/tasks/${e.id}`,{method:`DELETE`}),P.value===e.id&&(P.value=null),H()}function mt(e){P.value=e.id}function ht(){if(!F.value)return;let e={id:`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,6)}`,title:w(`@WORKBENCH:新子任务`),desc:``,status:`todo`,promptOverride:``};F.value.subtasks.push(e),W(!1)}function gt(e){F.value&&(F.value.subtasks=F.value.subtasks.filter(t=>t.id!==e.id),W(!1))}async function W(e){if(!F.value)return!1;let t=await fetch(`/api/workbench/tasks`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(F.value)}).then(e=>e.json());return t.success?(e&&d.success(w(`@WORKBENCH:已保存拆分`)),await H(),!0):(d.error(t.error||w(`@WORKBENCH:保存失败`)),!1)}async function _t(){await W(!0)}async function vt(e){if(!e.subtasks||e.subtasks.length===0){d.warning(w(`@WORKBENCH:请先拆分任务`));return}if(F.value&&F.value.id===e.id){let t=M.value.find(t=>t.id===e.id);if((!t||t.title!==F.value.title||t.desc!==F.value.desc||JSON.stringify(t.subtasks)!==JSON.stringify(F.value.subtasks)||t.promptId!==F.value.promptId)&&!await W(!1))return}let t=await fetch(`/api/workbench/tasks/${e.id}/run`,{method:`POST`}).then(e=>e.json());t.success?d.success(t.message||w(`@WORKBENCH:已加入执行队列`)):d.error(t.error||w(`@WORKBENCH:执行失败`))}function yt(e){switch(e){case`todo`:return w(`@WORKBENCH:待执行`);case`running`:return w(`@WORKBENCH:执行中`);case`done`:return w(`@WORKBENCH:已完成`);case`error`:return w(`@WORKBENCH:出错`);case`pending`:return w(`@WORKBENCH:排队中`);default:return e}}function bt(e){switch(e){case`running`:return`var(--color-primary)`;case`done`:return`#22c55e`;case`error`:return`#ef4444`;case`pending`:return`#f59e0b`;default:return`var(--text-tertiary)`}}g(async()=>{await Promise.all([V(),H(),at()]),U()}),h(()=>{R&&=(R.close(),null)});let G=C({});function xt(e){return t=>{G.value[e]=t}}f(()=>N.value.map(e=>({id:e.id,len:(e.output||``).length})),e=>{e.forEach(({id:e})=>{let t=N.value.find(t=>t.id===e);if(!t||t.status!==`running`)return;let n=G.value[t.subId];n&&ee(()=>{n.scrollTop=n.scrollHeight})})},{deep:!0,flush:`post`});function St(e){return e?e.length<=et?e:`${w(`@WORKBENCH:…(前文已截断)`)}\n${e.slice(-65536)}`:``}let Ct=new Set([`image/png`,`image/jpeg`,`image/jpg`,`image/gif`,`image/webp`,`image/bmp`,`image/svg+xml`,`application/pdf`,`text/plain`,`text/markdown`,`text/x-markdown`,`text/csv`,`application/json`,`text/json`,`text/x-log`]),K=C({}),q=C(null);function J(e){return!!K.value[e]}function Y(e,t){if(e instanceof File)return e;let n=e.type||`application/octet-stream`;return new File([e],t,{type:n})}function X(e,t){if(!e.clipboardData)return;let n=Array.from(e.clipboardData.items).filter(e=>e.kind===`file`&&e.type.startsWith(`image/`));if(n.length>0){e.preventDefault();for(let e of n){let n=e.getAsFile();if(!n)continue;let r=(n.type.split(`/`)[1]||`png`).replace(`jpeg`,`jpg`);Z(t,Y(n,`paste-${new Date().toISOString().replace(/[:.]/g,`-`)}.${r}`))}return}let r=Array.from(e.clipboardData.items).filter(e=>e.kind===`file`&&!e.type.startsWith(`image/`));if(r.length>0){e.preventDefault();for(let e of r){let n=e.getAsFile();n&&Z(t,Y(n,n.name||`pasted-file`))}}}function wt(e,t){q.value=null,Array.from(e.dataTransfer?.files||[]).forEach(e=>Z(t,e))}async function Z(e,t){if(t.size>nt){d.error(`「${t.name}」${w(`@WORKBENCH:超过 5MB 限制`)}`);return}if(!Ct.has(t.type)&&!t.name.match(/\.(png|jpg|jpeg|gif|webp|bmp|svg|pdf|txt|md|markdown|csv|json|log)$/i)){d.error(`${w(`@WORKBENCH:不支持的文件类型`)}(${t.name})`);return}if((e.attachments||[]).length>=9){d.error(w(`@WORKBENCH:单个子任务最多 9 个附件`));return}K.value[e.id]=!0;try{let n=await fetch(`/api/workbench/subtasks/${e.id}/attachments`,{method:`POST`,headers:{"Content-Type":`application/octet-stream`,"X-Original-Name":t.name,"X-Mime-Type":t.type||`application/octet-stream`},body:t}).then(e=>e.json());n.success?(Array.isArray(e.attachments)||(e.attachments=[]),e.attachments.push(n.attachment),d.success(`${w(`@WORKBENCH:已添加:`)}${t.name}`)):d.error(n.error||w(`@WORKBENCH:上传失败`))}catch(e){d.error(w(`@WORKBENCH:上传失败`)+`:`+(e&&e.message||e))}finally{K.value[e.id]=!1}}async function Tt(e,t){try{await l.confirm(w(`@WORKBENCH:删除附件「{name}」?`,{name:t.originalName}),w(`@WORKBENCH:确认`),{type:`warning`})}catch{return}let n=await fetch(`/api/workbench/subtasks/${e.id}/attachments/${t.id}`,{method:`DELETE`}).then(e=>e.json());n.success?(e.attachments=(e.attachments||[]).filter(e=>e.id!==t.id),d.success(w(`@WORKBENCH:已删除`))):d.error(n.error||w(`@WORKBENCH:删除失败`))}function Et(e){let t=document.createElement(`input`);t.type=`file`,t.accept=tt,t.multiple=!0,t.onchange=()=>{Array.from(t.files||[]).forEach(t=>Z(e,t))},t.click()}let Q=new Set([`png`,`jpg`,`jpeg`,`gif`,`webp`,`bmp`,`svg`]);function $(e){return Q.has(String(e.ext||``).toLowerCase())}function Dt(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/1024/1024).toFixed(2)} MB`}return(ee,l)=>{let d=ce,f=ae,h=te,g=re,b=e,x=se,C=ne;return o(),u(`div`,fe,[n(`aside`,pe,[n(`div`,me,[n(`h3`,null,v(_(w)(`@WORKBENCH:任务列表`)),1),s(d,{size:`small`,type:`primary`,onClick:dt},{default:t(()=>[i(v(_(w)(`@WORKBENCH:新建任务`)),1)]),_:1})]),n(`ul`,he,[(o(!0),u(r,null,a(M.value,e=>(o(),u(`li`,{key:e.id,class:S([`wb-task-item`,{active:e.id===P.value}]),onClick:t=>mt(e)},[n(`div`,_e,v(e.title),1),n(`div`,ve,[n(`span`,null,v(e.subtasks?.length||0)+` `+v(_(w)(`@WORKBENCH:个子任务`)),1),n(`button`,{class:`wb-task-item__del`,onClick:m(t=>pt(e),[`stop`]),title:_(w)(`@WORKBENCH:删除`)},`×`,8,ye)])],10,ge))),128)),M.value.length===0?(o(),u(`li`,be,v(_(w)(`@WORKBENCH:暂无任务,点击右上角新建`)),1)):c(``,!0)]),l[13]||=n(`div`,{class:`wb-sidebar__divider`},null,-1),n(`div`,xe,[n(`h3`,null,v(_(w)(`@WORKBENCH:预置提示词`)),1),s(d,{size:`small`,onClick:ot},{default:t(()=>[i(v(_(w)(`@WORKBENCH:新建`)),1)]),_:1})]),n(`ul`,Se,[(o(!0),u(r,null,a(T.value,e=>(o(),u(`li`,{key:e.id,class:`wb-prompt-item`},[n(`span`,{class:`wb-prompt-item__name`,onClick:t=>st(e),title:e.content},v(e.name),9,E),n(`button`,{class:`wb-prompt-item__del`,onClick:t=>ut(e)},`×`,8,D)]))),128)),T.value.length===0?(o(),u(`li`,O,v(_(w)(`@WORKBENCH:暂无提示词`)),1)):c(``,!0)])]),n(`section`,k,[F.value?(o(),u(r,{key:1},[n(`div`,j,[y(n(`input`,{class:`wb-input wb-input--title`,"onUpdate:modelValue":l[0]||=e=>F.value.title=e,placeholder:_(w)(`@WORKBENCH:任务标题`)},null,8,Ce),[[p,F.value.title]]),y(n(`select`,{class:`wb-select`,"onUpdate:modelValue":l[1]||=e=>F.value.promptId=e},[n(`option`,we,v(_(w)(`@WORKBENCH:不绑定预置提示词`)),1),(o(!0),u(r,null,a(T.value,e=>(o(),u(`option`,{key:e.id,value:e.id},v(e.name),9,Te))),128))],512),[[le,F.value.promptId]]),s(d,{type:`primary`,loading:!1,onClick:l[2]||=e=>vt(F.value)},{default:t(()=>[i(v(_(w)(`@WORKBENCH:执行任务`)),1)]),_:1})]),y(n(`textarea`,{class:`wb-textarea`,"onUpdate:modelValue":l[3]||=e=>F.value.desc=e,placeholder:_(w)(`@WORKBENCH:任务描述(可选)`),rows:`3`},null,8,Ee),[[p,F.value.desc]]),n(`div`,De,[n(`h4`,null,v(_(w)(`@WORKBENCH:子任务拆分`)),1),n(`div`,null,[s(d,{size:`small`,onClick:ht},{default:t(()=>[i(`+ `+v(_(w)(`@WORKBENCH:添加子任务`)),1)]),_:1}),s(d,{size:`small`,type:`primary`,onClick:_t},{default:t(()=>[i(v(_(w)(`@WORKBENCH:保存拆分`)),1)]),_:1})])]),n(`ul`,Oe,[(o(!0),u(r,null,a(F.value.subtasks,e=>(o(),u(`li`,{key:e.id,class:`wb-sub-item`},[n(`div`,ke,[n(`span`,{class:`wb-sub-item__status`,style:oe({background:bt(e.status)})},v(yt(e.status)),5),y(n(`input`,{class:`wb-input`,"onUpdate:modelValue":t=>e.title=t,placeholder:_(w)(`@WORKBENCH:子任务标题`),onPaste:t=>X(t,e)},null,40,Ae),[[p,e.title]]),B(e.id)?(o(),u(`span`,{key:0,class:`wb-sub-item__pid`,title:_(w)(`@WORKBENCH:进程ID`)},` PID: `+v(B(e.id)?.pid),9,je)):c(``,!0),n(`button`,{class:`wb-sub-item__del`,onClick:t=>gt(e)},`×`,8,Me)]),y(n(`textarea`,{class:`wb-textarea wb-textarea--sm`,"onUpdate:modelValue":t=>e.desc=t,placeholder:_(w)(`@WORKBENCH:子任务描述 / 独立提示词覆盖`),rows:`2`,onPaste:t=>X(t,e)},null,40,Ne),[[p,e.desc]]),B(e.id)?(o(),u(`details`,{key:0,class:`wb-log-details`,open:B(e.id)?.status===`running`||B(e.id)?.status===`pending`},[n(`summary`,Fe,[B(e.id)?.status===`running`?(o(),u(`span`,Ie,`● `+v(_(w)(`@WORKBENCH:正在执行…`)),1)):B(e.id)?.status===`pending`?(o(),u(`span`,Le,v(_(w)(`@WORKBENCH:排队中…`)),1)):(o(),u(`span`,Re,v(_(w)(`@WORKBENCH:查看执行日志`)),1)),n(`span`,ze,v((B(e.id)?.output||``).length)+` `+v(_(w)(`@WORKBENCH:字符`)),1)]),n(`pre`,{ref_for:!0,ref:xt(e.id),class:`wb-log-pre`},v(St(B(e.id)?.output)||_(w)(`@WORKBENCH:(暂无输出)`)),513)],8,Pe)):c(``,!0),n(`div`,{class:S([`wb-attachments`,{"is-paste-hover":q.value===e.id}]),onPaste:t=>X(t,e),onDragover:m(t=>q.value=e.id,[`prevent`]),onDragenter:m(t=>q.value=e.id,[`prevent`]),onDragleave:t=>q.value=q.value===e.id?null:q.value,onDrop:m(t=>wt(t,e),[`prevent`])},[n(`div`,Ve,[n(`span`,He,[i(v(_(w)(`@WORKBENCH:附件`))+` `,1),n(`span`,Ue,v((e.attachments||[]).length)+` / 9`,1)]),n(`button`,{class:`wb-attachments__add`,disabled:J(e.id)||(e.attachments||[]).length>=9,onClick:t=>Et(e)},v(J(e.id)?_(w)(`@WORKBENCH:上传中…`):_(w)(`@WORKBENCH:添加附件`)),9,We)]),q.value===e.id?(o(),u(`div`,Ge,v(_(w)(`@WORKBENCH:粘贴图片以快速添加`)),1)):c(``,!0),(e.attachments||[]).length>0?(o(),u(`ul`,Ke,[(o(!0),u(r,null,a(e.attachments,t=>(o(),u(`li`,{key:t.id,class:`wb-attachment`},[n(`div`,{class:S([`wb-attachment__icon`,{"wb-attachment__icon--img":$(t)}])},[$(t)?(o(),u(`img`,{key:0,src:`/api/workbench/attachments/${t.id}/raw`,alt:t.originalName,loading:`lazy`},null,8,qe)):(o(),u(`span`,Je,v(t.ext.toUpperCase()),1))],2),n(`div`,Ye,[n(`div`,{class:`wb-attachment__name`,title:t.originalName},v(t.originalName),9,Xe),n(`div`,Ze,v(Dt(t.size))+` · `+v(t.mimeType),1)]),n(`button`,{class:`wb-attachment__del`,onClick:n=>Tt(e,t),title:_(w)(`@WORKBENCH:删除`)},`×`,8,Qe)]))),128))])):c(``,!0)],42,Be)]))),128)),F.value.subtasks.length===0?(o(),u(`li`,$e,v(_(w)(`@WORKBENCH:暂无子任务,点击上方按钮添加`)),1)):c(``,!0)])],64)):(o(),u(`div`,A,[n(`p`,null,v(_(w)(`@WORKBENCH:左侧选择任务,或新建一个任务开始`)),1)]))]),s(b,{modelValue:I.visible,"onUpdate:modelValue":l[7]||=e=>I.visible=e,title:I.editing?_(w)(`@WORKBENCH:编辑提示词`):_(w)(`@WORKBENCH:新建提示词`),width:`640px`},{footer:t(()=>[s(d,{onClick:l[6]||=e=>I.visible=!1},{default:t(()=>[i(v(_(w)(`@WORKBENCH:取消`)),1)]),_:1}),s(d,{type:`primary`,onClick:lt},{default:t(()=>[i(v(_(w)(`@WORKBENCH:保存`)),1)]),_:1})]),default:t(()=>[s(g,{"label-position":`top`},{default:t(()=>[s(h,{label:_(w)(`@WORKBENCH:名称`)},{default:t(()=>[s(f,{modelValue:I.name,"onUpdate:modelValue":l[4]||=e=>I.name=e,placeholder:_(w)(`@WORKBENCH:如:代码审查 / 写测试`)},null,8,[`modelValue`,`placeholder`])]),_:1},8,[`label`]),s(h,null,{default:t(()=>[s(d,{type:`primary`,plain:``,loading:I.aiLoading,onClick:ct},{default:t(()=>[i(v(_(w)(`@WORKBENCH:AI 生成(基于当前项目)`)),1)]),_:1},8,[`loading`])]),_:1}),s(h,{label:_(w)(`@WORKBENCH:内容`)},{default:t(()=>[s(f,{modelValue:I.content,"onUpdate:modelValue":l[5]||=e=>I.content=e,type:`textarea`,rows:10,placeholder:_(w)(`@WORKBENCH:可用变量:{{task.title}} {{task.desc}} {{sub.title}} {{sub.desc}} {{repo.path}} {{branch}}`)},null,8,[`modelValue`,`placeholder`])]),_:1},8,[`label`])]),_:1})]),_:1},8,[`modelValue`,`title`]),s(b,{modelValue:L.visible,"onUpdate:modelValue":l[12]||=e=>L.visible=e,title:L.editing?_(w)(`@WORKBENCH:编辑任务`):_(w)(`@WORKBENCH:新建任务`),width:`560px`},{footer:t(()=>[s(d,{onClick:l[11]||=e=>L.visible=!1},{default:t(()=>[i(v(_(w)(`@WORKBENCH:取消`)),1)]),_:1}),s(d,{type:`primary`,onClick:ft},{default:t(()=>[i(v(_(w)(`@WORKBENCH:保存`)),1)]),_:1})]),default:t(()=>[s(g,{"label-position":`top`},{default:t(()=>[s(h,{label:_(w)(`@WORKBENCH:标题`)},{default:t(()=>[s(f,{modelValue:L.title,"onUpdate:modelValue":l[8]||=e=>L.title=e},null,8,[`modelValue`])]),_:1},8,[`label`]),s(h,{label:_(w)(`@WORKBENCH:描述`)},{default:t(()=>[s(f,{modelValue:L.desc,"onUpdate:modelValue":l[9]||=e=>L.desc=e,type:`textarea`,rows:3},null,8,[`modelValue`])]),_:1},8,[`label`]),s(h,{label:_(w)(`@WORKBENCH:预置提示词`)},{default:t(()=>[s(C,{modelValue:L.promptId,"onUpdate:modelValue":l[10]||=e=>L.promptId=e,clearable:``,placeholder:_(w)(`@WORKBENCH:不绑定`),style:{width:`100%`}},{default:t(()=>[(o(!0),u(r,null,a(T.value,e=>(o(),ie(x,{key:e.id,label:e.name,value:e.id},null,8,[`label`,`value`]))),128))]),_:1},8,[`modelValue`,`placeholder`])]),_:1},8,[`label`])]),_:1})]),_:1},8,[`modelValue`,`title`])])}}}),[[`__scopeId`,`data-v-3d63d0a0`]]);export{M as default};