autosnippet 1.7.2 → 1.7.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.
Files changed (30) hide show
  1. package/bin/dashboard/routes/core.js +4 -37
  2. package/bin/dashboard/routes/search.js +28 -6
  3. package/checksums.json +1 -1
  4. package/dashboard/dist/assets/{index-D9fS5ZxI.js → index-BoYBT7s4.js} +1 -1
  5. package/dashboard/dist/index.html +1 -1
  6. package/lib/ai/providers/GoogleGeminiProvider.js +20 -6
  7. package/lib/application/services/ContextServiceV2.js +8 -2
  8. package/lib/application/services/SearchServiceV2.js +10 -1
  9. package/lib/context/IndexingPipeline.js +2 -1
  10. package/lib/context/WindowContextManager.js +374 -0
  11. package/lib/infrastructure/vector/VectorMath.js +47 -4
  12. package/lib/injection/injectionService.js +137 -22
  13. package/lib/simulation/SimulatorInsertionManager.js +93 -0
  14. package/lib/watch/DirectiveDetector.js +0 -16
  15. package/lib/watch/FileWatchService.js +13 -9
  16. package/lib/watch/handlers/HeaderHandler.js +221 -13
  17. package/lib/watch/handlers/SearchHandler.js +273 -213
  18. package/package.json +7 -3
  19. package/resources/asd-entry/main.swift +3 -2
  20. package/scripts/build-asd-entry.js +25 -2
  21. package/scripts/build-native-ui.js +32 -3
  22. package/scripts/clear-old-vector-index.js +77 -0
  23. package/scripts/clear-vector-cache.js +76 -0
  24. package/scripts/postinstall-safe.js +66 -0
  25. package/templates/copilot-instructions.md +37 -0
  26. package/templates/cursor-rules/autosnippet-conventions.mdc +42 -0
  27. package/templates/recipes-setup/README.md +197 -0
  28. package/templates/recipes-setup/_template.md +106 -0
  29. package/templates/recipes-setup/example.md +119 -0
  30. package/bin/dashboard/routes/search.js.bak +0 -1005
@@ -360,51 +360,18 @@ function registerCoreRoutes(app, ctx) {
360
360
  });
361
361
 
362
362
  // API: 执行 Xcode 编辑器中的指令(search/create/audit)
