autosnippet 1.5.3 → 1.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -11,10 +11,10 @@
11
11
 
12
12
  | 角色 | 职责 | 能力 |
13
13
  |------|------|------|
14
- | **开发者** | 审核与决策;维护项目标准 | Dashboard 审核 Candidate、保存 Recipe;使用 Snippet 补全、`// as:search` 插入;运行 `asd embed`、`asd ui` |
15
- | **Cursor Agent** | 按规范生成代码;检索知识库 | 通过 Skills 理解规范;MCP 按需检索、打开新建 Recipe 页;起草内容供人工审核,不直接改 Knowledge |
16
- | **项目内 AI** | 提取、摘要、扫描、审查 | `asd ais` 扫描;Use Copied Code 分析填充;Guard 审查;Dashboard RAG。由 `.env` 配置 |
17
- | **知识库** | 存储与提供项目标准 | Recipes、Snippets、语义向量索引;Guard、搜索、两种 AI 的上下文均依赖此 |
14
+ | **开发者** | 审核与决策;维护项目标准 | Dashboard 审核 Candidate,保存 Recipe;使用 Snippet 补全、`// as:search` 插入;运行 `asd embed`、`asd ui` |
15
+ | **Cursor Agent** | 按规范生成代码;检索与提交 | Skills 理解规范;MCP 按需检索、打开新建 Recipe 页;`autosnippet_submit_candidates` 批量提交候选供人工审核;不直接改 Knowledge |
16
+ | **项目内 AI** | 提取、摘要、扫描、审查 | `asd ais` 扫描;Use Copied Code 分析填充;Guard 审查;Dashboard RAG;深度扫描结果可算相似度。由 `.env` 配置 |
17
+ | **知识库** | 存储与提供项目标准 | Recipes、Snippets、语义向量索引;Guard、搜索、质量评估、相似度分析;两种 AI 的上下文均依赖此 |
18
18
 
19
19
  ---
20
20
 
@@ -44,7 +44,7 @@ asd ui # 启动 Dashboard(建议常驻)
44
44
 
45
45
  ### 闭环
46
46
 
47
- **扫描 → 审核 → 沉淀 → Cursor/AI 使用 → 再沉淀**:项目 AI 通过扫描 target 批量提交候选,Cursor 完成的代码通过 Skill 提交候选,开发者完成的代码通过剪切板提交候选,Dashboard 中的候选经过人工审核进入知识库;知识库内 Recipe 为第一公民,拥有最高优先级。
47
+ **扫描 → 审核 → 沉淀 → Cursor/AI 使用 → 再沉淀**:项目 AI 通过扫描 Target 批量提交候选,Cursor 完成的代码通过 Skill 提交候选,开发者完成的代码通过剪切板提交候选,Dashboard 中的候选经过人工审核进入知识库;知识库内 Recipe 为第一公民,拥有最高优先级。
48
48
 
49
49
  开发者通过 Snippet 获取 Recipe 内容插入编辑器, Cursor 通过 Skills 把 Recipe 产生的 context 当做上下文使用,对向量库进行查询;AI 用知识库产生的代码,过审后添加到知识库,成为了 AI 新的上下文,使得 AI 的开发趋于标准化。
50
50
 
@@ -57,7 +57,7 @@ asd ui # 启动 Dashboard(建议常驻)
57
57
  | 指令 | 作用 |
58
58
  |------|------|
59
59
  | `// as:create` / `// as:c` | 无选项时只打开 Dashboard(路径已填),由用户点 Scan File 或 Use Copied Code。`-c` 强制用剪切板(静默创建或打开);`-f` 强制用路径(打开 Dashboard 并自动执行 Scan File) |
60
- | `// as:guard` / `// as:g` [关键词或规模] | 按知识库 AI 审查;无后缀时仅检查当前文件;后缀 **file** / **target** / **project** 可扩大范围(target=当前 target 内所有源文件,project=项目内所有源文件);其他为检索关键词 |
60
+ | `// as:guard` / `// as:g` [关键词或规模] | 按知识库 AI 审查;无后缀时仅检查当前文件;后缀 **file** / **target** / **project** 可扩大范围(target=当前 Target 内所有源文件,project=项目内所有源文件);其他为检索关键词 |
61
61
  | `// as:search` / `// as:s` [关键词] | 从知识库检索并插入 Recipe/Snippet |
62
62
  | `// as:include` / `// as:import` | Snippet 内头文件/模块标记,保存时自动注入 |
63
63
 
@@ -68,15 +68,16 @@ asd ui # 启动 Dashboard(建议常驻)
68
68
 
69
69
  | 命令 | 说明 |
70
70
  |------|------|
71
+ | `asd setup` | 初始化项目根(创建 AutoSnippetRoot.boxspec.json) |
71
72
  | `asd ui` | 启动 Dashboard + watch |
72
- | `asd status` | 环境自检(项目根、AI、索引、Native UI) |
73
+ | `asd status` | 环境自检(含项目根、AI、索引、Dashboard/Watch、Native UI) |
73
74
  | `asd create --clipboard` | 从剪贴板创建 Recipe/Snippet |
74
75
  | `asd candidate` | 从剪贴板创建候选(Dashboard 审核) |
75
76
  | `asd install` / `asd i` | 同步 Snippets 到 Xcode |
76
77
  | `asd ais [Target]` | AI 扫描 Target → Candidates |
77
78
  | `asd search [keyword] --copy` | 搜索并复制第一条到剪贴板 |
78
79
  | `asd search [keyword] --pick` | 交互选择后复制/插入 |
79
- | `asd install:cursor-skill --mcp` | 安装 Skills、Cursor 规则(`.cursor/rules/*.mdc`)并配置 MCP(需 `asd ui` 运行) |
80
+ | `asd install:cursor-skill --mcp` | 安装 Skills、Cursor 规则(`.cursor/rules/*.mdc`)并配置 MCP。配置时可运行;MCP 工具使用时需 `asd ui` 已启动 |
80
81
  | `asd install:full` | 全量安装;`--parser` 含 Swift 解析器;`--lancedb` 仅 LanceDB |
81
82
  | `asd embed` | 手动构建语义向量索引(`asd ui` 启动时也会自动执行) |
82
83
  | `asd spm-map` | 刷新 SPM 依赖映射(依赖关系图数据来源) |
@@ -85,7 +86,7 @@ asd ui # 启动 Dashboard(建议常驻)
85
86
 
86
87
  除 `asd ais [Target]`(项目内 AI)外,可用 **Cursor 作为批量扫描工具**:在 Cursor 里让 Agent 通过 **MCP 工具**(`autosnippet_get_targets` → `autosnippet_get_target_files` → 按文件提取 → `autosnippet_submit_candidates`)扫描指定 Target,用 Cursor 模型提取候选并提交到 Dashboard,再到 **Candidates** 页审核入库。
87
88
 
88
- 简单一句:「扫描 BDNetwork ,生产 Recipes 到候选」。AutoSnippet 将所有能力都通过语义交给 Cursor 了。
89
+ 简单一句:「扫描 BDNetwork ,生成 Recipes 到候选」。AutoSnippet 将所有能力都通过语义交给 Cursor 了。
89
90
 
90
91
  ## 全量安装与可选依赖
91
92
 
@@ -99,36 +100,29 @@ asd install:full --lancedb # 仅安装 LanceDB(向量检索更快)
99
100
 
100
101
  **Swift 解析器**:默认回退 `dump-package`;`--parser` 构建 ParsePackage 后 SPM 解析更准确,需本机已装 Swift。
101
102
 
102
- ### Postinstall 脚本说明(npm install 时)
103
-
104
- `npm install` 会执行以下**可选**脚本,均为本包内本地构建,**不访问网络、不执行动态代码**:
105
-
106
- | 脚本 | 作用 |
107
- |------|------|
108
- | `scripts/ensure-parse-package.js` | 仅当 `ASD_BUILD_SWIFT_PARSER=1` 时构建 Swift 解析器并打印「正在安装…」;否则打印跳过说明并退出。 |
109
- | `scripts/build-native-ui.js` | 仅在 macOS 上用本机 Swift 编译 `resources/native-ui/main.swift` → `resources/native-ui/native-ui`;失败则静默跳过。 |
110
-
111
- 未安装或跳过不影响核心功能。详见 [npm lifecycle scripts](https://docs.npmjs.com/cli/v10/using-npm/scripts#life-cycle-scripts)。
112
-
113
103
  ## 配置
114
104
 
115
- - **AI**:项目根 `.env`,设置 `ASD_GOOGLE_API_KEY` 等(见 `.env.example`)。可选 `ASD_AI_PROVIDER`、代理等。
105
+ - **AI**:项目根 `.env`,参考 `.env.example` 配置 `ASD_GOOGLE_API_KEY` 等。可选 `ASD_AI_PROVIDER`、代理等。
116
106
  - **LanceDB**:`asd install:full --lancedb`,在 boxspec 的 `context.storage.adapter` 中配置 `"lance"`。
117
107
  - **Native UI**(可选):macOS 上 `npm install` 会尝试构建 `resources/native-ui/native-ui`(需本机 Swift);未构建时回退到 AppleScript/inquirer,功能正常。
118
108
 
119
- ## Recipe 格式
120
-
121
- 完整 Recipe 为 Markdown 文件,需包含:
122
-
123
- - **Frontmatter**(`---` 包裹的 YAML):`title`、`trigger` 必填;可选 `category`、`language`、`headers` 等
124
- - **Snippet / Code Reference**:下接代码块,供 Snippet 与检索使用
125
- - **AI Context / Usage Guide**:使用说明,供 AI 与 Guard 检索
126
-
127
109
  ## 术语
128
110
 
129
- - **Recipe**:`Knowledge/recipes/` 下的 Markdown 知识,供 AI 检索、Guard、搜索
130
- - **Snippet**:Xcode 代码片段,通过 trigger(默认 `@`)补全
131
- - **项目根**:含 `AutoSnippetRoot.boxspec.json` 的目录
111
+ | 术语 | 说明 |
112
+ |------|------|
113
+ | **Recipe** | `Knowledge/recipes/` 下的 Markdown 知识(配方):含代码块 + 使用说明,供 AI 检索、Guard、搜索 |
114
+ | **Snippet** | Xcode 代码片段,通过 trigger(默认 `@`)补全,可与 Recipe 关联 |
115
+ | **Candidate(候选)** | 待审核入库的项;来自 `as:create`、MCP 提交、`asd ais` 扫描等,经 Dashboard 审核后保存为 Recipe/Snippet |
116
+ | **Knowledge** | 项目知识库目录,包含 `recipes/`、`.autosnippet/`(索引、candidates、guard 配置等);Snippet 配置在 root spec 的 list 中 |
117
+ | **Dashboard** | Web 管理后台(`asd ui` 启动),含 Recipes、Candidates、Guard、Snippets 等页面 |
118
+ | **watch** | 文件监听进程(`asd ui` 或 `asd watch` 启动),保存时触发 `as:create`、`as:guard`、`as:search` |
119
+ | **Guard** | 按 Recipe 知识库对代码做 AI 审查;`// as:guard` 触发 |
120
+ | **embed** | 语义向量索引构建;`asd embed` 或 `asd ui` 启动时自动执行,供语义检索与 MCP 使用 |
121
+ | **MCP** | Model Context Protocol;Cursor 通过 MCP 调用 `autosnippet_context_search` 等工具 |
122
+ | **Skills** | Cursor Agent Skills(`.cursor/skills/`),描述何时用、如何用 AutoSnippet 能力 |
123
+ | **trigger** | Snippet 触发前缀,默认 `@`,输入后 Xcode 联想补全 |
124
+ | **项目根** | 含 `AutoSnippetRoot.boxspec.json` 的目录 |
125
+ | **Target** | SPM 模块/编译单元;`asd ais <Target>` 扫描该 Target 下的源码提取候选 |
132
126
 
133
127
  **详细介绍**:启动 `asd ui` 后访问 Dashboard → **使用说明** 页;或参阅 [使用文档](docs/使用文档.md)(含 Skills 一览、AI 配置、闭环详解等)。
134
128
 
package/bin/asnip.js CHANGED
@@ -1028,6 +1028,7 @@ commander
1028
1028
  console.log(`${hasContext ? ok : fail} 语义索引: ${hasContext ? '已构建' : '未构建,运行 asd embed'}`);
1029
1029
 
1030
1030
  // 4. watch / ui
1031
+ let uiRunning = false;
1031
1032
  try {
1032
1033
  const net = require('net');
1033
1034
  const port = 3000;
@@ -1035,8 +1036,11 @@ commander
1035
1036
  const s = net.connect(port, '127.0.0.1', () => { s.destroy(); res(true); });
1036
1037
  s.on('error', () => res(false));
1037
1038
  });
1038
- const uiRunning = await Promise.race([check(), new Promise(r => setTimeout(() => r(false), 500))]);
1039
- console.log(`${uiRunning ? ok : fail} Dashboard: ${uiRunning ? 'http://localhost:3000 已运行' : '未运行,执行 asd ui'}`);
1039
+ uiRunning = await Promise.race([check(), new Promise(r => setTimeout(() => r(false), 500))]);
1040
+ console.log(`${uiRunning ? ok : fail} Dashboard/Watch: ${uiRunning ? 'http://localhost:3000 已运行' : '未运行'}`);
1041
+ if (!uiRunning) {
1042
+ console.log(` ⚠️ as:create、as:guard、as:search 依赖 watch,保存后不会触发。请执行: asd ui`);
1043
+ }
1040
1044
  } catch (_) {
1041
1045
  console.log(`${fail} Dashboard: 无法检测`);
1042
1046
  }
@@ -1046,6 +1050,23 @@ commander
1046
1050
  const hasNative = !!nativeUi.getNativeUiPath();
1047
1051
  console.log(`${hasNative ? ok : fail} Native UI: ${hasNative ? '已就绪 (Swift Helper)' : '未构建,执行 npm run build:native-ui (macOS)'}`);
1048
1052
 
1053
+ // 6. 下一步建议
1054
+ console.log('\n--- 下一步建议 ---');
1055
+ const suggestions = [];
1056
+ if (!projectRoot) {
1057
+ suggestions.push('asd root 或 asd setup — 初始化项目根');
1058
+ } else {
1059
+ if (!uiRunning) suggestions.push('asd ui — 启动 Dashboard 与 watch(编辑器内指令才能生效)');
1060
+ if (!hasContext) suggestions.push('asd embed — 构建语义索引(as:search 语义检索、MCP 需要)');
1061
+ if (!fs.existsSync(envPath)) suggestions.push('复制 .env.example 为 .env 并填写 API Key(AI 功能需要)');
1062
+ const cursorSkillDir = path.join(projectRoot, '.cursor', 'skills', 'autosnippet-recipes');
1063
+ if (!fs.existsSync(cursorSkillDir)) suggestions.push('asd install:cursor-skill --mcp — 安装 Cursor Skills 与 MCP');
1064
+ }
1065
+ if (suggestions.length > 0) {
1066
+ suggestions.forEach((s, i) => console.log(` ${i + 1}. ${s}`));
1067
+ } else {
1068
+ console.log(' 环境就绪,可以正常使用。');
1069
+ }
1049
1070
  console.log('');
1050
1071
  });
1051
1072
 
@@ -1063,6 +1084,12 @@ commander
1063
1084
  if (res.map && res.map.ok && res.map.created) {
1064
1085
  console.log(`✅ 已创建 SPM 映射文件: ${res.map.path}`);
1065
1086
  }
1087
+ console.log('\n下一步建议:');
1088
+ console.log(' 1. asd ui — 启动 Dashboard 与 watch(编辑器内 as:create、as:search、as:guard 需要)');
1089
+ console.log(' 2. 复制 .env.example 为 .env 并填写 API Key(AI 功能需要)');
1090
+ console.log(' 3. asd embed — 构建语义索引');
1091
+ console.log(' 4. asd install:cursor-skill --mcp — 安装 Cursor Skills 与 MCP');
1092
+ console.log('');
1066
1093
  });
1067
1094
 
1068
1095
  commander
package/bin/ui.js CHANGED
@@ -545,6 +545,37 @@ function launch(projectRoot, port = 3000, options = {}) {
545
545
  }
546
546
  });
547
547
 
548
+ // API: AI 翻译(中文 → 英文,用于 Recipe summary/usageGuide)
549
+ app.post('/api/ai/translate', async (req, res) => {
550
+ try {
551
+ const { summary, usageGuide } = req.body;
552
+ if (!summary && !usageGuide) {
553
+ return res.json({ summary_en: '', usageGuide_en: '' });
554
+ }
555
+ const ai = await AiFactory.getProvider(projectRoot);
556
+ const sys = 'You are a technical translator. Translate the following from Chinese to English. Keep technical terms (e.g. API names, class names) unchanged. Return ONLY valid JSON: { "summary_en": "...", "usageGuide_en": "..." }. Use empty string for missing input. Preserve Markdown in usageGuide.';
557
+ const parts = [];
558
+ if (summary) parts.push(`summary (摘要):\n${summary}`);
559
+ if (usageGuide) parts.push(`usageGuide (使用指南):\n${usageGuide}`);
560
+ const prompt = parts.join('\n\n');
561
+ const text = await ai.chat(prompt, [], sys);
562
+ const raw = (text || '').replace(/```json?\s*/gi, '').replace(/```\s*$/g, '').trim();
563
+ let out = { summary_en: '', usageGuide_en: '' };
564
+ try {
565
+ const parsed = JSON.parse(raw);
566
+ if (parsed.summary_en != null) out.summary_en = String(parsed.summary_en);
567
+ if (parsed.usageGuide_en != null) out.usageGuide_en = String(parsed.usageGuide_en);
568
+ } catch (_) {
569
+ // 若解析失败,尝试提取第一段作为 summary_en
570
+ if (summary) out.summary_en = raw.split('\n')[0] || summary;
571
+ }
572
+ res.json(out);
573
+ } catch (err) {
574
+ console.error(`[API Error]`, err);
575
+ res.status(500).json({ error: err.message });
576
+ }
577
+ });
578
+
548
579
  // API: AI 聊天
549
580
  app.post('/api/ai/chat', async (req, res) => {
550
581
  try {
@@ -0,0 +1,44 @@
1
+ import{n as Ve,L as Me,B as pe,H as Is,W as As,D as $s,Z as we,C as Ce,P as zs,G as _s,j as e,h as Rs,T as Ps,i as Gs,S as Ye,M as Ms,k as Je,l as Le,m as c,o as M,p as Ze,q as Qe,s as Ls,w as Pe,x as es,y as Es,z as Ds,A as Ge,E as Ts,F as Ne,I as Re,J as ss,K as ts,N as Us,O as Ee,X as ye,Q as _e,U as as,Y as Os,$ as Hs,a0 as Fs,a1 as qe,a2 as Ws,a3 as Ks,a4 as ls,a5 as Bs,a6 as Vs,a7 as qs,a8 as Xs,R as Ys}from"./vendor-DEnC4MH_.js";import{h as Js,o as Zs,M as Qs}from"./markdown-DO_keoHJ.js";(function(){const a=document.createElement("link").relList;if(a&&a.supports&&a.supports("modulepreload"))return;for(const n of document.querySelectorAll('link[rel="modulepreload"]'))x(n);new MutationObserver(n=>{for(const r of n)if(r.type==="childList")for(const g of r.addedNodes)g.tagName==="LINK"&&g.rel==="modulepreload"&&x(g)}).observe(document,{childList:!0,subtree:!0});function y(n){const r={};return n.integrity&&(r.integrity=n.integrity),n.referrerPolicy&&(r.referrerPolicy=n.referrerPolicy),n.crossOrigin==="use-credentials"?r.credentials="include":n.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function x(n){if(n.ep)return;n.ep=!0;const r=y(n);fetch(n.href,r)}})();const et="AutoSnippet";function st(s){if(typeof window>"u"||!("Notification"in window))return;const a=()=>{try{new Notification(et,{body:s,tag:"autosnippet"})}catch{}};if(Notification.permission==="granted"){a();return}Notification.permission!=="denied"&&Notification.requestPermission().then(y=>{y==="granted"&&a()})}function E(s,a){typeof document<"u"&&document.visibilityState==="visible"?(a==null?void 0:a.type)==="error"?Ve.error(s):Ve.success(s):st(s)}const de={All:{icon:_s,color:"text-slate-600",bg:"bg-slate-100",border:"border-slate-200"},View:{icon:zs,color:"text-pink-600",bg:"bg-pink-50",border:"border-pink-100"},Service:{icon:Ce,color:"text-indigo-600",bg:"bg-indigo-50",border:"border-indigo-100"},Tool:{icon:we,color:"text-amber-600",bg:"bg-amber-50",border:"border-amber-100"},Model:{icon:$s,color:"text-emerald-600",bg:"bg-emerald-50",border:"border-emerald-100"},Network:{icon:As,color:"text-blue-600",bg:"bg-blue-50",border:"border-blue-100"},Storage:{icon:Is,color:"text-purple-600",bg:"bg-purple-50",border:"border-purple-100"},UI:{icon:pe,color:"text-cyan-600",bg:"bg-cyan-50",border:"border-cyan-100"},Utility:{icon:Me,color:"text-orange-600",bg:"bg-orange-50",border:"border-orange-100"}},ns=["All","View","Service","Tool","Model","Network","Storage","UI","Utility"],tt=["snippets","recipes","ai","spm","candidates","depgraph","guard","help"],at="https://github.com/GxFn/AutoSnippet/issues/new?title=Guard%20误报%2F建议%3A%20&body=请描述误报的规则ID、代码片段或改进建议。",Ie=s=>["Example","Demo","Sample","Tests","Spec","Mock","Runner"].some(y=>s.endsWith(y)||s.includes(y)),lt=s=>s.startsWith("_"),nt=s=>s==="_pending",rt=({activeTab:s,navigateToTab:a,handleRefreshProject:y,candidateCount:x})=>e.jsxs("aside",{className:"w-64 bg-white border-r border-slate-200 flex flex-col shrink-0",children:[e.jsxs("div",{className:"p-6 border-b border-slate-100 flex items-center gap-3",children:[e.jsx("div",{className:"w-8 h-8 bg-blue-600 rounded-lg flex items-center justify-center text-white",children:e.jsx(Rs,{size:20})}),e.jsx("h1",{className:"font-bold text-lg",children:"AutoSnippet"})]}),e.jsxs("nav",{className:"flex-1 p-4 space-y-2 overflow-y-auto",children:[e.jsxs("button",{type:"button",onClick:()=>a("recipes"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="recipes"?"bg-blue-50 text-blue-700 font-medium":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(Ce,{size:20}),e.jsx("span",{children:"Recipes"})]}),e.jsxs("button",{type:"button",onClick:()=>a("snippets"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="snippets"?"bg-blue-50 text-blue-700 font-medium":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(Ps,{size:20}),e.jsx("span",{children:"Snippets"})]}),e.jsxs("button",{type:"button",onClick:()=>a("spm"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="spm"?"bg-blue-50 text-blue-700 font-medium":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(pe,{size:20}),e.jsx("span",{children:"SPM Explorer"})]}),e.jsxs("button",{type:"button",onClick:()=>a("candidates"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="candidates"?"bg-blue-50 text-blue-700 font-medium":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(we,{size:20}),e.jsxs("span",{children:["Candidates (",x,")"]})]}),e.jsxs("button",{type:"button",onClick:()=>a("depgraph"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="depgraph"?"bg-blue-50 text-blue-700 font-medium":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(Gs,{size:20}),e.jsx("span",{children:"依赖关系图"})]}),e.jsxs("button",{type:"button",onClick:()=>a("guard"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="guard"?"bg-blue-50 text-blue-700 font-medium":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(Ye,{size:20}),e.jsx("span",{children:"Guard"})]}),e.jsxs("button",{type:"button",onClick:()=>a("ai"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="ai"?"bg-blue-50 text-blue-700 font-medium":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(Ms,{size:20}),e.jsx("span",{children:"AI Assistant"})]}),e.jsxs("button",{type:"button",onClick:()=>a("help"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="help"?"bg-blue-50 text-blue-700 font-medium":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(Je,{size:20}),e.jsx("span",{children:"使用说明"})]})]}),e.jsx("div",{className:"p-4 border-t border-slate-100",children:e.jsxs("button",{onClick:y,className:"w-full flex items-center justify-center gap-2 text-[10px] font-bold text-slate-400 uppercase hover:text-blue-600 transition-colors",children:[e.jsx(Le,{size:12})," Refresh Project"]})})]}),it=({searchQuery:s,setSearchQuery:a,setShowCreateModal:y,handleSyncToXcode:x,aiConfig:n,onSemanticSearchResults:r,onBeforeAiSwitch:g,onAiConfigChange:k})=>{const[f,d]=c.useState(!1),[h,v]=c.useState(!1),[p,A]=c.useState([]),[D,O]=c.useState(!1),K=c.useRef(null);c.useEffect(()=>{h&&p.length===0&&M.get("/api/ai/providers").then(m=>A(m.data)).catch(()=>{})},[h,p.length]),c.useEffect(()=>{const m=U=>{K.current&&!K.current.contains(U.target)&&v(!1)};return document.addEventListener("click",m),()=>document.removeEventListener("click",m)},[]);const $=async()=>{if(s){d(!0);try{const m=await M.post("/api/search/semantic",{keyword:s});r&&r(m.data)}catch(m){console.error("Semantic search failed",m),alert("语义搜索失败。请确保已运行 asd embed 构建索引。")}finally{d(!1)}}},H=async m=>{O(!0);try{g==null||g(),await M.post("/api/ai/config",{provider:m.id,model:m.defaultModel}),v(!1),k&&k()}catch(U){console.error("AI config update failed",U),alert("切换 AI 失败,请检查项目根目录是否可写。")}finally{O(!1)}};return e.jsxs("header",{className:"h-16 bg-white border-b border-slate-200 flex items-center justify-between px-8 shrink-0",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsxs("div",{className:"relative w-96",children:[e.jsx(Ze,{className:"absolute left-3 top-1/2 -translate-y-1/2 text-slate-400",size:16}),e.jsx("input",{type:"text",placeholder:"Search knowledge...",className:"w-full pl-10 pr-4 py-2 bg-slate-100 border-transparent rounded-lg text-sm outline-none focus:ring-2 focus:ring-blue-500/20 transition-all",value:s,onChange:m=>a(m.target.value),onKeyDown:m=>m.key==="Enter"&&$()})]}),e.jsxs("button",{onClick:$,disabled:!s||f,className:`flex items-center gap-2 px-3 py-2 rounded-lg text-xs font-bold transition-all ${f?"bg-blue-50 text-blue-400":"bg-blue-50 text-blue-600 hover:bg-blue-100"}`,title:"Semantic Search (Brain AI)",children:[f?e.jsx(Qe,{size:14,className:"animate-spin"}):e.jsx(Ls,{size:14}),"Semantic"]})]}),e.jsxs("div",{className:"flex items-center gap-4",children:[n&&e.jsxs("div",{className:"relative",ref:K,children:[e.jsxs("button",{type:"button",onClick:m=>{m.stopPropagation(),v(U=>!U)},className:"flex items-center gap-2 px-3 py-1.5 rounded-lg bg-slate-100 text-slate-600 text-xs font-medium hover:bg-slate-200 transition-colors",title:"点击切换 AI 提供商",children:[e.jsx(Ce,{size:14}),n.provider," / ",n.model,e.jsx(Pe,{size:12,className:h?"rotate-180":""})]}),h&&e.jsxs("div",{className:"absolute top-full right-0 mt-1 py-1 rounded-lg border border-slate-200 bg-white shadow-lg z-50 min-w-[200px]",children:[e.jsx("div",{className:"px-3 py-2 text-xs text-slate-500 border-b border-slate-100",children:"切换 AI"}),e.jsx("div",{className:"px-3 py-1.5 text-[11px] text-slate-400 border-b border-slate-100",children:"API Key 仍从 .env 读取"}),p.length===0?e.jsx("div",{className:"px-3 py-2 text-xs text-slate-400",children:"加载中..."}):p.map(m=>e.jsxs("button",{type:"button",disabled:D,onClick:()=>H(m),className:`w-full text-left px-3 py-2 text-sm hover:bg-slate-50 flex items-center justify-between ${n.provider===m.id?"bg-blue-50 text-blue-700 font-medium":"text-slate-700"}`,children:[e.jsx("span",{children:m.label}),n.provider===m.id&&e.jsx("span",{className:"text-xs",children:"✓"})]},m.id))]})]}),e.jsxs("button",{onClick:()=>y(!0),className:"flex items-center gap-2 px-4 py-2 bg-slate-900 text-white rounded-lg text-sm font-medium hover:bg-slate-800 transition-colors",children:[e.jsx(es,{size:16})," New Recipe"]}),e.jsxs("button",{onClick:x,className:"flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg text-sm font-medium hover:bg-blue-700 transition-colors shadow-sm",children:[e.jsx(Le,{size:16})," Sync to Xcode"]})]})]})},ot=({selectedCategory:s,setSelectedCategory:a})=>e.jsx("div",{className:"bg-white border-b border-slate-100 shrink-0 overflow-hidden",children:e.jsx("div",{className:"flex items-center gap-2 overflow-x-auto no-scrollbar px-8 py-3",children:Object.entries(de).map(([y,x])=>{const n=x.icon,r=s===y;return e.jsxs("button",{onClick:()=>a(y),className:`flex items-center gap-1.5 px-3 py-1.5 rounded-full text-[10px] font-bold transition-all border whitespace-nowrap
2
+ ${r?`${x.bg} ${x.color} ${x.border} shadow-sm scale-105`:"bg-white text-slate-400 border-slate-100 hover:border-slate-200 hover:text-slate-600"}`,children:[e.jsx(n,{size:12}),y]},y)})})}),De=({currentPage:s,totalPages:a,totalItems:y,pageSize:x,onPageChange:n,onPageSizeChange:r,pageSizeOptions:g=[12,24,48,96]})=>{if(a<=1&&y<=g[0])return null;const k=(s-1)*x+1,f=Math.min(s*x,y),d=()=>{const h=[];if(a<=7)for(let p=1;p<=a;p++)h.push(p);else if(s<=3){for(let p=1;p<=5;p++)h.push(p);h.push("..."),h.push(a)}else if(s>=a-2){h.push(1),h.push("...");for(let p=a-5+1;p<=a;p++)h.push(p)}else{h.push(1),h.push("...");for(let p=s-1;p<=s+1;p++)h.push(p);h.push("..."),h.push(a)}return h};return e.jsxs("div",{className:"flex items-center justify-between mt-6 px-2",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsxs("span",{className:"text-sm text-slate-500",children:["显示 ",k,"-",f,",共 ",y," 条"]}),r&&e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-sm text-slate-500",children:"每页"}),e.jsx("select",{value:x,onChange:h=>r(Number(h.target.value)),className:"text-sm border border-slate-200 rounded-md px-2 py-1 bg-white focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent",children:g.map(h=>e.jsx("option",{value:h,children:h},h))}),e.jsx("span",{className:"text-sm text-slate-500",children:"条"})]})]}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx("button",{onClick:()=>n(1),disabled:s===1,className:"p-1.5 rounded-md hover:bg-slate-100 disabled:opacity-30 disabled:cursor-not-allowed transition-colors",title:"第一页",children:e.jsx(Es,{size:18,className:"text-slate-600"})}),e.jsx("button",{onClick:()=>n(s-1),disabled:s===1,className:"p-1.5 rounded-md hover:bg-slate-100 disabled:opacity-30 disabled:cursor-not-allowed transition-colors",title:"上一页",children:e.jsx(Ds,{size:18,className:"text-slate-600"})}),e.jsx("div",{className:"flex items-center gap-1 mx-2",children:d().map((h,v)=>typeof h=="number"?e.jsx("button",{onClick:()=>n(h),className:`min-w-[32px] h-8 px-2 rounded-md text-sm font-medium transition-colors ${s===h?"bg-blue-600 text-white":"hover:bg-slate-100 text-slate-600"}`,children:h},v):e.jsx("span",{className:"px-1 text-slate-400",children:h},v))}),e.jsx("button",{onClick:()=>n(s+1),disabled:s===a,className:"p-1.5 rounded-md hover:bg-slate-100 disabled:opacity-30 disabled:cursor-not-allowed transition-colors",title:"下一页",children:e.jsx(Ge,{size:18,className:"text-slate-600"})}),e.jsx("button",{onClick:()=>n(a),disabled:s===a,className:"p-1.5 rounded-md hover:bg-slate-100 disabled:opacity-30 disabled:cursor-not-allowed transition-colors",title:"最后一页",children:e.jsx(Ts,{size:18,className:"text-slate-600"})})]})]})},ct=({snippets:s,openSnippetEdit:a,handleDeleteSnippet:y})=>{const[x,n]=c.useState(1),[r,g]=c.useState(12);c.useEffect(()=>{n(1)},[s.length]);const k=Math.ceil(s.length/r),f=(x-1)*r,d=s.slice(f,f+r),h=p=>{n(p),window.scrollTo({top:0,behavior:"smooth"})},v=p=>{g(p),n(1)};return e.jsxs("div",{children:[e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6",children:d.map(p=>e.jsxs("div",{className:"bg-white p-6 rounded-xl border border-slate-200 shadow-sm hover:shadow-md transition-all group relative",children:[e.jsxs("div",{className:"absolute top-4 right-4 flex gap-2 opacity-0 group-hover:opacity-100 transition-opacity",children:[e.jsx("button",{onClick:A=>{A.stopPropagation(),a(p)},className:"p-1.5 bg-slate-50 text-slate-400 hover:text-blue-600 hover:bg-blue-50 rounded-md transition-colors",children:e.jsx(Ne,{size:14})}),e.jsx("button",{onClick:A=>{A.stopPropagation(),y(p.identifier,p.title)},className:"p-1.5 bg-slate-50 text-slate-400 hover:text-red-600 hover:bg-red-50 rounded-md transition-colors",children:e.jsx(Re,{size:14})})]}),e.jsxs("div",{onClick:()=>a(p),className:"cursor-pointer",children:[e.jsxs("div",{className:"flex justify-between items-start mb-4 pr-12",children:[e.jsx("h3",{className:"font-bold text-slate-900",children:p.title}),e.jsxs("div",{className:"flex flex-col items-end gap-1",children:[p.completionKey&&e.jsx("span",{className:"text-[10px] bg-blue-50 text-blue-700 font-bold px-2 py-1 rounded uppercase tracking-wider",children:p.completionKey}),(()=>{const A=p.category||"Utility",D=de[A]||de.Utility,O=D.icon;return e.jsxs("span",{className:`text-[8px] font-bold px-1.5 py-0.5 rounded uppercase flex items-center gap-1 border ${D.bg} ${D.color} ${D.border}`,children:[e.jsx(O,{size:10}),A]})})()]})]}),e.jsx("p",{className:"text-sm text-slate-600 line-clamp-2 mb-4",children:p.summary}),e.jsx("div",{className:"flex items-center gap-2",children:p.language&&e.jsx("span",{className:"text-xs font-medium text-slate-400 bg-slate-100 px-2 py-1 rounded",children:p.language})})]})]},p.identifier))}),e.jsx(De,{currentPage:x,totalPages:k,totalItems:s.length,pageSize:r,onPageChange:h,onPageSizeChange:v})]})},dt=({recipes:s,openRecipeEdit:a,handleDeleteRecipe:y,currentPage:x,onPageChange:n,pageSize:r,onPageSizeChange:g})=>{const[k,f]=c.useState(1),[d,h]=c.useState(12),v=x??k,p=r??d,A=n??f,D=g?m=>g(m):m=>{h(m),f(1)};c.useEffect(()=>{x==null&&f(1)},[s.length,x]);const O=Math.ceil(s.length/p),K=(v-1)*p,$=s.slice(K,K+p),H=m=>{A(m),window.scrollTo({top:0,behavior:"smooth"})};return e.jsxs("div",{children:[e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-6",children:$.map(m=>{var U,te;return e.jsxs("div",{className:"bg-white p-6 rounded-xl border border-slate-200 shadow-sm hover:shadow-md transition-all group relative",children:[e.jsxs("div",{className:"absolute top-4 right-4 flex gap-2 opacity-0 group-hover:opacity-100 transition-opacity",children:[e.jsx("button",{onClick:P=>{P.stopPropagation(),a(m)},className:"p-1.5 bg-slate-50 text-slate-400 hover:text-blue-600 hover:bg-blue-50 rounded-md transition-colors",children:e.jsx(Ne,{size:14})}),e.jsx("button",{onClick:P=>{P.stopPropagation(),y(m.name)},className:"p-1.5 bg-slate-50 text-slate-400 hover:text-red-600 hover:bg-red-50 rounded-md transition-colors",children:e.jsx(Re,{size:14})})]}),e.jsxs("div",{onClick:()=>a(m),className:"cursor-pointer",children:[e.jsxs("div",{className:"flex justify-between items-center mb-2 pr-12",children:[e.jsx("h3",{className:"font-bold text-slate-900",children:m.name}),e.jsxs("div",{className:"flex items-center gap-2",children:[(()=>{var Y,N;const P=((N=(Y=m.content.match(/category:\s*(.*)/))==null?void 0:Y[1])==null?void 0:N.trim())||"Utility",B=de[P]||de.Utility,V=B.icon;return e.jsxs("span",{className:`text-[8px] font-bold px-1.5 py-0.5 rounded uppercase flex items-center gap-1 border ${B.bg} ${B.color} ${B.border}`,children:[e.jsx(V,{size:10}),P]})})(),m.content.includes("type: preview")&&e.jsx("span",{className:"text-[10px] bg-amber-50 text-amber-700 border border-amber-200 px-1.5 py-0.5 rounded font-bold uppercase",children:"Preview Only"})]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2 mb-2 text-[10px] text-slate-500",children:[e.jsxs("span",{children:["权威 ",m.stats!=null?m.stats.authority:"—"]}),e.jsx("span",{children:"·"}),e.jsx("span",{children:m.stats!=null?`g:${m.stats.guardUsageCount} h:${m.stats.humanUsageCount} a:${m.stats.aiUsageCount}`:"g:0 h:0 a:0"}),e.jsx("span",{children:"·"}),e.jsxs("span",{children:["综合分 ",((U=m.stats)==null?void 0:U.authorityScore)!=null?m.stats.authorityScore.toFixed(2):"—"]}),((te=m.stats)==null?void 0:te.lastUsedAt)&&e.jsxs(e.Fragment,{children:[e.jsx("span",{children:"·"}),e.jsxs("span",{children:["最近 ",new Date(m.stats.lastUsedAt).toLocaleDateString()]})]}),e.jsx("span",{className:"text-slate-400",children:"(编辑时可设置权威分)"})]}),e.jsx("div",{className:"text-xs text-slate-500 bg-slate-50 p-4 rounded-lg overflow-hidden line-clamp-6 font-mono whitespace-pre-wrap",children:m.content})]})]},m.name)})}),e.jsx(De,{currentPage:v,totalPages:O,totalItems:s.length,pageSize:p,onPageChange:H,onPageSizeChange:D})]})},xt=()=>e.jsxs("div",{className:"max-w-3xl mx-auto py-8",children:[e.jsxs("h1",{className:"text-2xl font-bold text-slate-900 mb-8 flex items-center gap-2",children:[e.jsx(Je,{size:28,className:"text-blue-600"})," 使用说明"]}),e.jsxs("div",{className:"prose prose-slate max-w-none space-y-8 text-sm",children:[e.jsxs("section",{children:[e.jsx("h2",{className:"text-lg font-bold text-slate-800 mb-3",children:"开发者、AI 与知识库"}),e.jsx("div",{className:"overflow-x-auto mb-2",children:e.jsxs("table",{className:"min-w-full border border-slate-200 rounded-lg text-left text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"bg-slate-50",children:[e.jsx("th",{className:"px-3 py-2 border-b",children:"角色"}),e.jsx("th",{className:"px-3 py-2 border-b",children:"职责"}),e.jsx("th",{className:"px-3 py-2 border-b",children:"能力"})]})}),e.jsxs("tbody",{children:[e.jsxs("tr",{children:[e.jsx("td",{className:"px-3 py-2 border-b font-medium",children:"开发者"}),e.jsx("td",{className:"px-3 py-2 border-b",children:"审核与决策;维护项目标准"}),e.jsxs("td",{className:"px-3 py-2 border-b",children:["Dashboard 审核 Candidate、保存 Recipe;Snippet 补全、",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"// as:search"}),";",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd embed"}),"、",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd ui"})]})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-3 py-2 border-b font-medium",children:"Cursor Agent"}),e.jsx("td",{className:"px-3 py-2 border-b",children:"按规范生成代码;检索知识库"}),e.jsx("td",{className:"px-3 py-2 border-b",children:"Skills 理解规范;MCP 按需检索、打开新建 Recipe 页;起草供人工审核,不直接改 Knowledge"})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-3 py-2 border-b font-medium",children:"项目内 AI"}),e.jsx("td",{className:"px-3 py-2 border-b",children:"提取、摘要、扫描、审查"}),e.jsxs("td",{className:"px-3 py-2 border-b",children:[e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd ais"}),";Use Copied Code 分析;Guard 审查;Dashboard RAG。由 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:".env"})," 配置"]})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-3 py-2 font-medium",children:"知识库"}),e.jsx("td",{className:"px-3 py-2",children:"存储与提供项目标准"}),e.jsx("td",{className:"px-3 py-2",children:"Recipes、Snippets、语义向量;Guard、搜索、两种 AI 均依赖"})]})]})]})}),e.jsxs("p",{className:"text-slate-600",children:[e.jsx("strong",{children:"闭环"}),":扫描 → 审核 → 沉淀 → Cursor/AI 使用 → 再沉淀。用 Cursor 基于知识库写代码;写完通过 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"// as:create"}),"、",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd create --clipboard"})," 或 Dashboard 提交入库;用 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"// as:guard"})," 合规审查;用 Snippet 或 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"// as:search"})," 插入标准代码。知识库随人工审核持续更新。"]})]}),e.jsxs("section",{children:[e.jsx("h2",{className:"text-lg font-bold text-slate-800 mb-3",children:"页面说明"}),e.jsxs("ul",{className:"list-disc pl-6 space-y-2 text-slate-600",children:[e.jsxs("li",{children:[e.jsx("strong",{children:"Snippets"}),":查看、编辑、删除代码片段;点击「Sync to Xcode」同步到 Xcode CodeSnippets。"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"Recipes"}),":管理配方(Recipes)文档,与 Snippet 关联。"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"SPM Explorer"}),":按 Target 扫描源码,AI 提取候选;或从路径/剪贴板创建 Recipe。"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"Candidates"}),":审核由 CLI ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd ais"})," 或 Cursor MCP 批量扫描(",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"autosnippet_submit_candidates"}),")产生的候选,通过入库或忽略。"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"依赖关系图"}),":展示 SPM 包依赖;",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd spm-map"})," 更新。"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"AI Assistant"}),":基于本地 Snippets/Recipes 的 RAG 问答;支持语义搜索。"]})]})]}),e.jsxs("section",{children:[e.jsx("h2",{className:"text-lg font-bold text-slate-800 mb-3",children:"新建 Recipe"}),e.jsxs("p",{className:"text-slate-600 mb-2",children:["本页即 Dashboard。若从 Cursor 等外部打开,在浏览器访问 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"http://localhost:3000"})," 即可(Dashboard 需已运行;未运行则终端执行 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd ui"})," 启动)。"]}),e.jsx("p",{className:"text-slate-600 mb-2",children:"点击顶部「New Recipe」打开弹窗:"}),e.jsxs("ul",{className:"list-disc pl-6 space-y-2 text-slate-600",children:[e.jsxs("li",{children:[e.jsx("strong",{children:"按路径"}),":输入相对路径(如 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"Sources/MyMod/Foo.m"}),"),点击「Scan File」→ AI 提取标题/摘要/触发键/头文件,在 SPM Explorer 审核后保存。"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"按剪贴板"}),":复制代码后点击「Use Copied Code」。",e.jsx("strong",{children:"完整 Recipe MD"}),"(含 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"---"})," frontmatter、",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"## Snippet / Code Reference"}),"、",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"## AI Context / Usage Guide"}),")会直接解析,不调用 AI 重写。纯代码则由 AI 分析填充。若由 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"// as:create"})," 打开,会带当前文件路径自动解析头文件。"]})]})]}),e.jsxs("section",{children:[e.jsx("h2",{className:"text-lg font-bold text-slate-800 mb-3",children:"编辑器内指令"}),e.jsxs("p",{className:"text-slate-600 mb-2",children:["需先运行 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd watch"})," 或 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd ui"}),"。支持简写:",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"as:c"}),"=as:create、",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"as:s"}),"=as:search、",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"as:g"}),"=as:guard。"]}),e.jsxs("ul",{className:"list-disc pl-6 space-y-2 text-slate-600",children:[e.jsxs("li",{children:[e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"// as:create"})," / ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"// as:c"}),":无选项时只打开本页(路径已填),由您点 Scan File 或 Use Copied Code。",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"-c"})," 强制用剪切板(静默创建或打开),",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"-f"})," 强制用路径(打开本页并自动执行 Scan File)。"]}),e.jsxs("li",{children:[e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"// as:guard"})," / ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"// as:g"})," [关键词或规模]:无后缀时仅检查当前文件;后缀 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"file"})," / ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"target"})," / ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"project"})," 可扩大审查范围,结果输出终端。需 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd embed"})," 后优先用语义检索。"]}),e.jsxs("li",{children:[e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"// as:search"})," / ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"// as:s"})," [关键词]:从知识库检索 Recipe/Snippet,选一条插入替换该行。"]}),e.jsxs("li",{children:[e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"// as:include"})," / ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"// as:import"}),":Snippet 内头文件/模块标记;watch 保存时自动在文件头部注入对应 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"#import"})," 或 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"import"}),"。"]})]}),e.jsxs("p",{className:"text-slate-600 mt-3",children:[e.jsx("strong",{children:"静默候选"}),":在 Cursor 内用户提出保存案例,Cursor 生成草案;后台用草案静默创建候选,无需打开浏览器,到本页 ",e.jsx("strong",{children:"Candidates"})," 审核即可。在 Xcode 等编辑器内也可写 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"// as:c -c"}),"、复制代码后保存,剪贴板内容同样静默入库。",e.jsx("strong",{children:"搜索无跳转"}),":",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"// as:search"})," / ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"// as:s"})," 在编辑器内弹窗或终端选择,即选即插,无需跳转本页,不打断当前编辑。"]})]}),e.jsxs("section",{children:[e.jsx("h2",{className:"text-lg font-bold text-slate-800 mb-3",children:"语义能力"}),e.jsxs("ul",{className:"list-disc pl-6 space-y-2 text-slate-600",children:[e.jsxs("li",{children:[e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd embed"}),":构建语义向量索引。本 Dashboard 启动时自动检测并执行,亦可手动运行。可设 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"ASD_AUTO_EMBED=0"})," 关闭自动 embed。"]}),e.jsxs("li",{children:[e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd search -m [query]"}),":语义搜索知识库(自然语言)。"]}),e.jsxs("li",{children:[e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd install:cursor-skill --mcp"}),":安装 Skills、",e.jsx("strong",{children:"Cursor 规则"}),"(",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:".cursor/rules/*.mdc"}),")并配置 MCP;Cursor Agent 可调用 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"autosnippet_context_search"})," 按需检索、",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"autosnippet_open_create"})," 打开新建 Recipe 页;批量扫描可用 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"autosnippet_get_targets"}),"、",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"autosnippet_get_target_files"}),"、",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"autosnippet_submit_candidates"}),"。需本 Dashboard 运行。"]})]})]}),e.jsxs("section",{children:[e.jsx("h2",{className:"text-lg font-bold text-slate-800 mb-3",children:"Recipe 格式"}),e.jsxs("p",{className:"text-slate-600 mb-2",children:["完整 Recipe 为 Markdown:",e.jsx("strong",{children:"Frontmatter"}),"(",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"---"})," 包裹,",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"title"}),"、",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"trigger"})," 必填)+ ",e.jsx("strong",{children:"## Snippet / Code Reference"}),"(下接代码块)+ ",e.jsx("strong",{children:"## AI Context / Usage Guide"}),"(使用说明)。粘贴完整 Recipe MD 时直接解析入库,不调用 AI。多段 Recipe 用「空行 + ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"---"})," + 下一段 frontmatter」分隔可批量解析。"]})]}),e.jsxs("section",{children:[e.jsx("h2",{className:"text-lg font-bold text-slate-800 mb-3",children:"头文件与 watch"}),e.jsxs("p",{className:"text-slate-600 mb-2",children:["保存时可勾选「引入头文件」,会写入 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded text-xs",children:"// as:include <TargetName/Header.h>"}),"(ObjC)或 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded text-xs",children:"// as:import ModuleName"}),"(Swift)。在项目目录运行 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd watch"}),"(或 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd ui"}),")后,在 Xcode 中选中 Snippet 的 headerVersion 并保存,会自动在文件头部注入对应 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"#import"})," / ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"import"}),"。"]})]}),e.jsxs("section",{children:[e.jsx("h2",{className:"text-lg font-bold text-slate-800 mb-3",children:"全量安装与可选依赖"}),e.jsx("p",{className:"text-slate-600 mb-2",children:"任意目录执行:"}),e.jsxs("ul",{className:"list-disc pl-6 space-y-2 text-slate-600",children:[e.jsxs("li",{children:[e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd install:full"}),":核心 + 可选依赖 + Dashboard(前端不存在时构建)"]}),e.jsxs("li",{children:[e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd install:full --parser"}),":上述 + Swift 解析器(ParsePackage,SPM 解析更准确;默认回退 dump-package,需本机已装 Swift)"]}),e.jsxs("li",{children:[e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd install:full --lancedb"}),":仅安装 LanceDB(向量检索更快;再在 boxspec ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"context.storage.adapter"})," 配 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:'"lance"'}),")"]})]})]}),e.jsxs("section",{children:[e.jsx("h2",{className:"text-lg font-bold text-slate-800 mb-3",children:"AI 配置"}),e.jsxs("p",{className:"text-slate-600 mb-2",children:["项目根 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:".env"})," 设置 API Key(如 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"ASD_GOOGLE_API_KEY"}),")。可选 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"ASD_AI_PROVIDER"}),"、",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"ASD_AI_MODEL"}),"、代理(",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"https_proxy"}),")等。支持:Gemini、OpenAI、DeepSeek、Claude、Ollama(本地)。见 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:".env.example"}),"。"]})]}),e.jsxs("section",{children:[e.jsx("h2",{className:"text-lg font-bold text-slate-800 mb-3",children:"Cursor Skills 一览"}),e.jsxs("ul",{className:"list-disc pl-6 space-y-2 text-slate-600",children:[e.jsxs("li",{children:[e.jsx("strong",{children:"autosnippet-when"}),":路由,根据用户意图推荐对应能力"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"autosnippet-concepts"}),":知识库、Recipe、Context 存储、Recipe 优先级"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"autosnippet-recipes"}),":项目 Recipe 上下文、检索方式"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"autosnippet-create"}),":提交代码到 Dashboard、禁止直接写 Knowledge"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"autosnippet-search"}),":查找/插入推荐"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"autosnippet-guard"}),":审查推荐"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"autosnippet-dep-graph"}),":SPM 依赖结构"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"autosnippet-batch-scan"}),":用 Cursor 做批量扫描(何时用、流程语义);MCP 提供 get_targets / get_target_files / submit_candidates"]})]}),e.jsxs("p",{className:"text-slate-600 mt-2",children:["设计:",e.jsx("strong",{children:"Skills 做语义"}),"(何时用、怎么用)、",e.jsx("strong",{children:"MCP 提供能力"}),"(连接与工具)。安装时会写入 ",e.jsx("strong",{children:"Cursor 规则"}),"(",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:".cursor/rules/autosnippet-conventions.mdc"}),"),使会话中持久遵循上述约定。MCP 工具:",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"autosnippet_context_search"})," 按需检索;",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"autosnippet_open_create"})," 打开新建 Recipe 页;批量扫描:",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"autosnippet_get_targets"}),"、",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"autosnippet_get_target_files"}),"、",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"autosnippet_submit_candidates"}),"(语义见 autosnippet-batch-scan Skill)。"]})]}),e.jsxs("section",{children:[e.jsx("h2",{className:"text-lg font-bold text-slate-800 mb-3",children:"命令行速查"}),e.jsxs("ul",{className:"list-disc pl-6 space-y-2 text-slate-600",children:[e.jsxs("li",{children:[e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd ui"}),":启动本 Dashboard(并后台 watch)"]}),e.jsxs("li",{children:[e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd create --clipboard [--path 相对路径]"}),":从剪贴板用 AI 创建 Recipe/Snippet"]}),e.jsxs("li",{children:[e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd create"}),":从含 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"// as:code"})," 的文件用 AI 创建 Snippet"]}),e.jsxs("li",{children:[e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd install"}),":同步 Snippets 到 Xcode"]}),e.jsxs("li",{children:[e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd ais [Target]"})," / ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd ais --all"}),":AI 扫描,结果在 Candidates 审核"]}),e.jsxs("li",{children:[e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd search [keyword]"}),":关键词搜索;加 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"-m"})," 为语义搜索"]}),e.jsxs("li",{children:[e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd watch"}),":仅监听,不打开浏览器"]})]})]}),e.jsxs("section",{children:[e.jsx("h2",{className:"text-lg font-bold text-slate-800 mb-3",children:"术语"}),e.jsxs("ul",{className:"list-disc pl-6 space-y-1 text-slate-600",children:[e.jsxs("li",{children:[e.jsx("strong",{children:"Recipe"}),":",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"Knowledge/recipes/"})," 下的 Markdown 知识"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"Snippet"}),":Xcode 代码片段,trigger 补全(默认 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"@"}),")"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"项目根"}),":含 ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"AutoSnippetRoot.boxspec.json"})," 的目录"]})]})]})]})]}),mt={objectivec:"objectivec",objc:"objectivec","objective-c":"objectivec","obj-c":"objectivec",swift:"swift",markdown:"markdown",md:"markdown"},je=({code:s,language:a="text",className:y="",showLineNumbers:x=!1})=>{const n=mt[a==null?void 0:a.toLowerCase()]||(a==null?void 0:a.toLowerCase())||"text";return e.jsx("div",{className:`rounded-xl overflow-hidden text-sm ${y}`,children:e.jsx(Js,{language:n,style:Zs,showLineNumbers:x,customStyle:{margin:0,padding:"1rem 1.25rem",fontSize:"0.8125rem",lineHeight:1.5,borderRadius:"0.75rem"},codeTagProps:{style:{fontFamily:"ui-monospace, monospace"}},PreTag:"div",children:s})})};function Te(s){return!s||typeof s!="string"?s:s.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/,"").trim()||s}const fe=({content:s,className:a="",showLineNumbers:y=!1,stripFrontmatter:x=!1})=>{const n=x?Te(s):s;return e.jsx("div",{className:`markdown-body text-slate-700 ${a}`,children:e.jsx(Qs,{components:{code({node:r,className:g,children:k,...f}){const d=/language-(\w+)/.exec(g||"");return String(k).includes(`
3
+ `)&&d?e.jsx(je,{code:String(k).replace(/\n$/,""),language:d[1],showLineNumbers:y}):e.jsx("code",{className:"px-1.5 py-0.5 bg-slate-100 text-slate-800 rounded text-sm font-mono",...f,children:k})},p:({children:r})=>e.jsx("p",{className:"mb-3 last:mb-0",children:r}),h1:({children:r})=>e.jsx("h1",{className:"text-xl font-bold mb-2 mt-4 first:mt-0",children:r}),h2:({children:r})=>e.jsx("h2",{className:"text-lg font-bold mb-2 mt-4",children:r}),h3:({children:r})=>e.jsx("h3",{className:"text-base font-bold mb-1 mt-3",children:r}),ul:({children:r})=>e.jsx("ul",{className:"list-disc list-inside mb-3 space-y-1",children:r}),ol:({children:r})=>e.jsx("ol",{className:"list-decimal list-inside mb-3 space-y-1",children:r}),blockquote:({children:r})=>e.jsx("blockquote",{className:"border-l-4 border-slate-200 pl-4 my-3 text-slate-600 italic",children:r}),a:({href:r,children:g})=>e.jsx("a",{href:r,className:"text-blue-600 hover:underline",target:"_blank",rel:"noopener noreferrer",children:g})},children:n})})},Xe={_watch:"as:create",_draft:"草稿",_cli:"CLI",_pending:"待审核(24h)",_recipe:"New Recipe"};function ut(s,a,y,x){return[...s].sort(([n],[r])=>{const g=x(n),k=x(r);if(g&&!k)return 1;if(!g&&k)return-1;const f=y(n),d=y(r);if(f&&!d)return-1;if(!f&&d)return 1;const h=a(n),v=a(r);return h&&!v?1:!h&&v?-1:n.localeCompare(r)})}const pt=({data:s,isShellTarget:a,isSilentTarget:y=()=>!1,isPendingTarget:x=()=>!1,handleDeleteCandidate:n,handleDeleteAllInTarget:r,onAuditCandidate:g,onAuditAllInTarget:k,onEditRecipe:f})=>{const[d,h]=c.useState(null),[v,p]=c.useState({}),[A,D]=c.useState(null),[O,K]=c.useState({}),[$,H]=c.useState(null),[m,U]=c.useState(null),te=c.useRef(new Set),P=c.useCallback(async(u,R)=>{if(!te.current.has(R)){te.current.add(R),H(R);try{const j=await M.post("/api/candidates/similarity",{targetName:u,candidateId:R});K(t=>({...t,[R]:j.data.similar||[]}))}catch{K(t=>({...t,[R]:[]}))}finally{H(null)}}},[]),B=c.useCallback(async(u,R,j,t=[])=>{var z;let o="";const i=(z=s==null?void 0:s.recipes)==null?void 0:z.find(I=>I.name===j||I.name.endsWith("/"+j));if(i!=null&&i.content)o=i.content;else try{o=(await M.get(`/api/recipes/get?name=${encodeURIComponent(j)}`)).data.content}catch{return}const S={[j]:o};U({candidate:u,targetName:R,recipeName:j,recipeContent:o,similarList:t.slice(0,3),recipeContents:S})},[s==null?void 0:s.recipes]),V=s!=null&&s.candidates?Object.entries(s.candidates):[],Y=ut(V,a,y,x),N=Y.map(([u])=>u),L=A&&N.includes(A)?A:N[0]??null;return c.useEffect(()=>{N.length>0&&(!A||!N.includes(A))&&D(N[0])},[N.join(","),A]),c.useEffect(()=>{d&&L&&P(L,d)},[d,L,P]),e.jsxs("div",{className:"flex-1 flex flex-col overflow-hidden",children:[e.jsxs("div",{className:"mb-4 flex justify-between items-center shrink-0",children:[e.jsxs("h2",{className:"text-xl font-bold flex items-center gap-2",children:[e.jsx(we,{className:"text-amber-500"})," AI Scan Candidates"]}),e.jsx("div",{className:"text-xs text-slate-400 bg-slate-100 px-3 py-1 rounded-full",children:"这些内容由 AI 批量扫描生成,等待您的审核入库。"})]}),V.length>0&&e.jsx("div",{className:"shrink-0 bg-white border border-slate-100 rounded-xl px-3 py-2 mb-4",children:e.jsx("div",{className:"flex items-center gap-1.5 overflow-x-auto no-scrollbar",children:N.map(u=>{var z;const R=a(u),j=y(u),t=Xe[u],o=s.candidates[u],i=((z=o==null?void 0:o.items)==null?void 0:z.length)??0,S=L===u;return e.jsxs("button",{onClick:()=>D(u),className:`flex items-center gap-2 px-3 py-2 rounded-lg text-sm font-bold whitespace-nowrap transition-all border
4
+ ${S?"bg-blue-50 text-blue-700 border-blue-200 shadow-sm":"bg-slate-50/80 text-slate-600 border-slate-100 hover:border-slate-200 hover:bg-slate-100"}`,children:[R?e.jsx(pe,{size:14,className:S?"text-blue-500":"text-slate-400"}):e.jsx(pe,{size:14,className:S?"text-blue-600":"text-slate-500"}),e.jsx("span",{children:u}),j&&t&&e.jsx("span",{className:"text-[9px] text-amber-600 border border-amber-200 px-1 rounded",children:t}),e.jsxs("span",{className:"text-[10px] font-normal text-slate-400",children:["(",i,")"]})]},u)})})}),e.jsxs("div",{className:"flex-1 overflow-y-auto pr-2",children:[(!(s!=null&&s.candidates)||Object.keys(s.candidates).length===0)&&e.jsxs("div",{className:"h-64 flex flex-col items-center justify-center bg-white rounded-2xl border border-dashed border-slate-200 text-slate-400",children:[e.jsx(ss,{size:48,className:"mb-4 opacity-20"}),e.jsx("p",{children:"未发现候选内容。"}),e.jsxs("p",{className:"mt-2 text-xs",children:["可执行 ",e.jsx("code",{children:"asd ais --all"})," 扫描,或 ",e.jsx("code",{children:"asd candidate"})," 从剪贴板创建,或在代码中写 ",e.jsx("code",{children:"// as:create"})," 后保存。"]})]}),s&&L&&Y.filter(([u])=>u===L).map(([u,R])=>{const j=a(u),t=y(u),o=Xe[u]||"静默",i=v[u]||{page:1,pageSize:12},S=i.page,z=i.pageSize,I=R.items.length,q=Math.ceil(I/z),X=(S-1)*z,_=R.items.slice(X,X+z),F=G=>{p(J=>({...J,[u]:{...i,page:G}}))},W=G=>{p(J=>({...J,[u]:{page:1,pageSize:G}}))};return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:`flex items-center gap-2 px-3 py-2 rounded-lg border border-slate-100 ${j?"bg-slate-50/50":"bg-white"}`,children:[j?e.jsx(pe,{size:18,className:"text-slate-400"}):e.jsx(pe,{size:18,className:"text-blue-600"}),e.jsx("span",{className:`text-lg font-bold ${j?"text-slate-400":"text-slate-800"}`,children:u}),t&&e.jsx("span",{className:"text-[10px] font-bold text-amber-600 border border-amber-200 px-1 rounded ml-2",children:o}),j&&!t&&e.jsx("span",{className:"text-[10px] font-bold text-slate-300 border border-slate-200 px-1 rounded ml-2",children:"SHELL MODULE"}),e.jsxs("span",{className:"text-xs text-slate-400",children:["扫描于 ",new Date(R.scanTime).toLocaleString()]}),e.jsxs("div",{className:"flex items-center gap-2 ml-auto",children:[e.jsxs("span",{className:"text-xs text-slate-400",children:["共 ",R.items.length," 条"]}),I>z&&e.jsxs("span",{className:"text-xs text-slate-500",children:["(当前页 ",_.length," 条)"]}),e.jsx("button",{onClick:()=>k(_,u),className:"text-[10px] font-bold text-blue-600 hover:text-blue-700 px-2 py-1 rounded hover:bg-blue-50 transition-colors",title:"将当前页所有候选进入审核",children:"当前页进入审核"}),e.jsx("button",{onClick:()=>{window.confirm(`确定移除当前页的 ${_.length} 条候选?`)&&_.forEach(G=>n(u,G.id))},className:"text-[10px] font-bold text-orange-500 hover:text-orange-600 px-2 py-1 rounded hover:bg-orange-50 transition-colors",title:"移除当前页所有候选",children:"移除当前页"}),e.jsx("button",{onClick:()=>r(u),className:"text-[10px] font-bold text-red-600 hover:text-red-700 px-2 py-1 rounded hover:bg-red-50 transition-colors border border-red-200",title:"移除该 target 下的全部候选",children:"全部删除"})]})]}),e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:_.map(G=>{var J,ve,be;return e.jsxs("div",{className:`bg-white rounded-xl border border-slate-200 p-4 hover:shadow-md transition-shadow flex flex-col group ${j?"opacity-80":""}`,children:[e.jsxs("div",{className:"flex justify-between items-start mb-2",children:[e.jsxs("div",{className:"flex flex-col",children:[e.jsx("span",{className:`text-[10px] font-bold uppercase mb-0.5 ${j?"text-slate-400":"text-blue-500"}`,children:u}),e.jsx("h3",{className:"font-bold text-sm text-slate-800",children:G.title}),G.category&&e.jsxs("span",{className:`w-fit mt-1 text-[8px] font-bold px-1.5 py-0.5 rounded uppercase flex items-center gap-1 border ${((J=de[G.category])==null?void 0:J.bg)||"bg-slate-50"} ${((ve=de[G.category])==null?void 0:ve.color)||"text-slate-400"} ${((be=de[G.category])==null?void 0:be.border)||"border-slate-100"}`,children:[(()=>{var re;const oe=((re=de[G.category])==null?void 0:re.icon)||Me;return e.jsx(oe,{size:10})})(),G.category]})]}),e.jsx("div",{className:"flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity",children:e.jsx("button",{onClick:()=>n(u,G.id),title:"忽略",className:"p-1 hover:bg-red-50 text-slate-400 hover:text-red-500 rounded transition-colors",children:e.jsx(Re,{size:14})})})]}),e.jsx("p",{className:"text-xs text-slate-500 line-clamp-2 mb-4 flex-1 h-8 leading-relaxed",children:G.summary}),d===G.id&&e.jsxs("div",{className:"mb-4 space-y-3",children:[(()=>{const oe=O[G.id],re=$===G.id;return((oe==null?void 0:oe.length)??0)>0||re?e.jsxs("div",{className:"flex flex-wrap gap-1.5 items-center",children:[e.jsx("span",{className:"text-[10px] text-slate-400 font-bold",children:"相似 Recipe:"}),re?e.jsx("span",{className:"text-[10px] text-slate-400",children:"加载中..."}):(oe||[]).slice(0,3).map(me=>e.jsxs("button",{onClick:()=>B(G,u,me.recipeName,oe||[]),className:"text-[10px] font-bold px-2 py-1 rounded bg-amber-50 text-amber-700 border border-amber-200 hover:bg-amber-100 transition-colors flex items-center gap-1",title:`与 ${me.recipeName} 相似 ${(me.similarity*100).toFixed(0)}%,点击对比`,children:[e.jsx(ts,{size:10}),me.recipeName.replace(/\.md$/i,"")," ",(me.similarity*100).toFixed(0),"%"]},me.recipeName))]}):null})(),e.jsx("div",{className:"rounded-xl overflow-hidden border border-slate-100 bg-slate-50 max-h-60 overflow-y-auto",children:G.code?e.jsx(je,{code:G.code,language:G.language==="objc"?"objectivec":G.language}):e.jsx("div",{className:"p-4",children:e.jsx(fe,{content:G.usageGuide||""})})})]}),e.jsxs("div",{className:"flex justify-between items-center mt-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:()=>h(d===G.id?null:G.id),className:`p-1.5 rounded-lg transition-colors ${d===G.id?"bg-blue-100 text-blue-600":"bg-slate-100 text-slate-400 hover:text-blue-600"}`,title:d===G.id?"隐藏预览":"查看代码/指南预览",children:d===G.id?e.jsx(Us,{size:14}):e.jsx(Ee,{size:14})}),e.jsx("span",{className:`text-[10px] font-mono px-2 py-0.5 rounded font-bold ${j?"bg-slate-100 text-slate-500":"bg-blue-50 text-blue-600"}`,children:G.trigger}),e.jsx("span",{className:"text-[10px] text-slate-400 uppercase font-bold",children:G.language})]}),e.jsxs("button",{onClick:()=>g(G,u),className:"text-[10px] font-bold text-blue-600 hover:underline flex items-center gap-1",children:[e.jsx(Ne,{size:12})," 审核并保存"]})]})]},G.id)})}),I>12&&e.jsx(De,{currentPage:S,totalPages:q,totalItems:I,pageSize:z,onPageChange:F,onPageSizeChange:W})]},u)})]}),m&&(()=>{const u=m.candidate,R=u.language==="objc"||u.language==="objective-c"?"objectivec":u.language||"text",j=()=>{const I=[];u.code&&I.push("## Snippet / Code Reference\n\n```"+R+`
5
+ `+u.code+"\n```"),u.usageGuide&&I.push(`
6
+ ## AI Context / Usage Guide
7
+
8
+ `+u.usageGuide),navigator.clipboard.writeText(I.join(`
9
+ `)||"").then(()=>E("已复制候选内容"))},t=()=>{const I=Te(m.recipeContent);navigator.clipboard.writeText(I).then(()=>E("已复制 Recipe 内容"))},o=async I=>{var X;if(I===m.recipeName)return;const q=m.recipeContents[I];if(q)U(_=>_?{..._,recipeName:I,recipeContent:q}:null);else{let _="";const F=(X=s==null?void 0:s.recipes)==null?void 0:X.find(W=>W.name===I||W.name.endsWith("/"+I));if(F!=null&&F.content)_=F.content;else try{_=(await M.get(`/api/recipes/get?name=${encodeURIComponent(I)}`)).data.content}catch{return}U(W=>W?{...W,recipeName:I,recipeContent:_,recipeContents:{...W.recipeContents,[I]:_}}:null)}},i=async()=>{if(window.confirm("确定删除该候选?"))try{await n(m.targetName,u.id),U(null)}catch{}},S=()=>{g(u,m.targetName),U(null)},z=()=>{var q;const I=((q=s==null?void 0:s.recipes)==null?void 0:q.find(X=>X.name===m.recipeName||X.name.endsWith("/"+m.recipeName)))||{name:m.recipeName,content:m.recipeContent};f==null||f(I),U(null)};return e.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-2",onClick:()=>U(null),children:e.jsxs("div",{className:"bg-white rounded-2xl shadow-2xl w-[min(95vw,1600px)] max-h-[92vh] flex flex-col",onClick:I=>I.stopPropagation(),children:[e.jsxs("div",{className:"flex justify-between items-center px-4 py-3 border-b border-slate-200 shrink-0",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("h3",{className:"font-bold text-slate-800",children:"候选 vs Recipe 对比"}),e.jsx("button",{onClick:i,className:"text-xs text-red-600 hover:bg-red-50 px-2 py-1 rounded",children:"删除候选"}),e.jsx("button",{onClick:S,className:"text-xs text-blue-600 hover:bg-blue-50 px-2 py-1 rounded",children:"审核候选"}),e.jsx("button",{onClick:z,className:"text-xs text-emerald-600 hover:bg-emerald-50 px-2 py-1 rounded",children:"审核 Recipe"})]}),e.jsx("button",{onClick:()=>U(null),className:"p-2 hover:bg-slate-100 rounded-lg transition-colors",children:e.jsx(ye,{size:18})})]}),e.jsxs("div",{className:"flex-1 grid grid-cols-2 overflow-hidden min-h-0",style:{gridTemplateRows:"auto 1fr"},children:[e.jsxs("div",{className:"px-4 py-3 bg-blue-50 border-b border-r border-slate-100 flex flex-col justify-center min-h-0",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsxs("span",{className:"text-sm font-bold text-blue-700 truncate flex-1 min-w-0",title:u.title,children:["候选:",u.title]}),e.jsxs("button",{onClick:j,className:"p-1.5 hover:bg-blue-100 rounded-lg text-blue-600 shrink-0",title:"复制",children:[" ",e.jsx(_e,{size:14})," "]})]}),e.jsx("div",{className:"min-h-[28px] mt-2 shrink-0"})]}),e.jsxs("div",{className:"px-4 py-3 bg-emerald-50 border-b border-slate-100 flex flex-col justify-center min-h-0",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsxs("span",{className:"text-sm font-bold text-emerald-700 truncate flex-1 min-w-0",title:m.recipeName,children:["Recipe:",m.recipeName.replace(/\.md$/i,"")]}),e.jsxs("button",{onClick:t,className:"p-1.5 hover:bg-emerald-100 rounded-lg text-emerald-600 shrink-0",title:"复制",children:[" ",e.jsx(_e,{size:14})," "]})]}),m.similarList.length>1?e.jsx("div",{className:"flex flex-wrap gap-1 mt-2 shrink-0",children:m.similarList.map(I=>e.jsxs("button",{onClick:()=>o(I.recipeName),className:`text-[10px] font-bold px-2 py-1 rounded transition-colors ${m.recipeName===I.recipeName?"bg-emerald-200 text-emerald-800":"bg-white/80 text-emerald-600 hover:bg-emerald-100"}`,children:[I.recipeName.replace(/\.md$/i,"")," ",(I.similarity*100).toFixed(0),"%"]},I.recipeName))}):e.jsx("div",{className:"min-h-[28px] mt-2 shrink-0"})]}),e.jsxs("div",{className:"flex-1 overflow-auto p-4 min-h-0 border-r border-slate-200 markdown-body text-slate-700",children:[e.jsx("h2",{className:"text-lg font-bold mb-2 mt-4",children:"Snippet / Code Reference"}),u.code?e.jsx(je,{code:u.code,language:R,className:"!overflow-visible"}):e.jsx("p",{className:"text-slate-400 italic mb-3",children:"(无代码)"}),e.jsx("h2",{className:"text-lg font-bold mb-2 mt-4",children:"AI Context / Usage Guide"}),u.usageGuide?e.jsx(fe,{content:u.usageGuide}):e.jsx("p",{className:"text-slate-400 italic",children:"(无使用指南)"})]}),e.jsx("div",{className:"flex-1 overflow-auto p-4 min-h-0",children:e.jsx(fe,{content:m.recipeContent,stripFrontmatter:!0})})]})]})})})()]})},ht=({targets:s,filteredTargets:a,selectedTargetName:y,isScanning:x,scanProgress:n,scanFileList:r,scanResults:g,handleScanTarget:k,handleUpdateScanResult:f,handleSaveExtracted:d,handleDeleteCandidate:h,onEditRecipe:v,isShellTarget:p,recipes:A=[]})=>{const[D,O]=c.useState(null),[K,$]=c.useState(null),[H,m]=c.useState({}),[U,te]=c.useState(null),[P,B]=c.useState(null),V=c.useRef(new Set),Y=c.useRef([]),N=c.useRef(!1),L=t=>{const o=(t.language||"").toLowerCase();return o==="objectivec"||o==="objc"||o==="objective-c"||o==="obj-c"?"objectivec":t.language||"swift"},u=c.useCallback(async(t,o)=>{if(!V.current.has(t)){V.current.add(t),te(t);try{const i=o.candidateId&&o.targetName?{targetName:o.targetName,candidateId:o.candidateId}:{candidate:o.candidate||{}},S=await M.post("/api/candidates/similarity",i);m(z=>({...z,[t]:S.data.similar||[]}))}catch{m(S=>({...S,[t]:[]}))}finally{te(null)}}},[]),R=c.useCallback(async(t,o,i=[])=>{const S=t.candidateTargetName||"";let z="";const I=A==null?void 0:A.find(X=>X.name===o||X.name.endsWith("/"+o));if(I!=null&&I.content)z=I.content;else try{z=(await M.get(`/api/recipes/get?name=${encodeURIComponent(o)}`)).data.content}catch{return}const q={[o]:z};B({candidate:t,targetName:S,recipeName:o,recipeContent:z,similarList:i.slice(0,3),recipeContents:q})},[A]),j=c.useCallback(async(t,o)=>{var X,_;if(N.current)return;if(o==="cn"){f(t,{lang:"cn"});return}const i=g[t];if(!i)return;const S=i.summary_cn??i.summary??"",z=i.usageGuide_cn??i.usageGuide??"",I=!i.summary_en&&S.trim().length>0,q=!i.usageGuide_en&&z.trim().length>0;if(I||q){N.current=!0,$(t);try{const F=await M.post("/api/ai/translate",{summary:I?S:void 0,usageGuide:q?z:void 0}),W={lang:"en"};S&&(W.summary_cn=S),z&&(W.usageGuide_cn=z),F.data.summary_en!=null&&(W.summary_en=F.data.summary_en),F.data.usageGuide_en!=null&&(W.usageGuide_en=F.data.usageGuide_en),f(t,W),E("已翻译为英文")}catch(F){E(((_=(X=F==null?void 0:F.response)==null?void 0:X.data)==null?void 0:_.error)||(F==null?void 0:F.message)||"翻译失败",{type:"error"}),f(t,{lang:"en"})}finally{N.current=!1,$(null)}}else f(t,{lang:"en"})},[g,f]);return c.useEffect(()=>{const t=g.map((S,z)=>S.candidateId??`scan-${z}`),o=Y.current;(t.length!==o.length||t.some((S,z)=>S!==o[z]))&&(V.current.clear(),Y.current=t),g.forEach((S,z)=>{const I=S.candidateId??`scan-${z}`;S.candidateId&&S.candidateTargetName?u(I,{targetName:S.candidateTargetName,candidateId:S.candidateId}):u(I,{candidate:{title:S.title,summary:S.summary,code:S.code,usageGuide:S.usageGuide}})})},[g,u]),e.jsxs("div",{className:"flex gap-8 h-full",children:[e.jsxs("div",{className:"w-80 bg-white rounded-xl border border-slate-200 flex flex-col overflow-hidden shrink-0",children:[e.jsxs("div",{className:"p-4 bg-slate-50 border-b border-slate-200 font-bold text-sm",children:["项目 Target (",s.length,")"]}),e.jsx("div",{className:"flex-1 overflow-y-auto p-2 space-y-1",children:a.map(t=>{const o=p(t.name),i=y===t.name;return e.jsxs("button",{onClick:()=>k(t),disabled:x,className:`w-full text-left p-3 rounded-lg flex items-center justify-between group transition-all border ${x?"opacity-50 cursor-not-allowed":"hover:bg-slate-50"} ${i?"bg-blue-50 border-blue-200 ring-1 ring-blue-200":"bg-white border-transparent"} ${o?"opacity-90":""}`,children:[e.jsxs("div",{className:`flex flex-col max-w-[85%] ${o?"opacity-60":""}`,children:[e.jsxs("div",{className:"flex items-center gap-2",children:[!o&&e.jsx("div",{className:"w-1.5 h-1.5 rounded-full shrink-0 bg-blue-600"}),e.jsx("span",{className:`text-sm truncate ${o?"font-medium":"font-bold"} ${i?"text-blue-700":""}`,children:t.name})]}),e.jsx("span",{className:"text-[10px] text-slate-400 truncate pl-3",children:t.packageName})]}),o?e.jsx("span",{className:"text-[9px] font-bold text-slate-300 border border-slate-100 px-1 rounded",children:"SHELL"}):e.jsx(we,{size:14,className:`shrink-0 ${i?"text-blue-500 opacity-100":"text-blue-500 opacity-0 group-hover:opacity-100"} transition-opacity`})]},t.name)})})]}),e.jsxs("div",{className:"flex-1 bg-white rounded-xl border border-slate-200 flex flex-col overflow-hidden relative",children:[e.jsx("div",{className:"p-4 bg-slate-50 border-b border-slate-200 font-bold text-sm flex justify-between items-center",children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Ne,{size:16,className:"text-slate-400"}),e.jsxs("span",{children:["审核提取结果 ",g.length>0&&e.jsxs("span",{className:"text-blue-600 ml-1",children:["[",g[0].trigger?"Candidate":"New","]"]})]})]})}),e.jsxs("div",{className:"flex-1 overflow-y-auto p-6 space-y-8 relative",children:[x&&e.jsxs("div",{className:"absolute inset-0 bg-white/90 backdrop-blur-[2px] z-10 flex flex-col items-center justify-center text-blue-600 px-8 overflow-y-auto",children:[e.jsxs("div",{className:"relative mb-6",children:[e.jsx("div",{className:"w-16 h-16 border-4 border-blue-100 border-t-blue-600 rounded-full animate-spin"}),e.jsx(Ce,{size:32,className:"absolute inset-0 m-auto text-blue-600 animate-pulse"})]}),e.jsx("p",{className:"font-bold text-lg animate-pulse mb-1",children:"文件扫描与识别"}),e.jsx("p",{className:"text-sm text-slate-500 mb-4",children:n.status}),r.length>0&&e.jsxs("div",{className:"w-full max-w-lg mb-4 text-left",children:[e.jsxs("p",{className:"text-[10px] font-bold text-slate-400 uppercase mb-2",children:["本次扫描的文件 (",r.length,")"]}),e.jsx("div",{className:"max-h-32 overflow-y-auto space-y-1 rounded-lg bg-slate-50 border border-slate-200 p-2",children:r.map((t,o)=>e.jsx("div",{className:"text-xs font-mono text-slate-600 truncate",title:t.path,children:t.name},o))})]}),e.jsx("div",{className:"w-full max-w-md bg-slate-100 rounded-full h-2.5 overflow-hidden",children:e.jsx("div",{className:"h-full bg-blue-600 rounded-full transition-all duration-500 ease-out",style:{width:`${Math.min(n.total?n.current/n.total*100:0,98)}%`}})}),e.jsx("p",{className:"text-xs text-slate-400 mt-3",children:n.total?`${Math.round(n.current/n.total*100)}%`:"0%"})]}),!x&&g.length===0&&e.jsxs("div",{className:"h-full flex flex-col items-center justify-center text-slate-400 text-center",children:[e.jsx(pe,{size:48,className:"mb-4 opacity-20"}),e.jsx("p",{className:"font-medium text-slate-600",children:"深度扫描与提取"}),e.jsx("p",{className:"text-xs mt-2",children:"从左侧选择一个模块,让 AI 识别可复用的代码片段和最佳实践。"})]}),!x&&r.length>0&&e.jsxs("div",{className:"rounded-xl border border-slate-200 bg-slate-50 p-4",children:[e.jsxs("p",{className:"text-[10px] font-bold text-slate-400 uppercase mb-2",children:["本次扫描的文件 (",r.length,")"]}),e.jsx("div",{className:"flex flex-wrap gap-2",children:r.map((t,o)=>e.jsx("span",{className:"text-xs font-mono bg-white border border-slate-200 text-slate-600 px-2 py-1 rounded",title:t.path,children:t.name},o))})]}),g.map((t,o)=>e.jsxs("div",{className:"bg-slate-50 rounded-2xl border border-slate-200 overflow-hidden shadow-sm",children:[e.jsxs("div",{className:"p-4 bg-white border-b border-slate-100 flex justify-between items-center",children:[e.jsxs("div",{className:"flex items-center gap-4 flex-1",children:[e.jsxs("div",{className:"flex flex-col w-[512px]",children:[e.jsx("label",{className:"text-[9px] font-bold text-slate-400 uppercase ml-1 mb-0.5",children:"Recipe Title"}),e.jsx("input",{className:"font-bold bg-transparent border-b border-transparent hover:border-slate-200 focus:border-blue-500 outline-none px-1 text-base w-full",value:t.title,onChange:i=>f(o,{title:i.target.value})})]}),e.jsxs("div",{className:"flex flex-col w-64",children:[e.jsx("label",{className:"text-[9px] font-bold text-slate-400 uppercase ml-1 mb-0.5",children:"Triggers"}),e.jsx("input",{className:"font-mono font-bold text-blue-600 bg-blue-50 border border-blue-100 px-3 py-1.5 rounded-lg outline-none text-xs focus:ring-2 focus:ring-blue-500 w-full",value:t.trigger,placeholder:"@cmd",onChange:i=>f(o,{trigger:i.target.value})})]}),e.jsxs("div",{className:"flex flex-col",children:[e.jsx("label",{className:"text-[9px] font-bold text-slate-400 uppercase ml-1 mb-0.5",children:"Category"}),e.jsx("select",{className:"font-bold text-blue-600 bg-blue-50 border border-blue-100 px-2 py-1.5 rounded-lg outline-none text-[10px] focus:ring-2 focus:ring-blue-500",value:t.category,onChange:i=>f(o,{category:i.target.value}),children:ns.filter(i=>i!=="All").map(i=>e.jsx("option",{value:i,children:i},i))})]}),e.jsxs("div",{className:"flex flex-col",children:[e.jsx("label",{className:"text-[9px] font-bold text-slate-400 uppercase ml-1 mb-0.5",children:"Language"}),e.jsxs("div",{className:"flex bg-slate-100 p-1 rounded-lg",children:[e.jsx("button",{onClick:()=>f(o,{language:"swift"}),className:`px-2 py-1 rounded-md text-[9px] font-bold transition-all ${t.language==="swift"?"bg-white shadow-sm text-blue-600":"text-slate-400"}`,children:"Swift"}),e.jsx("button",{onClick:()=>f(o,{language:"objectivec"}),className:`px-2 py-1 rounded-md text-[9px] font-bold transition-all ${t.language==="objectivec"||t.language==="objc"?"bg-white shadow-sm text-blue-600":"text-slate-400"}`,children:"ObjC"})]})]}),e.jsxs("div",{className:"flex flex-col",children:[e.jsx("label",{className:"text-[9px] font-bold text-slate-400 uppercase ml-1 mb-0.5",children:"Content Lang"}),e.jsxs("div",{className:"flex bg-slate-100 p-1 rounded-lg items-center gap-1",children:[e.jsx("button",{onClick:()=>j(o,"cn"),disabled:K!==null,className:`px-2 py-1 rounded-md text-[9px] font-bold transition-all ${t.lang==="cn"?"bg-white shadow-sm text-blue-600":"text-slate-400"} disabled:opacity-50 disabled:cursor-not-allowed`,children:"CN"}),e.jsxs("button",{onClick:()=>j(o,"en"),disabled:K!==null,className:`px-2 py-1 rounded-md text-[9px] font-bold transition-all flex items-center gap-1 ${t.lang==="en"?"bg-white shadow-sm text-blue-600":"text-slate-400"} disabled:opacity-50 disabled:cursor-not-allowed`,children:[K===o?e.jsx(Qe,{size:10,className:"animate-spin"}):null,"EN"]})]})]}),e.jsxs("div",{className:"flex flex-col",children:[e.jsx("label",{className:"text-[9px] font-bold text-slate-400 uppercase ml-1 mb-0.5",children:"Mode"}),e.jsxs("div",{className:"flex bg-slate-100 p-1 rounded-lg",children:[e.jsx("button",{onClick:()=>f(o,{mode:"full"}),className:`px-4 py-1 rounded-md text-[9px] font-bold transition-all ${t.mode==="full"?"bg-white shadow-sm text-blue-600":"text-slate-400"}`,children:"SNIPPET + RECIPE"}),e.jsx("button",{onClick:()=>f(o,{mode:"preview"}),className:`px-4 py-1 rounded-md text-[9px] font-bold transition-all ${t.mode==="preview"?"bg-white shadow-sm text-amber-600":"text-slate-400"}`,children:"RECIPE ONLY"})]})]}),e.jsxs("div",{className:"flex flex-col",children:[e.jsx("label",{className:"text-[9px] font-bold text-slate-400 uppercase ml-1 mb-0.5",children:"引入头文件"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:()=>f(o,{includeHeaders:t.includeHeaders===!1}),className:`w-8 h-4 rounded-full relative transition-colors ${t.includeHeaders!==!1?"bg-blue-600":"bg-slate-300"}`,title:t.includeHeaders!==!1?"开启:snippet 内写入 // as:include 标记,watch 按标记注入":"关闭:不写入头文件标记",children:e.jsx("div",{className:`absolute top-0.5 w-3 h-3 bg-white rounded-full transition-all ${t.includeHeaders!==!1?"right-0.5":"left-0.5"}`})}),e.jsx("span",{className:"text-[9px] text-slate-500",children:t.includeHeaders!==!1?"按标记注入":"不引入"})]})]})]}),e.jsx("div",{className:"ml-4",children:e.jsxs("button",{onClick:()=>d(t),className:`text-xs px-5 py-2.5 rounded-xl font-bold transition-all shadow-sm flex items-center gap-2 active:scale-95 ${t.mode==="full"?"bg-blue-600 text-white hover:bg-blue-700":"bg-amber-600 text-white hover:bg-amber-700"}`,children:[e.jsx(as,{size:18}),"保存为 Recipe"]})})]}),e.jsxs("div",{className:"p-6 space-y-4",children:[e.jsx("div",{className:"flex gap-4",children:e.jsxs("div",{className:"flex-1",children:[e.jsxs("label",{className:"block text-[10px] font-bold text-slate-400 uppercase mb-1",children:["Summary (摘要) - ",t.lang==="cn"?"中文":"EN"]}),e.jsx("textarea",{rows:2,className:"w-full text-sm text-slate-600 bg-white border border-slate-200 rounded-xl px-3 py-2 outline-none resize-none leading-relaxed focus:ring-2 focus:ring-blue-500/10",value:t.summary,onChange:i=>f(o,{summary:i.target.value})})]})}),e.jsxs("div",{className:"space-y-1",children:[e.jsxs("label",{className:"block text-[10px] font-bold text-slate-400 uppercase mb-1",children:["头文件 Headers ",t.moduleName&&e.jsxs("span",{className:"text-slate-400 font-normal",children:["· ",t.moduleName]})]}),t.headers&&t.headers.length>0?e.jsx("div",{className:"flex flex-wrap gap-2",children:t.headers.map((i,S)=>{var z;return e.jsx("span",{className:"text-[10px] bg-slate-200 text-slate-600 px-2 py-0.5 rounded font-mono",title:(z=t.headerPaths)!=null&&z[S]?`相对路径: ${t.headerPaths[S]}`:void 0,children:i},S)})}):e.jsx("p",{className:"text-[10px] text-slate-400",children:"未解析到头文件(剪贴板需含 #import,且路径在 target 下)"})]}),(()=>{const i=t.candidateId??`scan-${o}`,S=H[i],z=U===i;return((S==null?void 0:S.length)??0)>0||z?e.jsxs("div",{className:"flex flex-wrap gap-1.5 items-center",children:[e.jsx("span",{className:"text-[10px] text-slate-400 font-bold",children:"相似 Recipe:"}),z?e.jsx("span",{className:"text-[10px] text-slate-400",children:"加载中..."}):(S||[]).slice(0,3).map(q=>e.jsxs("button",{onClick:()=>R(t,q.recipeName,S||[]),className:"text-[10px] font-bold px-2 py-1 rounded bg-amber-50 text-amber-700 border border-amber-200 hover:bg-amber-100 transition-colors flex items-center gap-1",title:`与 ${q.recipeName} 相似 ${(q.similarity*100).toFixed(0)}%,点击对比`,children:[e.jsx(ts,{size:10}),q.recipeName.replace(/\.md$/i,"")," ",(q.similarity*100).toFixed(0),"%"]},q.recipeName))]}):null})(),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-1",children:[e.jsx("label",{className:"text-[10px] font-bold text-slate-400 uppercase",children:"Standardized Usage Example (标准使用示例)"}),D===o?e.jsxs("button",{type:"button",onClick:()=>O(null),className:"flex items-center gap-1 text-[10px] font-bold text-blue-600 hover:text-blue-700 px-2 py-1 rounded bg-blue-50",children:[e.jsx(Os,{size:12})," 完成"]}):e.jsxs("button",{type:"button",onClick:()=>O(o),className:"flex items-center gap-1 text-[10px] font-bold text-slate-500 hover:text-slate-700 px-2 py-1 rounded hover:bg-slate-100",title:"编辑代码",children:[e.jsx(Hs,{size:12})," 编辑"]})]}),D===o?e.jsx("div",{className:"bg-slate-900 rounded-xl p-4 overflow-x-auto",children:e.jsx("textarea",{className:"w-full bg-transparent text-xs text-slate-100 font-mono leading-relaxed outline-none resize-none",rows:Math.min(12,t.code.split(`
10
+ `).length),value:t.code,onChange:i=>f(o,{code:i.target.value})})}):e.jsx(je,{code:t.code,language:L(t),showLineNumbers:!0})]}),e.jsxs("div",{children:[e.jsxs("label",{className:"block text-[10px] font-bold text-slate-400 uppercase mb-1",children:["Usage Guide (使用指南) - ",t.lang==="cn"?"中文":"EN"]}),e.jsx("textarea",{className:"w-full text-xs text-slate-500 bg-blue-50 p-4 rounded-xl border border-blue-100 outline-none min-h-[100px] leading-relaxed",value:t.usageGuide,onChange:i=>f(o,{usageGuide:i.target.value})})]})]})]},o))]})]}),P&&(()=>{const t=P.candidate,o=L(t),i=()=>{const _=[];t.code&&_.push("## Snippet / Code Reference\n\n```"+o+`
11
+ `+t.code+"\n```"),t.usageGuide&&_.push(`
12
+ ## AI Context / Usage Guide
13
+
14
+ `+t.usageGuide),navigator.clipboard.writeText(_.join(`
15
+ `)||"").then(()=>E("已复制候选内容"))},S=()=>{const _=Te(P.recipeContent);navigator.clipboard.writeText(_).then(()=>E("已复制 Recipe 内容"))},z=async _=>{if(_===P.recipeName)return;const F=P.recipeContents[_];if(F)B(W=>W?{...W,recipeName:_,recipeContent:F}:null);else{let W="";const G=A==null?void 0:A.find(J=>J.name===_||J.name.endsWith("/"+_));if(G!=null&&G.content)W=G.content;else try{W=(await M.get(`/api/recipes/get?name=${encodeURIComponent(_)}`)).data.content}catch{return}B(J=>J?{...J,recipeName:_,recipeContent:W,recipeContents:{...J.recipeContents,[_]:W}}:null)}},I=async()=>{if(!(!t.candidateId||!P.targetName||!h)&&window.confirm("确定删除该候选?"))try{await h(P.targetName,t.candidateId),B(null)}catch{}},q=()=>{d(t),B(null)},X=()=>{const _=(A==null?void 0:A.find(F=>F.name===P.recipeName||F.name.endsWith("/"+P.recipeName)))||{name:P.recipeName,content:P.recipeContent};v==null||v(_),B(null)};return e.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-2",onClick:()=>B(null),children:e.jsxs("div",{className:"bg-white rounded-2xl shadow-2xl w-[min(95vw,1600px)] max-h-[92vh] flex flex-col",onClick:_=>_.stopPropagation(),children:[e.jsxs("div",{className:"flex justify-between items-center px-4 py-3 border-b border-slate-200 shrink-0",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("h3",{className:"font-bold text-slate-800",children:"候选 vs Recipe 对比"}),t.candidateId&&P.targetName&&e.jsx("button",{onClick:I,className:"text-xs text-red-600 hover:bg-red-50 px-2 py-1 rounded",children:"删除候选"}),e.jsx("button",{onClick:q,className:"text-xs text-blue-600 hover:bg-blue-50 px-2 py-1 rounded",children:"审核候选"}),e.jsx("button",{onClick:X,className:"text-xs text-emerald-600 hover:bg-emerald-50 px-2 py-1 rounded",children:"审核 Recipe"})]}),e.jsx("button",{onClick:()=>B(null),className:"p-2 hover:bg-slate-100 rounded-lg transition-colors",children:e.jsx(ye,{size:18})})]}),e.jsxs("div",{className:"flex-1 grid grid-cols-2 overflow-hidden min-h-0",style:{gridTemplateRows:"auto 1fr"},children:[e.jsxs("div",{className:"px-4 py-3 bg-blue-50 border-b border-r border-slate-100 flex flex-col justify-center min-h-0",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsxs("span",{className:"text-sm font-bold text-blue-700 truncate flex-1 min-w-0",title:t.title,children:["候选:",t.title]}),e.jsxs("button",{onClick:i,className:"p-1.5 hover:bg-blue-100 rounded-lg text-blue-600 shrink-0",title:"复制",children:[" ",e.jsx(_e,{size:14})," "]})]}),e.jsx("div",{className:"min-h-[28px] mt-2 shrink-0"})]}),e.jsxs("div",{className:"px-4 py-3 bg-emerald-50 border-b border-slate-100 flex flex-col justify-center min-h-0",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsxs("span",{className:"text-sm font-bold text-emerald-700 truncate flex-1 min-w-0",title:P.recipeName,children:["Recipe:",P.recipeName.replace(/\.md$/i,"")]}),e.jsxs("button",{onClick:S,className:"p-1.5 hover:bg-emerald-100 rounded-lg text-emerald-600 shrink-0",title:"复制",children:[" ",e.jsx(_e,{size:14})," "]})]}),P.similarList.length>1?e.jsx("div",{className:"flex flex-wrap gap-1 mt-2 shrink-0",children:P.similarList.map(_=>e.jsxs("button",{onClick:()=>z(_.recipeName),className:`text-[10px] font-bold px-2 py-1 rounded transition-colors ${P.recipeName===_.recipeName?"bg-emerald-200 text-emerald-800":"bg-white/80 text-emerald-600 hover:bg-emerald-100"}`,children:[_.recipeName.replace(/\.md$/i,"")," ",(_.similarity*100).toFixed(0),"%"]},_.recipeName))}):e.jsx("div",{className:"min-h-[28px] mt-2 shrink-0"})]}),e.jsxs("div",{className:"flex-1 overflow-auto p-4 min-h-0 border-r border-slate-200 markdown-body text-slate-700",children:[e.jsx("h2",{className:"text-lg font-bold mb-2 mt-4",children:"Snippet / Code Reference"}),t.code?e.jsx(je,{code:t.code,language:o,className:"!overflow-visible"}):e.jsx("p",{className:"text-slate-400 italic mb-3",children:"(无代码)"}),e.jsx("h2",{className:"text-lg font-bold mb-2 mt-4",children:"AI Context / Usage Guide"}),t.usageGuide?e.jsx(fe,{content:t.usageGuide}):e.jsx("p",{className:"text-slate-400 italic",children:"(无使用指南)"})]}),e.jsx("div",{className:"flex-1 overflow-auto p-4 min-h-0",children:e.jsx(fe,{content:P.recipeContent,stripFrontmatter:!0})})]})]})})})()]})},Ae=72,$e=48,ge=40,rs=36,he=140,ze=40;function bt(s,a){const y=new Set(s.map(k=>k.id)),x=new Map;for(const k of a)!y.has(k.from)||!y.has(k.to)||(x.has(k.from)||x.set(k.from,[]),x.get(k.from).push(k.to));const n=new Map,r=new Set;function g(k){if(n.has(k))return n.get(k);if(r.has(k))return 0;r.add(k);const f=x.get(k);if(!f||f.length===0)return n.set(k,0),r.delete(k),0;const d=1+Math.max(...f.map(g));return n.set(k,d),r.delete(k),d}return s.forEach(k=>g(k.id)),n}function gt(s,a){const y=bt(s,a),x=new Map;for(const f of s){const d=y.get(f.id)??0;x.has(d)||x.set(d,[]),x.get(d).push(f.id)}const n=[...new Set(y.values())].sort((f,d)=>f-d),r=[...n].reverse(),g=new Map,k=n.reduce((f,d)=>{const h=x.get(d)??[],v=(h.length-1)*$e+h.length*he;return Math.max(f,v)},0);return r.forEach((f,d)=>{const h=x.get(f)??[],v=(h.length-1)*$e+h.length*he,p=(k-v)/2;h.forEach((A,D)=>{const O=ge+rs+p+D*(he+$e)+he/2,K=ge+d*Ae+ze/2;g.set(A,{x:O,y:K})})}),{positions:g,tiers:y,tierOrder:n}}const ft=()=>{const[s,a]=c.useState(null),[y,x]=c.useState(!0),[n,r]=c.useState(null),[g,k]=c.useState(null),f=async()=>{var N,L;x(!0),r(null);try{const R=(await M.get("/api/dep-graph")).data;a({nodes:Array.isArray(R==null?void 0:R.nodes)?R.nodes:[],edges:Array.isArray(R==null?void 0:R.edges)?R.edges:[],projectRoot:(R==null?void 0:R.projectRoot)??null,generatedAt:R==null?void 0:R.generatedAt})}catch(u){r(((L=(N=u.response)==null?void 0:N.data)==null?void 0:L.error)||u.message||"Failed to load dependency graph")}finally{x(!1)}};c.useEffect(()=>{f()},[]);const d=Array.isArray(s==null?void 0:s.nodes)?s.nodes:[],h=Array.isArray(s==null?void 0:s.edges)?s.edges:[],{positions:v,tiers:p,tierOrder:A}=c.useMemo(()=>gt(d,h),[d,h]),D=c.useMemo(()=>{const N=new Map;return d.forEach(L=>{const u=p.get(L.id)??0;N.has(u)||N.set(u,[]),N.get(u).push(L.id)}),N},[d,p]),O=c.useMemo(()=>[...A].reverse(),[A]),{dependsOn:K,dependedBy:$}=c.useMemo(()=>{const N=new Map,L=new Map;return h.forEach(u=>{N.has(u.from)||N.set(u.from,[]),N.get(u.from).push(u.to),L.has(u.to)||L.set(u.to,[]),L.get(u.to).push(u.from)}),{dependsOn:N,dependedBy:L}},[h]),H=A.length,m=Math.max(...A.map(N=>(D.get(N)??[]).length),1),te=(m-1)*$e+m*he+rs*2,P=Math.max(600,ge*2+te),B=Math.max(420,ge*2+H*Ae),V=[{bg:"rgb(239 246 255)",border:"rgb(147 197 253)",text:"rgb(30 64 175)"},{bg:"rgb(240 253 244)",border:"rgb(134 239 172)",text:"rgb(22 101 52)"},{bg:"rgb(254 249 195)",border:"rgb(253 224 71)",text:"rgb(113 63 18)"},{bg:"rgb(254 243 199)",border:"rgb(253 186 116)",text:"rgb(154 52 18)"},{bg:"rgb(243 232 255)",border:"rgb(216 180 254)",text:"rgb(91 33 182)"}],Y=N=>V[Math.min(N,V.length-1)]??V[0];return y?e.jsx("div",{className:"flex items-center justify-center min-h-[320px]",children:e.jsx("div",{className:"animate-spin rounded-full h-10 w-10 border-2 border-blue-600 border-t-transparent"})}):n?e.jsxs("div",{className:"rounded-xl border border-red-200 bg-red-50 p-6 text-red-700 shadow-sm",children:[e.jsx("p",{children:n}),e.jsx("button",{type:"button",onClick:f,className:"mt-4 px-4 py-2 rounded-lg bg-red-100 hover:bg-red-200 text-red-800 font-medium text-sm transition-colors",children:"重试"})]}):!s||d.length===0?e.jsxs("div",{className:"rounded-xl border border-slate-200 bg-slate-50 p-8 text-slate-600 shadow-sm",children:[e.jsx("p",{className:"font-medium text-slate-700",children:"当前项目内未扫描到 SPM 包依赖关系。"}),e.jsxs("p",{className:"mt-2 text-sm",children:["请确保项目根目录下存在 ",e.jsx("code",{className:"bg-slate-200 px-1.5 py-0.5 rounded text-slate-800",children:"Package.swift"})," 或子目录中的 SPM 包,然后点击「Refresh Project」或执行 ",e.jsx("code",{className:"bg-slate-200 px-1.5 py-0.5 rounded",children:"asd spm-map"})," 刷新。"]})]}):e.jsxs("div",{className:"w-full max-w-[1400px] mx-auto space-y-6",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"flex items-center justify-center w-10 h-10 rounded-xl bg-blue-50 border border-blue-100",children:e.jsx(Me,{size:22,className:"text-blue-600"})}),e.jsxs("div",{children:[e.jsx("h2",{className:"text-xl font-bold text-slate-900",children:"项目依赖关系图"}),s.projectRoot&&e.jsxs("p",{className:"text-sm text-slate-500 mt-0.5",children:["项目根: ",e.jsx("code",{className:"bg-slate-100 px-1.5 py-0.5 rounded text-slate-600",children:s.projectRoot}),s.generatedAt&&e.jsxs("span",{className:"ml-2",children:["· 生成于 ",new Date(s.generatedAt).toLocaleString()]})]})]})]}),e.jsxs("button",{type:"button",onClick:f,className:"flex items-center gap-2 px-4 py-2 rounded-lg border border-slate-200 bg-white hover:bg-slate-50 text-slate-700 font-medium text-sm shadow-sm transition-colors",children:[e.jsx(Le,{size:16})," 刷新"]})]}),e.jsxs("div",{className:"rounded-xl border border-slate-200 bg-slate-50/50 overflow-auto shadow-sm min-h-[480px] flex items-center justify-center relative",children:[e.jsxs("svg",{width:"100%",height:B,viewBox:`0 0 ${P} ${B}`,className:"block min-h-[480px] w-full",style:{maxHeight:640},children:[e.jsx("defs",{children:e.jsx("filter",{id:"nodeShadow",x:"-20%",y:"-20%",width:"140%",height:"140%",children:e.jsx("feDropShadow",{dx:"0",dy:"2",stdDeviation:"2",floodOpacity:"0.12"})})}),O.map((N,L)=>{const u=Y(L),R=ge+L*Ae;return e.jsx("rect",{x:ge,y:R-ze/2-4,width:te,height:Ae+8,rx:8,fill:u.bg,stroke:u.border,strokeWidth:"1",opacity:.6},N)}),d.map(N=>{const L=v.get(N.id);if(!L)return null;const u=p.get(N.id)??0,R=Y(O.indexOf(u)),j=N.label.length>14?N.label.slice(0,13)+"…":N.label,t=g===N.id,o=g?(K.get(g)??[]).includes(N.id):!1,i=g?($.get(g)??[]).includes(N.id):!1,S=g&&!t&&!o&&!i,z=g?t?{fill:"white",stroke:"rgb(59 130 246)",text:"rgb(30 64 175)",strokeWidth:3,opacity:1}:o?{fill:"rgb(240 253 244)",stroke:"rgb(34 197 94)",text:"rgb(22 101 52)",strokeWidth:2,opacity:1}:i?{fill:"rgb(245 243 255)",stroke:"rgb(139 92 246)",text:"rgb(91 33 182)",strokeWidth:2,opacity:1}:{fill:"rgb(248 250 252)",stroke:"rgb(203 213 225)",text:"rgb(148 163 184)",strokeWidth:1,opacity:.6}:{fill:"white",stroke:R.border,text:R.text,strokeWidth:2,opacity:1};return e.jsxs("g",{style:{cursor:"pointer",opacity:z.opacity},onClick:()=>k(t?null:N.id),children:[e.jsx("rect",{x:L.x-he/2,y:L.y-ze/2,width:he,height:ze,rx:10,ry:10,fill:z.fill,stroke:z.stroke,strokeWidth:z.strokeWidth,filter:S?void 0:"url(#nodeShadow)"}),e.jsx("text",{x:L.x,y:L.y,textAnchor:"middle",dominantBaseline:"middle",fontSize:"12",fontWeight:"600",fill:z.text,pointerEvents:"none",children:j})]},N.id)})]}),g&&e.jsxs("div",{className:"absolute top-4 right-4 w-72 rounded-xl border border-slate-200 bg-white shadow-lg z-10 p-4",role:"dialog","aria-label":"依赖关系",children:[e.jsxs("div",{className:"flex items-center justify-between mb-3 pb-2 border-b border-slate-100",children:[e.jsx("span",{className:"font-bold text-slate-800",children:g}),e.jsx("button",{type:"button",onClick:()=>k(null),className:"text-slate-400 hover:text-slate-600 text-lg leading-none","aria-label":"关闭",children:"×"})]}),e.jsxs("div",{className:"space-y-3 text-sm",children:[e.jsxs("div",{children:[e.jsx("div",{className:"font-semibold text-slate-600 mb-1",children:"依赖"}),e.jsx("ul",{className:"text-slate-700 space-y-0.5",children:(K.get(g)??[]).length===0?e.jsx("li",{className:"text-slate-400",children:"无"}):(K.get(g)??[]).map(N=>e.jsxs("li",{children:["→ ",N]},N))})]}),e.jsxs("div",{children:[e.jsx("div",{className:"font-semibold text-slate-600 mb-1",children:"被依赖"}),e.jsx("ul",{className:"text-slate-700 space-y-0.5",children:($.get(g)??[]).length===0?e.jsx("li",{className:"text-slate-400",children:"无"}):($.get(g)??[]).map(N=>e.jsxs("li",{children:["← ",N]},N))})]})]})]})]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-6",children:[e.jsxs("div",{className:"rounded-xl border border-slate-200 bg-white p-5 shadow-sm",children:[e.jsxs("h3",{className:"text-sm font-bold text-slate-800 mb-3 pb-2 border-b border-slate-100",children:["包列表 (",d.length,")"]}),e.jsx("ul",{className:"text-sm space-y-3 max-h-[280px] overflow-y-auto pr-1",children:d.map(N=>e.jsxs("li",{className:"pb-3 border-b border-slate-100 last:border-0 last:pb-0",children:[e.jsxs("div",{className:"flex items-baseline gap-2 flex-wrap",children:[e.jsx("span",{className:"font-semibold text-slate-800",children:N.id}),N.packageDir&&e.jsxs("span",{className:"text-slate-500 text-xs",children:["· ",N.packageDir]})]}),N.targets&&N.targets.length>0&&e.jsxs("div",{className:"mt-1.5 text-slate-500 text-xs pl-0",children:["Targets: ",e.jsx("span",{className:"text-slate-600",children:N.targets.join(", ")})]})]},N.id))})]}),e.jsxs("div",{className:"rounded-xl border border-slate-200 bg-white p-5 shadow-sm",children:[e.jsxs("h3",{className:"text-sm font-bold text-slate-800 mb-3 pb-2 border-b border-slate-100",children:["依赖关系(小图)(",h.length,")"]}),e.jsx("p",{className:"text-xs text-slate-500 mb-2",children:"主图不显示连线,点击节点可在浮窗查看该包依赖;此处列出全部 From → To。"}),e.jsx("ul",{className:"text-sm space-y-2 max-h-[280px] overflow-y-auto pr-1",children:h.map((N,L)=>e.jsxs("li",{className:"flex items-center gap-2 text-slate-700",children:[e.jsx("span",{className:"font-semibold text-slate-800",children:N.from}),e.jsx("span",{className:"text-slate-400 shrink-0",children:"→"}),e.jsx("span",{className:"font-semibold text-slate-800",children:N.to})]},`${N.from}-${N.to}-${L}`))})]})]})]})},jt=({onRefresh:s})=>{const[a,y]=c.useState({}),[x,n]=c.useState([]),[r,g]=c.useState(null),[k,f]=c.useState(!0),[d,h]=c.useState(!1),[v,p]=c.useState(!1),[A,D]=c.useState(""),[O,K]=c.useState(!1),[$,H]=c.useState({ruleId:"",message:"",severity:"warning",pattern:"",languages:["objc","swift"],note:"",dimension:""}),[m,U]=c.useState(!1),[te,P]=c.useState(""),B=async()=>{var j,t;try{const[o,i]=await Promise.all([M.get("/api/guard/rules"),M.get("/api/guard/violations")]);y(((j=o.data)==null?void 0:j.rules)||{}),n(((t=i.data)==null?void 0:t.runs)||[])}catch{y({}),n([])}finally{f(!1)}};c.useEffect(()=>{B()},[]);const V=async()=>{if(window.confirm("确定清空所有 Guard 违反记录?"))try{await M.post("/api/guard/violations/clear"),B(),s==null||s()}catch{}},Y=j=>{H(t=>({...t,languages:t.languages.includes(j)?t.languages.filter(o=>o!==j):[...t.languages,j]}))},N=async()=>{var j,t;if(!A.trim()){P("请先输入语义描述");return}P(""),K(!0);try{const i=(await M.post("/api/guard/rules/generate",{description:A.trim()})).data,S=i.dimension;H({ruleId:i.ruleId||"",message:i.message||"",severity:i.severity==="error"?"error":"warning",pattern:i.pattern||"",languages:Array.isArray(i.languages)&&i.languages.length>0?i.languages:["objc","swift"],note:i.note!=null?String(i.note):"",dimension:S==="file"||S==="target"||S==="project"?S:""}),p(!0)}catch(o){P(((t=(j=o==null?void 0:o.response)==null?void 0:j.data)==null?void 0:t.error)||(o==null?void 0:o.message)||"AI 生成失败")}finally{K(!1)}},L=async j=>{var t,o;if(j.preventDefault(),P(""),!$.ruleId.trim()||!$.message.trim()||!$.pattern.trim()||$.languages.length===0){P("请填写规则 ID、说明、正则和至少一种语言");return}U(!0);try{await M.post("/api/guard/rules",{ruleId:$.ruleId.trim(),message:$.message.trim(),severity:$.severity,pattern:$.pattern.trim(),languages:$.languages,note:$.note.trim()||void 0,...$.dimension?{dimension:$.dimension}:{}}),H({ruleId:"",message:"",severity:"warning",pattern:"",languages:["objc","swift"],note:"",dimension:""}),D(""),p(!1),B(),s==null||s()}catch(i){P(((o=(t=i==null?void 0:i.response)==null?void 0:t.data)==null?void 0:o.error)||(i==null?void 0:i.message)||"写入失败")}finally{U(!1)}};if(k)return e.jsx("div",{className:"p-6 text-slate-500",children:"加载中..."});const u=Object.entries(a),R=x.reduce((j,t)=>j+t.violations.length,0);return e.jsxs("div",{className:"p-6",children:[e.jsxs("div",{className:"flex items-center justify-between mb-6",children:[e.jsxs("h2",{className:"text-xl font-bold text-slate-900 flex items-center gap-2",children:[e.jsx(Ye,{size:24,className:"text-blue-600"}),"Guard 规则与违反记录"]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("a",{href:at,target:"_blank",rel:"noopener noreferrer",className:"flex items-center gap-1.5 px-3 py-1.5 text-sm text-slate-600 hover:text-slate-900 hover:bg-slate-100 rounded-lg transition-colors",children:[e.jsx(Fs,{size:16})," 提交误报/建议"]}),e.jsxs("button",{type:"button",onClick:()=>h(!d),className:"flex items-center gap-1.5 px-3 py-1.5 text-sm text-slate-600 hover:text-slate-900 hover:bg-slate-100 rounded-lg transition-colors",children:[d?e.jsx(Pe,{size:16}):e.jsx(Ge,{size:16}),"AI 写入规则"]}),x.length>0&&e.jsxs("button",{type:"button",onClick:V,className:"flex items-center gap-2 px-3 py-1.5 text-sm text-slate-500 hover:text-red-600 hover:bg-red-50 rounded-lg transition-colors",children:[e.jsx(Re,{size:14})," 清空历史"]})]})]}),d&&e.jsxs("section",{className:"mb-6",children:[e.jsxs("div",{className:"p-4 bg-slate-50 border border-slate-200 rounded-xl space-y-3",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-medium text-slate-600 mb-1",children:"语义描述(由 AI 生成规则表单)"}),e.jsx("textarea",{value:A,onChange:j=>{D(j.target.value),P("")},className:"w-full px-3 py-2 border border-slate-200 rounded-lg text-sm resize-y min-h-[80px]",placeholder:"例如:禁止在主线程使用 dispatch_sync 调用 main queue,易死锁",rows:3}),e.jsx("button",{type:"button",onClick:N,disabled:O||!A.trim(),className:"mt-2 px-4 py-2 bg-slate-600 text-white text-sm rounded-lg hover:bg-slate-700 disabled:opacity-50",children:O?"生成中...":"AI 生成"}),te&&e.jsx("p",{className:"mt-2 text-sm text-red-600",children:te})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{type:"button",onClick:()=>p(!v),className:"text-sm font-medium text-blue-600 hover:text-blue-700",children:v?"收起表单":"展开 / 编辑表单"}),$.ruleId&&e.jsxs("span",{className:"text-xs text-slate-500",children:["已生成规则 ID:",$.ruleId]})]})]}),v&&e.jsxs("form",{onSubmit:L,className:"mt-3 p-4 bg-white border border-slate-200 rounded-xl space-y-3",children:[e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-medium text-slate-600 mb-1",children:"规则 ID(英文,如 no-force-unwrap)"}),e.jsx("input",{type:"text",value:$.ruleId,onChange:j=>H(t=>({...t,ruleId:j.target.value})),className:"w-full px-3 py-2 border border-slate-200 rounded-lg text-sm",placeholder:"my-rule-id"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-medium text-slate-600 mb-1",children:"严重性"}),e.jsxs("select",{value:$.severity,onChange:j=>H(t=>({...t,severity:j.target.value})),className:"w-full px-3 py-2 border border-slate-200 rounded-lg text-sm",children:[e.jsx("option",{value:"warning",children:"warning"}),e.jsx("option",{value:"error",children:"error"})]})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-medium text-slate-600 mb-1",children:"说明(违反时提示)"}),e.jsx("input",{type:"text",value:$.message,onChange:j=>H(t=>({...t,message:j.target.value})),className:"w-full px-3 py-2 border border-slate-200 rounded-lg text-sm",placeholder:"禁止在主线程上使用 dispatch_sync(main)"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-medium text-slate-600 mb-1",children:"正则(对每行匹配,JSON 中反斜杠需双写)"}),e.jsx("input",{type:"text",value:$.pattern,onChange:j=>H(t=>({...t,pattern:j.target.value})),className:"w-full px-3 py-2 border border-slate-200 rounded-lg text-sm font-mono",placeholder:"dispatch_sync\\\\s*\\\\([^)]*main"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-medium text-slate-600 mb-1",children:"适用语言"}),e.jsxs("div",{className:"flex gap-4",children:[e.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:$.languages.includes("objc"),onChange:()=>Y("objc")}),"objc"]}),e.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:$.languages.includes("swift"),onChange:()=>Y("swift")}),"swift"]})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-medium text-slate-600 mb-1",children:"审查规模(可选,as:g 后缀可限定)"}),e.jsxs("select",{value:$.dimension,onChange:j=>H(t=>({...t,dimension:j.target.value})),className:"w-full px-3 py-2 border border-slate-200 rounded-lg text-sm",children:[e.jsx("option",{value:"",children:"不限制(任意 as:g / as:g file / as:g target / as:g project 均运行)"}),e.jsx("option",{value:"file",children:"同文件(仅 as:g file 时运行)"}),e.jsx("option",{value:"target",children:"同 target(仅 as:g target 时运行)"}),e.jsx("option",{value:"project",children:"同项目(仅 as:g project 时运行)"})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-medium text-slate-600 mb-1",children:"备注(可选)"}),e.jsx("input",{type:"text",value:$.note,onChange:j=>H(t=>({...t,note:j.target.value})),className:"w-full px-3 py-2 border border-slate-200 rounded-lg text-sm",placeholder:"仅作简单模式提示"})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("button",{type:"submit",disabled:m,className:"px-4 py-2 bg-blue-600 text-white text-sm rounded-lg hover:bg-blue-700 disabled:opacity-50",children:m?"写入中...":"确认写入"}),e.jsx("button",{type:"button",onClick:()=>p(!1),className:"px-4 py-2 text-slate-600 text-sm rounded-lg hover:bg-slate-100",children:"收起"})]})]})]}),e.jsxs("section",{className:"mb-8",children:[e.jsx("h3",{className:"text-sm font-semibold text-slate-700 mb-3",children:"iOS 版本规则(guard-rules.json)"}),e.jsx("div",{className:"bg-white border border-slate-200 rounded-xl overflow-hidden",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{className:"bg-slate-50 border-b border-slate-200",children:e.jsxs("tr",{children:[e.jsx("th",{className:"text-left py-2 px-4 font-medium text-slate-600",children:"规则 ID"}),e.jsx("th",{className:"text-left py-2 px-4 font-medium text-slate-600",children:"严重性"}),e.jsx("th",{className:"text-left py-2 px-4 font-medium text-slate-600",children:"说明"}),e.jsx("th",{className:"text-left py-2 px-4 font-medium text-slate-600",children:"适用语言"}),e.jsx("th",{className:"text-left py-2 px-4 font-medium text-slate-600",children:"审查规模"})]})}),e.jsx("tbody",{children:u.length===0?e.jsx("tr",{children:e.jsx("td",{colSpan:5,className:"py-4 px-4 text-slate-500",children:"暂无规则"})}):u.map(([j,t])=>e.jsxs("tr",{className:"border-b border-slate-100 last:border-0",children:[e.jsx("td",{className:"py-2 px-4 font-mono text-xs",children:j}),e.jsx("td",{className:"py-2 px-4",children:e.jsx("span",{className:`text-xs font-medium px-1.5 py-0.5 rounded ${t.severity==="error"?"bg-red-100 text-red-700":"bg-amber-100 text-amber-700"}`,children:t.severity})}),e.jsx("td",{className:"py-2 px-4 text-slate-700",children:t.message}),e.jsx("td",{className:"py-2 px-4 text-slate-500",children:(t.languages||[]).join(", ")}),e.jsx("td",{className:"py-2 px-4 text-slate-500 text-xs",children:t.dimension==="file"?"同文件":t.dimension==="target"?"同 target":t.dimension==="project"?"同项目":"—"})]},j))})]})})]}),e.jsxs("section",{children:[e.jsxs("h3",{className:"text-sm font-semibold text-slate-700 mb-3",children:["违反记录(共 ",x.length," 次运行,",R," 处违反)"]}),x.length===0?e.jsxs("div",{className:"bg-slate-50 border border-slate-200 rounded-xl py-12 text-center text-slate-500",children:["暂无违反记录。在源码中写入 ",e.jsx("code",{className:"bg-slate-200 px-1 rounded",children:"// as:guard"})," 并保存,watch 会执行静态规则检查并记录在此。"]}):e.jsx("div",{className:"space-y-2",children:x.map(j=>{const t=r===j.id,o=j.violations.length>0;return e.jsxs("div",{className:"bg-white border border-slate-200 rounded-xl overflow-hidden",children:[e.jsxs("button",{type:"button",onClick:()=>g(t?null:j.id),className:"w-full flex items-center gap-2 py-3 px-4 text-left hover:bg-slate-50 transition-colors",children:[t?e.jsx(Pe,{size:16}):e.jsx(Ge,{size:16}),e.jsx("span",{className:"font-mono text-sm text-slate-700",children:j.filePath}),e.jsx("span",{className:"text-xs text-slate-400",children:new Date(j.triggeredAt).toLocaleString()}),o?e.jsxs("span",{className:"ml-auto flex items-center gap-1 text-amber-600 text-xs font-medium",children:[e.jsx(qe,{size:14})," ",j.violations.length," 处违反"]}):e.jsx("span",{className:"ml-auto text-slate-400 text-xs",children:"无违反"})]}),t&&e.jsx("div",{className:"border-t border-slate-100 bg-slate-50/50 p-4",children:j.violations.length===0?e.jsx("p",{className:"text-sm text-slate-500",children:"本次运行未发现违反。"}):e.jsx("ul",{className:"space-y-2",children:j.violations.map((i,S)=>e.jsxs("li",{className:"flex items-start gap-2 text-sm",children:[i.severity==="error"?e.jsx(Ws,{size:16,className:"text-red-500 shrink-0 mt-0.5"}):e.jsx(qe,{size:16,className:"text-amber-500 shrink-0 mt-0.5"}),e.jsxs("div",{children:[e.jsxs("span",{className:"font-mono text-xs text-slate-500",children:["[",i.ruleId,"] ",i.filePath?`${i.filePath}:${i.line}`:`L${i.line}`]}),i.dimension&&e.jsx("span",{className:"ml-1.5 text-xs px-1.5 py-0.5 rounded bg-slate-200 text-slate-600",children:i.dimension==="file"?"同文件":i.dimension==="target"?"同 target":"同项目"}),e.jsx("span",{className:"text-slate-700 ml-2",children:i.message}),i.snippet&&e.jsx("pre",{className:"mt-1 text-xs text-slate-600 bg-slate-100 p-2 rounded overflow-x-auto",children:i.snippet})]})]},S))})})]},j.id)})})]})]})},Nt=({chatHistory:s,userInput:a,setUserInput:y,handleChat:x,isAiThinking:n})=>e.jsxs("div",{className:"max-w-3xl mx-auto flex flex-col h-full",children:[e.jsxs("div",{className:"flex-1 overflow-y-auto space-y-4 mb-4 pr-2",children:[s.map((r,g)=>e.jsx("div",{className:`flex ${r.role==="user"?"justify-end":"justify-start"}`,children:e.jsx("div",{className:`max-w-[80%] p-3 rounded-xl text-sm ${r.role==="user"?"bg-blue-600 text-white":"bg-white border border-slate-200 text-slate-800"}`,children:r.text})},g)),n&&e.jsx("div",{className:"text-slate-400 text-xs animate-pulse",children:"AI is thinking..."})]}),e.jsxs("form",{onSubmit:x,className:"flex gap-2 bg-white p-2 rounded-xl border border-slate-200 shadow-sm",children:[e.jsx("input",{type:"text",value:a,onChange:r=>y(r.target.value),placeholder:"Ask anything about your project...",className:"flex-1 px-4 py-2 outline-none text-sm"}),e.jsx("button",{type:"submit",disabled:n,className:"bg-blue-600 text-white px-4 py-2 rounded-lg text-sm font-medium hover:bg-blue-700 transition-colors disabled:bg-slate-300",children:"Ask"})]})]}),yt=({editingSnippet:s,setEditingSnippet:a,handleSaveSnippet:y,closeSnippetEdit:x})=>{const[n,r]=c.useState("preview"),g=(s.content||s.body||[]).join(`
16
+ `),k=s.language==="objc"?"objectivec":s.language||"text",f=async()=>{try{const d=await M.post("/api/ai/summarize",{code:(s.content||s.body||[]).join(`
17
+ `),language:s.language});(d.data.title_cn||d.data.title)&&a({...s,title:d.data.title_cn||d.data.title,summary:d.data.summary_cn||d.data.summary,completionKey:d.data.trigger,content:d.data.code?d.data.code.split(`
18
+ `):s.content||s.body||[]})}catch{alert("AI rewrite failed")}};return e.jsx("div",{className:"fixed inset-0 bg-slate-900/50 backdrop-blur-sm z-50 flex items-center justify-center p-4",children:e.jsxs("div",{className:"bg-white w-full max-w-6xl rounded-2xl shadow-2xl flex flex-col max-h-[90vh]",children:[e.jsxs("div",{className:"p-6 border-b border-slate-100 flex justify-between items-center",children:[e.jsx("h2",{className:"text-xl font-bold",children:"Edit Snippet"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("div",{className:"flex bg-slate-100 p-1 rounded-lg mr-4",children:[e.jsxs("button",{onClick:()=>r("preview"),className:`px-4 py-1.5 rounded-md text-xs font-bold transition-all flex items-center gap-2 ${n==="preview"?"bg-white shadow-sm text-blue-600":"text-slate-400"}`,children:[e.jsx(Ee,{size:14})," Preview"]}),e.jsxs("button",{onClick:()=>r("edit"),className:`px-4 py-1.5 rounded-md text-xs font-bold transition-all flex items-center gap-2 ${n==="edit"?"bg-white shadow-sm text-blue-600":"text-slate-400"}`,children:[e.jsx(Ne,{size:14})," Edit"]})]}),e.jsx("button",{onClick:x,className:"p-2 hover:bg-slate-100 rounded-full",children:e.jsx(ye,{size:20})})]})]}),e.jsxs("div",{className:"p-6 space-y-4 overflow-y-auto",children:[e.jsxs("div",{className:"grid grid-cols-4 gap-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-bold text-slate-400 uppercase mb-1",children:"Title"}),e.jsx("input",{className:"w-full p-2 bg-slate-50 border border-slate-200 rounded-lg text-sm",value:s.title,onChange:d=>a({...s,title:d.target.value})})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-bold text-slate-400 uppercase mb-1",children:"Trigger"}),e.jsx("input",{className:"w-full p-2 bg-slate-50 border border-slate-200 rounded-lg text-sm",value:s.completionKey,onChange:d=>a({...s,completionKey:d.target.value})})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-bold text-slate-400 uppercase mb-1",children:"Category"}),e.jsx("select",{className:"w-full p-2 bg-slate-50 border border-slate-200 rounded-lg text-sm outline-none",value:s.category||"Utility",onChange:d=>a({...s,category:d.target.value}),children:ns.filter(d=>d!=="All").map(d=>e.jsx("option",{value:d,children:d},d))})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-bold text-slate-400 uppercase mb-1",children:"Language"}),e.jsxs("div",{className:"flex bg-slate-100 p-1 rounded-lg",children:[e.jsx("button",{onClick:()=>a({...s,language:"swift"}),className:`flex-1 px-2 py-1 rounded-md text-[10px] font-bold transition-all ${s.language==="swift"?"bg-white shadow-sm text-blue-600":"text-slate-400"}`,children:"Swift"}),e.jsx("button",{onClick:()=>a({...s,language:"objectivec"}),className:`flex-1 px-2 py-1 rounded-md text-[10px] font-bold transition-all ${s.language==="objectivec"||s.language==="objc"?"bg-white shadow-sm text-blue-600":"text-slate-400"}`,children:"ObjC"})]})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-bold text-slate-400 uppercase mb-1",children:"Summary"}),e.jsx("textarea",{rows:2,className:"w-full p-2 bg-slate-50 border border-slate-200 rounded-lg text-sm outline-none resize-none",value:s.summary,onChange:d=>a({...s,summary:d.target.value})})]}),n==="edit"?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"bg-slate-50 p-4 rounded-xl space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("label",{className:"flex items-center gap-2 text-xs font-bold text-slate-400 uppercase",children:[e.jsx(Ks,{size:14})," Headers / Imports"]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-[10px] font-bold text-slate-400 uppercase",children:"Auto-include in Snippet"}),e.jsx("button",{onClick:()=>a({...s,includeHeaders:!s.includeHeaders}),className:`w-8 h-4 rounded-full relative transition-colors ${s.includeHeaders?"bg-blue-600":"bg-slate-300"}`,children:e.jsx("div",{className:`absolute top-0.5 w-3 h-3 bg-white rounded-full transition-all ${s.includeHeaders?"right-0.5":"left-0.5"}`})})]})]}),e.jsx("textarea",{rows:2,className:"w-full p-2 bg-white border border-slate-200 rounded-lg text-xs font-mono outline-none",placeholder:"e.g. #import <UIKit/UIKit.h> or import Foundation",value:(s.headers||[]).join(`
19
+ `),onChange:d=>a({...s,headers:d.target.value.split(`
20
+ `)})})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex justify-between items-center mb-1",children:[e.jsx("label",{className:"block text-xs font-bold text-slate-400 uppercase",children:"Code"}),e.jsx("button",{onClick:f,className:"text-[10px] text-blue-600 font-bold hover:underline",children:"AI Rewrite"})]}),e.jsx("textarea",{className:"w-full h-64 p-4 bg-slate-900 text-slate-100 font-mono text-xs rounded-xl outline-none",value:g,onChange:d=>a({...s,content:(d.target.value||"").split(`
21
+ `)})})]})]}):e.jsx("div",{className:"space-y-6",children:e.jsxs("div",{className:"bg-white p-8 rounded-2xl border border-slate-100 shadow-sm min-h-[400px]",children:[e.jsxs("div",{className:"flex justify-between items-center mb-4",children:[e.jsx("label",{className:"block text-[10px] font-bold text-slate-400 uppercase tracking-widest",children:"Code Preview"}),e.jsx("button",{onClick:f,className:"text-[10px] text-blue-600 font-bold hover:underline",children:"AI Rewrite"})]}),e.jsx(je,{code:g,language:k,showLineNumbers:!0})]})})]}),e.jsxs("div",{className:"p-6 border-t border-slate-100 flex justify-end gap-3",children:[e.jsx("button",{onClick:x,className:"px-4 py-2 text-slate-600 font-medium",children:"Cancel"}),e.jsxs("button",{onClick:y,className:"px-6 py-2 bg-blue-600 text-white rounded-lg font-medium flex items-center gap-2 hover:bg-blue-700",children:[e.jsx(ls,{size:18}),"Save Changes"]})]})]})})},vt={authority:0,guardUsageCount:0,humanUsageCount:0,aiUsageCount:0,lastUsedAt:null,authorityScore:0},wt=({editingRecipe:s,setEditingRecipe:a,handleSaveRecipe:y,closeRecipeEdit:x})=>{var h;const[n,r]=c.useState("preview"),g=async v=>{try{await M.post("/api/recipes/set-authority",{name:s.name,authority:v});const p=s.stats?{...s.stats,authority:v}:{...vt,authority:v};a({...s,stats:p})}catch{}},k=v=>{const p=v.split(`
22
+ `),A={};let D=0,O=!1;for(let $=0;$<p.length;$++){const H=p[$].trim();if(H==="---"){if(!O&&$===0){O=!0;continue}else if(O){O=!1,D=$+1;break}}const m=H.match(/^([a-zA-Z0-9_-]+):\s*(.*)/);if(m)A[m[1]]=m[2],O||(D=$+1);else if(!O&&H!==""){D=$;break}}const K=p.slice(D).join(`
23
+ `).trim();return{metadata:A,body:K}},{metadata:f,body:d}=k(s.content||"");return e.jsx("div",{className:"fixed inset-0 bg-slate-900/50 backdrop-blur-sm z-50 flex items-center justify-center p-4",children:e.jsxs("div",{className:"bg-white w-full max-w-6xl rounded-2xl shadow-2xl flex flex-col h-[85vh]",children:[e.jsxs("div",{className:"p-6 border-b border-slate-100 flex justify-between items-center flex-wrap gap-4",children:[e.jsx("h2",{className:"text-xl font-bold",children:"Edit Recipe"}),e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs font-medium text-slate-500",children:"权威分"}),n==="preview"?e.jsx("span",{className:"text-sm text-slate-700",children:((h=s.stats)==null?void 0:h.authority)??0}):e.jsx("div",{className:"flex gap-0.5",children:[1,2,3,4,5].map(v=>{var p,A;return e.jsx("button",{type:"button",onClick:()=>g(v),className:`p-1 rounded ${(((p=s.stats)==null?void 0:p.authority)??0)>=v?"text-amber-500":"text-slate-300 hover:text-amber-400"}`,title:`设为 ${v} 星`,children:e.jsx(Bs,{size:18,fill:(((A=s.stats)==null?void 0:A.authority)??0)>=v?"currentColor":"none"})},v)})})]}),e.jsxs("div",{className:"flex bg-slate-100 p-1 rounded-lg mr-4",children:[e.jsxs("button",{onClick:()=>r("preview"),className:`px-4 py-1.5 rounded-md text-xs font-bold transition-all flex items-center gap-2 ${n==="preview"?"bg-white shadow-sm text-blue-600":"text-slate-400"}`,children:[e.jsx(Ee,{size:14})," Preview"]}),e.jsxs("button",{onClick:()=>r("edit"),className:`px-4 py-1.5 rounded-md text-xs font-bold transition-all flex items-center gap-2 ${n==="edit"?"bg-white shadow-sm text-blue-600":"text-slate-400"}`,children:[e.jsx(Ne,{size:14})," Edit"]})]}),e.jsx("button",{onClick:x,className:"p-2 hover:bg-slate-100 rounded-full",children:e.jsx(ye,{size:20})})]})]}),e.jsxs("div",{className:"p-6 space-y-4 flex-1 flex flex-col overflow-hidden",children:[n==="edit"&&e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-bold text-slate-400 uppercase mb-1",children:"Path"}),e.jsx("input",{className:"w-full p-2 bg-slate-50 border border-slate-200 rounded-lg text-sm",value:s.name,onChange:v=>a({...s,name:v.target.value})})]}),e.jsx("div",{className:"flex-1 flex flex-col min-h-0",children:n==="edit"?e.jsxs(e.Fragment,{children:[e.jsx("label",{className:"block text-xs font-bold text-slate-400 uppercase mb-1",children:"Markdown Content"}),e.jsx("textarea",{className:"w-full flex-1 p-4 bg-slate-900 text-slate-100 font-mono text-xs rounded-xl outline-none leading-relaxed",value:s.content||"",onChange:v=>a({...s,content:v.target.value})})]}):e.jsxs("div",{className:"flex-1 overflow-y-auto space-y-6",children:[Object.keys(f).length>0&&e.jsxs("div",{className:"bg-slate-50 border border-slate-200 rounded-2xl p-6",children:[e.jsx("h3",{className:"text-[10px] font-bold text-slate-400 uppercase tracking-widest mb-4",children:"Recipe Metadata"}),e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-y-4 gap-x-8",children:Object.entries(f).map(([v,p])=>e.jsxs("div",{className:"flex flex-col",children:[e.jsx("span",{className:"text-[10px] text-slate-400 font-bold uppercase mb-1",children:v}),e.jsx("span",{className:"text-sm text-slate-700 break-all font-medium",children:p.startsWith("[")&&p.endsWith("]")?e.jsx("div",{className:"flex flex-wrap gap-1 mt-1",children:p.slice(1,-1).split(",").map((A,D)=>e.jsx("span",{className:"px-2 py-0.5 bg-white border border-slate-200 rounded text-[10px] font-mono",children:A.trim()},D))}):p})]},v))})]}),e.jsx("div",{className:"bg-white p-8 rounded-2xl border border-slate-100 shadow-sm min-h-[400px]",children:d?e.jsx(fe,{content:d,showLineNumbers:!0}):e.jsx("div",{className:"flex items-center justify-center h-full text-slate-300 italic",children:"No content body"})})]})})]}),e.jsxs("div",{className:"p-6 border-t border-slate-100 flex justify-end gap-3",children:[e.jsx("button",{onClick:x,className:"px-4 py-2 text-slate-600 font-medium",children:"Cancel"}),e.jsxs("button",{onClick:y,className:"px-6 py-2 bg-blue-600 text-white rounded-lg font-medium flex items-center gap-2 hover:bg-blue-700",children:[e.jsx(ls,{size:18}),"Save Changes"]})]})]})})},Ct=({setShowCreateModal:s,createPath:a,setCreatePath:y,handleCreateFromPath:x,handleCreateFromClipboard:n,isExtracting:r})=>e.jsx("div",{className:"fixed inset-0 bg-slate-900/50 backdrop-blur-sm z-50 flex items-center justify-center p-4",children:e.jsxs("div",{className:"bg-white w-full max-w-lg rounded-2xl shadow-2xl overflow-hidden",children:[e.jsxs("div",{className:"p-6 border-b border-slate-100 flex justify-between items-center bg-slate-50",children:[e.jsxs("h2",{className:"text-xl font-bold flex items-center gap-2 text-slate-800",children:[e.jsx(es,{size:24,className:"text-blue-600"})," New Recipe"]}),e.jsx("button",{onClick:()=>s(!1),className:"p-2 hover:bg-white rounded-full transition-colors",children:e.jsx(ye,{size:20})})]}),e.jsxs("div",{className:"p-8 space-y-6",children:[e.jsxs("div",{className:"space-y-3",children:[e.jsxs("label",{className:"flex items-center gap-2 text-xs font-bold text-slate-400 uppercase tracking-widest",children:[e.jsx(ss,{size:14})," Import from Project Path"]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("input",{className:"flex-1 p-3 bg-slate-100 border-none rounded-xl text-sm outline-none focus:ring-2 focus:ring-blue-500",placeholder:"e.g. Sources/MyModule/Auth.swift",value:a,onChange:g=>y(g.target.value)}),e.jsx("button",{onClick:x,disabled:!a||r,className:"bg-slate-900 text-white px-4 py-2 rounded-xl text-sm font-bold hover:bg-slate-800 disabled:opacity-50",children:"Scan File"})]})]}),e.jsxs("div",{className:"relative",children:[e.jsx("div",{className:"absolute inset-0 flex items-center",children:e.jsx("div",{className:"w-full border-t border-slate-100"})}),e.jsx("div",{className:"relative flex justify-center text-xs uppercase",children:e.jsx("span",{className:"bg-white px-2 text-slate-300 font-bold",children:"Or"})})]}),e.jsxs("div",{className:"space-y-3",children:[e.jsxs("label",{className:"flex items-center gap-2 text-xs font-bold text-slate-400 uppercase tracking-widest",children:[e.jsx(Vs,{size:14})," Import from Clipboard"]}),e.jsxs("button",{onClick:()=>n(),disabled:r,className:"w-full flex items-center justify-center gap-3 p-4 bg-blue-50 text-blue-700 rounded-xl font-bold hover:bg-blue-100 transition-all border border-blue-100",children:[e.jsx(we,{size:20})," Use Copied Code"]})]})]}),r&&e.jsxs("div",{className:"bg-blue-600 text-white p-4 flex items-center justify-center gap-3 animate-pulse",children:[e.jsx(Ce,{size:20,className:"animate-spin"}),e.jsx("span",{className:"font-bold text-sm",children:"AI is thinking..."})]})]})});function St(s){const a=s.replace(/^---[\s\S]*?---\s*\n?/,"").trim(),y=a.match(/```[\w]*\n([\s\S]*?)```/);return y&&y[1]?y[1].trim():a.slice(0,8e3)}const kt=({searchQ:s,insertPath:a,onClose:y})=>{const[x,n]=c.useState([]),[r,g]=c.useState(!0),[k,f]=c.useState(null);c.useEffect(()=>{const h=s?encodeURIComponent(s):"";M.get(`/api/recipes/search?q=${h}`).then(v=>n(v.data.results||[])).catch(()=>n([])).finally(()=>g(!1))},[s]);const d=async h=>{f(h.name);try{const v=St(h.content);await M.post("/api/insert-at-search-mark",{path:a,content:v}),alert("✅ 已插入到 "+a),y()}catch{alert("❌ 插入失败")}finally{f(null)}};return e.jsx("div",{className:"fixed inset-0 bg-slate-900/50 backdrop-blur-sm z-50 flex items-center justify-center p-4",children:e.jsxs("div",{className:"bg-white w-full max-w-2xl rounded-2xl shadow-2xl overflow-hidden flex flex-col max-h-[85vh]",children:[e.jsxs("div",{className:"p-6 border-b border-slate-100 flex justify-between items-center bg-slate-50",children:[e.jsxs("h2",{className:"text-xl font-bold flex items-center gap-2 text-slate-800",children:[e.jsx(Ze,{size:24,className:"text-blue-600"})," as:search — 选择并插入"]}),e.jsx("button",{onClick:y,className:"p-2 hover:bg-white rounded-full transition-colors",children:e.jsx(ye,{size:20})})]}),e.jsxs("div",{className:"p-4 text-sm text-slate-500 border-b border-slate-100",children:["关键词: ",s||"(全部)"," · 插入到: ",a]}),e.jsx("div",{className:"flex-1 overflow-y-auto p-4",children:r?e.jsx("div",{className:"flex items-center justify-center py-12",children:e.jsx("div",{className:"animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"})}):x.length===0?e.jsx("div",{className:"text-slate-500 text-center py-8",children:"未找到匹配的 Recipe"}):e.jsx("ul",{className:"space-y-2",children:x.map(h=>e.jsx("li",{children:e.jsxs("button",{type:"button",onClick:()=>d(h),disabled:k!==null,className:"w-full flex items-center justify-between gap-3 p-4 rounded-xl border border-slate-200 hover:border-blue-300 hover:bg-blue-50/50 transition-all text-left disabled:opacity-50",children:[e.jsx("span",{className:"font-medium text-slate-800 truncate flex-1",children:h.name}),k===h.name?e.jsxs("span",{className:"text-blue-600 text-sm flex items-center gap-1",children:[e.jsx("span",{className:"animate-spin",children:"⏳"})," 插入中..."]}):e.jsxs("span",{className:"text-blue-600 text-sm flex items-center gap-1",children:[e.jsx(as,{size:16})," 插入"]})]})},h.name))})})]})})},It=()=>{const s=()=>{const l=window.location.pathname.replace(/^\//,"").split("/")[0]||"";return tt.includes(l)?l:"recipes"},[a,y]=c.useState(null),[x,n]=c.useState(s()),[r,g]=c.useState(""),[k,f]=c.useState(!0),[d,h]=c.useState(null),[v,p]=c.useState(null),[A,D]=c.useState([]),[O,K]=c.useState(null),[$,H]=c.useState(!1),[m,U]=c.useState({current:0,total:0,status:""}),[te,P]=c.useState([]),[B,V]=c.useState([]),[Y,N]=c.useState("All"),[L,u]=c.useState(1),[R,j]=c.useState(12),[t,o]=c.useState(!1),[i,S]=c.useState(""),[z,I]=c.useState(!1),[q,X]=c.useState([]),[_,F]=c.useState(""),[W,G]=c.useState(!1),[J,ve]=c.useState(null),[be,oe]=c.useState(null),re=c.useRef(null),xe=c.useRef(null);c.useEffect(()=>{u(1)},[r,Y]);const me=()=>{re.current&&re.current.abort(),xe.current&&xe.current.abort(),G(!1)},ue=(l,b)=>{n(l);const C=b!=null&&b.preserveSearch&&window.location.search?window.location.search:"";window.history.pushState({},document.title,`/${l}${C}`)},Ue=l=>{const b=l.title.replace(/^\[.*?\]\s*/,"");h({...l,title:b}),n("snippets");const C=new URLSearchParams(window.location.search);C.set("edit",l.identifier),window.history.pushState({},document.title,`/snippets?${C.toString()}`)},Oe=()=>{h(null),window.history.replaceState({},document.title,"/snippets")},Se=l=>{p(l),n("recipes");const b=new URLSearchParams(window.location.search);b.set("edit",encodeURIComponent(l.name)),window.history.pushState({},document.title,`/recipes?${b.toString()}`)},He=()=>{p(null),window.history.replaceState({},document.title,"/recipes")};c.useEffect(()=>{r===""&&ve(null)},[r]),c.useEffect(()=>{n(s())},[]),c.useEffect(()=>{var w;if(!a)return;const l=window.location.pathname.replace(/^\//,"").split("/")[0],C=new URLSearchParams(window.location.search).get("edit");if(l==="snippets"&&C&&((w=a.rootSpec)!=null&&w.list)){const T=a.rootSpec.list.find(Q=>Q.identifier===C);T&&!d&&(n("snippets"),Ue(T))}if(l==="recipes"&&C&&a.recipes)try{const T=decodeURIComponent(C),Q=a.recipes.find(ae=>ae.name===T);Q&&!v&&(n("recipes"),Se(Q))}catch{}},[a]),c.useEffect(()=>{le(),Fe();const l=()=>{n(s())};window.addEventListener("popstate",l);const b=new URLSearchParams(window.location.search),C=b.get("action"),w=b.get("path"),T=b.get("q")||"";C==="search"&&w?oe({q:T,path:w}):C==="create"&&w&&(S(w),o(!0),b.get("autoScan")==="1"&&setTimeout(()=>cs(w),500))},[]);const le=async()=>{f(!0);try{const l=await M.get("/api/data");y(l.data)}catch{}finally{f(!1)}},Fe=async()=>{try{const l=await M.get("/api/spm/targets");D(l.data)}catch{}},is=async()=>{try{await M.post("/api/commands/install"),E("已同步到 Xcode CodeSnippets")}catch{E("同步失败",{type:"error"})}},os=async()=>{try{await M.post("/api/commands/spm-map"),Fe(),E("项目结构已刷新")}catch{E("刷新失败",{type:"error"})}},cs=async l=>{var b;I(!0);try{const C=await M.post("/api/extract/path",{relativePath:l});V(C.data.result.map(w=>({...w,mode:"full",lang:"cn",includeHeaders:!0,category:w.category||"Utility",summary:w.summary_cn||w.summary||"",usageGuide:w.usageGuide_cn||w.usageGuide||""}))),ue("spm",{preserveSearch:!0}),o(!1),le(),((b=C.data.result)==null?void 0:b.length)>0&&E("提取完成,已加入候选池,请在 Candidates 页审核")}catch{E("Extraction failed",{type:"error"})}finally{I(!1)}},ds=async()=>{var l;if(i){I(!0);try{const b=await M.post("/api/extract/path",{relativePath:i});V(b.data.result.map(C=>({...C,mode:"full",lang:"cn",includeHeaders:!0,category:C.category||"Utility",summary:C.summary_cn||C.summary||"",usageGuide:C.usageGuide_cn||C.usageGuide||""}))),ue("spm"),o(!1),le(),((l=b.data.result)==null?void 0:l.length)>0?E(b.data.isMarked?"提取完成(精准锁定),已加入候选池":"提取完成,已加入候选池"):b.data.isMarked||E("未找到标记,AI 正在分析完整文件")}catch{E("Extraction failed",{type:"error"})}finally{I(!1)}}},xs=async l=>{var b,C,w,T;try{const Q=await navigator.clipboard.readText();if(!Q)return E("剪贴板为空");E("已收到剪贴板内容,正在调用 AI 识别..."),I(!0);const ae=l||i;try{const se=(await M.post("/api/extract/text",{text:Q,...ae?{relativePath:ae}:{}})).data,Z=se._multipleCount;V([{...se,mode:"full",lang:"cn",includeHeaders:!0,category:se.category||"Utility",summary:se.summary_cn||se.summary||"",usageGuide:se.usageGuide_cn||se.usageGuide||""}]),ue("spm",{preserveSearch:!0}),o(!1),le(),E(Z?`已识别 ${Z} 条 Recipe,已加入候选池`:"AI 识别成功,已加入候选池")}catch(ee){const se=((C=(b=ee.response)==null?void 0:b.data)==null?void 0:C.aiError)===!0,Z=((T=(w=ee.response)==null?void 0:w.data)==null?void 0:T.error)||ee.message;se?E(`AI 识别失败: ${Z}`,{type:"error"}):E(`操作失败: ${Z}`,{type:"error"})}}catch{E("剪贴板读取失败",{type:"error"})}finally{I(!1)}},We=[{status:"正在读取 Target 源文件...",percent:15},{status:"正在发送到 AI 分析...",percent:35},{status:"正在识别可复用代码片段...",percent:55},{status:"正在生成摘要与使用指南...",percent:75},{status:"即将完成...",percent:92}],ms=async l=>{var Q,ae,ee,se;if($)return;re.current&&re.current.abort();const b=new AbortController;re.current=b,K(l.name),H(!0),V([]),P([]),U({current:0,total:100,status:"正在获取待扫描文件列表..."});const C=4e3;let w=0;const T=setInterval(()=>{w=Math.min(w+1,We.length);const Z=We[w-1];Z&&U(ie=>({...ie,current:Z.percent,status:Z.status}))},C);try{const Z=await M.post("/api/spm/target-files",{target:l},{signal:b.signal}),ie=((Q=Z.data)==null?void 0:Q.files)||[],Ss=((ae=Z.data)==null?void 0:ae.count)??ie.length;P(ie),U(ce=>({...ce,current:10,status:`正在分析 ${Ss} 个文件...`}));const ks=await M.post("/api/spm/scan",{target:l},{signal:b.signal});clearInterval(T),U({current:100,total:100,status:"扫描完成"});const ne=ks.data,ke=Array.isArray(ne)?ne:(ne==null?void 0:ne.recipes)??[],Be=!Array.isArray(ne)&&(ne!=null&&ne.scannedFiles)?ne.scannedFiles:ie;ke.length>0||Be.length>0?(V(ke.map(ce=>({...ce,mode:"full",lang:"cn",includeHeaders:ce.includeHeaders!==!1,category:ce.category||"Utility",summary:ce.summary_cn||ce.summary||"",usageGuide:ce.usageGuide_cn||ce.usageGuide||""}))),P(Be),le(),ke.length>0&&E(`${ke.length} 条已加入候选池(24h),请在 Candidates 页审核`)):typeof ne=="object"&&ne!==null&&"message"in ne?E(ne.message||"Scan failed: No source files.",{type:"error"}):E("Scan failed: Unexpected response format",{type:"error"})}catch(Z){if(clearInterval(T),M.isCancel(Z))return;E(`Scan failed: ${((se=(ee=Z.response)==null?void 0:ee.data)==null?void 0:se.error)||Z.message}`,{type:"error"})}finally{re.current===b&&(H(!1),U({current:0,total:0,status:""}),re.current=null)}},us=(l,b)=>{const C=[...B],w={...C[l],...b};b.lang!==void 0?(w.summary=b.lang==="cn"?w.summary_cn||w.summary:w.summary_en||w.summary,w.usageGuide=b.lang==="cn"?w.usageGuide_cn||w.usageGuide:w.usageGuide_en||w.usageGuide):(b.summary!==void 0&&(w.lang==="cn"?w.summary_cn=b.summary:w.summary_en=b.summary),b.usageGuide!==void 0&&(w.lang==="cn"?w.usageGuide_cn=b.usageGuide:w.usageGuide_en=b.usageGuide)),C[l]=w,V(C)},ps=async l=>{try{const b=l.trigger.split(/[,,\s]+/).map(ee=>ee.trim()).filter(Boolean),C=crypto.randomUUID().toUpperCase();if(l.mode==="full")for(let ee=0;ee<b.length;ee++){const se=b[ee],Z=l.includeHeaders!==!1,ie={identifier:ee===0?C:crypto.randomUUID().toUpperCase(),title:b.length>1?`${l.title} (${se})`:l.title,completionKey:se,category:l.category,summary:l.summary,language:l.language,content:l.code.split(`
24
+ `),headers:Z?l.headers||[]:[],headerPaths:Z?l.headerPaths||[]:void 0,moduleName:l.moduleName,includeHeaders:Z};await M.post("/api/snippets/save",{snippet:ie})}const w=`${l.title.replace(/\s+/g,"-")}.md`,T=`---
25
+ id: ${l.mode==="full"?C:"preview-only"}
26
+ title: ${l.title}
27
+ language: ${l.language}
28
+ trigger: ${b.join(", ")}
29
+ category: ${l.category||"Utility"}
30
+ summary: ${l.summary}
31
+ type: ${l.mode}
32
+ headers: ${JSON.stringify(l.headers||[])}
33
+ ---
34
+
35
+ ## Snippet / Code Reference
36
+
37
+ \`\`\`${l.language}
38
+ ${l.code}
39
+ \`\`\`
40
+
41
+ ## AI Context / Usage Guide
42
+
43
+ ${l.usageGuide}
44
+ `;await M.post("/api/recipes/save",{name:w,content:T}),E(l.mode==="full"?"已保存为 Snippet 和 Recipe":"已保存到 KB"),V(ee=>ee.filter(se=>se.title!==l.title));const Q=l.candidateTargetName,ae=l.candidateId;if(Q&&ae)try{await M.post("/api/candidates/delete",{targetName:Q,candidateId:ae})}catch{}le()}catch{E("保存失败",{type:"error"})}},hs=async()=>{if(v)try{await M.post("/api/recipes/save",{name:v.name,content:v.content}),He(),le()}catch{E("保存 Recipe 失败",{type:"error"})}},bs=async l=>{if(window.confirm("Are you sure?"))try{await M.post("/api/recipes/delete",{name:l}),le()}catch{E("删除失败",{type:"error"})}},Ke=async(l,b)=>{try{await M.post("/api/candidates/delete",{targetName:l,candidateId:b}),V(C=>C.filter(w=>!(w.candidateId===b&&w.candidateTargetName===l))),le()}catch(C){throw E("操作失败",{type:"error"}),C}},gs=async l=>{if(window.confirm(`确定移除「${l}」下的全部候选?`))try{await M.post("/api/candidates/delete-target",{targetName:l}),le(),E(`已移除 ${l} 下的全部候选`)}catch{E("操作失败",{type:"error"})}},fs=async()=>{if(d)try{await M.post("/api/snippets/save",{snippet:d}),Oe(),le()}catch{E("保存 Snippet 失败",{type:"error"})}},js=async(l,b)=>{if(window.confirm(`Delete snippet: ${b}?`))try{await M.post("/api/snippets/delete",{identifier:l}),le()}catch{E("删除失败",{type:"error"})}},Ns=async l=>{if(l.preventDefault(),!_.trim()||W)return;xe.current&&xe.current.abort();const b=new AbortController;xe.current=b;const C={role:"user",text:_};X(w=>[...w,C]),F(""),G(!0);try{const w=await M.post("/api/ai/chat",{prompt:_,history:q.map(T=>({role:T.role,content:T.text}))},{signal:b.signal});X(T=>[...T,{role:"model",text:w.data.text}])}catch(w){if(M.isCancel(w))return;X(T=>[...T,{role:"model",text:"Error"}])}finally{xe.current===b&&(xe.current=null,G(!1))}},ys=(a==null?void 0:a.rootSpec.list.filter(l=>{const b=l.title||"",C=l.completionKey||"",w=b.toLowerCase().includes(r.toLowerCase())||C.toLowerCase().includes(r.toLowerCase());if(Y==="All")return w;const T=l.category||"Utility";return w&&T===Y}))||[],vs=((a==null?void 0:a.recipes)||[]).filter(l=>{if(J)return J.some(ae=>ae.metadata.type==="recipe"&&ae.metadata.name===l.name);const b=l.name||"",C=l.content||"",w=b.toLowerCase().includes(r.toLowerCase())||C.toLowerCase().includes(r.toLowerCase());if(Y==="All")return w;const T=C?C.match(/category:\s*(.*)/):null,Q=T?T[1].trim():"Utility";return w&&Q===Y}).sort((l,b)=>{var T,Q,ae,ee;if(J){const se=((T=J.find(ie=>ie.metadata.name===l.name))==null?void 0:T.similarity)||0;return(((Q=J.find(ie=>ie.metadata.name===b.name))==null?void 0:Q.similarity)||0)-se}const C=((ae=l.stats)==null?void 0:ae.authorityScore)??0;return(((ee=b.stats)==null?void 0:ee.authorityScore)??0)-C}),ws=A.filter(l=>l.name.toLowerCase().includes(r.toLowerCase())).sort((l,b)=>{const C=Ie(l.name),w=Ie(b.name);return C&&!w?1:!C&&w?-1:l.name.localeCompare(b.name)}),Cs=Object.values((a==null?void 0:a.candidates)||{}).reduce((l,b)=>l+b.items.length,0);return e.jsxs("div",{className:"flex h-screen bg-slate-50 text-slate-900 overflow-hidden font-sans",children:[e.jsx(qs,{position:"top-center",toastOptions:{duration:3e3}}),e.jsx(rt,{activeTab:x,navigateToTab:ue,handleRefreshProject:os,candidateCount:Cs}),e.jsxs("main",{className:"flex-1 flex flex-col overflow-hidden relative",children:[e.jsx(it,{searchQuery:r,setSearchQuery:g,setShowCreateModal:o,handleSyncToXcode:is,aiConfig:a==null?void 0:a.aiConfig,onBeforeAiSwitch:me,onAiConfigChange:le,onSemanticSearchResults:l=>{ve(l),x!=="recipes"&&x!=="snippets"&&ue("recipes")}}),(x==="snippets"||x==="recipes")&&e.jsx(ot,{selectedCategory:Y,setSelectedCategory:N}),e.jsx("div",{className:"flex-1 overflow-y-auto p-8",children:k?e.jsx("div",{className:"flex items-center justify-center h-full",children:e.jsx("div",{className:"animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"})}):x==="snippets"?e.jsx(ct,{snippets:ys,openSnippetEdit:Ue,handleDeleteSnippet:js}):x==="recipes"?e.jsx(dt,{recipes:vs,openRecipeEdit:Se,handleDeleteRecipe:bs,onRefresh:le,currentPage:L,onPageChange:u,pageSize:R,onPageSizeChange:l=>{j(l),u(1)}}):x==="guard"?e.jsx(jt,{onRefresh:le}):x==="help"?e.jsx(xt,{}):x==="candidates"?e.jsx(pt,{data:a,isShellTarget:Ie,isSilentTarget:lt,isPendingTarget:nt,handleDeleteCandidate:Ke,onEditRecipe:Se,onAuditCandidate:(l,b)=>{V([{...l,mode:"full",lang:"cn",includeHeaders:!0,summary:l.summary_cn||l.summary||"",usageGuide:l.usageGuide_cn||l.usageGuide||"",candidateId:l.id,candidateTargetName:b}]),ue("spm")},onAuditAllInTarget:(l,b)=>{V(l.map(C=>({...C,mode:"full",lang:"cn",includeHeaders:!0,summary:C.summary_cn||C.summary||"",usageGuide:C.usageGuide_cn||C.usageGuide||"",candidateId:C.id,candidateTargetName:b}))),ue("spm")},handleDeleteAllInTarget:gs}):x==="depgraph"?e.jsx(ft,{}):x==="spm"?e.jsx(ht,{targets:A,filteredTargets:ws,selectedTargetName:O,isScanning:$,scanProgress:m,scanFileList:te,scanResults:B,handleScanTarget:ms,handleUpdateScanResult:us,handleSaveExtracted:ps,handleDeleteCandidate:Ke,onEditRecipe:Se,isShellTarget:Ie,recipes:(a==null?void 0:a.recipes)??[]}):e.jsx(Nt,{chatHistory:q,userInput:_,setUserInput:F,handleChat:Ns,isAiThinking:W})}),d&&e.jsx(yt,{editingSnippet:d,setEditingSnippet:h,handleSaveSnippet:fs,closeSnippetEdit:Oe}),v&&e.jsx(wt,{editingRecipe:v,setEditingRecipe:p,handleSaveRecipe:hs,closeRecipeEdit:He}),t&&e.jsx(Ct,{setShowCreateModal:o,createPath:i,setCreatePath:S,handleCreateFromPath:ds,handleCreateFromClipboard:xs,isExtracting:z}),be&&e.jsx(kt,{searchQ:be.q,insertPath:be.path,onClose:()=>{oe(null),window.history.replaceState({},document.title,window.location.pathname)}})]})]})};Xs.createRoot(document.getElementById("root")).render(e.jsx(Ys.StrictMode,{children:e.jsx(It,{})}));