363
- // 通过创建临时文件触发 FileWatchService,调用真实的处理逻辑
363
+ // ⚠️ 已禁用:不再通过临时文件触发 watch - 模拟器搜索处理已关闭
364
364
  app.post('/api/execute', async (req, res) => {
365
365
  try {
366
- const { type, query, line, content, source } = req.body;
366
+ const { type, query, line, content } = req.body;
367
367
 
368
368
  if (!type || !query) {
369
369
  return res.status(400).json({ error: 'Missing type or query' });
370
370
  }
371
371
 
372
- // 生成指令标记
373
- let directiveContent = '';
374
-
375
- // 添加来源标记(可以让 handler 知道是从模拟器还是真实 Xcode 发起)
376
- if (source === 'simulator') {
377
- directiveContent = `// SOURCE: simulator\n`;
378
- }
379
-
380
- if (type === 'search') {
381
- directiveContent += `// as:search ${query}\n`;
382
- } else if (type === 'create') {
383
- directiveContent += `// as:create ${query}\n`;
384
- } else if (type === 'audit') {
385
- directiveContent += `// as:audit ${query}\n`;
386
- } else {
387
- return res.status(400).json({ error: `Unknown type: ${type}` });
388
- }
389
-
390
- // 创建临时文件来触发 watch
391
- const tempDir = path.join(projectRoot, '.autosnippet-temp');
392
- if (!fs.existsSync(tempDir)) {
393
- fs.mkdirSync(tempDir, { recursive: true });
394
- }
395
-
396
- const timestamp = Date.now();
397
- const tempFileName = `.as-${type}-${timestamp}.swift`;
398
- const tempFilePath = path.join(tempDir, tempFileName);
399
-
400
- // 写入指令到临时文件(包括来源标记)
401
- fs.writeFileSync(tempFilePath, directiveContent + (content || ''), 'utf8');
402
-
403
- console.log(`[API Execute] 已创建临时文件以触发 watch: ${tempFilePath}`);
404
- console.log(`[API Execute] 来源: ${source === 'simulator' ? '✨ Xcode 模拟器' : '💻 真实 Xcode'}`);
405
- console.log(`[API Execute] 指令内容: ${directiveContent.trim()}`);
372
+ console.log(`[API Execute] 模拟器搜索已禁用: type=${type}, query=${query}`);
406
373
 
407
- // 对于搜索请求,同时返回搜索结果
374
+ // 对于搜索请求,直接返回搜索结果(不创建临时文件)
408
375
  let searchResults = [];
409
376
  if (type === 'search') {
410
377
  const rootSpecPath = Paths.getProjectSpecPath(projectRoot);
@@ -168,6 +168,19 @@ function registerSearchRoutes(app, ctx) {
168
168
  }
169
169
 
170
170
  // 4. 合并和评分
171
+ // 路径标准化:移除多种前缀形式(兼容不同的数据来源)
172
+ // 源头修复:lib/context/IndexingPipeline.js 现在只保存相对路径,不含前缀
173
+ // 此函数处理来自不同来源的数据格式不一致问题
174
+ function normalizePath(pathStr) {
175
+ if (!pathStr) return pathStr;
176
+ // 移除前缀,优先级从高到低:
177
+ // 1. "recipe_" 前缀(来自向量索引的id字段)
178
+ // 2. "AutoSnippet/recipes/" 或 "AutoSnippet\\recipes\\"(旧形式的sourcePath)
179
+ return pathStr
180
+ .replace(/^recipe_/, '') // 移除 vr.id 中的 "recipe_" 前缀
181
+ .replace(/^AutoSnippet[\\/]recipes[\\/]/, ''); // 移除旧 sourcePath 前缀
182
+ }
183
+
171
184
  debug(taskId, '4️⃣ Merge & Score Start', {
172
185
  vectorCount: vectorResults.length,
173
186
  keywordCount: keywordResults.length
@@ -175,23 +188,32 @@ function registerSearchRoutes(app, ctx) {
175
188
  const mergedMap = new Map();
176
189
 
177
190
  for (const vr of vectorResults) {
178
- const key = vr.metadata?.name || vr.id || '';
191
+ const rawName = vr.metadata?.name || vr.id || '';
192
+ const normalizedName = normalizePath(rawName);
193
+ const key = normalizedName || rawName;
179
194
  if (!mergedMap.has(key)) {
180
195
  mergedMap.set(key, {
181
- name: key,
196
+ name: normalizedName,
182
197
  content: vr.content || '',
183
198
  _vectorScore: vr._vectorScore,
184
199
  _keywordScore: 0,
185
- ...vr
200
+ ...vr,
201
+ _originalName: rawName
186
202
  });
187
203
  }
188
204
  }
189
205
 
190
206
  for (const kr of keywordResults) {
191
- if (!mergedMap.has(kr.name)) {
192
- mergedMap.set(kr.name, kr);
207
+ const normalizedName = normalizePath(kr.name);
208
+ const key = normalizedName || kr.name;
209
+ if (!mergedMap.has(key)) {
210
+ mergedMap.set(key, {
211
+ ...kr,
212
+ name: normalizedName,
213
+ _originalName: kr.name
214
+ });
193
215
  } else {
194
- const existing = mergedMap.get(kr.name);
216
+ const existing = mergedMap.get(key);
195
217
  existing._keywordScore = kr._keywordScore;
196
218
  existing._contextMatches = kr._contextMatches;
197
219
  existing._isContextRelevant = kr._isContextRelevant;
package/checksums.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "lib/writeGuard.js": "74213c17149406d8c4f8ca0fb41c4da05e59fc105d9052124c799bd8343ab37d",
5
5
  "lib/rateLimit.js": "c93b1bace6535b75ee6c0f2184c7176dd7b6bc2398cb1f93832b1c7c7374bc1e",
6
6
  "lib/services/context/ContextService.js": "76d595e5b311a8b75a77483c1b35120245a8e4d80186ea648947e84d1f89bae1",
7
- "lib/application/services/ContextServiceV2.js": "032a6a9c67c50ba3a532c0c70dc31661dc599f276032305283cfa0e98930da4b",
7
+ "lib/application/services/ContextServiceV2.js": "808bd0f495e12289e0351f76a0587d80768b7cb36626fba9bbcbdead7b8fe761",
8
8
  "lib/context/adapters/MilvusAdapter.js": "b5438d013b78b73cf4c15d4f480737abe4bc03c82271e949c11702426b57c2c2",
9
9
  "lib/context/adapters/JsonAdapter.js": "49fbd46f32ace04ec0ddac1195b61c16f9906d9047ab5824a8a0cb55ecbcbc4d",
10
10
  "lib/ai/AiFactory.js": "fa759c85afa8014e5c23ed5f30b406619a8412baeb594d62470d2ac3c35d97f3",
@@ -1,4 +1,4 @@
1
- import{n as is,L as Ye,B as Le,H as Ws,W as qs,D as us,Z as Se,C as Be,P as Bs,G as Ks,j as e,h as Ke,i as Vs,k as Fe,F as Xs,l as Js,m as hs,S as Ze,M as ps,o as Ae,p as Ys,q as Qe,s as a,w as $e,x as Ce,y as Zs,z as Me,A as bs,E as Qs,I as et,J as Ue,K as st,T as Oe,N as tt,O as lt,Q as gs,U as at,X as os,Y as fs,$ as js,a0 as nt,a1 as es,a2 as ke,a3 as Je,a4 as Ns,a5 as ys,a6 as rt,a7 as it,a8 as ot,a9 as cs,aa as ct,ab as ss,ac as dt,ad as ds,ae as xt,af as mt,ag as ut,ah as ht,ai as pt,aj as bt,R as gt}from"./vendor-CJtnAZ4B.js";import{a as V}from"./axios-D5GkNzM3.js";import{h as vs,o as ws}from"./syntax-highlighter-4Pe1PNPg.js";import{M as ft}from"./react-markdown-DEEoHGnk.js";import"./yaml-qRaU8Ldn.js";(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const l of document.querySelectorAll('link[rel="modulepreload"]'))d(l);new MutationObserver(l=>{for(const c of l)if(c.type==="childList")for(const y of c.addedNodes)y.tagName==="LINK"&&y.rel==="modulepreload"&&d(y)}).observe(document,{childList:!0,subtree:!0});function w(l){const c={};return l.integrity&&(c.integrity=l.integrity),l.referrerPolicy&&(c.referrerPolicy=l.referrerPolicy),l.crossOrigin==="use-credentials"?c.credentials="include":l.crossOrigin==="anonymous"?c.credentials="omit":c.credentials="same-origin",c}function d(l){if(l.ep)return;l.ep=!0;const c=w(l);fetch(l.href,c)}})();const jt="AutoSnippet";function Nt(s){if(typeof window>"u"||!("Notification"in window))return;const t=()=>{try{new Notification(jt,{body:s,tag:"autosnippet"})}catch{}};if(Notification.permission==="granted"){t();return}Notification.permission!=="denied"&&Notification.requestPermission().then(w=>{w==="granted"&&t()})}function J(s,t){typeof document<"u"&&document.visibilityState==="visible"?(t==null?void 0:t.type)==="error"?is.error(s):is.success(s):Nt(s)}const ve={All:{icon:Ks,color:"text-slate-600",bg:"bg-slate-100",border:"border-slate-200"},View:{icon:Bs,color:"text-pink-600",bg:"bg-pink-50",border:"border-pink-100"},Service:{icon:Be,color:"text-indigo-600",bg:"bg-indigo-50",border:"border-indigo-100"},Tool:{icon:Se,color:"text-amber-600",bg:"bg-amber-50",border:"border-amber-100"},Model:{icon:us,color:"text-emerald-600",bg:"bg-emerald-50",border:"border-emerald-100"},Network:{icon:qs,color:"text-blue-600",bg:"bg-blue-50",border:"border-blue-100"},Storage:{icon:Ws,color:"text-purple-600",bg:"bg-purple-50",border:"border-purple-100"},UI:{icon:Le,color:"text-cyan-600",bg:"bg-cyan-50",border:"border-cyan-100"},Utility:{icon:Ye,color:"text-orange-600",bg:"bg-orange-50",border:"border-orange-100"}},Cs=["All","View","Service","Tool","Model","Network","Storage","UI","Utility"],yt=["snippets","recipes","ai","spm","candidates","depgraph","guard","editor","help"],vt="https://github.com/GxFn/AutoSnippet/issues/new?title=Guard%20误报%2F建议%3A%20&body=请描述误报的规则ID、代码片段或改进建议。",He=s=>["Example","Demo","Sample","Tests","Spec","Mock","Runner"].some(w=>s.endsWith(w)||s.includes(w)),wt=s=>s.startsWith("_"),Ct=s=>s==="_pending",St="您暂无写入权限,无法保存。如需此权限请联系管理员;请勿擅自修改核心代码或安装包,以免影响团队协作与数据安全。";function Ge(s){var l,c;const t=s==null?void 0:s.response;if((t==null?void 0:t.status)!==403)return null;const w=(l=t.data)==null?void 0:l.code,d=(c=t.data)==null?void 0:c.error;return w==="RECIPE_WRITE_FORBIDDEN"||typeof d=="string"&&d.includes("没权限")?St:null}const kt="保存过于频繁,请稍后再试。";function xs(s){var w;const t=s==null?void 0:s.response;return t!=null&&t.data?t.status===403?Ge(s)??null:t.status===429&&((w=t.data)==null?void 0:w.code)==="RECIPE_SAVE_RATE_LIMIT"?kt:null:null}const r={xs:12,sm:14,md:16,lg:20,xl:24,xxl:32,xxxl:48},It=({activeTab:s,navigateToTab:t,handleRefreshProject:w,candidateCount:d,isDarkMode:l=!1})=>e.jsxs("aside",{className:`w-64 ${l?"bg-[#252526] border-r border-[#3e3e42]":"bg-white border-r border-slate-200"} flex flex-col shrink-0`,children:[e.jsxs("div",{className:`p-6 border-b ${l?"border-[#3e3e42]":"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(Ke,{size:r.lg})}),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:()=>t("recipes"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="recipes"?l?"bg-blue-900/30 text-blue-400 font-medium":"bg-blue-50 text-blue-700 font-medium":l?"text-slate-300 hover:bg-slate-700/50":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(Vs,{size:r.lg}),e.jsx("span",{children:"Recipes"})]}),e.jsxs("button",{type:"button",onClick:()=>t("snippets"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="snippets"?l?"bg-blue-900/30 text-blue-400 font-medium":"bg-blue-50 text-blue-700 font-medium":l?"text-slate-300 hover:bg-slate-700/50":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(Fe,{size:r.lg}),e.jsx("span",{children:"Snippets"})]}),e.jsxs("button",{type:"button",onClick:()=>t("spm"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="spm"?l?"bg-blue-900/30 text-blue-400 font-medium":"bg-blue-50 text-blue-700 font-medium":l?"text-slate-300 hover:bg-slate-700/50":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(Xs,{size:r.lg}),e.jsx("span",{children:"SPM Explorer"})]}),e.jsxs("button",{type:"button",onClick:()=>t("candidates"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="candidates"?l?"bg-blue-900/30 text-blue-400 font-medium":"bg-blue-50 text-blue-700 font-medium":l?"text-slate-300 hover:bg-slate-700/50":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(Js,{size:r.lg}),e.jsxs("span",{children:["Candidates (",d,")"]})]}),e.jsxs("button",{type:"button",onClick:()=>t("depgraph"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="depgraph"?l?"bg-blue-900/30 text-blue-400 font-medium":"bg-blue-50 text-blue-700 font-medium":l?"text-slate-300 hover:bg-slate-700/50":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(hs,{size:r.lg}),e.jsx("span",{children:"依赖关系图"})]}),e.jsxs("button",{type:"button",onClick:()=>t("guard"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="guard"?l?"bg-blue-900/30 text-blue-400 font-medium":"bg-blue-50 text-blue-700 font-medium":l?"text-slate-300 hover:bg-slate-700/50":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(Ze,{size:r.lg}),e.jsx("span",{children:"Guard"})]}),e.jsxs("button",{type:"button",onClick:()=>t("ai"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="ai"?l?"bg-blue-900/30 text-blue-400 font-medium":"bg-blue-50 text-blue-700 font-medium":l?"text-slate-300 hover:bg-slate-700/50":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(ps,{size:r.lg}),e.jsx("span",{children:"AI Assistant"})]}),e.jsxs("button",{type:"button",onClick:()=>t("editor"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="editor"?l?"bg-blue-900/30 text-blue-400 font-medium":"bg-blue-50 text-blue-700 font-medium":l?"text-slate-300 hover:bg-slate-700/50":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(Ae,{size:r.lg}),e.jsx("span",{children:"Xcode 编辑器"})]}),e.jsxs("button",{type:"button",onClick:()=>t("help"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="help"?l?"bg-blue-900/30 text-blue-400 font-medium":"bg-blue-50 text-blue-700 font-medium":l?"text-slate-300 hover:bg-slate-700/50":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(Ys,{size:r.lg}),e.jsx("span",{children:"使用说明"})]})]}),e.jsx("div",{className:`p-4 ${l?"border-t border-[#3e3e42]":"border-t border-slate-100"}`,children:e.jsxs("button",{onClick:w,className:`w-full flex items-center justify-center gap-2 text-[10px] font-bold ${l?"text-slate-400 hover:text-blue-400":"text-slate-400 hover:text-blue-600"} uppercase transition-colors`,children:[e.jsx(Qe,{size:r.xs})," Refresh Project"]})})]}),zt=({searchQuery:s,setSearchQuery:t,setShowCreateModal:w,handleSyncToXcode:d,aiConfig:l,onSemanticSearchResults:c,onBeforeAiSwitch:y,onAiConfigChange:p,isDarkMode:m=!1})=>{const[S,v]=a.useState(!1),[x,h]=a.useState(!1),[T,K]=a.useState([]),[ee,re]=a.useState(!1),F=a.useRef(null);a.useEffect(()=>{x&&T.length===0&&V.get("/api/ai/providers").then(N=>K(N.data)).catch(()=>{})},[x,T.length]),a.useEffect(()=>{const N=R=>{F.current&&!F.current.contains(R.target)&&h(!1)};return document.addEventListener("click",N),()=>document.removeEventListener("click",N)},[]);const W=async()=>{if(s){v(!0);try{const N=await V.post("/api/search/semantic",{keyword:s});c&&c(N.data)}catch(N){console.error("Semantic search failed",N),alert("语义搜索失败。请确保已运行 asd embed 构建索引。")}finally{v(!1)}}},u=async N=>{re(!0);try{y==null||y(),await V.post("/api/ai/config",{provider:N.id,model:N.defaultModel}),h(!1),p&&p()}catch(R){console.error("AI config update failed",R),alert("切换 AI 失败,请检查项目根目录是否可写。")}finally{re(!1)}};return e.jsxs("header",{className:`h-16 ${m?"bg-[#252526] border-b border-[#3e3e42]":"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($e,{className:`absolute left-3 top-1/2 -translate-y-1/2 ${m?"text-slate-500":"text-slate-400"}`,size:r.md}),e.jsx("input",{type:"text",placeholder:"Search knowledge...",className:`w-full pl-10 pr-4 py-2 ${m?"bg-[#1e1e1e] text-slate-300 placeholder-slate-500":"bg-slate-100 text-slate-900"} border-transparent rounded-lg text-sm outline-none focus:ring-2 focus:ring-blue-500/20 transition-all`,value:s,onChange:N=>t(N.target.value),onKeyDown:N=>N.key==="Enter"&&W()})]}),e.jsxs("button",{onClick:W,disabled:!s||S,className:`flex items-center gap-2 px-3 py-2 rounded-lg text-xs font-bold transition-all ${S?"bg-blue-50 text-blue-400":"bg-blue-50 text-blue-600 hover:bg-blue-100"}`,title:"Semantic Search (Brain AI)",children:[S?e.jsx(Ce,{size:r.sm,className:"animate-spin"}):e.jsx(Zs,{size:r.sm}),"Semantic"]})]}),e.jsxs("div",{className:"flex items-center gap-4",children:[l&&e.jsxs("div",{className:"relative",ref:F,children:[e.jsxs("button",{type:"button",onClick:N=>{N.stopPropagation(),h(R=>!R)},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(Be,{size:r.sm}),l.provider," / ",l.model,e.jsx(Me,{size:r.xs,className:x?"rotate-180":""})]}),x&&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 读取"}),T.length===0?e.jsx("div",{className:"px-3 py-2 text-xs text-slate-400",children:"加载中..."}):T.map(N=>e.jsxs("button",{type:"button",disabled:ee,onClick:()=>u(N),className:`w-full text-left px-3 py-2 text-sm hover:bg-slate-50 flex items-center justify-between ${l.provider===N.id?"bg-blue-50 text-blue-700 font-medium":"text-slate-700"}`,children:[e.jsx("span",{children:N.label}),l.provider===N.id&&e.jsx("span",{className:"text-xs",children:"✓"})]},N.id))]})]}),e.jsxs("button",{onClick:()=>w(!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(bs,{size:r.md})," New Recipe"]}),e.jsxs("button",{onClick:d,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(Qe,{size:r.md})," Sync to Xcode"]})]})]})},$t=({selectedCategory:s,setSelectedCategory:t})=>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(ve).map(([w,d])=>{const l=d.icon,c=s===w;return e.jsxs("button",{onClick:()=>t(w),className:`flex items-center gap-1.5 px-3 py-1.5 rounded-full text-[10px] font-bold transition-all border whitespace-nowrap
1
+ import{n as is,L as Ye,B as Le,H as Ws,W as qs,D as us,Z as Se,C as Be,P as Bs,G as Ks,j as e,h as Ke,i as Vs,k as Fe,F as Xs,l as Js,m as hs,S as Ze,M as ps,o as Ae,p as Ys,q as Qe,s as a,w as $e,x as Ce,y as Zs,z as Me,A as bs,E as Qs,I as et,J as Ue,K as st,T as Oe,N as tt,O as lt,Q as gs,U as at,X as os,Y as fs,$ as js,a0 as nt,a1 as es,a2 as ke,a3 as Je,a4 as Ns,a5 as ys,a6 as rt,a7 as it,a8 as ot,a9 as cs,aa as ct,ab as ss,ac as dt,ad as ds,ae as xt,af as mt,ag as ut,ah as ht,ai as pt,aj as bt,R as gt}from"./vendor-CJtnAZ4B.js";import{a as V}from"./axios-D5GkNzM3.js";import{h as vs,o as ws}from"./syntax-highlighter-4Pe1PNPg.js";import{M as ft}from"./react-markdown-DEEoHGnk.js";import"./yaml-qRaU8Ldn.js";(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const l of document.querySelectorAll('link[rel="modulepreload"]'))d(l);new MutationObserver(l=>{for(const c of l)if(c.type==="childList")for(const y of c.addedNodes)y.tagName==="LINK"&&y.rel==="modulepreload"&&d(y)}).observe(document,{childList:!0,subtree:!0});function w(l){const c={};return l.integrity&&(c.integrity=l.integrity),l.referrerPolicy&&(c.referrerPolicy=l.referrerPolicy),l.crossOrigin==="use-credentials"?c.credentials="include":l.crossOrigin==="anonymous"?c.credentials="omit":c.credentials="same-origin",c}function d(l){if(l.ep)return;l.ep=!0;const c=w(l);fetch(l.href,c)}})();const jt="AutoSnippet";function Nt(s){if(typeof window>"u"||!("Notification"in window))return;const t=()=>{try{new Notification(jt,{body:s,tag:"autosnippet"})}catch{}};if(Notification.permission==="granted"){t();return}Notification.permission!=="denied"&&Notification.requestPermission().then(w=>{w==="granted"&&t()})}function J(s,t){typeof document<"u"&&document.visibilityState==="visible"?(t==null?void 0:t.type)==="error"?is.error(s):is.success(s):Nt(s)}const ve={All:{icon:Ks,color:"text-slate-600",bg:"bg-slate-100",border:"border-slate-200"},View:{icon:Bs,color:"text-pink-600",bg:"bg-pink-50",border:"border-pink-100"},Service:{icon:Be,color:"text-indigo-600",bg:"bg-indigo-50",border:"border-indigo-100"},Tool:{icon:Se,color:"text-amber-600",bg:"bg-amber-50",border:"border-amber-100"},Model:{icon:us,color:"text-emerald-600",bg:"bg-emerald-50",border:"border-emerald-100"},Network:{icon:qs,color:"text-blue-600",bg:"bg-blue-50",border:"border-blue-100"},Storage:{icon:Ws,color:"text-purple-600",bg:"bg-purple-50",border:"border-purple-100"},UI:{icon:Le,color:"text-cyan-600",bg:"bg-cyan-50",border:"border-cyan-100"},Utility:{icon:Ye,color:"text-orange-600",bg:"bg-orange-50",border:"border-orange-100"}},Cs=["All","View","Service","Tool","Model","Network","Storage","UI","Utility"],yt=["snippets","recipes","ai","spm","candidates","depgraph","guard","editor","help"],vt="https://github.com/GxFn/AutoSnippet/issues/new?title=Guard%20误报%2F建议%3A%20&body=请描述误报的规则ID、代码片段或改进建议。",He=s=>["Example","Demo","Sample","Tests","Spec","Mock","Runner"].some(w=>s.endsWith(w)||s.includes(w)),wt=s=>s.startsWith("_"),Ct=s=>s==="_pending",St="您暂无写入权限,无法保存。如需此权限请联系管理员;请勿擅自修改核心代码或安装包,以免影响团队协作与数据安全。";function Ge(s){var l,c;const t=s==null?void 0:s.response;if((t==null?void 0:t.status)!==403)return null;const w=(l=t.data)==null?void 0:l.code,d=(c=t.data)==null?void 0:c.error;return w==="RECIPE_WRITE_FORBIDDEN"||typeof d=="string"&&d.includes("没权限")?St:null}const kt="保存过于频繁,请稍后再试。";function xs(s){var w;const t=s==null?void 0:s.response;return t!=null&&t.data?t.status===403?Ge(s)??null:t.status===429&&((w=t.data)==null?void 0:w.code)==="RECIPE_SAVE_RATE_LIMIT"?kt:null:null}const r={xs:12,sm:14,md:16,lg:20,xl:24,xxl:32,xxxl:48},It=({activeTab:s,navigateToTab:t,handleRefreshProject:w,candidateCount:d,isDarkMode:l=!1})=>e.jsxs("aside",{className:`w-64 ${l?"bg-[#252526] border-r border-[#3e3e42]":"bg-white border-r border-slate-200"} flex flex-col shrink-0`,children:[e.jsxs("div",{className:`p-6 border-b ${l?"border-[#3e3e42]":"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(Ke,{size:r.lg})}),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:()=>t("recipes"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="recipes"?l?"bg-blue-900/30 text-blue-400 font-medium":"bg-blue-50 text-blue-700 font-medium":l?"text-slate-300 hover:bg-slate-700/50":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(Vs,{size:r.lg}),e.jsx("span",{children:"Recipes"})]}),e.jsxs("button",{type:"button",onClick:()=>t("snippets"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="snippets"?l?"bg-blue-900/30 text-blue-400 font-medium":"bg-blue-50 text-blue-700 font-medium":l?"text-slate-300 hover:bg-slate-700/50":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(Fe,{size:r.lg}),e.jsx("span",{children:"Snippets"})]}),e.jsxs("button",{type:"button",onClick:()=>t("spm"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="spm"?l?"bg-blue-900/30 text-blue-400 font-medium":"bg-blue-50 text-blue-700 font-medium":l?"text-slate-300 hover:bg-slate-700/50":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(Xs,{size:r.lg}),e.jsx("span",{children:"SPM Explorer"})]}),e.jsxs("button",{type:"button",onClick:()=>t("candidates"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="candidates"?l?"bg-blue-900/30 text-blue-400 font-medium":"bg-blue-50 text-blue-700 font-medium":l?"text-slate-300 hover:bg-slate-700/50":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(Js,{size:r.lg}),e.jsxs("span",{children:["Candidates (",d,")"]})]}),e.jsxs("button",{type:"button",onClick:()=>t("depgraph"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="depgraph"?l?"bg-blue-900/30 text-blue-400 font-medium":"bg-blue-50 text-blue-700 font-medium":l?"text-slate-300 hover:bg-slate-700/50":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(hs,{size:r.lg}),e.jsx("span",{children:"依赖关系图"})]}),e.jsxs("button",{type:"button",onClick:()=>t("guard"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="guard"?l?"bg-blue-900/30 text-blue-400 font-medium":"bg-blue-50 text-blue-700 font-medium":l?"text-slate-300 hover:bg-slate-700/50":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(Ze,{size:r.lg}),e.jsx("span",{children:"Guard"})]}),e.jsxs("button",{type:"button",onClick:()=>t("ai"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="ai"?l?"bg-blue-900/30 text-blue-400 font-medium":"bg-blue-50 text-blue-700 font-medium":l?"text-slate-300 hover:bg-slate-700/50":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(ps,{size:r.lg}),e.jsx("span",{children:"AI Assistant"})]}),e.jsxs("button",{type:"button",onClick:()=>t("editor"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="editor"?l?"bg-blue-900/30 text-blue-400 font-medium":"bg-blue-50 text-blue-700 font-medium":l?"text-slate-300 hover:bg-slate-700/50":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(Ae,{size:r.lg}),e.jsx("span",{children:"编辑器(测试)"})]}),e.jsxs("button",{type:"button",onClick:()=>t("help"),className:`w-full flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${s==="help"?l?"bg-blue-900/30 text-blue-400 font-medium":"bg-blue-50 text-blue-700 font-medium":l?"text-slate-300 hover:bg-slate-700/50":"text-slate-600 hover:bg-slate-50"}`,children:[e.jsx(Ys,{size:r.lg}),e.jsx("span",{children:"使用说明"})]})]}),e.jsx("div",{className:`p-4 ${l?"border-t border-[#3e3e42]":"border-t border-slate-100"}`,children:e.jsxs("button",{onClick:w,className:`w-full flex items-center justify-center gap-2 text-[10px] font-bold ${l?"text-slate-400 hover:text-blue-400":"text-slate-400 hover:text-blue-600"} uppercase transition-colors`,children:[e.jsx(Qe,{size:r.xs})," Refresh Project"]})})]}),zt=({searchQuery:s,setSearchQuery:t,setShowCreateModal:w,handleSyncToXcode:d,aiConfig:l,onSemanticSearchResults:c,onBeforeAiSwitch:y,onAiConfigChange:p,isDarkMode:m=!1})=>{const[S,v]=a.useState(!1),[x,h]=a.useState(!1),[T,K]=a.useState([]),[ee,re]=a.useState(!1),F=a.useRef(null);a.useEffect(()=>{x&&T.length===0&&V.get("/api/ai/providers").then(N=>K(N.data)).catch(()=>{})},[x,T.length]),a.useEffect(()=>{const N=R=>{F.current&&!F.current.contains(R.target)&&h(!1)};return document.addEventListener("click",N),()=>document.removeEventListener("click",N)},[]);const W=async()=>{if(s){v(!0);try{const N=await V.post("/api/search/semantic",{keyword:s});c&&c(N.data)}catch(N){console.error("Semantic search failed",N),alert("语义搜索失败。请确保已运行 asd embed 构建索引。")}finally{v(!1)}}},u=async N=>{re(!0);try{y==null||y(),await V.post("/api/ai/config",{provider:N.id,model:N.defaultModel}),h(!1),p&&p()}catch(R){console.error("AI config update failed",R),alert("切换 AI 失败,请检查项目根目录是否可写。")}finally{re(!1)}};return e.jsxs("header",{className:`h-16 ${m?"bg-[#252526] border-b border-[#3e3e42]":"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($e,{className:`absolute left-3 top-1/2 -translate-y-1/2 ${m?"text-slate-500":"text-slate-400"}`,size:r.md}),e.jsx("input",{type:"text",placeholder:"Search knowledge...",className:`w-full pl-10 pr-4 py-2 ${m?"bg-[#1e1e1e] text-slate-300 placeholder-slate-500":"bg-slate-100 text-slate-900"} border-transparent rounded-lg text-sm outline-none focus:ring-2 focus:ring-blue-500/20 transition-all`,value:s,onChange:N=>t(N.target.value),onKeyDown:N=>N.key==="Enter"&&W()})]}),e.jsxs("button",{onClick:W,disabled:!s||S,className:`flex items-center gap-2 px-3 py-2 rounded-lg text-xs font-bold transition-all ${S?"bg-blue-50 text-blue-400":"bg-blue-50 text-blue-600 hover:bg-blue-100"}`,title:"Semantic Search (Brain AI)",children:[S?e.jsx(Ce,{size:r.sm,className:"animate-spin"}):e.jsx(Zs,{size:r.sm}),"Semantic"]})]}),e.jsxs("div",{className:"flex items-center gap-4",children:[l&&e.jsxs("div",{className:"relative",ref:F,children:[e.jsxs("button",{type:"button",onClick:N=>{N.stopPropagation(),h(R=>!R)},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(Be,{size:r.sm}),l.provider," / ",l.model,e.jsx(Me,{size:r.xs,className:x?"rotate-180":""})]}),x&&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 读取"}),T.length===0?e.jsx("div",{className:"px-3 py-2 text-xs text-slate-400",children:"加载中..."}):T.map(N=>e.jsxs("button",{type:"button",disabled:ee,onClick:()=>u(N),className:`w-full text-left px-3 py-2 text-sm hover:bg-slate-50 flex items-center justify-between ${l.provider===N.id?"bg-blue-50 text-blue-700 font-medium":"text-slate-700"}`,children:[e.jsx("span",{children:N.label}),l.provider===N.id&&e.jsx("span",{className:"text-xs",children:"✓"})]},N.id))]})]}),e.jsxs("button",{onClick:()=>w(!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(bs,{size:r.md})," New Recipe"]}),e.jsxs("button",{onClick:d,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(Qe,{size:r.md})," Sync to Xcode"]})]})]})},$t=({selectedCategory:s,setSelectedCategory:t})=>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(ve).map(([w,d])=>{const l=d.icon,c=s===w;return e.jsxs("button",{onClick:()=>t(w),className:`flex items-center gap-1.5 px-3 py-1.5 rounded-full text-[10px] font-bold transition-all border whitespace-nowrap
2
2
  ${c?`${d.bg} ${d.color} ${d.border} shadow-sm scale-105`:"bg-white text-slate-400 border-slate-100 hover:border-slate-200 hover:text-slate-600"}`,children:[e.jsx(l,{size:r.xs}),w]},w)})})}),ts=({currentPage:s,totalPages:t,totalItems:w,pageSize:d,onPageChange:l,onPageSizeChange:c,pageSizeOptions:y=[12,24,48,96]})=>{if(t<=1&&w<=y[0])return null;const p=(s-1)*d+1,m=Math.min(s*d,w),S=()=>{const v=[];if(t<=7)for(let h=1;h<=t;h++)v.push(h);else if(s<=3){for(let h=1;h<=5;h++)v.push(h);v.push("..."),v.push(t)}else if(s>=t-2){v.push(1),v.push("...");for(let h=t-5+1;h<=t;h++)v.push(h)}else{v.push(1),v.push("...");for(let h=s-1;h<=s+1;h++)v.push(h);v.push("..."),v.push(t)}return v};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:["显示 ",p,"-",m,",共 ",w," 条"]}),c&&e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-sm text-slate-500",children:"每页"}),e.jsx("select",{value:d,onChange:v=>c(Number(v.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:y.map(v=>e.jsx("option",{value:v,children:v},v))}),e.jsx("span",{className:"text-sm text-slate-500",children:"条"})]})]}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx("button",{onClick:()=>l(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(Qs,{size:r.md,className:"text-slate-600"})}),e.jsx("button",{onClick:()=>l(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(et,{size:r.md,className:"text-slate-600"})}),e.jsx("div",{className:"flex items-center gap-1 mx-2",children:S().map((v,x)=>typeof v=="number"?e.jsx("button",{onClick:()=>l(v),className:`min-w-[32px] h-8 px-2 rounded-md text-sm font-medium transition-colors ${s===v?"bg-blue-600 text-white":"hover:bg-slate-100 text-slate-600"}`,children:v},x):e.jsx("span",{className:"px-1 text-slate-400",children:v},x))}),e.jsx("button",{onClick:()=>l(s+1),disabled:s===t,className:"p-1.5 rounded-md hover:bg-slate-100 disabled:opacity-30 disabled:cursor-not-allowed transition-colors",title:"下一页",children:e.jsx(Ue,{size:r.md,className:"text-slate-600"})}),e.jsx("button",{onClick:()=>l(t),disabled:s===t,className:"p-1.5 rounded-md hover:bg-slate-100 disabled:opacity-30 disabled:cursor-not-allowed transition-colors",title:"最后一页",children:e.jsx(st,{size:r.md,className:"text-slate-600"})})]})]})},_t=({snippets:s,openSnippetEdit:t,handleDeleteSnippet:w})=>{const[d,l]=a.useState(1),[c,y]=a.useState(12);a.useEffect(()=>{l(1)},[s.length]);const p=Math.ceil(s.length/c),m=(d-1)*c,S=s.slice(m,m+c),v=h=>{l(h),window.scrollTo({top:0,behavior:"smooth"})},x=h=>{y(h),l(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:S.map(h=>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:T=>{T.stopPropagation(),t(h)},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(Ae,{size:r.sm})}),e.jsx("button",{onClick:T=>{T.stopPropagation(),w(h.identifier,h.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(Oe,{size:r.sm})})]}),e.jsxs("div",{onClick:()=>t(h),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:h.title}),e.jsxs("div",{className:"flex flex-col items-end gap-1",children:[h.completionKey&&e.jsx("span",{className:"text-[10px] bg-blue-50 text-blue-700 font-bold px-2 py-1 rounded uppercase tracking-wider",children:h.completionKey}),(()=>{const T=h.category||"Utility",K=ve[T]||ve.Utility,ee=K.icon;return e.jsxs("span",{className:`text-[8px] font-bold px-1.5 py-0.5 rounded uppercase flex items-center gap-1 border ${K.bg} ${K.color} ${K.border}`,children:[e.jsx(ee,{size:r.xs}),T]})})()]})]}),e.jsx("p",{className:"text-sm text-slate-600 line-clamp-2 mb-4",children:h.summary}),e.jsx("div",{className:"flex items-center gap-2",children:h.language&&e.jsx("span",{className:"text-xs font-medium text-slate-400 bg-slate-100 px-2 py-1 rounded",children:h.language})})]})]},h.identifier))}),e.jsx(ts,{currentPage:d,totalPages:p,totalItems:s.length,pageSize:c,onPageChange:v,onPageSizeChange:x})]})},At=({recipes:s,openRecipeEdit:t,handleDeleteRecipe:w,currentPage:d,onPageChange:l,pageSize:c,onPageSizeChange:y})=>{const[p,m]=a.useState(1),[S,v]=a.useState(12),x=d??p,h=c??S,T=l??m,K=y?u=>y(u):u=>{v(u),m(1)};a.useEffect(()=>{d==null&&m(1)},[s.length,d]);const ee=Math.ceil(s.length/h),re=(x-1)*h,F=s.slice(re,re+h),W=u=>{T(u),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:F.map(u=>{var N,R;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:O=>{O.stopPropagation(),t(u)},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(Ae,{size:r.sm})}),e.jsx("button",{onClick:O=>{O.stopPropagation(),w(u.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(Oe,{size:r.sm})})]}),e.jsxs("div",{onClick:()=>t(u),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:u.name}),e.jsxs("div",{className:"flex items-center gap-2",children:[(()=>{var M,E;const O=((E=(M=u.content.match(/category:\s*(.*)/))==null?void 0:M[1])==null?void 0:E.trim())||"Utility",se=ve[O]||ve.Utility,le=se.icon;return e.jsxs("span",{className:`text-[8px] font-bold px-1.5 py-0.5 rounded uppercase flex items-center gap-1 border ${se.bg} ${se.color} ${se.border}`,children:[e.jsx(le,{size:r.xs}),O]})})(),u.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:["权威 ",u.stats!=null?u.stats.authority:"—"]}),e.jsx("span",{children:"·"}),e.jsx("span",{children:u.stats!=null?`g:${u.stats.guardUsageCount} h:${u.stats.humanUsageCount} a:${u.stats.aiUsageCount}`:"g:0 h:0 a:0"}),e.jsx("span",{children:"·"}),e.jsxs("span",{children:["综合分 ",((N=u.stats)==null?void 0:N.authorityScore)!=null?u.stats.authorityScore.toFixed(2):"—"]}),((R=u.stats)==null?void 0:R.lastUsedAt)&&e.jsxs(e.Fragment,{children:[e.jsx("span",{children:"·"}),e.jsxs("span",{children:["最近 ",new Date(u.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:u.content})]})]},u.name)})}),e.jsx(ts,{currentPage:x,totalPages:ee,totalItems:s.length,pageSize:h,onPageChange:W,onPageSizeChange:K})]})},Rt=()=>{const[s,t]=a.useState(new Set(["quick-start"])),w=l=>{const c=new Set(s);c.has(l)?c.delete(l):c.add(l),t(c)},d=({id:l,title:c,icon:y,children:p})=>{const m=s.has(l);return e.jsxs("section",{className:"border border-slate-200 rounded-lg overflow-hidden",children:[e.jsxs("button",{onClick:()=>w(l),className:"w-full flex items-center justify-between p-4 bg-slate-50 hover:bg-slate-100 transition-colors",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[y,e.jsx("h2",{className:"text-lg font-bold text-slate-800",children:c})]}),m?e.jsx(Me,{size:r.lg}):e.jsx(Ue,{size:r.lg})]}),m&&e.jsx("div",{className:"p-4 bg-white",children:p})]})};return e.jsxs("div",{className:"max-w-5xl mx-auto py-8 px-4",children:[e.jsxs("div",{className:"mb-8 text-center",children:[e.jsxs("h1",{className:"text-4xl font-bold text-slate-900 mb-4 flex items-center justify-center gap-3",children:[e.jsx(tt,{size:r.xxl,className:"text-blue-600"}),"AutoSnippet 使用说明"]}),e.jsx("p",{className:"text-slate-600 text-lg max-w-3xl mx-auto",children:"连接开发者、AI 与项目知识库:人工审核沉淀标准,知识库存储 Recipe + Snippet,AI 按规范生成代码"}),e.jsxs("div",{className:"mt-6 flex gap-4 justify-center text-sm",children:[e.jsx("a",{href:"https://github.com/GxFn/AutoSnippet",target:"_blank",rel:"noopener noreferrer",className:"px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors",children:"查看 GitHub"}),e.jsx("a",{href:"/docs/USER_MANUAL.md",target:"_blank",rel:"noopener noreferrer",className:"px-4 py-2 border border-slate-300 text-slate-700 rounded-lg hover:bg-slate-50 transition-colors",children:"完整文档"})]})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsx(d,{id:"quick-start",title:"快速开始",icon:e.jsx(lt,{size:r.xl,className:"text-blue-600"}),children:e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-4",children:[e.jsxs("div",{className:"bg-blue-50 rounded-lg p-4 border border-blue-200",children:[e.jsx("div",{className:"bg-blue-600 text-white rounded-full w-8 h-8 flex items-center justify-center mb-3 font-bold",children:"1"}),e.jsx("h3",{className:"font-semibold text-slate-800 mb-2",children:"安装与初始化"}),e.jsx("pre",{className:"bg-slate-100 px-3 py-2 rounded text-xs overflow-x-auto",children:e.jsxs("code",{children:["npm install -g autosnippet",`
3
3
  `,"asd setup",`
4
4
  `,"asd ui"]})})]}),e.jsxs("div",{className:"bg-green-50 rounded-lg p-4 border border-green-200",children:[e.jsx("div",{className:"bg-green-600 text-white rounded-full w-8 h-8 flex items-center justify-center mb-3 font-bold",children:"2"}),e.jsx("h3",{className:"font-semibold text-slate-800 mb-2",children:"创建第一个 Recipe"}),e.jsxs("p",{className:"text-slate-600 text-sm mb-2",children:["点击顶部 ",e.jsx("strong",{children:"New Recipe"})]}),e.jsxs("p",{className:"text-slate-600 text-sm",children:["选择 ",e.jsx("strong",{children:"Use Copied Code"})]}),e.jsx("p",{className:"text-slate-600 text-sm",children:"复制代码 → AI 填充 → 保存"})]}),e.jsxs("div",{className:"bg-purple-50 rounded-lg p-4 border border-purple-200",children:[e.jsx("div",{className:"bg-purple-600 text-white rounded-full w-8 h-8 flex items-center justify-center mb-3 font-bold",children:"3"}),e.jsx("h3",{className:"font-semibold text-slate-800 mb-2",children:"同步到 Xcode"}),e.jsx("pre",{className:"bg-slate-100 px-3 py-2 rounded text-xs mb-2",children:e.jsx("code",{children:"asd extract"})}),e.jsxs("p",{className:"text-slate-600 text-sm",children:["在 Xcode 输入 ",e.jsx("code",{className:"bg-slate-200 px-1 rounded",children:"@trigger"})," 补全"]})]})]})}),e.jsxs(d,{id:"concepts",title:"核心概念",icon:e.jsx(us,{size:r.xl,className:"text-blue-600"}),children:[e.jsxs("div",{className:"mb-6",children:[e.jsx("h3",{className:"text-lg font-semibold text-slate-700 mb-3",children:"三大角色"}),e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"min-w-full border border-slate-200 rounded-lg text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"bg-slate-50",children:[e.jsx("th",{className:"px-4 py-3 border-b text-left font-semibold",children:"角色"}),e.jsx("th",{className:"px-4 py-3 border-b text-left font-semibold",children:"职责"}),e.jsx("th",{className:"px-4 py-3 border-b text-left font-semibold",children:"能力"})]})}),e.jsxs("tbody",{children:[e.jsxs("tr",{className:"hover:bg-slate-50",children:[e.jsx("td",{className:"px-4 py-3 border-b font-medium text-blue-700",children:"开发者"}),e.jsx("td",{className:"px-4 py-3 border-b",children:"审核与决策、维护项目标准"}),e.jsxs("td",{className:"px-4 py-3 border-b text-xs",children:["Dashboard 审核候选、保存 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 ui"})]})]}),e.jsxs("tr",{className:"hover:bg-slate-50",children:[e.jsx("td",{className:"px-4 py-3 border-b font-medium text-green-700",children:"Cursor Agent"}),e.jsx("td",{className:"px-4 py-3 border-b",children:"按规范生成代码、检索知识库"}),e.jsx("td",{className:"px-4 py-3 border-b text-xs",children:"Skills 理解规范;MCP 工具按需检索、提交候选;不直接修改知识库"})]}),e.jsxs("tr",{className:"hover:bg-slate-50",children:[e.jsx("td",{className:"px-4 py-3 font-medium text-purple-700",children:"项目内 AI"}),e.jsx("td",{className:"px-4 py-3",children:"提取、摘要、扫描、审查"}),e.jsxs("td",{className:"px-4 py-3 text-xs",children:[e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd ais"})," 批量扫描;分析剪贴板;Guard 审查;Dashboard RAG"]})]})]})]})})]}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-lg font-semibold text-slate-700 mb-3",children:"四大组件"}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[e.jsxs("div",{className:"bg-blue-50 rounded-lg p-4 border border-blue-200",children:[e.jsxs("h4",{className:"font-semibold text-blue-900 mb-2 flex items-center gap-2",children:[e.jsx(gs,{size:r.lg}),"Recipe(配方)"]}),e.jsx("p",{className:"text-blue-800 text-sm mb-3",children:"Markdown 格式的知识文档"}),e.jsxs("ul",{className:"text-blue-700 text-xs space-y-1 list-disc list-inside",children:[e.jsxs("li",{children:["位置:",e.jsx("code",{className:"bg-blue-100 px-1 rounded",children:"AutoSnippet/recipes/*.md"})]}),e.jsxs("li",{children:["优先级:",e.jsx("strong",{children:"最高"}),",项目第一标准"]}),e.jsx("li",{children:"用途:为 Cursor、Guard、搜索提供上下文"})]})]}),e.jsxs("div",{className:"bg-green-50 rounded-lg p-4 border border-green-200",children:[e.jsxs("h4",{className:"font-semibold text-green-900 mb-2 flex items-center gap-2",children:[e.jsx(Se,{size:r.lg}),"Snippet(代码片段)"]}),e.jsx("p",{className:"text-green-800 text-sm mb-3",children:"Xcode 代码补全片段"}),e.jsxs("ul",{className:"text-green-700 text-xs space-y-1 list-disc list-inside",children:[e.jsxs("li",{children:["位置:",e.jsx("code",{className:"bg-green-100 px-1 rounded",children:"AutoSnippet/snippets/*.json"})]}),e.jsx("li",{children:"触发:在 Xcode 输入 trigger 自动补全"}),e.jsx("li",{children:"关联:通常与 Recipe 一一对应"})]})]}),e.jsxs("div",{className:"bg-purple-50 rounded-lg p-4 border border-purple-200",children:[e.jsxs("h4",{className:"font-semibold text-purple-900 mb-2 flex items-center gap-2",children:[e.jsx($e,{size:r.lg}),"向量索引(Context)"]}),e.jsx("p",{className:"text-purple-800 text-sm mb-3",children:"语义搜索引擎"}),e.jsxs("ul",{className:"text-purple-700 text-xs space-y-1 list-disc list-inside",children:[e.jsxs("li",{children:["位置:",e.jsx("code",{className:"bg-purple-100 px-1 rounded",children:".autosnippet/context/"})]}),e.jsxs("li",{children:["生成:",e.jsx("code",{className:"bg-purple-100 px-1 rounded",children:"asd embed"})," 或启动时自动"]}),e.jsx("li",{children:"用途:语义搜索、相似度匹配、个性化推荐"})]})]}),e.jsxs("div",{className:"bg-amber-50 rounded-lg p-4 border border-amber-200",children:[e.jsxs("h4",{className:"font-semibold text-amber-900 mb-2 flex items-center gap-2",children:[e.jsx(at,{size:r.lg}),"Candidates(候选)"]}),e.jsx("p",{className:"text-amber-800 text-sm mb-3",children:"待审核的 Recipe 草案"}),e.jsxs("ul",{className:"text-amber-700 text-xs space-y-1 list-disc list-inside",children:[e.jsxs("li",{children:["位置:",e.jsx("code",{className:"bg-amber-100 px-1 rounded",children:"candidates.json"})]}),e.jsx("li",{children:"来源:AI 扫描、Cursor、剪贴板、Dashboard"}),e.jsx("li",{children:"用途:人工审核后入库,确保质量"})]})]})]})]}),e.jsxs("div",{className:"mt-6 bg-gradient-to-r from-blue-50 to-purple-50 rounded-lg p-5 border border-slate-200",children:[e.jsx("h3",{className:"text-lg font-semibold text-slate-700 mb-4",children:"知识库闭环"}),e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[e.jsxs("div",{className:"flex-1 min-w-[100px] text-center",children:[e.jsx("div",{className:"bg-blue-500 text-white rounded-full w-10 h-10 flex items-center justify-center mx-auto mb-2 font-bold text-lg",children:"1"}),e.jsx("p",{className:"text-slate-700 font-medium text-sm",children:"扫描提取"}),e.jsx("p",{className:"text-slate-500 text-xs",children:"AI/Cursor"})]}),e.jsx("div",{className:"text-slate-400 text-2xl",children:"→"}),e.jsxs("div",{className:"flex-1 min-w-[100px] text-center",children:[e.jsx("div",{className:"bg-green-500 text-white rounded-full w-10 h-10 flex items-center justify-center mx-auto mb-2 font-bold text-lg",children:"2"}),e.jsx("p",{className:"text-slate-700 font-medium text-sm",children:"人工审核"}),e.jsx("p",{className:"text-slate-500 text-xs",children:"Dashboard"})]}),e.jsx("div",{className:"text-slate-400 text-2xl",children:"→"}),e.jsxs("div",{className:"flex-1 min-w-[100px] text-center",children:[e.jsx("div",{className:"bg-purple-500 text-white rounded-full w-10 h-10 flex items-center justify-center mx-auto mb-2 font-bold text-lg",children:"3"}),e.jsx("p",{className:"text-slate-700 font-medium text-sm",children:"知识沉淀"}),e.jsx("p",{className:"text-slate-500 text-xs",children:"入库"})]}),e.jsx("div",{className:"text-slate-400 text-2xl",children:"→"}),e.jsxs("div",{className:"flex-1 min-w-[100px] text-center",children:[e.jsx("div",{className:"bg-amber-500 text-white rounded-full w-10 h-10 flex items-center justify-center mx-auto mb-2 font-bold text-lg",children:"4"}),e.jsx("p",{className:"text-slate-700 font-medium text-sm",children:"智能使用"}),e.jsx("p",{className:"text-slate-500 text-xs",children:"Cursor/Xcode"})]}),e.jsx("div",{className:"text-slate-400 text-2xl",children:"→"}),e.jsxs("div",{className:"flex-1 min-w-[100px] text-center",children:[e.jsx("div",{className:"bg-rose-500 text-white rounded-full w-10 h-10 flex items-center justify-center mx-auto mb-2 font-bold text-lg",children:"5"}),e.jsx("p",{className:"text-slate-700 font-medium text-sm",children:"持续优化"}),e.jsx("p",{className:"text-slate-500 text-xs",children:"评分排序"})]})]})]})]}),e.jsx(d,{id:"features",title:"核心功能",icon:e.jsx(Se,{size:r.xl,className:"text-blue-600"}),children:e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-5",children:[e.jsxs("div",{className:"border border-slate-200 rounded-lg p-5 hover:shadow-lg transition-shadow",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-3",children:[e.jsx(Ke,{size:r.lg,className:"text-blue-600"}),e.jsx("h3",{className:"font-semibold text-slate-800",children:"知识库构建"})]}),e.jsxs("ul",{className:"text-slate-600 text-sm space-y-2 list-disc list-inside",children:[e.jsxs("li",{children:[e.jsx("strong",{children:"AI 扫描"}),":",e.jsx("code",{className:"bg-slate-100 px-1 rounded text-xs",children:"asd ais [Target]"})," 批量提取"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"Cursor 扫描"}),':对 Copilot 说 "扫描 Module"']}),e.jsxs("li",{children:[e.jsx("strong",{children:"手动创建"}),":New Recipe → Use Copied Code"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"编辑器内"}),":复制代码 → ",e.jsx("code",{className:"bg-slate-100 px-1 rounded text-xs",children:"// as:create -c"})]})]})]}),e.jsxs("div",{className:"border border-slate-200 rounded-lg p-5 hover:shadow-lg transition-shadow",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-3",children:[e.jsx($e,{size:r.lg,className:"text-blue-600"}),e.jsx("h3",{className:"font-semibold text-slate-800",children:"语义检索"})]}),e.jsxs("ul",{className:"text-slate-600 text-sm space-y-2 list-disc list-inside",children:[e.jsxs("li",{children:[e.jsx("strong",{children:"语义搜索"}),":",e.jsx("code",{className:"bg-slate-100 px-1 rounded text-xs",children:'asd search -m "query"'})]}),e.jsxs("li",{children:[e.jsx("strong",{children:"编辑器内"}),":",e.jsx("code",{className:"bg-slate-100 px-1 rounded text-xs",children:"// as:search keyword"})]}),e.jsxs("li",{children:[e.jsx("strong",{children:"Cursor MCP"}),":自动检索知识库"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"Dashboard"}),":搜索框支持语义 + 关键词"]})]})]}),e.jsxs("div",{className:"border border-slate-200 rounded-lg p-5 hover:shadow-lg transition-shadow",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-3",children:[e.jsx(Ze,{size:r.lg,className:"text-blue-600"}),e.jsx("h3",{className:"font-semibold text-slate-800",children:"代码审查(Audit)"})]}),e.jsxs("ul",{className:"text-slate-600 text-sm space-y-2 list-disc list-inside",children:[e.jsxs("li",{children:[e.jsx("strong",{children:"文件审查"}),":",e.jsx("code",{className:"bg-slate-100 px-1 rounded text-xs",children:"// as:audit"})]}),e.jsxs("li",{children:[e.jsx("strong",{children:"Target 审查"}),":",e.jsx("code",{className:"bg-slate-100 px-1 rounded text-xs",children:"// as:audit target"})]}),e.jsxs("li",{children:[e.jsx("strong",{children:"项目审查"}),":",e.jsx("code",{className:"bg-slate-100 px-1 rounded text-xs",children:"// as:audit project"})]}),e.jsxs("li",{children:[e.jsx("strong",{children:"Dashboard"}),":Guard 页面可视化审查"]})]})]}),e.jsxs("div",{className:"border border-slate-200 rounded-lg p-5 hover:shadow-lg transition-shadow",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-3",children:[e.jsx(hs,{size:20,className:"text-blue-600"}),e.jsx("h3",{className:"font-semibold text-slate-800",children:"依赖关系图"})]}),e.jsxs("ul",{className:"text-slate-600 text-sm space-y-2 list-disc list-inside",children:[e.jsxs("li",{children:[e.jsx("strong",{children:"刷新映射"}),":",e.jsx("code",{className:"bg-slate-100 px-1 rounded text-xs",children:"asd spm-map"})]}),e.jsxs("li",{children:[e.jsx("strong",{children:"可视化"}),":Dashboard → 依赖关系图"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"用途"}),":理解 SPM 包依赖结构"]})]})]})]})}),e.jsxs(d,{id:"editor-directives",title:"编辑器指令",icon:e.jsx(os,{size:r.xl,className:"text-blue-600"}),children:[e.jsxs("p",{className:"text-slate-600 text-sm mb-4",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.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[e.jsxs("div",{className:"bg-slate-50 rounded-lg p-4 border border-slate-200",children:[e.jsxs("h4",{className:"font-semibold text-slate-800 mb-2",children:[e.jsx("code",{className:"bg-slate-200 px-2 py-1 rounded",children:"// as:create"})," / ",e.jsx("code",{className:"bg-slate-200 px-2 py-1 rounded",children:"// as:c"})]}),e.jsx("p",{className:"text-slate-600 text-sm mb-2",children:"创建 Recipe/Snippet"}),e.jsxs("ul",{className:"text-slate-600 text-xs space-y-1 list-disc list-inside",children:[e.jsx("li",{children:"无选项:打开 Dashboard"}),e.jsxs("li",{children:[e.jsx("code",{children:"-c"}),":从剪贴板静默创建"]}),e.jsxs("li",{children:[e.jsx("code",{children:"-f"}),":扫描当前文件"]})]})]}),e.jsxs("div",{className:"bg-slate-50 rounded-lg p-4 border border-slate-200",children:[e.jsxs("h4",{className:"font-semibold text-slate-800 mb-2",children:[e.jsx("code",{className:"bg-slate-200 px-2 py-1 rounded",children:"// as:search"})," / ",e.jsx("code",{className:"bg-slate-200 px-2 py-1 rounded",children:"// as:s"})]}),e.jsx("p",{className:"text-slate-600 text-sm mb-2",children:"搜索并插入"}),e.jsxs("ul",{className:"text-slate-600 text-xs space-y-1 list-disc list-inside",children:[e.jsx("li",{children:"从知识库检索 Recipe/Snippet"}),e.jsx("li",{children:"选择后插入代码,替换该行"}),e.jsx("li",{children:"记录一次人工使用"})]})]}),e.jsxs("div",{className:"bg-slate-50 rounded-lg p-4 border border-slate-200",children:[e.jsxs("h4",{className:"font-semibold text-slate-800 mb-2",children:[e.jsx("code",{className:"bg-slate-200 px-2 py-1 rounded",children:"// as:audit"})," / ",e.jsx("code",{className:"bg-slate-200 px-2 py-1 rounded",children:"// as:a"})]}),e.jsx("p",{className:"text-slate-600 text-sm mb-2",children:"代码审查"}),e.jsxs("ul",{className:"text-slate-600 text-xs space-y-1 list-disc list-inside",children:[e.jsx("li",{children:"无后缀:审查当前文件"}),e.jsxs("li",{children:[e.jsx("code",{children:"target"}),":审查当前 Target"]}),e.jsxs("li",{children:[e.jsx("code",{children:"project"}),":审查整个项目"]})]})]}),e.jsxs("div",{className:"bg-slate-50 rounded-lg p-4 border border-slate-200",children:[e.jsxs("h4",{className:"font-semibold text-slate-800 mb-2",children:[e.jsx("code",{className:"bg-slate-200 px-2 py-1 rounded",children:"// as:include"})," / ",e.jsx("code",{className:"bg-slate-200 px-2 py-1 rounded",children:"// as:import"})]}),e.jsx("p",{className:"text-slate-600 text-sm mb-2",children:"自动注入头文件/模块"}),e.jsxs("ul",{className:"text-slate-600 text-xs space-y-1 list-disc list-inside",children:[e.jsx("li",{children:"Snippet 中包含此标记"}),e.jsx("li",{children:"补全后自动注入 import"})]})]})]})]}),e.jsxs(d,{id:"cursor-integration",title:"Cursor AI 集成",icon:e.jsx(ps,{size:r.xl,className:"text-blue-600"}),children:[e.jsxs("div",{className:"mb-5",children:[e.jsx("h3",{className:"font-semibold text-slate-800 mb-3",children:"MCP 工具"}),e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"min-w-full border border-slate-200 rounded-lg text-xs",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"bg-slate-50",children:[e.jsx("th",{className:"px-3 py-2 border-b text-left",children:"工具"}),e.jsx("th",{className:"px-3 py-2 border-b text-left",children:"用途"})]})}),e.jsxs("tbody",{children:[e.jsxs("tr",{children:[e.jsx("td",{className:"px-3 py-2 border-b",children:e.jsx("code",{children:"context_search"})}),e.jsx("td",{className:"px-3 py-2 border-b",children:"智能检索知识库"})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-3 py-2 border-b",children:e.jsx("code",{children:"open_create"})}),e.jsx("td",{className:"px-3 py-2 border-b",children:"打开新建 Recipe 页"})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-3 py-2 border-b",children:e.jsx("code",{children:"get_targets"})}),e.jsx("td",{className:"px-3 py-2 border-b",children:"获取所有 Target"})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-3 py-2 border-b",children:e.jsx("code",{children:"get_target_files"})}),e.jsx("td",{className:"px-3 py-2 border-b",children:"获取 Target 源文件"})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-3 py-2 border-b",children:e.jsx("code",{children:"submit_candidates"})}),e.jsx("td",{className:"px-3 py-2 border-b",children:"批量提交候选"})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-3 py-2",children:e.jsx("code",{children:"confirm_recipe_usage"})}),e.jsx("td",{className:"px-3 py-2",children:"确认 Recipe 使用"})]})]})]})})]}),e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-slate-800 mb-3",children:"使用示例"}),e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"bg-blue-50 rounded p-3 border border-blue-200",children:[e.jsx("p",{className:"font-medium text-blue-900 text-sm mb-1",children:"检索知识库"}),e.jsx("p",{className:"text-blue-800 text-xs",children:'对 Cursor 说:"查找网络请求错误处理的代码"'})]}),e.jsxs("div",{className:"bg-green-50 rounded p-3 border border-green-200",children:[e.jsx("p",{className:"font-medium text-green-900 text-sm mb-1",children:"批量扫描"}),e.jsx("p",{className:"text-green-800 text-xs",children:'对 Cursor 说:"扫描 NetworkModule,生成 Recipes 到候选"'})]}),e.jsxs("div",{className:"bg-purple-50 rounded p-3 border border-purple-200",children:[e.jsx("p",{className:"font-medium text-purple-900 text-sm mb-1",children:"提交代码"}),e.jsx("p",{className:"text-purple-800 text-xs",children:'对 Cursor 说:"把这段代码保存为 Recipe"'})]})]})]})]}),e.jsx(d,{id:"cli-reference",title:"命令行速查",icon:e.jsx(os,{size:r.xl,className:"text-blue-600"}),children:e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-slate-800 mb-2",children:"初始化与环境"}),e.jsxs("div",{className:"space-y-1 text-sm",children:[e.jsxs("div",{className:"flex justify-between bg-slate-50 px-3 py-2 rounded",children:[e.jsx("code",{children:"asd setup"}),e.jsx("span",{className:"text-slate-500 text-xs",children:"初始化项目"})]}),e.jsxs("div",{className:"flex justify-between bg-slate-50 px-3 py-2 rounded",children:[e.jsx("code",{children:"asd status"}),e.jsx("span",{className:"text-slate-500 text-xs",children:"环境自检"})]}),e.jsxs("div",{className:"flex justify-between bg-slate-50 px-3 py-2 rounded",children:[e.jsx("code",{children:"asd ui"}),e.jsx("span",{className:"text-slate-500 text-xs",children:"启动 Dashboard"})]})]})]}),e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-slate-800 mb-2",children:"Recipe/Snippet 管理"}),e.jsxs("div",{className:"space-y-1 text-sm",children:[e.jsxs("div",{className:"flex justify-between bg-slate-50 px-3 py-2 rounded",children:[e.jsx("code",{children:"// as:create -c"}),e.jsx("span",{className:"text-slate-500 text-xs",children:"编辑器内从剪贴板创建"})]}),e.jsxs("div",{className:"flex justify-between bg-slate-50 px-3 py-2 rounded",children:[e.jsx("code",{children:"asd extract"}),e.jsx("span",{className:"text-slate-500 text-xs",children:"同步到 Xcode"})]}),e.jsxs("div",{className:"flex justify-between bg-slate-50 px-3 py-2 rounded",children:[e.jsx("code",{children:"asd candidate"}),e.jsx("span",{className:"text-slate-500 text-xs",children:"创建候选"})]})]})]}),e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-slate-800 mb-2",children:"搜索与扫描"}),e.jsxs("div",{className:"space-y-1 text-sm",children:[e.jsxs("div",{className:"flex justify-between bg-slate-50 px-3 py-2 rounded",children:[e.jsx("code",{children:"asd search [keyword]"}),e.jsx("span",{className:"text-slate-500 text-xs",children:"关键词搜索"})]}),e.jsxs("div",{className:"flex justify-between bg-slate-50 px-3 py-2 rounded",children:[e.jsx("code",{children:"asd search -m [query]"}),e.jsx("span",{className:"text-slate-500 text-xs",children:"语义搜索"})]}),e.jsxs("div",{className:"flex justify-between bg-slate-50 px-3 py-2 rounded",children:[e.jsx("code",{children:"asd ais [Target]"}),e.jsx("span",{className:"text-slate-500 text-xs",children:"AI 扫描"})]})]})]}),e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-slate-800 mb-2",children:"高级功能"}),e.jsxs("div",{className:"space-y-1 text-sm",children:[e.jsxs("div",{className:"flex justify-between bg-slate-50 px-3 py-2 rounded",children:[e.jsx("code",{children:"asd embed"}),e.jsx("span",{className:"text-slate-500 text-xs",children:"构建向量索引"})]}),e.jsxs("div",{className:"flex justify-between bg-slate-50 px-3 py-2 rounded",children:[e.jsx("code",{children:"asd spm-map"}),e.jsx("span",{className:"text-slate-500 text-xs",children:"刷新依赖"})]}),e.jsxs("div",{className:"flex justify-between bg-slate-50 px-3 py-2 rounded",children:[e.jsx("code",{children:"asd install:full"}),e.jsx("span",{className:"text-slate-500 text-xs",children:"完整安装"})]})]})]})]})})]}),e.jsx("div",{className:"mt-8 p-4 bg-blue-50 border border-blue-200 rounded-lg text-center",children:e.jsxs("p",{className:"text-slate-700 text-sm",children:["需要更详细的说明?查看 ",e.jsx("a",{href:"/docs/USER_MANUAL.md",target:"_blank",rel:"noopener noreferrer",className:"text-blue-600 hover:underline font-medium",children:"完整使用说明书"})]})})]})},Et={objectivec:"objectivec",objc:"objectivec","objective-c":"objectivec","obj-c":"objectivec",swift:"swift",markdown:"markdown",md:"markdown"},_e=({code:s,language:t="text",className:w="",showLineNumbers:d=!1})=>{const l=Et[t==null?void 0:t.toLowerCase()]||(t==null?void 0:t.toLowerCase())||"text";return e.jsx("div",{className:`rounded-xl overflow-hidden text-sm ${w}`,children:e.jsx(vs,{language:l,style:ws,showLineNumbers:d,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 ls(s){return!s||typeof s!="string"?s:s.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/,"").trim()||s}const ze=({content:s,className:t="",showLineNumbers:w=!1,stripFrontmatter:d=!1})=>{const l=p=>!p||typeof p!="string"?p:p.replace(/\\\\n/g,`
@@ -5,7 +5,7 @@
5
5
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>AutoSnippet Dashboard</title>
8
- <script type="module" crossorigin src="/assets/index-D9fS5ZxI.js"></script>
8
+ <script type="module" crossorigin src="/assets/index-BoYBT7s4.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="/assets/yaml-qRaU8Ldn.js">
10
10
  <link rel="modulepreload" crossorigin href="/assets/vendor-CJtnAZ4B.js">
11
11
  <link rel="modulepreload" crossorigin href="/assets/axios-D5GkNzM3.js">
@@ -357,24 +357,38 @@ For each utility:
357
357
  }
358
358
 
359
359
  /**
360
- * 生成文本向量
360
+ * 生成文本向量(根据官方 API 文档)
361
361
  * @param {string|string[]} text
362
362
  */
363
363
  async embed(text) {
364
364
  return this._withRetry(async () => {
365
+ // 检查是否禁用 embedding
366
+ if (process.env.ASD_DISABLE_EMBEDDING === '1') {
367
+ console.log('[GoogleGemini] Embedding disabled by ASD_DISABLE_EMBEDDING');
368
+ return [];
369
+ }
370
+
365
371
  const isArray = Array.isArray(text);
372
+
373
+ // 根据官方文档: https://ai.google.dev/gemini-api/docs/embeddings
374
+ // 使用 gemini-embedding-001 模型,输出 768 维向量(推荐值)
366
375
  const url = isArray
367
- ? `https://generativelanguage.googleapis.com/v1beta/models/text-embedding-004:batchEmbedContents?key=${this.apiKey}`
368
- : `https://generativelanguage.googleapis.com/v1beta/models/text-embedding-004:embedContent?key=${this.apiKey}`;
376
+ ? `https://generativelanguage.googleapis.com/v1beta/models/gemini-embedding-001:batchEmbedContents?key=${this.apiKey}`
377
+ : `https://generativelanguage.googleapis.com/v1beta/models/gemini-embedding-001:embedContent?key=${this.apiKey}`;
378
+
369
379
  const body = isArray
370
380
  ? {
381
+ // 批量请求:requests 数组,每个包含 model 和 content
371
382
  requests: text.map(t => ({
372
- model: 'models/text-embedding-004',
373
- content: { parts: [{ text: t }] }
383
+ model: 'models/gemini-embedding-001',
384
+ content: { parts: [{ text: t }] },
385
+ outputDimensionality: 768 // 统一使用 768 维
374
386
  }))
375
387
  }
376
388
  : {
377
- content: { parts: [{ text }] }
389
+ // 单个请求:只需 content,不需要 model 字段
390
+ content: { parts: [{ text }] },
391
+ outputDimensionality: 768 // 统一使用 768 维
378
392
  };
379
393
 
380
394
  const result = await this._postJson(url, body);
@@ -318,11 +318,17 @@ class ContextServiceV2 {
318
318
  const vec = await ai.embed(query);
319
319
 
320
320
  // 处理不同的向量返回格式
321
+ let result = [];
321
322
  if (Array.isArray(vec)) {
322
- return Array.isArray(vec[0]) ? vec[0] : vec;
323
+ result = Array.isArray(vec[0]) ? vec[0] : vec;
323
324
  }
324
325
 
325
- return [];
326
+ // 调试:记录向量维度
327
+ if (process.env.ASD_DEBUG === '1' && result.length > 0) {
328
+ console.log(`[ContextServiceV2] Query vector dimension: ${result.length}`);
329
+ }
330
+
331
+ return result;
326
332
  } catch (e) {
327
333
  this.logger.warn('[ContextServiceV2] ⚠️ embedding 失败,使用纯关键词搜索', { error: e.message });
328
334
  return [];
@@ -433,9 +433,18 @@ class SearchServiceV2 {
433
433
 
434
434
  const { parseRecipeMd } = require('../../recipe/parseRecipeMd');
435
435
 
436
+ // 标准化路径:移除多种前缀形式(兼容不同的数据来源)
437
+ const normalizePath = (pathStr) => {
438
+ if (!pathStr) return pathStr;
439
+ return pathStr
440
+ .replace(/^recipe_/, '') // 移除 id 中的 "recipe_" 前缀
441
+ .replace(/^AutoSnippet[\\/]recipes[\\/]/, ''); // 移除旧 sourcePath 前缀
442
+ };
443
+
436
444
  return items.map(res => {
437
445
  const percent = ((res.similarity || 0) * 100).toFixed(0);
438
- const name = res.metadata?.name || res.metadata?.sourcePath || res.id;
446
+ const rawName = res.metadata?.name || res.metadata?.sourcePath || res.id;
447
+ const name = normalizePath(rawName);
439
448
  const content = res.content || '';
440
449
  const trigger = getTriggerFromContent(content) || undefined;
441
450
 
@@ -101,7 +101,8 @@ async function scan(projectRoot, config) {
101
101
  try {
102
102
  const content = fs.readFileSync(absPath, 'utf8');
103
103
  const stat = fs.statSync(absPath);
104
- const sourcePath = path.join(p.path, rel).replace(/\\/g, '/').replace(/\/+/g, '/');
104
+ // 只保存相对于源目录的路径,不包含 p.path 前缀(如 "AutoSnippet/recipes")
105
+ const sourcePath = rel.replace(/\\/g, '/').replace(/\/+/g, '/');
105
106
  const metadata = {};
106
107
  if (type === defaults.SOURCE_TYPE_RECIPE) {
107
108
  const fmMatch = content.trim().match(/^---\r?\n([\s\S]*?)\r?\n---/);