autosnippet 1.4.0 → 1.4.2
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 +50 -264
- package/dashboard/dist/assets/index-ByWAR53z.css +1 -0
- package/dashboard/dist/assets/{index-DmHm4WCA.js → index-l2znexhV.js} +10 -10
- package/dashboard/dist/index.html +2 -2
- package/package.json +1 -1
- package/scripts/mcp-server.js +2 -2
- package/skills/autosnippet-create/SKILL.md +14 -10
- package/dashboard/dist/assets/index-DeK7dG-V.css +0 -1
package/README.md
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
# AutoSnippet
|
|
2
2
|
|
|
3
|
-
连接开发者、AI 与项目知识库:人工审核沉淀标准,知识库存储 Recipe + Snippet,AI 按规范生成代码。基于 SPM,打通 Xcode 补全与 Cursor
|
|
3
|
+
连接开发者、AI 与项目知识库:人工审核沉淀标准,知识库存储 Recipe + Snippet,AI 按规范生成代码。基于 SPM,打通 Xcode 补全与 Cursor 按需检索。
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/autosnippet)
|
|
6
|
-
[](https://www.npmjs.com/package/autosnippet)
|
|
7
6
|
[](https://github.com/GxFn/AutoSnippet/blob/main/LICENSE)
|
|
8
7
|
|
|
9
8
|
---
|
|
@@ -12,306 +11,93 @@
|
|
|
12
11
|
|
|
13
12
|
| 角色 | 职责 | 能力 |
|
|
14
13
|
|------|------|------|
|
|
15
|
-
| **开发者** |
|
|
16
|
-
| **Cursor Agent
|
|
17
|
-
|
|
|
18
|
-
| **知识库** |
|
|
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 的上下文均依赖此 |
|
|
19
18
|
|
|
20
19
|
---
|
|
21
20
|
|
|
22
|
-
##
|
|
21
|
+
## 安装与快速开始
|
|
23
22
|
|
|
24
23
|
```bash
|
|
25
24
|
npm install -g autosnippet
|
|
26
25
|
```
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
## 快速开始
|
|
31
|
-
|
|
32
|
-
**项目根目录**:即将在此目录创建 `AutoSnippetRoot.boxspec.json` 的目录(单仓库用仓库根即可)。后续 `asd ui`、编辑器内指令、命令行等均以此目录为基准。
|
|
33
|
-
|
|
34
|
-
在**你的业务项目根目录**执行:
|
|
27
|
+
在**项目根目录**执行:
|
|
35
28
|
|
|
36
29
|
```bash
|
|
37
|
-
#
|
|
38
|
-
asd
|
|
39
|
-
|
|
40
|
-
# 2) 启动 Web 管理后台(会同时启动 watch,编辑器内指令才会生效)
|
|
41
|
-
asd ui
|
|
30
|
+
asd setup # 初始化
|
|
31
|
+
asd ui # 启动 Dashboard(建议常驻)
|
|
42
32
|
```
|
|
43
33
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
### 界面预览
|
|
34
|
+
`asd ui` 会启动 Web 管理后台并后台 watch;首次运行若前端不存在会自动构建。浏览器会自动打开 Dashboard。
|
|
47
35
|
|
|
48
36
|

|
|
49
37
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-

|
|
53
|
-
|
|
54
|
-
---
|
|
55
|
-
|
|
56
|
-
## 新项目:AI 扫描 + 人工审核 → 知识库与依赖 → 与 Cursor/AI 形成闭环
|
|
57
|
-
|
|
58
|
-
新项目在完成「快速开始」后,可按以下方式**用 AI 扫描 + 人工审核**快速组建知识库和依赖关系,再配合 Cursor 与其他 AI 形成闭环:
|
|
59
|
-
|
|
60
|
-
1. **组建知识库**:在项目根执行 **`asd ais <Target>`** 或 **`asd ais --all`**,对 SPM Target 做批量 AI 扫描;结果进入 Dashboard 的 **Candidates** 页。在 Dashboard 中逐条审核,通过则入库为 Recipe(或 Snippet+Recipe),不需要的删除。反复几轮即可把现有代码中的「标准用法」沉淀到 `Knowledge/recipes/`。
|
|
38
|
+
## 核心流程
|
|
61
39
|
|
|
62
|
-
|
|
40
|
+
1. **组建知识库**:`asd ais <Target>` 或 `asd ais --all` → Dashboard Candidates 审核 → Recipe 入库
|
|
41
|
+
2. **依赖关系**:`asd spm-map` 或 Dashboard 刷新
|
|
42
|
+
3. **Cursor 集成**:`asd install:cursor-skill --mcp`(安装 Skills + MCP,需 `asd ui` 运行)
|
|
43
|
+
4. **语义索引**:`asd ui` 启动时自动 embed;也可手动 `asd embed`
|
|
63
44
|
|
|
64
|
-
|
|
45
|
+
### 闭环
|
|
65
46
|
|
|
66
|
-
|
|
47
|
+
**扫描 → 审核 → 沉淀 → Cursor/AI 使用 → 再沉淀**:项目 AI 通过扫描 target 批量提交候选,Cursor 完成的代码通过 Skill 提交候选,开发者完成的代码通过剪切板提交候选,Dashboard 中的候选经过人工审核进入知识库;知识库内 Recipe 为第一公民,拥有最高优先级。
|
|
67
48
|
|
|
68
|
-
|
|
49
|
+
开发者通过 Snippet 获取 Recipe 内容插入编辑器, Cursor 通过 Skills 把 Recipe 产生的 context 当做上下文使用,对向量库进行查询;AI 用知识库产生的代码,过审后添加到知识库,成为了 AI 新的上下文,使得 AI 的开发趋于标准化。
|
|
69
50
|
|
|
70
|
-
|
|
51
|
+
知识库随人工审核持续更新,AI 始终基于最新上下文,Recipe 会在使用中获得评级调整。
|
|
71
52
|
|
|
72
53
|
## 编辑器内指令
|
|
73
54
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
如果你接入了 AI 开发流程,这些功能会作为 Skills 交给 AI 在恰当的时机提供给你选择执行。
|
|
77
|
-
|
|
78
|
-
| 指令 | 作用 | 触发时机 |
|
|
79
|
-
|------|------|----------|
|
|
80
|
-
| **`// as:create`** | 用剪贴板 + 当前文件路径创建 Recipe,打开 Dashboard | 保存文件后 watch 检测 |
|
|
81
|
-
| **`// as:guard`** [关键词] | 按知识库(Recipes)用 AI 审查当前文件,结果输出终端 | 保存文件后 watch 检测 |
|
|
82
|
-
| **`// as:search`** [关键词] | 从知识库检索 Recipe/Snippet 并插入 | 保存后 watch 检测 |
|
|
83
|
-
| **`// as:include`** Header [path] | Snippet 体内的头文件标记,自动在文件头部注入 `#import` | 保存文件后 watch 检测 |
|
|
84
|
-
| **`// as:import`** ModuleName | Snippet 体内的 Swift 模块标记,自动在文件头部注入 `import` | 保存文件后 watch 检测 |
|
|
85
|
-
|
|
86
|
-
### // as:create
|
|
87
|
-
|
|
88
|
-
在源码中写一行 **`// as:create`**,把要沉淀的代码**复制到剪贴板**,保存文件。watch 检测到后会**打开 Dashboard** 并带当前文件路径;若剪贴板有内容,会走「Use Copied Code」流程并自动解析头文件。适合:在编辑器里写完模块使用代码后,直接提交到 web、加入知识库。
|
|
89
|
-
|
|
90
|
-
### // as:guard
|
|
91
|
-
|
|
92
|
-
在源码中写 **`// as:guard`** 或 **`// as:guard 关键字`**,保存文件。watch 会按 **知识库(Recipes)** 用 AI 审查当前文件是否符合项目规范,**结果输出到终端**。若已执行 `asd embed`,会优先用语义检索选取相关 Recipe。
|
|
93
|
-
|
|
94
|
-
### // as:search
|
|
95
|
-
|
|
96
|
-
在源码中写 **`// as:search`** 或 **`// as:search 关键词`**,保存文件。watch 检测到后会**打开 Dashboard**,展示从知识库(Recipes)中按关键词检索到的候选;不写关键词则展示全部。在列表中点选一条 Recipe 并点击「插入」,该 Recipe 的代码块会**替换当前行**(即 `// as:search` 所在行)并写回文件,实现「选即插」。插入标准代码也可在 Xcode 中通过 **Snippet 联想(trigger 补全)** 直接选用已同步的 Snippet。
|
|
97
|
-
|
|
98
|
-
### // as:include 与 // as:import(头文件/模块标记)
|
|
99
|
-
|
|
100
|
-
用于 **Snippet 体内**(写入 `.codesnippet` 的 body),表示插入该 Snippet 时需要的头文件/模块;**watch** 在用户保存文件时,会在**文件头部**自动注入对应的 `#import` 或 `import`。
|
|
101
|
-
|
|
102
|
-
- **ObjC 头文件**:`// as:include <ModuleName/Header.h> [相对路径]`
|
|
103
|
-
- **Swift**:`// as:import ModuleName`
|
|
104
|
-
|
|
105
|
-
保存时可勾选「引入头文件」,会写入上述标记;在项目根运行 `asd watch`(或 `asd ui`)后,在 Xcode 中选中 Snippet 的 headerVersion 并保存,即可在文件头部注入依赖。
|
|
55
|
+
需先运行 `asd watch` 或 `asd ui`。在源码中写入并保存:
|
|
106
56
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
## 术语
|
|
110
|
-
|
|
111
|
-
- **Snippet**:写入 Xcode 的代码片段,通过 trigger(补全键)或库面板使用;trigger 以配置的触发符开头(默认 **@**,可通过环境变量 `ASD_TRIGGER_SYMBOL` 更换)。
|
|
112
|
-
- **Recipe**:存放在 `Knowledge/recipes/` 下的 Markdown 知识,供 AI 检索、Guard 审查与搜索。
|
|
113
|
-
- **项目根**:含 `AutoSnippetRoot.boxspec.json` 的目录。
|
|
114
|
-
|
|
115
|
-
---
|
|
116
|
-
|
|
117
|
-
## AI 支持与配置
|
|
118
|
-
|
|
119
|
-
### 当前支持的 AI
|
|
120
|
-
|
|
121
|
-
| 提供商 | 默认模型 | 说明 |
|
|
122
|
-
|--------|----------|------|
|
|
123
|
-
| **Google Gemini** | `gemini-2.0-flash` | 用于 Snippet 提取、摘要、RAG 问答等 |
|
|
124
|
-
| **OpenAI** | `gpt-4o` | 支持 OpenAI 标准接口 |
|
|
125
|
-
| **DeepSeek** | `deepseek-chat` | 深度求索系列模型 |
|
|
126
|
-
| **Anthropic Claude** | `claude-3-5-sonnet-20240620` | 支持 Claude 系列模型 |
|
|
127
|
-
| **Ollama** | `llama3` | **本地 AI 支持**,默认地址 `http://localhost:11434/v1` |
|
|
128
|
-
|
|
129
|
-
### 配置指南
|
|
130
|
-
|
|
131
|
-
**1. 必填:API Key**
|
|
132
|
-
|
|
133
|
-
在**项目根目录**创建 `.env` 文件(可复制 `.env.example`),或通过环境变量传入 API Key:
|
|
134
|
-
|
|
135
|
-
```bash
|
|
136
|
-
export ASD_GOOGLE_API_KEY="你的 API Key" # 或 ASD_OPENAI_API_KEY、ASD_DEEPSEEK_API_KEY、ASD_CLAUDE_API_KEY
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
在项目根执行 `asd ai-test` 可验证当前配置是否可用。未配置时,依赖 AI 的功能会报错或提示。
|
|
140
|
-
|
|
141
|
-
**2. 可选**:`ASD_AI_PROVIDER`、`ASD_AI_MODEL`、各提供商 `_BASE_URL` 等,见项目内 `.env.example`。
|
|
142
|
-
|
|
143
|
-
**3. 可选:代理**:设置 `https_proxy` / `http_proxy` 访问外网 API。国内直连 Google/OpenAI 易失败,建议在 `.env` 中配置代理(如 `https_proxy=http://127.0.0.1:7890`)或改用国内可用的 `ASD_AI_PROVIDER=deepseek` 等。
|
|
144
|
-
|
|
145
|
-
---
|
|
146
|
-
|
|
147
|
-
## Cursor 集成
|
|
148
|
-
|
|
149
|
-
若使用 [Cursor](https://cursor.com) 编辑项目,可将 AutoSnippet 自带的 skills 安装到**当前项目**的 Cursor 环境(项目根 `.cursor/skills/`),让 Agent 识别 Recipe、知识库与创建流程,并**在合适时机推荐**对应能力(由 AI 决定是否推荐,不强制)。
|
|
150
|
-
|
|
151
|
-
在**项目根目录**执行:
|
|
152
|
-
|
|
153
|
-
```bash
|
|
154
|
-
# 基础安装(Skills 引用)
|
|
155
|
-
asd install:cursor-skill
|
|
156
|
-
|
|
157
|
-
# 推荐:加上 MCP,启用按需语义检索与打开新建 Recipe 页
|
|
158
|
-
asd install:cursor-skill --mcp
|
|
159
|
-
|
|
160
|
-
# 安装后同时更新语义索引(可选)
|
|
161
|
-
asd install:cursor-skill --embed
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
**`--mcp`**:添加 MCP 配置,使 Agent 可调用 `autosnippet_context_search`(按需语义检索知识库)、`autosnippet_open_create`(打开新建 Recipe 页)。需先运行 `asd ui`。**`--embed`**:安装后执行 embed 更新语义索引;亦可依赖 `asd ui` 的自动 embed。
|
|
165
|
-
|
|
166
|
-
安装后重启 Cursor 或新开 Agent 对话即可生效。更新 AutoSnippet 或增删 skills 后重新执行,会同步所有 skill 到 `.cursor/skills/`。
|
|
167
|
-
|
|
168
|
-
### 安装的 Skills 一览
|
|
169
|
-
|
|
170
|
-
| Skill | 作用 |
|
|
171
|
-
|-------|------|
|
|
172
|
-
| **autosnippet-when** | 路由:根据用户意图(加入知识库 / 查规范 / 审查 / 补全 / 依赖等)决定何时推荐哪项能力,再跳转到对应 skill。 |
|
|
173
|
-
| **autosnippet-concepts** | 概念:知识库、Recipe、Snippet、Candidates、Context 存储(向量库);Recipe 优先级高于项目实现;能力与内容摘要。 |
|
|
174
|
-
| **autosnippet-recipes** | 项目上下文:读 `references/project-recipes-context.md`;Recipe 优先于代码搜索;in-context / 终端 / MCP 三种检索方式。 |
|
|
175
|
-
| **autosnippet-create** | 创建:如何把代码提交到 Dashboard(Use Copied Code、Scan File);禁止直接写 Knowledge;MCP `autosnippet_open_create` 打开新建页。 |
|
|
176
|
-
| **autosnippet-search** | 查找/插入:用户想「查项目里怎么写、插入标准代码」时,推荐 `// as:search`、`asd search`、Dashboard 搜索。 |
|
|
177
|
-
| **autosnippet-guard** | 审查:用户想「检查规范、Guard」时,推荐在文件中写 `// as:guard` 并保存。 |
|
|
178
|
-
| **autosnippet-dep-graph** | 依赖结构:`Knowledge/AutoSnippet.spmmap.json` 的读法、`asd spm-map` 更新;包/模块依赖、跨模块建议。 |
|
|
179
|
-
|
|
180
|
-
**MCP 工具**(`--mcp` 配置后):`autosnippet_context_search` 按需语义检索;`autosnippet_open_create` 打开新建 Recipe 页。Skills 表达语义,MCP 做能力支持。
|
|
181
|
-
|
|
182
|
-
---
|
|
183
|
-
|
|
184
|
-
## Web Dashboard(asd ui)
|
|
185
|
-
|
|
186
|
-
启动后访问 `http://localhost:3000`。若已运行 `asd ui`,watch 在后台启动,编辑器内指令(as:create、as:guard、头文件注入等)在保存时生效;MCP 按需检索、`// as:create` / `// as:search` 跳转均依赖此。
|
|
187
|
-
|
|
188
|
-
- **macOS**:再次运行 `asd ui` 会复用已有 `localhost:3000` 标签并聚焦(Chromium 系浏览器)。
|
|
189
|
-
|
|
190
|
-
| 页面 | 说明 |
|
|
57
|
+
| 指令 | 作用 |
|
|
191
58
|
|------|------|
|
|
192
|
-
|
|
|
193
|
-
|
|
|
194
|
-
|
|
|
195
|
-
|
|
|
196
|
-
| **依赖关系图** | 展示 SPM 包依赖(packages + edges) |
|
|
197
|
-
| **AI Assistant** | 基于本地 Snippets/Recipes 的 RAG 问答 |
|
|
198
|
-
| **使用说明** | 使用说明的 Web 版 |
|
|
199
|
-
|
|
200
|
-
### 新建 Recipe
|
|
201
|
-
|
|
202
|
-
- **按路径**:输入相对路径(如 `Sources/MyMod/Foo.m`)→ **Scan File** → AI 提取标题/摘要/触发键/头文件,审核后保存到 `Knowledge/recipes/`。
|
|
203
|
-
- **按剪贴板**:复制代码后点击 **Use Copied Code** → AI 分析并填充;若由 `// as:create` 打开会带当前文件路径,自动解析头文件。
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
|
|
207
|
-
## 可选依赖与全量安装
|
|
208
|
-
|
|
209
|
-
以下为按需安装项,缺省不影响核心功能。**统一使用 `asd` 命令**,任意目录可执行:
|
|
210
|
-
|
|
211
|
-
```bash
|
|
212
|
-
# 全量安装(核心 + 可选依赖 + Dashboard)
|
|
213
|
-
asd install:full
|
|
214
|
-
|
|
215
|
-
# 含 Swift 解析器
|
|
216
|
-
asd install:full --parser
|
|
217
|
-
|
|
218
|
-
# 仅安装 LanceDB
|
|
219
|
-
asd install:full --lancedb
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
| 依赖 | 用途 | 按需安装 | 默认 |
|
|
223
|
-
|------|------|----------|------|
|
|
224
|
-
| **LanceDB** | 向量存储,Recipe 多时检索更快 | `asd install:full --lancedb` | JSON 存储,无需安装 |
|
|
225
|
-
| **ParsePackage** | SPM 解析更准确 | `asd install:full --parser` | 回退 dump-package |
|
|
226
|
-
| **Dashboard** | Web 管理后台 | 预构建不存在时 `asd install:full` 会构建;首次 `asd ui` 也会自动构建 | 包内可含预构建 |
|
|
59
|
+
| `// as:create` | 剪贴板代码 → 打开 Dashboard 新建 Recipe |
|
|
60
|
+
| `// as:guard` [关键词] | 按知识库 AI 审查当前文件,输出到终端 |
|
|
61
|
+
| `// as:search` [关键词] | 从知识库检索并插入 Recipe/Snippet |
|
|
62
|
+
| `// as:include` / `// as:import` | Snippet 内头文件/模块标记,保存时自动注入 |
|
|
227
63
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
语义索引默认用 JSON;若 Recipes 较多,可改用 LanceDB:
|
|
231
|
-
|
|
232
|
-
```bash
|
|
233
|
-
asd install:full --lancedb
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
在 `AutoSnippetRoot.boxspec.json` 中配置:
|
|
237
|
-
|
|
238
|
-
```json
|
|
239
|
-
{
|
|
240
|
-
"context": {
|
|
241
|
-
"storage": {
|
|
242
|
-
"adapter": "lance"
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
配置后,`asd embed` 会将索引写入 `Knowledge/.autosnippet/context/index/lancedb/`。切换 adapter 时建议执行 `asd embed --clear` 全量重建。
|
|
249
|
-
|
|
250
|
-
| adapter | 说明 |
|
|
251
|
-
|---------|------|
|
|
252
|
-
| `json` | 默认,无需额外依赖 |
|
|
253
|
-
| `lance` | 需执行 `asd install:full --lancedb` |
|
|
254
|
-
|
|
255
|
-
---
|
|
256
|
-
|
|
257
|
-
## 命令行
|
|
258
|
-
|
|
259
|
-
以下命令均在**项目根目录**执行。**编辑器内指令**已在上文优先说明;此处为 CLI 能力速查与补充。
|
|
260
|
-
|
|
261
|
-
### 语义能力
|
|
262
|
-
|
|
263
|
-
| 命令 | 说明 |
|
|
264
|
-
|------|------|
|
|
265
|
-
| `asd embed` | **构建语义向量索引**;`asd search -m`、Guard 语义检索、MCP 按需检索均依赖此。`asd ui` 启动时自动检测并执行(无索引或 Recipe 变更),亦可手动运行。 |
|
|
266
|
-
| `asd search -m [query]` | **语义搜索**知识库(自然语言);需先 `asd embed`。优先于关键词搜索。 |
|
|
267
|
-
| `asd install:cursor-skill --mcp` | 安装 Skills 并**配置 MCP**;Agent 可调用 `autosnippet_context_search` 按需检索、`autosnippet_open_create` 打开新建 Recipe 页。需 `asd ui` 运行。 |
|
|
268
|
-
|
|
269
|
-
### 常用命令
|
|
64
|
+
## 常用命令
|
|
270
65
|
|
|
271
66
|
| 命令 | 说明 |
|
|
272
67
|
|------|------|
|
|
273
|
-
| `asd ui` | 启动
|
|
274
|
-
| `asd create --clipboard` |
|
|
275
|
-
| `asd
|
|
276
|
-
| `asd
|
|
277
|
-
| `asd
|
|
278
|
-
| `asd
|
|
279
|
-
| `asd
|
|
280
|
-
| `asd install:cursor-skill` | 将 AutoSnippet skills 安装到项目 `.cursor/skills/`;加 `--mcp` 启用 MCP;加 `--embed` 安装后执行 embed |
|
|
68
|
+
| `asd ui` | 启动 Dashboard + watch |
|
|
69
|
+
| `asd create --clipboard` | 从剪贴板创建 Recipe/Snippet |
|
|
70
|
+
| `asd install` / `asd i` | 同步 Snippets 到 Xcode |
|
|
71
|
+
| `asd ais [Target]` | AI 扫描 Target → Candidates |
|
|
72
|
+
| `asd search [keyword]` | 关键词搜索;加 `-m` 语义搜索 |
|
|
73
|
+
| `asd install:cursor-skill --mcp` | 安装 Skills 并配置 MCP |
|
|
74
|
+
| `asd install:full` | 全量安装;`--parser` 含 Swift 解析器;`--lancedb` 仅 LanceDB |
|
|
281
75
|
|
|
282
|
-
|
|
76
|
+
## 全量安装与可选依赖
|
|
283
77
|
|
|
284
|
-
|
|
285
|
-
- **从文件**:源码中用 `// as:code` 包裹要提炼的片段,再执行 `asd create` 并选择该文件。
|
|
286
|
-
- **传统模式**:`asd create --no-ai`、`asd --preset preset.json create`。
|
|
78
|
+
克隆或需完整能力时,**任意目录**执行:
|
|
287
79
|
|
|
288
|
-
|
|
80
|
+
```bash
|
|
81
|
+
asd install:full # 核心 + 可选依赖 + Dashboard(前端不存在时构建)
|
|
82
|
+
asd install:full --parser # 上述 + Swift 解析器(ParsePackage,SPM 解析更准确)
|
|
83
|
+
asd install:full --lancedb # 仅安装 LanceDB(向量检索更快)
|
|
84
|
+
```
|
|
289
85
|
|
|
290
|
-
|
|
291
|
-
- `asd root`:在当前目录创建/更新项目根标记(`AutoSnippetRoot.boxspec.json`)。
|
|
292
|
-
- `asd init`:在 SPM 模块目录创建模块工作空间。
|
|
293
|
-
- `asd share`:共享本地 Snippet。
|
|
294
|
-
- `asd u <word> [key] [value]`:按 trigger 更新 Snippet 字段。
|
|
295
|
-
- `asd install:full`:全量安装;`--parser` 含 Swift 解析器;`--lancedb` 仅安装 LanceDB。**任意目录可执行**。
|
|
86
|
+
**Swift 解析器**:默认回退 `dump-package`;`--parser` 构建 ParsePackage 后 SPM 解析更准确,需本机已装 Swift。
|
|
296
87
|
|
|
297
|
-
|
|
88
|
+
## 配置
|
|
298
89
|
|
|
299
|
-
-
|
|
300
|
-
-
|
|
301
|
-
- 环境变量:`ASD_PRESET` / `ASD_TEST_PRESET` 指定预置路径。
|
|
90
|
+
- **AI**:项目根 `.env`,设置 `ASD_GOOGLE_API_KEY` 等(见 `.env.example`)。可选 `ASD_AI_PROVIDER`、代理等。
|
|
91
|
+
- **LanceDB**:`asd install:full --lancedb`,在 boxspec 的 `context.storage.adapter` 中配置 `"lance"`。
|
|
302
92
|
|
|
303
|
-
|
|
93
|
+
## 术语
|
|
304
94
|
|
|
305
|
-
|
|
95
|
+
- **Recipe**:`Knowledge/recipes/` 下的 Markdown 知识,供 AI 检索、Guard、搜索
|
|
96
|
+
- **Snippet**:Xcode 代码片段,通过 trigger(默认 `@`)补全
|
|
97
|
+
- **项目根**:含 `AutoSnippetRoot.boxspec.json` 的目录
|
|
306
98
|
|
|
307
|
-
|
|
99
|
+
**详细介绍**:启动 `asd ui` 后访问 Dashboard → **使用说明** 页,可查看完整文档(含 Skills 一览、AI 配置、闭环详解等)。
|
|
308
100
|
|
|
309
101
|
---
|
|
310
102
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
欢迎提交 Issue 与 Pull Request。
|
|
314
|
-
|
|
315
|
-
## 许可证
|
|
316
|
-
|
|
317
|
-
MIT,见 [LICENSE](LICENSE).
|
|
103
|
+
欢迎 [Issue](https://github.com/GxFn/AutoSnippet/issues) 与 [PR](https://github.com/GxFn/AutoSnippet/pulls)。MIT 许可证。
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-red-800:oklch(44.4% .177 26.899);--color-orange-50:oklch(98% .016 73.684);--color-orange-100:oklch(95.4% .038 75.164);--color-orange-600:oklch(64.6% .222 41.116);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-700:oklch(55.5% .163 48.998);--color-emerald-50:oklch(97.9% .021 166.113);--color-emerald-100:oklch(95% .052 163.051);--color-emerald-600:oklch(59.6% .145 163.225);--color-cyan-50:oklch(98.4% .019 200.873);--color-cyan-100:oklch(95.6% .045 203.388);--color-cyan-600:oklch(60.9% .126 221.723);--color-blue-50:oklch(97% .014 254.604);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-200:oklch(88.2% .059 254.128);--color-blue-300:oklch(80.9% .105 251.813);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-indigo-50:oklch(96.2% .018 272.314);--color-indigo-100:oklch(93% .034 272.788);--color-indigo-600:oklch(51.1% .262 276.966);--color-purple-50:oklch(97.7% .014 308.299);--color-purple-100:oklch(94.6% .033 307.174);--color-purple-600:oklch(55.8% .288 302.321);--color-pink-50:oklch(97.1% .014 343.198);--color-pink-100:oklch(94.8% .028 342.258);--color-pink-600:oklch(59.2% .249 .584);--color-slate-50:oklch(98.4% .003 247.858);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-200:oklch(92.9% .013 255.508);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-500:oklch(55.4% .046 257.417);--color-slate-600:oklch(44.6% .043 257.281);--color-slate-700:oklch(37.2% .044 257.287);--color-slate-800:oklch(27.9% .041 260.031);--color-slate-900:oklch(20.8% .042 265.755);--color-white:#fff;--spacing:.25rem;--container-md:28rem;--container-lg:32rem;--container-2xl:42rem;--container-3xl:48rem;--container-6xl:72rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75/1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-wider:.05em;--tracking-widest:.1em;--leading-relaxed:1.625;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--ease-out:cubic-bezier(0,0,.2,1);--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--blur-sm:8px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.inset-0{inset:calc(var(--spacing)*0)}.top-0\.5{top:calc(var(--spacing)*.5)}.top-1\/2{top:50%}.top-4{top:calc(var(--spacing)*4)}.top-full{top:100%}.right-0{right:calc(var(--spacing)*0)}.right-0\.5{right:calc(var(--spacing)*.5)}.right-4{right:calc(var(--spacing)*4)}.left-0\.5{left:calc(var(--spacing)*.5)}.left-3{left:calc(var(--spacing)*3)}.z-10{z-index:10}.z-50{z-index:50}.m-auto{margin:auto}.mx-auto{margin-inline:auto}.my-3{margin-block:calc(var(--spacing)*3)}.mt-0\.5{margin-top:calc(var(--spacing)*.5)}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-1\.5{margin-top:calc(var(--spacing)*1.5)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-3{margin-top:calc(var(--spacing)*3)}.mt-4{margin-top:calc(var(--spacing)*4)}.mr-4{margin-right:calc(var(--spacing)*4)}.mb-0\.5{margin-bottom:calc(var(--spacing)*.5)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-3{margin-bottom:calc(var(--spacing)*3)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.mb-6{margin-bottom:calc(var(--spacing)*6)}.mb-8{margin-bottom:calc(var(--spacing)*8)}.ml-1{margin-left:calc(var(--spacing)*1)}.ml-2{margin-left:calc(var(--spacing)*2)}.ml-4{margin-left:calc(var(--spacing)*4)}.ml-auto{margin-left:auto}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-6{-webkit-line-clamp:6;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.flex{display:flex}.grid{display:grid}.h-1\.5{height:calc(var(--spacing)*1.5)}.h-2\.5{height:calc(var(--spacing)*2.5)}.h-3{height:calc(var(--spacing)*3)}.h-4{height:calc(var(--spacing)*4)}.h-8{height:calc(var(--spacing)*8)}.h-10{height:calc(var(--spacing)*10)}.h-16{height:calc(var(--spacing)*16)}.h-64{height:calc(var(--spacing)*64)}.h-\[85vh\]{height:85vh}.h-full{height:100%}.h-screen{height:100vh}.max-h-32{max-height:calc(var(--spacing)*32)}.max-h-60{max-height:calc(var(--spacing)*60)}.max-h-\[85vh\]{max-height:85vh}.max-h-\[90vh\]{max-height:90vh}.max-h-\[280px\]{max-height:280px}.min-h-0{min-height:calc(var(--spacing)*0)}.min-h-\[100px\]{min-height:100px}.min-h-\[320px\]{min-height:320px}.min-h-\[400px\]{min-height:400px}.min-h-\[480px\]{min-height:480px}.w-1\.5{width:calc(var(--spacing)*1.5)}.w-3{width:calc(var(--spacing)*3)}.w-8{width:calc(var(--spacing)*8)}.w-10{width:calc(var(--spacing)*10)}.w-16{width:calc(var(--spacing)*16)}.w-64{width:calc(var(--spacing)*64)}.w-72{width:calc(var(--spacing)*72)}.w-80{width:calc(var(--spacing)*80)}.w-96{width:calc(var(--spacing)*96)}.w-\[512px\]{width:512px}.w-fit{width:fit-content}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-3xl{max-width:var(--container-3xl)}.max-w-6xl{max-width:var(--container-6xl)}.max-w-\[80\%\]{max-width:80%}.max-w-\[85\%\]{max-width:85%}.max-w-\[1400px\]{max-width:1400px}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-none{max-width:none}.min-w-\[200px\]{min-width:200px}.min-w-full{min-width:100%}.flex-1{flex:1}.shrink-0{flex-shrink:0}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x)var(--tw-translate-y)}.scale-105{--tw-scale-x:105%;--tw-scale-y:105%;--tw-scale-z:105%;scale:var(--tw-scale-x)var(--tw-scale-y)}.rotate-180{rotate:180deg}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize-none{resize:none}.list-inside{list-style-position:inside}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-start{justify-content:flex-start}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.gap-6{gap:calc(var(--spacing)*6)}.gap-8{gap:calc(var(--spacing)*8)}:where(.space-y-0\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*.5)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*.5)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*3)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*3)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*6)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*6)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*8)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*8)*calc(1 - var(--tw-space-y-reverse)))}.gap-x-8{column-gap:calc(var(--spacing)*8)}.gap-y-4{row-gap:calc(var(--spacing)*4)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-4{border-style:var(--tw-border-style);border-width:4px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-l-4{border-left-style:var(--tw-border-style);border-left-width:4px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-none{--tw-border-style:none;border-style:none}.border-amber-100{border-color:var(--color-amber-100)}.border-amber-200{border-color:var(--color-amber-200)}.border-blue-100{border-color:var(--color-blue-100)}.border-blue-200{border-color:var(--color-blue-200)}.border-blue-600{border-color:var(--color-blue-600)}.border-cyan-100{border-color:var(--color-cyan-100)}.border-emerald-100{border-color:var(--color-emerald-100)}.border-indigo-100{border-color:var(--color-indigo-100)}.border-orange-100{border-color:var(--color-orange-100)}.border-pink-100{border-color:var(--color-pink-100)}.border-purple-100{border-color:var(--color-purple-100)}.border-red-200{border-color:var(--color-red-200)}.border-slate-100{border-color:var(--color-slate-100)}.border-slate-200{border-color:var(--color-slate-200)}.border-transparent{border-color:#0000}.border-t-blue-600{border-top-color:var(--color-blue-600)}.border-t-transparent{border-top-color:#0000}.bg-amber-50{background-color:var(--color-amber-50)}.bg-amber-600{background-color:var(--color-amber-600)}.bg-blue-50{background-color:var(--color-blue-50)}.bg-blue-100{background-color:var(--color-blue-100)}.bg-blue-600{background-color:var(--color-blue-600)}.bg-cyan-50{background-color:var(--color-cyan-50)}.bg-emerald-50{background-color:var(--color-emerald-50)}.bg-indigo-50{background-color:var(--color-indigo-50)}.bg-orange-50{background-color:var(--color-orange-50)}.bg-pink-50{background-color:var(--color-pink-50)}.bg-purple-50{background-color:var(--color-purple-50)}.bg-red-50{background-color:var(--color-red-50)}.bg-red-100{background-color:var(--color-red-100)}.bg-slate-50{background-color:var(--color-slate-50)}.bg-slate-50\/50{background-color:#f8fafc80}@supports (color:color-mix(in lab,red,red)){.bg-slate-50\/50{background-color:color-mix(in oklab,var(--color-slate-50)50%,transparent)}}.bg-slate-100{background-color:var(--color-slate-100)}.bg-slate-200{background-color:var(--color-slate-200)}.bg-slate-300{background-color:var(--color-slate-300)}.bg-slate-900{background-color:var(--color-slate-900)}.bg-slate-900\/50{background-color:#0f172b80}@supports (color:color-mix(in lab,red,red)){.bg-slate-900\/50{background-color:color-mix(in oklab,var(--color-slate-900)50%,transparent)}}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.bg-white\/90{background-color:#ffffffe6}@supports (color:color-mix(in lab,red,red)){.bg-white\/90{background-color:color-mix(in oklab,var(--color-white)90%,transparent)}}.p-1{padding:calc(var(--spacing)*1)}.p-1\.5{padding:calc(var(--spacing)*1.5)}.p-2{padding:calc(var(--spacing)*2)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.p-5{padding:calc(var(--spacing)*5)}.p-6{padding:calc(var(--spacing)*6)}.p-8{padding:calc(var(--spacing)*8)}.px-1{padding-inline:calc(var(--spacing)*1)}.px-1\.5{padding-inline:calc(var(--spacing)*1.5)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-5{padding-inline:calc(var(--spacing)*5)}.px-6{padding-inline:calc(var(--spacing)*6)}.px-8{padding-inline:calc(var(--spacing)*8)}.py-0\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.py-2\.5{padding-block:calc(var(--spacing)*2.5)}.py-3{padding-block:calc(var(--spacing)*3)}.py-8{padding-block:calc(var(--spacing)*8)}.py-12{padding-block:calc(var(--spacing)*12)}.pr-1{padding-right:calc(var(--spacing)*1)}.pr-2{padding-right:calc(var(--spacing)*2)}.pr-4{padding-right:calc(var(--spacing)*4)}.pr-12{padding-right:calc(var(--spacing)*12)}.pb-2{padding-bottom:calc(var(--spacing)*2)}.pb-3{padding-bottom:calc(var(--spacing)*3)}.pl-0{padding-left:calc(var(--spacing)*0)}.pl-3{padding-left:calc(var(--spacing)*3)}.pl-4{padding-left:calc(var(--spacing)*4)}.pl-6{padding-left:calc(var(--spacing)*6)}.pl-10{padding-left:calc(var(--spacing)*10)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[8px\]{font-size:8px}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-amber-500{color:var(--color-amber-500)}.text-amber-600{color:var(--color-amber-600)}.text-amber-700{color:var(--color-amber-700)}.text-blue-400{color:var(--color-blue-400)}.text-blue-500{color:var(--color-blue-500)}.text-blue-600{color:var(--color-blue-600)}.text-blue-700{color:var(--color-blue-700)}.text-cyan-600{color:var(--color-cyan-600)}.text-emerald-600{color:var(--color-emerald-600)}.text-indigo-600{color:var(--color-indigo-600)}.text-orange-600{color:var(--color-orange-600)}.text-pink-600{color:var(--color-pink-600)}.text-purple-600{color:var(--color-purple-600)}.text-red-700{color:var(--color-red-700)}.text-red-800{color:var(--color-red-800)}.text-slate-100{color:var(--color-slate-100)}.text-slate-300{color:var(--color-slate-300)}.text-slate-400{color:var(--color-slate-400)}.text-slate-500{color:var(--color-slate-500)}.text-slate-600{color:var(--color-slate-600)}.text-slate-700{color:var(--color-slate-700)}.text-slate-800{color:var(--color-slate-800)}.text-slate-900{color:var(--color-slate-900)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.italic{font-style:italic}.opacity-0{opacity:0}.opacity-20{opacity:.2}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-80{opacity:.8}.opacity-90{opacity:.9}.opacity-100{opacity:1}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-1{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-blue-200{--tw-ring-color:var(--color-blue-200)}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.backdrop-blur-\[2px\]{--tw-backdrop-blur:blur(2px);-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-shadow{transition-property:box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-500{--tw-duration:.5s;transition-duration:.5s}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.outline-none{--tw-outline-style:none;outline-style:none}@media(hover:hover){.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}}.first\:mt-0:first-child{margin-top:calc(var(--spacing)*0)}.last\:mb-0:last-child{margin-bottom:calc(var(--spacing)*0)}.last\:border-0:last-child{border-style:var(--tw-border-style);border-width:0}.last\:pb-0:last-child{padding-bottom:calc(var(--spacing)*0)}@media(hover:hover){.hover\:border-blue-300:hover{border-color:var(--color-blue-300)}.hover\:border-slate-200:hover{border-color:var(--color-slate-200)}.hover\:bg-amber-700:hover{background-color:var(--color-amber-700)}.hover\:bg-blue-50:hover{background-color:var(--color-blue-50)}.hover\:bg-blue-50\/50:hover{background-color:#eff6ff80}@supports (color:color-mix(in lab,red,red)){.hover\:bg-blue-50\/50:hover{background-color:color-mix(in oklab,var(--color-blue-50)50%,transparent)}}.hover\:bg-blue-100:hover{background-color:var(--color-blue-100)}.hover\:bg-blue-700:hover{background-color:var(--color-blue-700)}.hover\:bg-red-50:hover{background-color:var(--color-red-50)}.hover\:bg-red-200:hover{background-color:var(--color-red-200)}.hover\:bg-slate-50:hover{background-color:var(--color-slate-50)}.hover\:bg-slate-100:hover{background-color:var(--color-slate-100)}.hover\:bg-slate-200:hover{background-color:var(--color-slate-200)}.hover\:bg-slate-800:hover{background-color:var(--color-slate-800)}.hover\:bg-white:hover{background-color:var(--color-white)}.hover\:text-blue-600:hover{color:var(--color-blue-600)}.hover\:text-blue-700:hover{color:var(--color-blue-700)}.hover\:text-red-500:hover{color:var(--color-red-500)}.hover\:text-red-600:hover{color:var(--color-red-600)}.hover\:text-slate-600:hover{color:var(--color-slate-600)}.hover\:text-slate-700:hover{color:var(--color-slate-700)}.hover\:underline:hover{text-decoration-line:underline}.hover\:shadow-md:hover{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}}.focus\:border-blue-500:focus{border-color:var(--color-blue-500)}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-blue-500:focus{--tw-ring-color:var(--color-blue-500)}.focus\:ring-blue-500\/10:focus{--tw-ring-color:#3080ff1a}@supports (color:color-mix(in lab,red,red)){.focus\:ring-blue-500\/10:focus{--tw-ring-color:color-mix(in oklab,var(--color-blue-500)10%,transparent)}}.focus\:ring-blue-500\/20:focus{--tw-ring-color:#3080ff33}@supports (color:color-mix(in lab,red,red)){.focus\:ring-blue-500\/20:focus{--tw-ring-color:color-mix(in oklab,var(--color-blue-500)20%,transparent)}}.active\:scale-95:active{--tw-scale-x:95%;--tw-scale-y:95%;--tw-scale-z:95%;scale:var(--tw-scale-x)var(--tw-scale-y)}.disabled\:bg-slate-300:disabled{background-color:var(--color-slate-300)}.disabled\:opacity-50:disabled{opacity:.5}@media(min-width:48rem){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(min-width:64rem){.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}}.no-scrollbar::-webkit-scrollbar{display:none}.no-scrollbar{-ms-overflow-style:none;scrollbar-width:none}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import{L as fe,B as ae,H as ds,W as xs,D as ms,Z as re,C as ne,P as us,G as ps,j as e,h as hs,T as bs,i as gs,M as fs,k as
|
|
2
|
-
${o?`${a.bg} ${a.color} ${a.border} shadow-sm scale-105`:"bg-white text-slate-400 border-slate-100 hover:border-slate-200 hover:text-slate-600"}`,children:[e.jsx(r,{size:12}),p]},p)})})}),Ds=({snippets:s,openSnippetEdit:n,handleDeleteSnippet:p})=>e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6",children:s.map(a=>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:r=>{r.stopPropagation(),n(a)},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(Y,{size:14})}),e.jsx("button",{onClick:r=>{r.stopPropagation(),p(a.identifier,a.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(ye,{size:14})})]}),e.jsxs("div",{onClick:()=>n(a),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:a.title}),e.jsxs("div",{className:"flex flex-col items-end gap-1",children:[a.completionKey&&e.jsx("span",{className:"text-[10px] bg-blue-50 text-blue-700 font-bold px-2 py-1 rounded uppercase tracking-wider",children:a.completionKey}),(()=>{const r=a.category||"Utility",o=T[r]||T.Utility,x=o.icon;return e.jsxs("span",{className:`text-[8px] font-bold px-1.5 py-0.5 rounded uppercase flex items-center gap-1 border ${o.bg} ${o.color} ${o.border}`,children:[e.jsx(x,{size:10}),r]})})()]})]}),e.jsx("p",{className:"text-sm text-slate-600 line-clamp-2 mb-4",children:a.summary}),e.jsx("div",{className:"flex items-center gap-2",children:a.language&&e.jsx("span",{className:"text-xs font-medium text-slate-400 bg-slate-100 px-2 py-1 rounded",children:a.language})})]})]},a.identifier))}),Gs=({recipes:s,openRecipeEdit:n,handleDeleteRecipe:p})=>e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-6",children:s.map(a=>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:r=>{r.stopPropagation(),n(a)},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(Y,{size:14})}),e.jsx("button",{onClick:r=>{r.stopPropagation(),p(a.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(ye,{size:14})})]}),e.jsxs("div",{onClick:()=>n(a),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:a.name}),e.jsxs("div",{className:"flex items-center gap-2",children:[(()=>{var m,d;const r=((d=(m=a.content.match(/category:\s*(.*)/))==null?void 0:m[1])==null?void 0:d.trim())||"Utility",o=T[r]||T.Utility,x=o.icon;return e.jsxs("span",{className:`text-[8px] font-bold px-1.5 py-0.5 rounded uppercase flex items-center gap-1 border ${o.bg} ${o.color} ${o.border}`,children:[e.jsx(x,{size:10}),r]})})(),a.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.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:a.content})]})]},a.name))}),_s=()=>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(Re,{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:"页面说明"}),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"})," 批量扫描产生的候选,通过入库或忽略。"]}),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.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.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"}),":剪贴板 + 当前路径创建 Recipe,打开本页。复制代码后保存即可。"]}),e.jsxs("li",{children:[e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"// as:guard"})," [关键词]:按知识库 AI 审查当前文件,结果输出终端。需 ",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"})," [关键词]:从知识库检索 Recipe/Snippet,选一条插入替换该行。"]})]})]}),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 并配置 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 页。需本 Dashboard 运行。"]})]})]}),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> path"}),"。在项目目录运行 ",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.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("li",{children:[e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"asd install:full"})," [",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"--parser"}),"|",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"--lancedb"}),"]:全量安装;",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"--parser"})," 含 Swift 解析器;",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"--lancedb"})," 仅 LanceDB"]})]})]})]})]}),Hs={objectivec:"objectivec",objc:"objectivec",swift:"swift",markdown:"markdown",md:"markdown"},he=({code:s,language:n="text",className:p="",showLineNumbers:a=!1})=>{const r=Hs[n==null?void 0:n.toLowerCase()]||(n==null?void 0:n.toLowerCase())||"text";return e.jsx("div",{className:`rounded-xl overflow-hidden text-sm ${p}`,children:e.jsx(Is,{language:r,style:zs,showLineNumbers:a,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})})},Ue=({content:s,className:n="",showLineNumbers:p=!1})=>e.jsx("div",{className:`markdown-body text-slate-700 ${n}`,children:e.jsx(Ms,{components:{code({node:a,className:r,children:o,...x}){const m=/language-(\w+)/.exec(r||"");return String(o).includes(`
|
|
3
|
-
`)&&m?e.jsx(he,{code:String(o).replace(/\n$/,""),language:m[1],showLineNumbers:p}):e.jsx("code",{className:"px-1.5 py-0.5 bg-slate-100 text-slate-800 rounded text-sm font-mono",...x,children:o})},p:({children:a})=>e.jsx("p",{className:"mb-3 last:mb-0",children:a}),h1:({children:a})=>e.jsx("h1",{className:"text-xl font-bold mb-2 mt-4 first:mt-0",children:a}),h2:({children:a})=>e.jsx("h2",{className:"text-lg font-bold mb-2 mt-4",children:a}),h3:({children:a})=>e.jsx("h3",{className:"text-base font-bold mb-1 mt-3",children:a}),ul:({children:a})=>e.jsx("ul",{className:"list-disc list-inside mb-3 space-y-1",children:a}),ol:({children:a})=>e.jsx("ol",{className:"list-decimal list-inside mb-3 space-y-1",children:a}),blockquote:({children:a})=>e.jsx("blockquote",{className:"border-l-4 border-slate-200 pl-4 my-3 text-slate-600 italic",children:a}),a:({href:a,children:r})=>e.jsx("a",{href:a,className:"text-blue-600 hover:underline",target:"_blank",rel:"noopener noreferrer",children:r})},children:s})}),Os=({data:s,isShellTarget:n,handleDeleteCandidate:p,onAuditCandidate:a})=>{const[r,o]=h.useState(null);return e.jsxs("div",{className:"flex-1 flex flex-col overflow-hidden",children:[e.jsxs("div",{className:"mb-6 flex justify-between items-center",children:[e.jsxs("h2",{className:"text-xl font-bold flex items-center gap-2",children:[e.jsx(re,{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 批量扫描生成,等待您的审核入库。"})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto pr-2 space-y-8",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(_e,{size:48,className:"mb-4 opacity-20"}),e.jsx("p",{children:"未发现候选内容。请在终端执行 `asd ais --all` 开始扫描。"})]}),s&&Object.entries(s.candidates).sort(([x],[m])=>{const d=n(x),l=n(m);return d&&!l?1:!d&&l?-1:x.localeCompare(m)}).map(([x,m])=>{const d=n(x);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 ${d?"bg-slate-50/50":"bg-white"}`,children:[d?e.jsx(ae,{size:18,className:"text-slate-400"}):e.jsx(ae,{size:18,className:"text-blue-600"}),e.jsx("span",{className:`text-lg font-bold ${d?"text-slate-400":"text-slate-800"}`,children:x}),d&&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 ml-auto",children:["扫描于 ",new Date(m.scanTime).toLocaleString()]})]}),e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:m.items.map(l=>{var f,w,k;return e.jsxs("div",{className:`bg-white rounded-xl border border-slate-200 p-4 hover:shadow-md transition-shadow flex flex-col group ${d?"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 ${d?"text-slate-400":"text-blue-500"}`,children:x}),e.jsx("h3",{className:"font-bold text-sm text-slate-800",children:l.title}),l.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 ${((f=T[l.category])==null?void 0:f.bg)||"bg-slate-50"} ${((w=T[l.category])==null?void 0:w.color)||"text-slate-400"} ${((k=T[l.category])==null?void 0:k.border)||"border-slate-100"}`,children:[(()=>{var i;const I=((i=T[l.category])==null?void 0:i.icon)||fe;return e.jsx(I,{size:10})})(),l.category]})]}),e.jsx("div",{className:"flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity",children:e.jsx("button",{onClick:()=>p(x,l.id),title:"忽略",className:"p-1 hover:bg-red-50 text-slate-400 hover:text-red-500 rounded transition-colors",children:e.jsx(ye,{size:14})})})]}),e.jsx("p",{className:"text-xs text-slate-500 line-clamp-2 mb-4 flex-1 h-8 leading-relaxed",children:l.summary}),r===l.id&&e.jsx("div",{className:"mb-4 rounded-xl overflow-hidden border border-slate-100 bg-slate-50 max-h-60 overflow-y-auto",children:l.code?e.jsx(he,{code:l.code,language:l.language==="objc"?"objectivec":l.language}):e.jsx("div",{className:"p-4",children:e.jsx(Ue,{content:l.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:()=>o(r===l.id?null:l.id),className:`p-1.5 rounded-lg transition-colors ${r===l.id?"bg-blue-100 text-blue-600":"bg-slate-100 text-slate-400 hover:text-blue-600"}`,title:r===l.id?"隐藏预览":"查看代码/指南预览",children:r===l.id?e.jsx(ws,{size:14}):e.jsx(Ne,{size:14})}),e.jsx("span",{className:`text-[10px] font-mono px-2 py-0.5 rounded font-bold ${d?"bg-slate-100 text-slate-500":"bg-blue-50 text-blue-600"}`,children:l.trigger}),e.jsx("span",{className:"text-[10px] text-slate-400 uppercase font-bold",children:l.language})]}),e.jsxs("button",{onClick:()=>a(l),className:"text-[10px] font-bold text-blue-600 hover:underline flex items-center gap-1",children:[e.jsx(Y,{size:12})," 审核并保存"]})]})]},l.id)})})]},x)})]})]})},Ts=({targets:s,filteredTargets:n,selectedTargetName:p,isScanning:a,scanProgress:r,scanFileList:o,scanResults:x,handleScanTarget:m,handleUpdateScanResult:d,handleSaveExtracted:l,isShellTarget:f})=>{const[w,k]=h.useState(null),I=i=>i.language==="objectivec"||i.language==="objc"?"objectivec":i.language||"swift";return 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:n.map(i=>{const j=f(i.name),y=p===i.name;return e.jsxs("button",{onClick:()=>m(i),disabled:a,className:`w-full text-left p-3 rounded-lg flex items-center justify-between group transition-all border ${a?"opacity-50 cursor-not-allowed":"hover:bg-slate-50"} ${y?"bg-blue-50 border-blue-200 ring-1 ring-blue-200":"bg-white border-transparent"} ${j?"opacity-90":""}`,children:[e.jsxs("div",{className:`flex flex-col max-w-[85%] ${j?"opacity-60":""}`,children:[e.jsxs("div",{className:"flex items-center gap-2",children:[!j&&e.jsx("div",{className:"w-1.5 h-1.5 rounded-full shrink-0 bg-blue-600"}),e.jsx("span",{className:`text-sm truncate ${j?"font-medium":"font-bold"} ${y?"text-blue-700":""}`,children:i.name})]}),e.jsx("span",{className:"text-[10px] text-slate-400 truncate pl-3",children:i.packageName})]}),j?e.jsx("span",{className:"text-[9px] font-bold text-slate-300 border border-slate-100 px-1 rounded",children:"SHELL"}):e.jsx(re,{size:14,className:`shrink-0 ${y?"text-blue-500 opacity-100":"text-blue-500 opacity-0 group-hover:opacity-100"} transition-opacity`})]},i.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(Y,{size:16,className:"text-slate-400"}),e.jsxs("span",{children:["审核提取结果 ",x.length>0&&e.jsxs("span",{className:"text-blue-600 ml-1",children:["[",x[0].trigger?"Candidate":"New","]"]})]})]})}),e.jsxs("div",{className:"flex-1 overflow-y-auto p-6 space-y-8 relative",children:[a&&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(ne,{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:r.status}),o.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:["本次扫描的文件 (",o.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:o.map((i,j)=>e.jsx("div",{className:"text-xs font-mono text-slate-600 truncate",title:i.path,children:i.name},j))})]}),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(r.total?r.current/r.total*100:0,98)}%`}})}),e.jsx("p",{className:"text-xs text-slate-400 mt-3",children:r.total?`${Math.round(r.current/r.total*100)}%`:"0%"})]}),!a&&x.length===0&&e.jsxs("div",{className:"h-full flex flex-col items-center justify-center text-slate-400 text-center",children:[e.jsx(ae,{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 识别可复用的代码片段和最佳实践。"})]}),!a&&o.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:["本次扫描的文件 (",o.length,")"]}),e.jsx("div",{className:"flex flex-wrap gap-2",children:o.map((i,j)=>e.jsx("span",{className:"text-xs font-mono bg-white border border-slate-200 text-slate-600 px-2 py-1 rounded",title:i.path,children:i.name},j))})]}),x.map((i,j)=>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:i.title,onChange:y=>d(j,{title:y.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:i.trigger,placeholder:"@cmd",onChange:y=>d(j,{trigger:y.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:i.category,onChange:y=>d(j,{category:y.target.value}),children:Te.filter(y=>y!=="All").map(y=>e.jsx("option",{value:y,children:y},y))})]}),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:()=>d(j,{language:"swift"}),className:`px-2 py-1 rounded-md text-[9px] font-bold transition-all ${i.language==="swift"?"bg-white shadow-sm text-blue-600":"text-slate-400"}`,children:"Swift"}),e.jsx("button",{onClick:()=>d(j,{language:"objectivec"}),className:`px-2 py-1 rounded-md text-[9px] font-bold transition-all ${i.language==="objectivec"||i.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",children:[e.jsx("button",{onClick:()=>d(j,{lang:"cn"}),className:`px-2 py-1 rounded-md text-[9px] font-bold transition-all ${i.lang==="cn"?"bg-white shadow-sm text-blue-600":"text-slate-400"}`,children:"CN"}),e.jsx("button",{onClick:()=>d(j,{lang:"en"}),className:`px-2 py-1 rounded-md text-[9px] font-bold transition-all ${i.lang==="en"?"bg-white shadow-sm text-blue-600":"text-slate-400"}`,children:"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:()=>d(j,{mode:"full"}),className:`px-4 py-1 rounded-md text-[9px] font-bold transition-all ${i.mode==="full"?"bg-white shadow-sm text-blue-600":"text-slate-400"}`,children:"SNIPPET + RECIPE"}),e.jsx("button",{onClick:()=>d(j,{mode:"preview"}),className:`px-4 py-1 rounded-md text-[9px] font-bold transition-all ${i.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:()=>d(j,{includeHeaders:i.includeHeaders===!1}),className:`w-8 h-4 rounded-full relative transition-colors ${i.includeHeaders!==!1?"bg-blue-600":"bg-slate-300"}`,title:i.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 ${i.includeHeaders!==!1?"right-0.5":"left-0.5"}`})}),e.jsx("span",{className:"text-[9px] text-slate-500",children:i.includeHeaders!==!1?"按标记注入":"不引入"})]})]})]}),e.jsx("div",{className:"ml-4",children:e.jsxs("button",{onClick:()=>l(i),className:`text-xs px-5 py-2.5 rounded-xl font-bold transition-all shadow-sm flex items-center gap-2 active:scale-95 ${i.mode==="full"?"bg-blue-600 text-white hover:bg-blue-700":"bg-amber-600 text-white hover:bg-amber-700"}`,children:[e.jsx(He,{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 (摘要) - ",i.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:i.summary,onChange:y=>d(j,{summary:y.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 ",i.moduleName&&e.jsxs("span",{className:"text-slate-400 font-normal",children:["· ",i.moduleName]})]}),i.headers&&i.headers.length>0?e.jsx("div",{className:"flex flex-wrap gap-2",children:i.headers.map((y,P)=>{var _;return e.jsx("span",{className:"text-[10px] bg-slate-200 text-slate-600 px-2 py-0.5 rounded font-mono",title:(_=i.headerPaths)!=null&&_[P]?`相对路径: ${i.headerPaths[P]}`:void 0,children:y},P)})}):e.jsx("p",{className:"text-[10px] text-slate-400",children:"未解析到头文件(剪贴板需含 #import,且路径在 target 下)"})]}),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 (标准使用示例)"}),w===j?e.jsxs("button",{type:"button",onClick:()=>k(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(vs,{size:12})," 完成"]}):e.jsxs("button",{type:"button",onClick:()=>k(j),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(Cs,{size:12})," 编辑"]})]}),w===j?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,i.code.split(`
|
|
4
|
-
`).length),value:i.code,onChange:y=>d(j,{code:y.target.value})})}):e.jsx(he,{code:i.code,language:I(i),showLineNumbers:!0})]}),e.jsxs("div",{children:[e.jsxs("label",{className:"block text-[10px] font-bold text-slate-400 uppercase mb-1",children:["Usage Guide (使用指南) - ",i.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:i.usageGuide,onChange:y=>d(j,{usageGuide:y.target.value})})]})]})]},j))]})]})]})},xe=72,me=48,X=40,Fe=36,K=140,ue=40;function Us(s,n){const p=new Set(s.map(m=>m.id)),a=new Map;for(const m of n)!p.has(m.from)||!p.has(m.to)||(a.has(m.from)||a.set(m.from,[]),a.get(m.from).push(m.to));const r=new Map,o=new Set;function x(m){if(r.has(m))return r.get(m);if(o.has(m))return 0;o.add(m);const d=a.get(m);if(!d||d.length===0)return r.set(m,0),o.delete(m),0;const l=1+Math.max(...d.map(x));return r.set(m,l),o.delete(m),l}return s.forEach(m=>x(m.id)),r}function Fs(s,n){const p=Us(s,n),a=new Map;for(const d of s){const l=p.get(d.id)??0;a.has(l)||a.set(l,[]),a.get(l).push(d.id)}const r=[...new Set(p.values())].sort((d,l)=>d-l),o=[...r].reverse(),x=new Map,m=r.reduce((d,l)=>{const f=a.get(l)??[],w=(f.length-1)*me+f.length*K;return Math.max(d,w)},0);return o.forEach((d,l)=>{const f=a.get(d)??[],w=(f.length-1)*me+f.length*K,k=(m-w)/2;f.forEach((I,i)=>{const j=X+Fe+k+i*(K+me)+K/2,y=X+l*xe+ue/2;x.set(I,{x:j,y})})}),{positions:x,tiers:p,tierOrder:r}}const Ws=()=>{const[s,n]=h.useState(null),[p,a]=h.useState(!0),[r,o]=h.useState(null),[x,m]=h.useState(null),d=async()=>{var b,$;a(!0),o(null);try{const A=(await S.get("/api/dep-graph")).data;n({nodes:Array.isArray(A==null?void 0:A.nodes)?A.nodes:[],edges:Array.isArray(A==null?void 0:A.edges)?A.edges:[],projectRoot:(A==null?void 0:A.projectRoot)??null,generatedAt:A==null?void 0:A.generatedAt})}catch(C){o((($=(b=C.response)==null?void 0:b.data)==null?void 0:$.error)||C.message||"Failed to load dependency graph")}finally{a(!1)}};h.useEffect(()=>{d()},[]);const l=Array.isArray(s==null?void 0:s.nodes)?s.nodes:[],f=Array.isArray(s==null?void 0:s.edges)?s.edges:[],{positions:w,tiers:k,tierOrder:I}=h.useMemo(()=>Fs(l,f),[l,f]),i=h.useMemo(()=>{const b=new Map;return l.forEach($=>{const C=k.get($.id)??0;b.has(C)||b.set(C,[]),b.get(C).push($.id)}),b},[l,k]),j=h.useMemo(()=>[...I].reverse(),[I]),{dependsOn:y,dependedBy:P}=h.useMemo(()=>{const b=new Map,$=new Map;return f.forEach(C=>{b.has(C.from)||b.set(C.from,[]),b.get(C.from).push(C.to),$.has(C.to)||$.set(C.to,[]),$.get(C.to).push(C.from)}),{dependsOn:b,dependedBy:$}},[f]),_=I.length,v=Math.max(...I.map(b=>(i.get(b)??[]).length),1),oe=(v-1)*me+v*K+Fe*2,Z=Math.max(600,X*2+oe),J=Math.max(420,X*2+_*xe),R=[{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)"}],U=b=>R[Math.min(b,R.length-1)]??R[0];return p?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"})}):r?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:r}),e.jsx("button",{type:"button",onClick:d,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||l.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(fe,{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:d,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(je,{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:J,viewBox:`0 0 ${Z} ${J}`,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"})})}),j.map((b,$)=>{const C=U($),A=X+$*xe;return e.jsx("rect",{x:X,y:A-ue/2-4,width:oe,height:xe+8,rx:8,fill:C.bg,stroke:C.border,strokeWidth:"1",opacity:.6},b)}),l.map(b=>{const $=w.get(b.id);if(!$)return null;const C=k.get(b.id)??0,A=U(j.indexOf(C)),ce=b.label.length>14?b.label.slice(0,13)+"…":b.label,Q=x===b.id,H=x?(y.get(x)??[]).includes(b.id):!1,ee=x?(P.get(x)??[]).includes(b.id):!1,se=x&&!Q&&!H&&!ee,D=x?Q?{fill:"white",stroke:"rgb(59 130 246)",text:"rgb(30 64 175)",strokeWidth:3,opacity:1}:H?{fill:"rgb(240 253 244)",stroke:"rgb(34 197 94)",text:"rgb(22 101 52)",strokeWidth:2,opacity:1}:ee?{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:A.border,text:A.text,strokeWidth:2,opacity:1};return e.jsxs("g",{style:{cursor:"pointer",opacity:D.opacity},onClick:()=>m(Q?null:b.id),children:[e.jsx("rect",{x:$.x-K/2,y:$.y-ue/2,width:K,height:ue,rx:10,ry:10,fill:D.fill,stroke:D.stroke,strokeWidth:D.strokeWidth,filter:se?void 0:"url(#nodeShadow)"}),e.jsx("text",{x:$.x,y:$.y,textAnchor:"middle",dominantBaseline:"middle",fontSize:"12",fontWeight:"600",fill:D.text,pointerEvents:"none",children:ce})]},b.id)})]}),x&&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:x}),e.jsx("button",{type:"button",onClick:()=>m(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:(y.get(x)??[]).length===0?e.jsx("li",{className:"text-slate-400",children:"无"}):(y.get(x)??[]).map(b=>e.jsxs("li",{children:["→ ",b]},b))})]}),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:(P.get(x)??[]).length===0?e.jsx("li",{className:"text-slate-400",children:"无"}):(P.get(x)??[]).map(b=>e.jsxs("li",{children:["← ",b]},b))})]})]})]})]}),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:["包列表 (",l.length,")"]}),e.jsx("ul",{className:"text-sm space-y-3 max-h-[280px] overflow-y-auto pr-1",children:l.map(b=>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:b.id}),b.packageDir&&e.jsxs("span",{className:"text-slate-500 text-xs",children:["· ",b.packageDir]})]}),b.targets&&b.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:b.targets.join(", ")})]})]},b.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:["依赖关系(小图)(",f.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:f.map((b,$)=>e.jsxs("li",{className:"flex items-center gap-2 text-slate-700",children:[e.jsx("span",{className:"font-semibold text-slate-800",children:b.from}),e.jsx("span",{className:"text-slate-400 shrink-0",children:"→"}),e.jsx("span",{className:"font-semibold text-slate-800",children:b.to})]},`${b.from}-${b.to}-${$}`))})]})]})]})},Bs=({chatHistory:s,userInput:n,setUserInput:p,handleChat:a,isAiThinking:r})=>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((o,x)=>e.jsx("div",{className:`flex ${o.role==="user"?"justify-end":"justify-start"}`,children:e.jsx("div",{className:`max-w-[80%] p-3 rounded-xl text-sm ${o.role==="user"?"bg-blue-600 text-white":"bg-white border border-slate-200 text-slate-800"}`,children:o.text})},x)),r&&e.jsx("div",{className:"text-slate-400 text-xs animate-pulse",children:"AI is thinking..."})]}),e.jsxs("form",{onSubmit:a,className:"flex gap-2 bg-white p-2 rounded-xl border border-slate-200 shadow-sm",children:[e.jsx("input",{type:"text",value:n,onChange:o=>p(o.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:r,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"})]})]}),Ks=({editingSnippet:s,setEditingSnippet:n,handleSaveSnippet:p,closeSnippetEdit:a})=>{const[r,o]=h.useState("preview"),x=(s.content||s.body||[]).join(`
|
|
1
|
+
import{L as fe,B as ae,H as ds,W as xs,D as ms,Z as re,C as ne,P as us,G as ps,j as e,h as hs,T as bs,i as gs,M as fs,k as De,l as je,m as h,n as S,S as Le,o as js,p as Ns,q as ys,s as _e,w as Y,x as Ne,F as Ge,E as ws,y as ye,z as Oe,A as vs,I as Cs,X as pe,J as ks,K as He,N as Ss,O as As,R as Is}from"./vendor-CAT0H0kn.js";import{h as $s,o as zs,M as Ps}from"./markdown-CBiIpHBr.js";(function(){const n=document.createElement("link").relList;if(n&&n.supports&&n.supports("modulepreload"))return;for(const r of document.querySelectorAll('link[rel="modulepreload"]'))a(r);new MutationObserver(r=>{for(const o of r)if(o.type==="childList")for(const x of o.addedNodes)x.tagName==="LINK"&&x.rel==="modulepreload"&&a(x)}).observe(document,{childList:!0,subtree:!0});function p(r){const o={};return r.integrity&&(o.integrity=r.integrity),r.referrerPolicy&&(o.referrerPolicy=r.referrerPolicy),r.crossOrigin==="use-credentials"?o.credentials="include":r.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function a(r){if(r.ep)return;r.ep=!0;const o=p(r);fetch(r.href,o)}})();const T={All:{icon:ps,color:"text-slate-600",bg:"bg-slate-100",border:"border-slate-200"},View:{icon:us,color:"text-pink-600",bg:"bg-pink-50",border:"border-pink-100"},Service:{icon:ne,color:"text-indigo-600",bg:"bg-indigo-50",border:"border-indigo-100"},Tool:{icon:re,color:"text-amber-600",bg:"bg-amber-50",border:"border-amber-100"},Model:{icon:ms,color:"text-emerald-600",bg:"bg-emerald-50",border:"border-emerald-100"},Network:{icon:xs,color:"text-blue-600",bg:"bg-blue-50",border:"border-blue-100"},Storage:{icon:ds,color:"text-purple-600",bg:"bg-purple-50",border:"border-purple-100"},UI:{icon:ae,color:"text-cyan-600",bg:"bg-cyan-50",border:"border-cyan-100"},Utility:{icon:fe,color:"text-orange-600",bg:"bg-orange-50",border:"border-orange-100"}},Te=["All","View","Service","Tool","Model","Network","Storage","UI","Utility"],Ms=["snippets","recipes","ai","spm","candidates","depgraph","help"],de=s=>["Example","Demo","Sample","Tests","Spec","Mock","Runner"].some(p=>s.endsWith(p)||s.includes(p)),Rs=({activeTab:s,navigateToTab:n,handleRefreshProject:p,candidateCount:a})=>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(hs,{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:()=>n("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(bs,{size:20}),e.jsx("span",{children:"Snippets"})]}),e.jsxs("button",{type:"button",onClick:()=>n("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(ne,{size:20}),e.jsx("span",{children:"Recipes"})]}),e.jsxs("button",{type:"button",onClick:()=>n("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(ae,{size:20}),e.jsx("span",{children:"SPM Explorer"})]}),e.jsxs("button",{type:"button",onClick:()=>n("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(re,{size:20}),e.jsxs("span",{children:["Candidates (",a,")"]})]}),e.jsxs("button",{type:"button",onClick:()=>n("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:()=>n("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(fs,{size:20}),e.jsx("span",{children:"AI Assistant"})]}),e.jsxs("button",{type:"button",onClick:()=>n("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(De,{size:20}),e.jsx("span",{children:"使用说明"})]})]}),e.jsx("div",{className:"p-4 border-t border-slate-100",children:e.jsxs("button",{onClick:p,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(je,{size:12})," Refresh Project"]})})]}),Es=({searchQuery:s,setSearchQuery:n,setShowCreateModal:p,handleSyncToXcode:a,aiConfig:r,onSemanticSearchResults:o,onBeforeAiSwitch:x,onAiConfigChange:m})=>{const[d,l]=h.useState(!1),[f,w]=h.useState(!1),[k,$]=h.useState([]),[i,j]=h.useState(!1),N=h.useRef(null);h.useEffect(()=>{f&&k.length===0&&S.get("/api/ai/providers").then(v=>$(v.data)).catch(()=>{})},[f,k.length]),h.useEffect(()=>{const v=E=>{N.current&&!N.current.contains(E.target)&&w(!1)};return document.addEventListener("click",v),()=>document.removeEventListener("click",v)},[]);const M=async()=>{if(s){l(!0);try{const v=await S.post("/api/search/semantic",{keyword:s});o&&o(v.data)}catch(v){console.error("Semantic search failed",v),alert("语义搜索失败。请确保已运行 asd embed 构建索引。")}finally{l(!1)}}},G=async v=>{j(!0);try{x==null||x(),await S.post("/api/ai/config",{provider:v.id,model:v.defaultModel}),w(!1),m&&m()}catch(E){console.error("AI config update failed",E),alert("切换 AI 失败,请检查项目根目录是否可写。")}finally{j(!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(Le,{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:v=>n(v.target.value),onKeyDown:v=>v.key==="Enter"&&M()})]}),e.jsxs("button",{onClick:M,disabled:!s||d,className:`flex items-center gap-2 px-3 py-2 rounded-lg text-xs font-bold transition-all ${d?"bg-blue-50 text-blue-400":"bg-blue-50 text-blue-600 hover:bg-blue-100"}`,title:"Semantic Search (Brain AI)",children:[d?e.jsx(js,{size:14,className:"animate-spin"}):e.jsx(Ns,{size:14}),"Semantic"]})]}),e.jsxs("div",{className:"flex items-center gap-4",children:[r&&e.jsxs("div",{className:"relative",ref:N,children:[e.jsxs("button",{type:"button",onClick:v=>{v.stopPropagation(),w(E=>!E)},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(ne,{size:14}),r.provider," / ",r.model,e.jsx(ys,{size:12,className:f?"rotate-180":""})]}),f&&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 读取"}),k.length===0?e.jsx("div",{className:"px-3 py-2 text-xs text-slate-400",children:"加载中..."}):k.map(v=>e.jsxs("button",{type:"button",disabled:i,onClick:()=>G(v),className:`w-full text-left px-3 py-2 text-sm hover:bg-slate-50 flex items-center justify-between ${r.provider===v.id?"bg-blue-50 text-blue-700 font-medium":"text-slate-700"}`,children:[e.jsx("span",{children:v.label}),r.provider===v.id&&e.jsx("span",{className:"text-xs",children:"✓"})]},v.id))]})]}),e.jsxs("button",{onClick:()=>p(!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(_e,{size:16})," New Recipe"]}),e.jsxs("button",{onClick:a,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(je,{size:16})," Sync to Xcode"]})]})]})},Ds=({selectedCategory:s,setSelectedCategory:n})=>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(T).map(([p,a])=>{const r=a.icon,o=s===p;return e.jsxs("button",{onClick:()=>n(p),className:`flex items-center gap-1.5 px-3 py-1.5 rounded-full text-[10px] font-bold transition-all border whitespace-nowrap
|
|
2
|
+
${o?`${a.bg} ${a.color} ${a.border} shadow-sm scale-105`:"bg-white text-slate-400 border-slate-100 hover:border-slate-200 hover:text-slate-600"}`,children:[e.jsx(r,{size:12}),p]},p)})})}),Ls=({snippets:s,openSnippetEdit:n,handleDeleteSnippet:p})=>e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6",children:s.map(a=>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:r=>{r.stopPropagation(),n(a)},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(Y,{size:14})}),e.jsx("button",{onClick:r=>{r.stopPropagation(),p(a.identifier,a.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(Ne,{size:14})})]}),e.jsxs("div",{onClick:()=>n(a),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:a.title}),e.jsxs("div",{className:"flex flex-col items-end gap-1",children:[a.completionKey&&e.jsx("span",{className:"text-[10px] bg-blue-50 text-blue-700 font-bold px-2 py-1 rounded uppercase tracking-wider",children:a.completionKey}),(()=>{const r=a.category||"Utility",o=T[r]||T.Utility,x=o.icon;return e.jsxs("span",{className:`text-[8px] font-bold px-1.5 py-0.5 rounded uppercase flex items-center gap-1 border ${o.bg} ${o.color} ${o.border}`,children:[e.jsx(x,{size:10}),r]})})()]})]}),e.jsx("p",{className:"text-sm text-slate-600 line-clamp-2 mb-4",children:a.summary}),e.jsx("div",{className:"flex items-center gap-2",children:a.language&&e.jsx("span",{className:"text-xs font-medium text-slate-400 bg-slate-100 px-2 py-1 rounded",children:a.language})})]})]},a.identifier))}),_s=({recipes:s,openRecipeEdit:n,handleDeleteRecipe:p})=>e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-6",children:s.map(a=>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:r=>{r.stopPropagation(),n(a)},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(Y,{size:14})}),e.jsx("button",{onClick:r=>{r.stopPropagation(),p(a.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(Ne,{size:14})})]}),e.jsxs("div",{onClick:()=>n(a),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:a.name}),e.jsxs("div",{className:"flex items-center gap-2",children:[(()=>{var m,d;const r=((d=(m=a.content.match(/category:\s*(.*)/))==null?void 0:m[1])==null?void 0:d.trim())||"Utility",o=T[r]||T.Utility,x=o.icon;return e.jsxs("span",{className:`text-[8px] font-bold px-1.5 py-0.5 rounded uppercase flex items-center gap-1 border ${o.bg} ${o.color} ${o.border}`,children:[e.jsx(x,{size:10}),r]})})(),a.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.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:a.content})]})]},a.name))}),Gs=()=>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(De,{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"})," 批量扫描产生的候选,通过入库或忽略。"]}),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.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"}),":剪贴板 + 当前路径创建 Recipe,打开本页。复制代码后保存即可。"]}),e.jsxs("li",{children:[e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"// as:guard"})," [关键词]:按知识库 AI 审查当前文件,结果输出终端。需 ",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"})," [关键词]:从知识库检索 Recipe/Snippet,选一条插入替换该行。"]})]})]}),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 并配置 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 页。需本 Dashboard 运行。"]})]})]}),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> path"}),"。在项目目录运行 ",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.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("p",{className:"text-slate-600 mt-2",children:["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.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"})," 的目录"]})]})]})]})]}),Os={objectivec:"objectivec",objc:"objectivec",swift:"swift",markdown:"markdown",md:"markdown"},he=({code:s,language:n="text",className:p="",showLineNumbers:a=!1})=>{const r=Os[n==null?void 0:n.toLowerCase()]||(n==null?void 0:n.toLowerCase())||"text";return e.jsx("div",{className:`rounded-xl overflow-hidden text-sm ${p}`,children:e.jsx($s,{language:r,style:zs,showLineNumbers:a,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})})},Ue=({content:s,className:n="",showLineNumbers:p=!1})=>e.jsx("div",{className:`markdown-body text-slate-700 ${n}`,children:e.jsx(Ps,{components:{code({node:a,className:r,children:o,...x}){const m=/language-(\w+)/.exec(r||"");return String(o).includes(`
|
|
3
|
+
`)&&m?e.jsx(he,{code:String(o).replace(/\n$/,""),language:m[1],showLineNumbers:p}):e.jsx("code",{className:"px-1.5 py-0.5 bg-slate-100 text-slate-800 rounded text-sm font-mono",...x,children:o})},p:({children:a})=>e.jsx("p",{className:"mb-3 last:mb-0",children:a}),h1:({children:a})=>e.jsx("h1",{className:"text-xl font-bold mb-2 mt-4 first:mt-0",children:a}),h2:({children:a})=>e.jsx("h2",{className:"text-lg font-bold mb-2 mt-4",children:a}),h3:({children:a})=>e.jsx("h3",{className:"text-base font-bold mb-1 mt-3",children:a}),ul:({children:a})=>e.jsx("ul",{className:"list-disc list-inside mb-3 space-y-1",children:a}),ol:({children:a})=>e.jsx("ol",{className:"list-decimal list-inside mb-3 space-y-1",children:a}),blockquote:({children:a})=>e.jsx("blockquote",{className:"border-l-4 border-slate-200 pl-4 my-3 text-slate-600 italic",children:a}),a:({href:a,children:r})=>e.jsx("a",{href:a,className:"text-blue-600 hover:underline",target:"_blank",rel:"noopener noreferrer",children:r})},children:s})}),Hs=({data:s,isShellTarget:n,handleDeleteCandidate:p,onAuditCandidate:a})=>{const[r,o]=h.useState(null);return e.jsxs("div",{className:"flex-1 flex flex-col overflow-hidden",children:[e.jsxs("div",{className:"mb-6 flex justify-between items-center",children:[e.jsxs("h2",{className:"text-xl font-bold flex items-center gap-2",children:[e.jsx(re,{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 批量扫描生成,等待您的审核入库。"})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto pr-2 space-y-8",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(Ge,{size:48,className:"mb-4 opacity-20"}),e.jsx("p",{children:"未发现候选内容。请在终端执行 `asd ais --all` 开始扫描。"})]}),s&&Object.entries(s.candidates).sort(([x],[m])=>{const d=n(x),l=n(m);return d&&!l?1:!d&&l?-1:x.localeCompare(m)}).map(([x,m])=>{const d=n(x);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 ${d?"bg-slate-50/50":"bg-white"}`,children:[d?e.jsx(ae,{size:18,className:"text-slate-400"}):e.jsx(ae,{size:18,className:"text-blue-600"}),e.jsx("span",{className:`text-lg font-bold ${d?"text-slate-400":"text-slate-800"}`,children:x}),d&&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 ml-auto",children:["扫描于 ",new Date(m.scanTime).toLocaleString()]})]}),e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:m.items.map(l=>{var f,w,k;return e.jsxs("div",{className:`bg-white rounded-xl border border-slate-200 p-4 hover:shadow-md transition-shadow flex flex-col group ${d?"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 ${d?"text-slate-400":"text-blue-500"}`,children:x}),e.jsx("h3",{className:"font-bold text-sm text-slate-800",children:l.title}),l.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 ${((f=T[l.category])==null?void 0:f.bg)||"bg-slate-50"} ${((w=T[l.category])==null?void 0:w.color)||"text-slate-400"} ${((k=T[l.category])==null?void 0:k.border)||"border-slate-100"}`,children:[(()=>{var i;const $=((i=T[l.category])==null?void 0:i.icon)||fe;return e.jsx($,{size:10})})(),l.category]})]}),e.jsx("div",{className:"flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity",children:e.jsx("button",{onClick:()=>p(x,l.id),title:"忽略",className:"p-1 hover:bg-red-50 text-slate-400 hover:text-red-500 rounded transition-colors",children:e.jsx(Ne,{size:14})})})]}),e.jsx("p",{className:"text-xs text-slate-500 line-clamp-2 mb-4 flex-1 h-8 leading-relaxed",children:l.summary}),r===l.id&&e.jsx("div",{className:"mb-4 rounded-xl overflow-hidden border border-slate-100 bg-slate-50 max-h-60 overflow-y-auto",children:l.code?e.jsx(he,{code:l.code,language:l.language==="objc"?"objectivec":l.language}):e.jsx("div",{className:"p-4",children:e.jsx(Ue,{content:l.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:()=>o(r===l.id?null:l.id),className:`p-1.5 rounded-lg transition-colors ${r===l.id?"bg-blue-100 text-blue-600":"bg-slate-100 text-slate-400 hover:text-blue-600"}`,title:r===l.id?"隐藏预览":"查看代码/指南预览",children:r===l.id?e.jsx(ws,{size:14}):e.jsx(ye,{size:14})}),e.jsx("span",{className:`text-[10px] font-mono px-2 py-0.5 rounded font-bold ${d?"bg-slate-100 text-slate-500":"bg-blue-50 text-blue-600"}`,children:l.trigger}),e.jsx("span",{className:"text-[10px] text-slate-400 uppercase font-bold",children:l.language})]}),e.jsxs("button",{onClick:()=>a(l),className:"text-[10px] font-bold text-blue-600 hover:underline flex items-center gap-1",children:[e.jsx(Y,{size:12})," 审核并保存"]})]})]},l.id)})})]},x)})]})]})},Ts=({targets:s,filteredTargets:n,selectedTargetName:p,isScanning:a,scanProgress:r,scanFileList:o,scanResults:x,handleScanTarget:m,handleUpdateScanResult:d,handleSaveExtracted:l,isShellTarget:f})=>{const[w,k]=h.useState(null),$=i=>i.language==="objectivec"||i.language==="objc"?"objectivec":i.language||"swift";return 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:n.map(i=>{const j=f(i.name),N=p===i.name;return e.jsxs("button",{onClick:()=>m(i),disabled:a,className:`w-full text-left p-3 rounded-lg flex items-center justify-between group transition-all border ${a?"opacity-50 cursor-not-allowed":"hover:bg-slate-50"} ${N?"bg-blue-50 border-blue-200 ring-1 ring-blue-200":"bg-white border-transparent"} ${j?"opacity-90":""}`,children:[e.jsxs("div",{className:`flex flex-col max-w-[85%] ${j?"opacity-60":""}`,children:[e.jsxs("div",{className:"flex items-center gap-2",children:[!j&&e.jsx("div",{className:"w-1.5 h-1.5 rounded-full shrink-0 bg-blue-600"}),e.jsx("span",{className:`text-sm truncate ${j?"font-medium":"font-bold"} ${N?"text-blue-700":""}`,children:i.name})]}),e.jsx("span",{className:"text-[10px] text-slate-400 truncate pl-3",children:i.packageName})]}),j?e.jsx("span",{className:"text-[9px] font-bold text-slate-300 border border-slate-100 px-1 rounded",children:"SHELL"}):e.jsx(re,{size:14,className:`shrink-0 ${N?"text-blue-500 opacity-100":"text-blue-500 opacity-0 group-hover:opacity-100"} transition-opacity`})]},i.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(Y,{size:16,className:"text-slate-400"}),e.jsxs("span",{children:["审核提取结果 ",x.length>0&&e.jsxs("span",{className:"text-blue-600 ml-1",children:["[",x[0].trigger?"Candidate":"New","]"]})]})]})}),e.jsxs("div",{className:"flex-1 overflow-y-auto p-6 space-y-8 relative",children:[a&&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(ne,{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:r.status}),o.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:["本次扫描的文件 (",o.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:o.map((i,j)=>e.jsx("div",{className:"text-xs font-mono text-slate-600 truncate",title:i.path,children:i.name},j))})]}),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(r.total?r.current/r.total*100:0,98)}%`}})}),e.jsx("p",{className:"text-xs text-slate-400 mt-3",children:r.total?`${Math.round(r.current/r.total*100)}%`:"0%"})]}),!a&&x.length===0&&e.jsxs("div",{className:"h-full flex flex-col items-center justify-center text-slate-400 text-center",children:[e.jsx(ae,{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 识别可复用的代码片段和最佳实践。"})]}),!a&&o.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:["本次扫描的文件 (",o.length,")"]}),e.jsx("div",{className:"flex flex-wrap gap-2",children:o.map((i,j)=>e.jsx("span",{className:"text-xs font-mono bg-white border border-slate-200 text-slate-600 px-2 py-1 rounded",title:i.path,children:i.name},j))})]}),x.map((i,j)=>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:i.title,onChange:N=>d(j,{title:N.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:i.trigger,placeholder:"@cmd",onChange:N=>d(j,{trigger:N.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:i.category,onChange:N=>d(j,{category:N.target.value}),children:Te.filter(N=>N!=="All").map(N=>e.jsx("option",{value:N,children:N},N))})]}),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:()=>d(j,{language:"swift"}),className:`px-2 py-1 rounded-md text-[9px] font-bold transition-all ${i.language==="swift"?"bg-white shadow-sm text-blue-600":"text-slate-400"}`,children:"Swift"}),e.jsx("button",{onClick:()=>d(j,{language:"objectivec"}),className:`px-2 py-1 rounded-md text-[9px] font-bold transition-all ${i.language==="objectivec"||i.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",children:[e.jsx("button",{onClick:()=>d(j,{lang:"cn"}),className:`px-2 py-1 rounded-md text-[9px] font-bold transition-all ${i.lang==="cn"?"bg-white shadow-sm text-blue-600":"text-slate-400"}`,children:"CN"}),e.jsx("button",{onClick:()=>d(j,{lang:"en"}),className:`px-2 py-1 rounded-md text-[9px] font-bold transition-all ${i.lang==="en"?"bg-white shadow-sm text-blue-600":"text-slate-400"}`,children:"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:()=>d(j,{mode:"full"}),className:`px-4 py-1 rounded-md text-[9px] font-bold transition-all ${i.mode==="full"?"bg-white shadow-sm text-blue-600":"text-slate-400"}`,children:"SNIPPET + RECIPE"}),e.jsx("button",{onClick:()=>d(j,{mode:"preview"}),className:`px-4 py-1 rounded-md text-[9px] font-bold transition-all ${i.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:()=>d(j,{includeHeaders:i.includeHeaders===!1}),className:`w-8 h-4 rounded-full relative transition-colors ${i.includeHeaders!==!1?"bg-blue-600":"bg-slate-300"}`,title:i.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 ${i.includeHeaders!==!1?"right-0.5":"left-0.5"}`})}),e.jsx("span",{className:"text-[9px] text-slate-500",children:i.includeHeaders!==!1?"按标记注入":"不引入"})]})]})]}),e.jsx("div",{className:"ml-4",children:e.jsxs("button",{onClick:()=>l(i),className:`text-xs px-5 py-2.5 rounded-xl font-bold transition-all shadow-sm flex items-center gap-2 active:scale-95 ${i.mode==="full"?"bg-blue-600 text-white hover:bg-blue-700":"bg-amber-600 text-white hover:bg-amber-700"}`,children:[e.jsx(Oe,{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 (摘要) - ",i.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:i.summary,onChange:N=>d(j,{summary:N.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 ",i.moduleName&&e.jsxs("span",{className:"text-slate-400 font-normal",children:["· ",i.moduleName]})]}),i.headers&&i.headers.length>0?e.jsx("div",{className:"flex flex-wrap gap-2",children:i.headers.map((N,M)=>{var G;return e.jsx("span",{className:"text-[10px] bg-slate-200 text-slate-600 px-2 py-0.5 rounded font-mono",title:(G=i.headerPaths)!=null&&G[M]?`相对路径: ${i.headerPaths[M]}`:void 0,children:N},M)})}):e.jsx("p",{className:"text-[10px] text-slate-400",children:"未解析到头文件(剪贴板需含 #import,且路径在 target 下)"})]}),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 (标准使用示例)"}),w===j?e.jsxs("button",{type:"button",onClick:()=>k(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(vs,{size:12})," 完成"]}):e.jsxs("button",{type:"button",onClick:()=>k(j),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(Cs,{size:12})," 编辑"]})]}),w===j?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,i.code.split(`
|
|
4
|
+
`).length),value:i.code,onChange:N=>d(j,{code:N.target.value})})}):e.jsx(he,{code:i.code,language:$(i),showLineNumbers:!0})]}),e.jsxs("div",{children:[e.jsxs("label",{className:"block text-[10px] font-bold text-slate-400 uppercase mb-1",children:["Usage Guide (使用指南) - ",i.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:i.usageGuide,onChange:N=>d(j,{usageGuide:N.target.value})})]})]})]},j))]})]})]})},xe=72,me=48,X=40,Fe=36,B=140,ue=40;function Us(s,n){const p=new Set(s.map(m=>m.id)),a=new Map;for(const m of n)!p.has(m.from)||!p.has(m.to)||(a.has(m.from)||a.set(m.from,[]),a.get(m.from).push(m.to));const r=new Map,o=new Set;function x(m){if(r.has(m))return r.get(m);if(o.has(m))return 0;o.add(m);const d=a.get(m);if(!d||d.length===0)return r.set(m,0),o.delete(m),0;const l=1+Math.max(...d.map(x));return r.set(m,l),o.delete(m),l}return s.forEach(m=>x(m.id)),r}function Fs(s,n){const p=Us(s,n),a=new Map;for(const d of s){const l=p.get(d.id)??0;a.has(l)||a.set(l,[]),a.get(l).push(d.id)}const r=[...new Set(p.values())].sort((d,l)=>d-l),o=[...r].reverse(),x=new Map,m=r.reduce((d,l)=>{const f=a.get(l)??[],w=(f.length-1)*me+f.length*B;return Math.max(d,w)},0);return o.forEach((d,l)=>{const f=a.get(d)??[],w=(f.length-1)*me+f.length*B,k=(m-w)/2;f.forEach(($,i)=>{const j=X+Fe+k+i*(B+me)+B/2,N=X+l*xe+ue/2;x.set($,{x:j,y:N})})}),{positions:x,tiers:p,tierOrder:r}}const Ws=()=>{const[s,n]=h.useState(null),[p,a]=h.useState(!0),[r,o]=h.useState(null),[x,m]=h.useState(null),d=async()=>{var b,I;a(!0),o(null);try{const A=(await S.get("/api/dep-graph")).data;n({nodes:Array.isArray(A==null?void 0:A.nodes)?A.nodes:[],edges:Array.isArray(A==null?void 0:A.edges)?A.edges:[],projectRoot:(A==null?void 0:A.projectRoot)??null,generatedAt:A==null?void 0:A.generatedAt})}catch(C){o(((I=(b=C.response)==null?void 0:b.data)==null?void 0:I.error)||C.message||"Failed to load dependency graph")}finally{a(!1)}};h.useEffect(()=>{d()},[]);const l=Array.isArray(s==null?void 0:s.nodes)?s.nodes:[],f=Array.isArray(s==null?void 0:s.edges)?s.edges:[],{positions:w,tiers:k,tierOrder:$}=h.useMemo(()=>Fs(l,f),[l,f]),i=h.useMemo(()=>{const b=new Map;return l.forEach(I=>{const C=k.get(I.id)??0;b.has(C)||b.set(C,[]),b.get(C).push(I.id)}),b},[l,k]),j=h.useMemo(()=>[...$].reverse(),[$]),{dependsOn:N,dependedBy:M}=h.useMemo(()=>{const b=new Map,I=new Map;return f.forEach(C=>{b.has(C.from)||b.set(C.from,[]),b.get(C.from).push(C.to),I.has(C.to)||I.set(C.to,[]),I.get(C.to).push(C.from)}),{dependsOn:b,dependedBy:I}},[f]),G=$.length,v=Math.max(...$.map(b=>(i.get(b)??[]).length),1),oe=(v-1)*me+v*B+Fe*2,Z=Math.max(600,X*2+oe),J=Math.max(420,X*2+G*xe),D=[{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)"}],U=b=>D[Math.min(b,D.length-1)]??D[0];return p?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"})}):r?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:r}),e.jsx("button",{type:"button",onClick:d,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||l.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(fe,{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:d,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(je,{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:J,viewBox:`0 0 ${Z} ${J}`,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"})})}),j.map((b,I)=>{const C=U(I),A=X+I*xe;return e.jsx("rect",{x:X,y:A-ue/2-4,width:oe,height:xe+8,rx:8,fill:C.bg,stroke:C.border,strokeWidth:"1",opacity:.6},b)}),l.map(b=>{const I=w.get(b.id);if(!I)return null;const C=k.get(b.id)??0,A=U(j.indexOf(C)),ce=b.label.length>14?b.label.slice(0,13)+"…":b.label,Q=x===b.id,O=x?(N.get(x)??[]).includes(b.id):!1,ee=x?(M.get(x)??[]).includes(b.id):!1,se=x&&!Q&&!O&&!ee,L=x?Q?{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}:ee?{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:A.border,text:A.text,strokeWidth:2,opacity:1};return e.jsxs("g",{style:{cursor:"pointer",opacity:L.opacity},onClick:()=>m(Q?null:b.id),children:[e.jsx("rect",{x:I.x-B/2,y:I.y-ue/2,width:B,height:ue,rx:10,ry:10,fill:L.fill,stroke:L.stroke,strokeWidth:L.strokeWidth,filter:se?void 0:"url(#nodeShadow)"}),e.jsx("text",{x:I.x,y:I.y,textAnchor:"middle",dominantBaseline:"middle",fontSize:"12",fontWeight:"600",fill:L.text,pointerEvents:"none",children:ce})]},b.id)})]}),x&&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:x}),e.jsx("button",{type:"button",onClick:()=>m(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:(N.get(x)??[]).length===0?e.jsx("li",{className:"text-slate-400",children:"无"}):(N.get(x)??[]).map(b=>e.jsxs("li",{children:["→ ",b]},b))})]}),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:(M.get(x)??[]).length===0?e.jsx("li",{className:"text-slate-400",children:"无"}):(M.get(x)??[]).map(b=>e.jsxs("li",{children:["← ",b]},b))})]})]})]})]}),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:["包列表 (",l.length,")"]}),e.jsx("ul",{className:"text-sm space-y-3 max-h-[280px] overflow-y-auto pr-1",children:l.map(b=>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:b.id}),b.packageDir&&e.jsxs("span",{className:"text-slate-500 text-xs",children:["· ",b.packageDir]})]}),b.targets&&b.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:b.targets.join(", ")})]})]},b.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:["依赖关系(小图)(",f.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:f.map((b,I)=>e.jsxs("li",{className:"flex items-center gap-2 text-slate-700",children:[e.jsx("span",{className:"font-semibold text-slate-800",children:b.from}),e.jsx("span",{className:"text-slate-400 shrink-0",children:"→"}),e.jsx("span",{className:"font-semibold text-slate-800",children:b.to})]},`${b.from}-${b.to}-${I}`))})]})]})]})},Ks=({chatHistory:s,userInput:n,setUserInput:p,handleChat:a,isAiThinking:r})=>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((o,x)=>e.jsx("div",{className:`flex ${o.role==="user"?"justify-end":"justify-start"}`,children:e.jsx("div",{className:`max-w-[80%] p-3 rounded-xl text-sm ${o.role==="user"?"bg-blue-600 text-white":"bg-white border border-slate-200 text-slate-800"}`,children:o.text})},x)),r&&e.jsx("div",{className:"text-slate-400 text-xs animate-pulse",children:"AI is thinking..."})]}),e.jsxs("form",{onSubmit:a,className:"flex gap-2 bg-white p-2 rounded-xl border border-slate-200 shadow-sm",children:[e.jsx("input",{type:"text",value:n,onChange:o=>p(o.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:r,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"})]})]}),Bs=({editingSnippet:s,setEditingSnippet:n,handleSaveSnippet:p,closeSnippetEdit:a})=>{const[r,o]=h.useState("preview"),x=(s.content||s.body||[]).join(`
|
|
5
5
|
`),m=s.language==="objc"?"objectivec":s.language||"text",d=async()=>{try{const l=await S.post("/api/ai/summarize",{code:(s.content||s.body||[]).join(`
|
|
6
6
|
`),language:s.language});(l.data.title_cn||l.data.title)&&n({...s,title:l.data.title_cn||l.data.title,summary:l.data.summary_cn||l.data.summary,completionKey:l.data.trigger,content:l.data.code?l.data.code.split(`
|
|
7
|
-
`):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:()=>o("preview"),className:`px-4 py-1.5 rounded-md text-xs font-bold transition-all flex items-center gap-2 ${r==="preview"?"bg-white shadow-sm text-blue-600":"text-slate-400"}`,children:[e.jsx(
|
|
7
|
+
`):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:()=>o("preview"),className:`px-4 py-1.5 rounded-md text-xs font-bold transition-all flex items-center gap-2 ${r==="preview"?"bg-white shadow-sm text-blue-600":"text-slate-400"}`,children:[e.jsx(ye,{size:14})," Preview"]}),e.jsxs("button",{onClick:()=>o("edit"),className:`px-4 py-1.5 rounded-md text-xs font-bold transition-all flex items-center gap-2 ${r==="edit"?"bg-white shadow-sm text-blue-600":"text-slate-400"}`,children:[e.jsx(Y,{size:14})," Edit"]})]}),e.jsx("button",{onClick:a,className:"p-2 hover:bg-slate-100 rounded-full",children:e.jsx(pe,{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:l=>n({...s,title:l.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:l=>n({...s,completionKey:l.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:l=>n({...s,category:l.target.value}),children:Te.filter(l=>l!=="All").map(l=>e.jsx("option",{value:l,children:l},l))})]}),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:()=>n({...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:()=>n({...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:l=>n({...s,summary:l.target.value})})]}),r==="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:()=>n({...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(`
|
|
8
8
|
`),onChange:l=>n({...s,headers:l.target.value.split(`
|
|
9
9
|
`)})})]}),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:d,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:x,onChange:l=>n({...s,content:(l.target.value||"").split(`
|
|
10
|
-
`)})})]})]}):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:d,className:"text-[10px] text-blue-600 font-bold hover:underline",children:"AI Rewrite"})]}),e.jsx(he,{code:x,language:m,showLineNumbers:!0})]})})]}),e.jsxs("div",{className:"p-6 border-t border-slate-100 flex justify-end gap-3",children:[e.jsx("button",{onClick:a,className:"px-4 py-2 text-slate-600 font-medium",children:"Cancel"}),e.jsxs("button",{onClick:p,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(
|
|
11
|
-
`),w={};let k=0
|
|
12
|
-
`).trim();return{metadata:w,body:i}},{metadata:m,body:d}=x(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",children:[e.jsx("h2",{className:"text-xl font-bold",children:"Edit Recipe"}),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:()=>o("preview"),className:`px-4 py-1.5 rounded-md text-xs font-bold transition-all flex items-center gap-2 ${r==="preview"?"bg-white shadow-sm text-blue-600":"text-slate-400"}`,children:[e.jsx(Ne,{size:14})," Preview"]}),e.jsxs("button",{onClick:()=>o("edit"),className:`px-4 py-1.5 rounded-md text-xs font-bold transition-all flex items-center gap-2 ${r==="edit"?"bg-white shadow-sm text-blue-600":"text-slate-400"}`,children:[e.jsx(Y,{size:14})," Edit"]})]}),e.jsx("button",{onClick:a,className:"p-2 hover:bg-slate-100 rounded-full",children:e.jsx(pe,{size:20})})]})]}),e.jsxs("div",{className:"p-6 space-y-4 flex-1 flex flex-col overflow-hidden",children:[r==="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:l=>n({...s,name:l.target.value})})]}),e.jsx("div",{className:"flex-1 flex flex-col min-h-0",children:r==="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:l=>n({...s,content:l.target.value})})]}):e.jsxs("div",{className:"flex-1 overflow-y-auto space-y-6",children:[Object.keys(m).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(m).map(([l,f])=>e.jsxs("div",{className:"flex flex-col",children:[e.jsx("span",{className:"text-[10px] text-slate-400 font-bold uppercase mb-1",children:l}),e.jsx("span",{className:"text-sm text-slate-700 break-all font-medium",children:f.startsWith("[")&&f.endsWith("]")?e.jsx("div",{className:"flex flex-wrap gap-1 mt-1",children:f.slice(1,-1).split(",").map((w,k)=>e.jsx("span",{className:"px-2 py-0.5 bg-white border border-slate-200 rounded text-[10px] font-mono",children:w.trim()},k))}):f})]},l))})]}),e.jsx("div",{className:"bg-white p-8 rounded-2xl border border-slate-100 shadow-sm min-h-[400px]",children:d?e.jsx(Ue,{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:a,className:"px-4 py-2 text-slate-600 font-medium",children:"Cancel"}),e.jsxs("button",{onClick:p,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(Oe,{size:18}),"Save Changes"]})]})]})})},Vs=({setShowCreateModal:s,createPath:n,setCreatePath:p,handleCreateFromPath:a,handleCreateFromClipboard:r,isExtracting:o})=>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(Ge,{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(pe,{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(_e,{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:n,onChange:x=>p(x.target.value)}),e.jsx("button",{onClick:a,disabled:!n||o,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(Ss,{size:14})," Import from Clipboard"]}),e.jsxs("button",{onClick:()=>r(),disabled:o,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(re,{size:20})," Use Copied Code"]})]})]}),o&&e.jsxs("div",{className:"bg-blue-600 text-white p-4 flex items-center justify-center gap-3 animate-pulse",children:[e.jsx(ne,{size:20,className:"animate-spin"}),e.jsx("span",{className:"font-bold text-sm",children:"AI is thinking..."})]})]})});function Xs(s){const n=s.replace(/^---[\s\S]*?---\s*\n?/,"").trim(),p=n.match(/```[\w]*\n([\s\S]*?)```/);return p&&p[1]?p[1].trim():n.slice(0,8e3)}const Ys=({searchQ:s,insertPath:n,onClose:p})=>{const[a,r]=h.useState([]),[o,x]=h.useState(!0),[m,d]=h.useState(null);h.useEffect(()=>{const f=s?encodeURIComponent(s):"";S.get(`/api/recipes/search?q=${f}`).then(w=>r(w.data.results||[])).catch(()=>r([])).finally(()=>x(!1))},[s]);const l=async f=>{d(f.name);try{const w=Xs(f.content);await S.post("/api/insert-at-search-mark",{path:n,content:w}),alert("✅ 已插入到 "+n),p()}catch{alert("❌ 插入失败")}finally{d(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(De,{size:24,className:"text-blue-600"})," as:search — 选择并插入"]}),e.jsx("button",{onClick:p,className:"p-2 hover:bg-white rounded-full transition-colors",children:e.jsx(pe,{size:20})})]}),e.jsxs("div",{className:"p-4 text-sm text-slate-500 border-b border-slate-100",children:["关键词: ",s||"(全部)"," · 插入到: ",n]}),e.jsx("div",{className:"flex-1 overflow-y-auto p-4",children:o?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"})}):a.length===0?e.jsx("div",{className:"text-slate-500 text-center py-8",children:"未找到匹配的 Recipe"}):e.jsx("ul",{className:"space-y-2",children:a.map(f=>e.jsx("li",{children:e.jsxs("button",{type:"button",onClick:()=>l(f),disabled:m!==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:f.name}),m===f.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(He,{size:16})," 插入"]})]})},f.name))})})]})})},Zs=()=>{const s=()=>{const t=window.location.pathname.replace(/^\//,"").split("/")[0]||"";return Ps.includes(t)?t:"snippets"},[n,p]=h.useState(null),[a,r]=h.useState(s()),[o,x]=h.useState(""),[m,d]=h.useState(!0),[l,f]=h.useState(null),[w,k]=h.useState(null),[I,i]=h.useState([]),[j,y]=h.useState(null),[P,_]=h.useState(!1),[v,L]=h.useState({current:0,total:0,status:""}),[oe,Z]=h.useState([]),[J,R]=h.useState([]),[U,b]=h.useState("All"),[$,C]=h.useState(!1),[A,ce]=h.useState(""),[Q,H]=h.useState(!1),[ee,se]=h.useState([]),[D,we]=h.useState(""),[ve,be]=h.useState(!1),[te,Ce]=h.useState(null),[ge,ke]=h.useState(null),W=h.useRef(null),B=h.useRef(null),We=()=>{W.current&&W.current.abort(),B.current&&B.current.abort(),be(!1)},q=(t,c)=>{r(t);const g=c!=null&&c.preserveSearch&&window.location.search?window.location.search:"";window.history.pushState({},document.title,`/${t}${g}`)},Se=t=>{const c=t.title.replace(/^\[.*?\]\s*/,"");f({...t,title:c}),r("snippets");const g=new URLSearchParams(window.location.search);g.set("edit",t.identifier),window.history.pushState({},document.title,`/snippets?${g.toString()}`)},Ae=()=>{f(null),window.history.replaceState({},document.title,"/snippets")},$e=t=>{k(t),r("recipes");const c=new URLSearchParams(window.location.search);c.set("edit",encodeURIComponent(t.name)),window.history.pushState({},document.title,`/recipes?${c.toString()}`)},Ie=()=>{k(null),window.history.replaceState({},document.title,"/recipes")};h.useEffect(()=>{o===""&&Ce(null)},[o]),h.useEffect(()=>{r(s())},[]),h.useEffect(()=>{var u;if(!n)return;const t=window.location.pathname.replace(/^\//,"").split("/")[0],g=new URLSearchParams(window.location.search).get("edit");if(t==="snippets"&&g&&((u=n.rootSpec)!=null&&u.list)){const N=n.rootSpec.list.find(z=>z.identifier===g);N&&!l&&(r("snippets"),Se(N))}if(t==="recipes"&&g&&n.recipes)try{const N=decodeURIComponent(g),z=n.recipes.find(M=>M.name===N);z&&!w&&(r("recipes"),$e(z))}catch{}},[n]),h.useEffect(()=>{F(),ze();const t=()=>{r(s())};window.addEventListener("popstate",t);const c=new URLSearchParams(window.location.search),g=c.get("action"),u=c.get("path"),N=c.get("source"),z=c.get("q")||"";g==="search"&&u?ke({q:z,path:u}):g==="create"&&u&&(ce(u),C(!0),setTimeout(async()=>{if(N==="clipboard")try{const M=await navigator.clipboard.readText();if(M&&M.trim()){Me(u);return}}catch{}qe(u)},500))},[]);const F=async()=>{d(!0);try{const t=await S.get("/api/data");p(t.data)}catch{}finally{d(!1)}},ze=async()=>{try{const t=await S.get("/api/spm/targets");i(t.data)}catch{}},Be=async()=>{try{await S.post("/api/commands/install"),alert("✅ Successfully synced to Xcode CodeSnippets!")}catch{alert("❌ Sync failed")}},Ke=async()=>{try{await S.post("/api/commands/spm-map"),ze(),alert("✅ Project structure refreshed!")}catch{alert("❌ Refresh failed")}},qe=async t=>{H(!0);try{const c=await S.post("/api/extract/path",{relativePath:t});R(c.data.result.map(g=>({...g,mode:"full",lang:"cn",includeHeaders:!0,category:g.category||"Utility",summary:g.summary_cn||g.summary||"",usageGuide:g.usageGuide_cn||g.usageGuide||""}))),q("spm",{preserveSearch:!0}),C(!1)}catch{alert("Extraction failed.")}finally{H(!1)}},Ve=async()=>{if(A){H(!0);try{const t=await S.post("/api/extract/path",{relativePath:A});R(t.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||""}))),q("spm"),C(!1),t.data.isMarked?alert("🎯 Precision Lock: Successfully extracted code between // as:code markers."):alert("ℹ️ No markers found. AI is analyzing the full file.")}catch{alert("Extraction failed. Check path.")}finally{H(!1)}}},Me=async t=>{try{const c=await navigator.clipboard.readText();if(!c)return alert("Clipboard is empty");H(!0);const g=t||A,N=(await S.post("/api/extract/text",{text:c,...g?{relativePath:g}:{}})).data;R([{...N,mode:"full",lang:"cn",includeHeaders:!0,category:N.category||"Utility",summary:N.summary_cn||N.summary||"",usageGuide:N.usageGuide_cn||N.usageGuide||""}]),q("spm",{preserveSearch:!0}),C(!1)}catch{alert("Failed to read clipboard or AI error")}finally{H(!1)}},Pe=[{status:"正在读取 Target 源文件...",percent:15},{status:"正在发送到 AI 分析...",percent:35},{status:"正在识别可复用代码片段...",percent:55},{status:"正在生成摘要与使用指南...",percent:75},{status:"即将完成...",percent:92}],Xe=async t=>{var z,M,V,ie;if(P)return;W.current&&W.current.abort();const c=new AbortController;W.current=c,y(t.name),_(!0),R([]),Z([]),L({current:0,total:100,status:"正在获取待扫描文件列表..."});const g=4e3;let u=0;const N=setInterval(()=>{u=Math.min(u+1,Pe.length);const G=Pe[u-1];G&&L(le=>({...le,current:G.percent,status:G.status}))},g);try{const G=await S.post("/api/spm/target-files",{target:t},{signal:c.signal}),le=((z=G.data)==null?void 0:z.files)||[],cs=((M=G.data)==null?void 0:M.count)??le.length;Z(le),L(O=>({...O,current:10,status:`正在分析 ${cs} 个文件...`}));const is=await S.post("/api/spm/scan",{target:t},{signal:c.signal});clearInterval(N),L({current:100,total:100,status:"扫描完成"});const E=is.data,Ee=Array.isArray(E)?E:(E==null?void 0:E.recipes)??[],Le=!Array.isArray(E)&&(E!=null&&E.scannedFiles)?E.scannedFiles:le;Ee.length>0||Le.length>0?(R(Ee.map(O=>({...O,mode:"full",lang:"cn",includeHeaders:O.includeHeaders!==!1,category:O.category||"Utility",summary:O.summary_cn||O.summary||"",usageGuide:O.usageGuide_cn||O.usageGuide||""}))),Z(Le)):typeof E=="object"&&E!==null&&"message"in E?alert(E.message||"Scan failed: No source files."):alert("Scan failed: Unexpected response format")}catch(G){if(clearInterval(N),S.isCancel(G))return;alert(`Scan failed: ${((ie=(V=G.response)==null?void 0:V.data)==null?void 0:ie.error)||G.message}`)}finally{W.current===c&&(_(!1),L({current:0,total:0,status:""}),W.current=null)}},Ye=(t,c)=>{const g=[...J],u={...g[t],...c};c.lang!==void 0?(u.summary=c.lang==="cn"?u.summary_cn||u.summary:u.summary_en||u.summary,u.usageGuide=c.lang==="cn"?u.usageGuide_cn||u.usageGuide:u.usageGuide_en||u.usageGuide):(c.summary!==void 0&&(u.lang==="cn"?u.summary_cn=c.summary:u.summary_en=c.summary),c.usageGuide!==void 0&&(u.lang==="cn"?u.usageGuide_cn=c.usageGuide:u.usageGuide_en=c.usageGuide)),g[t]=u,R(g)},Ze=async t=>{try{const c=t.trigger.split(/[,,\s]+/).map(z=>z.trim()).filter(Boolean),g=crypto.randomUUID().toUpperCase();if(t.mode==="full")for(let z=0;z<c.length;z++){const M=c[z],V=t.includeHeaders!==!1,ie={identifier:z===0?g:crypto.randomUUID().toUpperCase(),title:c.length>1?`${t.title} (${M})`:t.title,completionKey:M,category:t.category,summary:t.summary,language:t.language,content:t.code.split(`
|
|
13
|
-
`),headers:
|
|
10
|
+
`)})})]})]}):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:d,className:"text-[10px] text-blue-600 font-bold hover:underline",children:"AI Rewrite"})]}),e.jsx(he,{code:x,language:m,showLineNumbers:!0})]})})]}),e.jsxs("div",{className:"p-6 border-t border-slate-100 flex justify-end gap-3",children:[e.jsx("button",{onClick:a,className:"px-4 py-2 text-slate-600 font-medium",children:"Cancel"}),e.jsxs("button",{onClick:p,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(He,{size:18}),"Save Changes"]})]})]})})},Vs=({editingRecipe:s,setEditingRecipe:n,handleSaveRecipe:p,closeRecipeEdit:a})=>{const[r,o]=h.useState("preview"),x=l=>{const f=l.split(`
|
|
11
|
+
`),w={};let k=0,$=!1;for(let j=0;j<f.length;j++){const N=f[j].trim();if(N==="---"){if(!$&&j===0){$=!0;continue}else if($){$=!1,k=j+1;break}}const M=N.match(/^([a-zA-Z0-9_-]+):\s*(.*)/);if(M)w[M[1]]=M[2],$||(k=j+1);else if(!$&&N!==""){k=j;break}}const i=f.slice(k).join(`
|
|
12
|
+
`).trim();return{metadata:w,body:i}},{metadata:m,body:d}=x(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",children:[e.jsx("h2",{className:"text-xl font-bold",children:"Edit Recipe"}),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:()=>o("preview"),className:`px-4 py-1.5 rounded-md text-xs font-bold transition-all flex items-center gap-2 ${r==="preview"?"bg-white shadow-sm text-blue-600":"text-slate-400"}`,children:[e.jsx(ye,{size:14})," Preview"]}),e.jsxs("button",{onClick:()=>o("edit"),className:`px-4 py-1.5 rounded-md text-xs font-bold transition-all flex items-center gap-2 ${r==="edit"?"bg-white shadow-sm text-blue-600":"text-slate-400"}`,children:[e.jsx(Y,{size:14})," Edit"]})]}),e.jsx("button",{onClick:a,className:"p-2 hover:bg-slate-100 rounded-full",children:e.jsx(pe,{size:20})})]})]}),e.jsxs("div",{className:"p-6 space-y-4 flex-1 flex flex-col overflow-hidden",children:[r==="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:l=>n({...s,name:l.target.value})})]}),e.jsx("div",{className:"flex-1 flex flex-col min-h-0",children:r==="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:l=>n({...s,content:l.target.value})})]}):e.jsxs("div",{className:"flex-1 overflow-y-auto space-y-6",children:[Object.keys(m).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(m).map(([l,f])=>e.jsxs("div",{className:"flex flex-col",children:[e.jsx("span",{className:"text-[10px] text-slate-400 font-bold uppercase mb-1",children:l}),e.jsx("span",{className:"text-sm text-slate-700 break-all font-medium",children:f.startsWith("[")&&f.endsWith("]")?e.jsx("div",{className:"flex flex-wrap gap-1 mt-1",children:f.slice(1,-1).split(",").map((w,k)=>e.jsx("span",{className:"px-2 py-0.5 bg-white border border-slate-200 rounded text-[10px] font-mono",children:w.trim()},k))}):f})]},l))})]}),e.jsx("div",{className:"bg-white p-8 rounded-2xl border border-slate-100 shadow-sm min-h-[400px]",children:d?e.jsx(Ue,{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:a,className:"px-4 py-2 text-slate-600 font-medium",children:"Cancel"}),e.jsxs("button",{onClick:p,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(He,{size:18}),"Save Changes"]})]})]})})},qs=({setShowCreateModal:s,createPath:n,setCreatePath:p,handleCreateFromPath:a,handleCreateFromClipboard:r,isExtracting:o})=>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(_e,{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(pe,{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(Ge,{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:n,onChange:x=>p(x.target.value)}),e.jsx("button",{onClick:a,disabled:!n||o,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(Ss,{size:14})," Import from Clipboard"]}),e.jsxs("button",{onClick:()=>r(),disabled:o,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(re,{size:20})," Use Copied Code"]})]})]}),o&&e.jsxs("div",{className:"bg-blue-600 text-white p-4 flex items-center justify-center gap-3 animate-pulse",children:[e.jsx(ne,{size:20,className:"animate-spin"}),e.jsx("span",{className:"font-bold text-sm",children:"AI is thinking..."})]})]})});function Xs(s){const n=s.replace(/^---[\s\S]*?---\s*\n?/,"").trim(),p=n.match(/```[\w]*\n([\s\S]*?)```/);return p&&p[1]?p[1].trim():n.slice(0,8e3)}const Ys=({searchQ:s,insertPath:n,onClose:p})=>{const[a,r]=h.useState([]),[o,x]=h.useState(!0),[m,d]=h.useState(null);h.useEffect(()=>{const f=s?encodeURIComponent(s):"";S.get(`/api/recipes/search?q=${f}`).then(w=>r(w.data.results||[])).catch(()=>r([])).finally(()=>x(!1))},[s]);const l=async f=>{d(f.name);try{const w=Xs(f.content);await S.post("/api/insert-at-search-mark",{path:n,content:w}),alert("✅ 已插入到 "+n),p()}catch{alert("❌ 插入失败")}finally{d(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(Le,{size:24,className:"text-blue-600"})," as:search — 选择并插入"]}),e.jsx("button",{onClick:p,className:"p-2 hover:bg-white rounded-full transition-colors",children:e.jsx(pe,{size:20})})]}),e.jsxs("div",{className:"p-4 text-sm text-slate-500 border-b border-slate-100",children:["关键词: ",s||"(全部)"," · 插入到: ",n]}),e.jsx("div",{className:"flex-1 overflow-y-auto p-4",children:o?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"})}):a.length===0?e.jsx("div",{className:"text-slate-500 text-center py-8",children:"未找到匹配的 Recipe"}):e.jsx("ul",{className:"space-y-2",children:a.map(f=>e.jsx("li",{children:e.jsxs("button",{type:"button",onClick:()=>l(f),disabled:m!==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:f.name}),m===f.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(Oe,{size:16})," 插入"]})]})},f.name))})})]})})},Zs=()=>{const s=()=>{const t=window.location.pathname.replace(/^\//,"").split("/")[0]||"";return Ms.includes(t)?t:"snippets"},[n,p]=h.useState(null),[a,r]=h.useState(s()),[o,x]=h.useState(""),[m,d]=h.useState(!0),[l,f]=h.useState(null),[w,k]=h.useState(null),[$,i]=h.useState([]),[j,N]=h.useState(null),[M,G]=h.useState(!1),[v,E]=h.useState({current:0,total:0,status:""}),[oe,Z]=h.useState([]),[J,D]=h.useState([]),[U,b]=h.useState("All"),[I,C]=h.useState(!1),[A,ce]=h.useState(""),[Q,O]=h.useState(!1),[ee,se]=h.useState([]),[L,we]=h.useState(""),[ve,be]=h.useState(!1),[te,Ce]=h.useState(null),[ge,ke]=h.useState(null),W=h.useRef(null),K=h.useRef(null),We=()=>{W.current&&W.current.abort(),K.current&&K.current.abort(),be(!1)},V=(t,c)=>{r(t);const g=c!=null&&c.preserveSearch&&window.location.search?window.location.search:"";window.history.pushState({},document.title,`/${t}${g}`)},Se=t=>{const c=t.title.replace(/^\[.*?\]\s*/,"");f({...t,title:c}),r("snippets");const g=new URLSearchParams(window.location.search);g.set("edit",t.identifier),window.history.pushState({},document.title,`/snippets?${g.toString()}`)},Ae=()=>{f(null),window.history.replaceState({},document.title,"/snippets")},Ie=t=>{k(t),r("recipes");const c=new URLSearchParams(window.location.search);c.set("edit",encodeURIComponent(t.name)),window.history.pushState({},document.title,`/recipes?${c.toString()}`)},$e=()=>{k(null),window.history.replaceState({},document.title,"/recipes")};h.useEffect(()=>{o===""&&Ce(null)},[o]),h.useEffect(()=>{r(s())},[]),h.useEffect(()=>{var u;if(!n)return;const t=window.location.pathname.replace(/^\//,"").split("/")[0],g=new URLSearchParams(window.location.search).get("edit");if(t==="snippets"&&g&&((u=n.rootSpec)!=null&&u.list)){const y=n.rootSpec.list.find(z=>z.identifier===g);y&&!l&&(r("snippets"),Se(y))}if(t==="recipes"&&g&&n.recipes)try{const y=decodeURIComponent(g),z=n.recipes.find(P=>P.name===y);z&&!w&&(r("recipes"),Ie(z))}catch{}},[n]),h.useEffect(()=>{F(),ze();const t=()=>{r(s())};window.addEventListener("popstate",t);const c=new URLSearchParams(window.location.search),g=c.get("action"),u=c.get("path"),y=c.get("source"),z=c.get("q")||"";g==="search"&&u?ke({q:z,path:u}):g==="create"&&u&&(ce(u),C(!0),setTimeout(async()=>{if(y==="clipboard")try{const P=await navigator.clipboard.readText();if(P&&P.trim()){Pe(u);return}}catch{}Ve(u)},500))},[]);const F=async()=>{d(!0);try{const t=await S.get("/api/data");p(t.data)}catch{}finally{d(!1)}},ze=async()=>{try{const t=await S.get("/api/spm/targets");i(t.data)}catch{}},Ke=async()=>{try{await S.post("/api/commands/install"),alert("✅ Successfully synced to Xcode CodeSnippets!")}catch{alert("❌ Sync failed")}},Be=async()=>{try{await S.post("/api/commands/spm-map"),ze(),alert("✅ Project structure refreshed!")}catch{alert("❌ Refresh failed")}},Ve=async t=>{O(!0);try{const c=await S.post("/api/extract/path",{relativePath:t});D(c.data.result.map(g=>({...g,mode:"full",lang:"cn",includeHeaders:!0,category:g.category||"Utility",summary:g.summary_cn||g.summary||"",usageGuide:g.usageGuide_cn||g.usageGuide||""}))),V("spm",{preserveSearch:!0}),C(!1)}catch{alert("Extraction failed.")}finally{O(!1)}},qe=async()=>{if(A){O(!0);try{const t=await S.post("/api/extract/path",{relativePath:A});D(t.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||""}))),V("spm"),C(!1),t.data.isMarked?alert("🎯 Precision Lock: Successfully extracted code between // as:code markers."):alert("ℹ️ No markers found. AI is analyzing the full file.")}catch{alert("Extraction failed. Check path.")}finally{O(!1)}}},Pe=async t=>{try{const c=await navigator.clipboard.readText();if(!c)return alert("Clipboard is empty");O(!0);const g=t||A,y=(await S.post("/api/extract/text",{text:c,...g?{relativePath:g}:{}})).data;D([{...y,mode:"full",lang:"cn",includeHeaders:!0,category:y.category||"Utility",summary:y.summary_cn||y.summary||"",usageGuide:y.usageGuide_cn||y.usageGuide||""}]),V("spm",{preserveSearch:!0}),C(!1)}catch{alert("Failed to read clipboard or AI error")}finally{O(!1)}},Me=[{status:"正在读取 Target 源文件...",percent:15},{status:"正在发送到 AI 分析...",percent:35},{status:"正在识别可复用代码片段...",percent:55},{status:"正在生成摘要与使用指南...",percent:75},{status:"即将完成...",percent:92}],Xe=async t=>{var z,P,q,ie;if(M)return;W.current&&W.current.abort();const c=new AbortController;W.current=c,N(t.name),G(!0),D([]),Z([]),E({current:0,total:100,status:"正在获取待扫描文件列表..."});const g=4e3;let u=0;const y=setInterval(()=>{u=Math.min(u+1,Me.length);const _=Me[u-1];_&&E(le=>({...le,current:_.percent,status:_.status}))},g);try{const _=await S.post("/api/spm/target-files",{target:t},{signal:c.signal}),le=((z=_.data)==null?void 0:z.files)||[],cs=((P=_.data)==null?void 0:P.count)??le.length;Z(le),E(H=>({...H,current:10,status:`正在分析 ${cs} 个文件...`}));const is=await S.post("/api/spm/scan",{target:t},{signal:c.signal});clearInterval(y),E({current:100,total:100,status:"扫描完成"});const R=is.data,Re=Array.isArray(R)?R:(R==null?void 0:R.recipes)??[],Ee=!Array.isArray(R)&&(R!=null&&R.scannedFiles)?R.scannedFiles:le;Re.length>0||Ee.length>0?(D(Re.map(H=>({...H,mode:"full",lang:"cn",includeHeaders:H.includeHeaders!==!1,category:H.category||"Utility",summary:H.summary_cn||H.summary||"",usageGuide:H.usageGuide_cn||H.usageGuide||""}))),Z(Ee)):typeof R=="object"&&R!==null&&"message"in R?alert(R.message||"Scan failed: No source files."):alert("Scan failed: Unexpected response format")}catch(_){if(clearInterval(y),S.isCancel(_))return;alert(`Scan failed: ${((ie=(q=_.response)==null?void 0:q.data)==null?void 0:ie.error)||_.message}`)}finally{W.current===c&&(G(!1),E({current:0,total:0,status:""}),W.current=null)}},Ye=(t,c)=>{const g=[...J],u={...g[t],...c};c.lang!==void 0?(u.summary=c.lang==="cn"?u.summary_cn||u.summary:u.summary_en||u.summary,u.usageGuide=c.lang==="cn"?u.usageGuide_cn||u.usageGuide:u.usageGuide_en||u.usageGuide):(c.summary!==void 0&&(u.lang==="cn"?u.summary_cn=c.summary:u.summary_en=c.summary),c.usageGuide!==void 0&&(u.lang==="cn"?u.usageGuide_cn=c.usageGuide:u.usageGuide_en=c.usageGuide)),g[t]=u,D(g)},Ze=async t=>{try{const c=t.trigger.split(/[,,\s]+/).map(z=>z.trim()).filter(Boolean),g=crypto.randomUUID().toUpperCase();if(t.mode==="full")for(let z=0;z<c.length;z++){const P=c[z],q=t.includeHeaders!==!1,ie={identifier:z===0?g:crypto.randomUUID().toUpperCase(),title:c.length>1?`${t.title} (${P})`:t.title,completionKey:P,category:t.category,summary:t.summary,language:t.language,content:t.code.split(`
|
|
13
|
+
`),headers:q?t.headers||[]:[],headerPaths:q?t.headerPaths||[]:void 0,moduleName:t.moduleName,includeHeaders:q};await S.post("/api/snippets/save",{snippet:ie})}const u=`${t.title.replace(/\s+/g,"-")}.md`,y=`---
|
|
14
14
|
id: ${t.mode==="full"?g:"preview-only"}
|
|
15
15
|
title: ${t.title}
|
|
16
16
|
language: ${t.language}
|
|
@@ -30,4 +30,4 @@ ${t.code}
|
|
|
30
30
|
## AI Context / Usage Guide
|
|
31
31
|
|
|
32
32
|
${t.usageGuide}
|
|
33
|
-
`;await S.post("/api/recipes/save",{name:u,content:
|
|
33
|
+
`;await S.post("/api/recipes/save",{name:u,content:y}),alert(t.mode==="full"?"✅ Saved as Snippet & Recipe!":"✅ Saved to KB!"),F(),D(z=>z.filter(P=>P.title!==t.title))}catch{alert("❌ Failed to save")}},Je=async()=>{if(w)try{await S.post("/api/recipes/save",{name:w.name,content:w.content}),$e(),F()}catch{alert("Failed to save recipe")}},Qe=async t=>{if(window.confirm("Are you sure?"))try{await S.post("/api/recipes/delete",{name:t}),F()}catch{alert("Failed to delete")}},es=async(t,c)=>{try{await S.post("/api/candidates/delete",{targetName:t,candidateId:c}),F()}catch{alert("Action failed.")}},ss=async()=>{if(l)try{await S.post("/api/snippets/save",{snippet:l}),Ae(),F()}catch{alert("Failed to save snippet")}},ts=async(t,c)=>{if(window.confirm(`Delete snippet: ${c}?`))try{await S.post("/api/snippets/delete",{identifier:t}),F()}catch{alert("Failed to delete")}},ls=async t=>{if(t.preventDefault(),!L.trim()||ve)return;K.current&&K.current.abort();const c=new AbortController;K.current=c;const g={role:"user",text:L};se(u=>[...u,g]),we(""),be(!0);try{const u=await S.post("/api/ai/chat",{prompt:L,history:ee.map(y=>({role:y.role,content:y.text}))},{signal:c.signal});se(y=>[...y,{role:"model",text:u.data.text}])}catch(u){if(S.isCancel(u))return;se(y=>[...y,{role:"model",text:"Error"}])}finally{K.current===c&&(K.current=null,be(!1))}},as=(n==null?void 0:n.rootSpec.list.filter(t=>{const c=t.title||"",g=t.completionKey||"",u=c.toLowerCase().includes(o.toLowerCase())||g.toLowerCase().includes(o.toLowerCase());if(U==="All")return u;const y=t.category||"Utility";return u&&y===U}))||[],rs=((n==null?void 0:n.recipes)||[]).filter(t=>{if(te)return te.some(P=>P.metadata.type==="recipe"&&P.metadata.name===t.name);const c=t.name||"",g=t.content||"",u=c.toLowerCase().includes(o.toLowerCase())||g.toLowerCase().includes(o.toLowerCase());if(U==="All")return u;const y=g?g.match(/category:\s*(.*)/):null,z=y?y[1].trim():"Utility";return u&&z===U}).sort((t,c)=>{var g,u;if(te){const y=((g=te.find(P=>P.metadata.name===t.name))==null?void 0:g.similarity)||0;return(((u=te.find(P=>P.metadata.name===c.name))==null?void 0:u.similarity)||0)-y}return 0}),ns=$.filter(t=>t.name.toLowerCase().includes(o.toLowerCase())).sort((t,c)=>{const g=de(t.name),u=de(c.name);return g&&!u?1:!g&&u?-1:t.name.localeCompare(c.name)}),os=Object.values((n==null?void 0:n.candidates)||{}).reduce((t,c)=>t+c.items.length,0);return e.jsxs("div",{className:"flex h-screen bg-slate-50 text-slate-900 overflow-hidden font-sans",children:[e.jsx(Rs,{activeTab:a,navigateToTab:V,handleRefreshProject:Be,candidateCount:os}),e.jsxs("main",{className:"flex-1 flex flex-col overflow-hidden relative",children:[e.jsx(Es,{searchQuery:o,setSearchQuery:x,setShowCreateModal:C,handleSyncToXcode:Ke,aiConfig:n==null?void 0:n.aiConfig,onBeforeAiSwitch:We,onAiConfigChange:F,onSemanticSearchResults:t=>{Ce(t),a!=="recipes"&&a!=="snippets"&&V("recipes")}}),(a==="snippets"||a==="recipes")&&e.jsx(Ds,{selectedCategory:U,setSelectedCategory:b}),e.jsx("div",{className:"flex-1 overflow-y-auto p-8",children:m?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"})}):a==="snippets"?e.jsx(Ls,{snippets:as,openSnippetEdit:Se,handleDeleteSnippet:ts}):a==="recipes"?e.jsx(_s,{recipes:rs,openRecipeEdit:Ie,handleDeleteRecipe:Qe}):a==="help"?e.jsx(Gs,{}):a==="candidates"?e.jsx(Hs,{data:n,isShellTarget:de,handleDeleteCandidate:es,onAuditCandidate:t=>{D([{...t,mode:"full",lang:"cn",includeHeaders:!0,summary:t.summary_cn||t.summary||"",usageGuide:t.usageGuide_cn||t.usageGuide||""}]),V("spm")}}):a==="depgraph"?e.jsx(Ws,{}):a==="spm"?e.jsx(Ts,{targets:$,filteredTargets:ns,selectedTargetName:j,isScanning:M,scanProgress:v,scanFileList:oe,scanResults:J,handleScanTarget:Xe,handleUpdateScanResult:Ye,handleSaveExtracted:Ze,isShellTarget:de}):e.jsx(Ks,{chatHistory:ee,userInput:L,setUserInput:we,handleChat:ls,isAiThinking:ve})}),l&&e.jsx(Bs,{editingSnippet:l,setEditingSnippet:f,handleSaveSnippet:ss,closeSnippetEdit:Ae}),w&&e.jsx(Vs,{editingRecipe:w,setEditingRecipe:k,handleSaveRecipe:Je,closeRecipeEdit:$e}),I&&e.jsx(qs,{setShowCreateModal:C,createPath:A,setCreatePath:ce,handleCreateFromPath:qe,handleCreateFromClipboard:Pe,isExtracting:Q}),ge&&e.jsx(Ys,{searchQ:ge.q,insertPath:ge.path,onClose:()=>{ke(null),window.history.replaceState({},document.title,window.location.pathname)}})]})]})};As.createRoot(document.getElementById("root")).render(e.jsx(Is.StrictMode,{children:e.jsx(Zs,{})}));
|
|
@@ -5,10 +5,10 @@
|
|
|
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-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-l2znexhV.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/vendor-CAT0H0kn.js">
|
|
10
10
|
<link rel="modulepreload" crossorigin href="/assets/markdown-CBiIpHBr.js">
|
|
11
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
11
|
+
<link rel="stylesheet" crossorigin href="/assets/index-ByWAR53z.css">
|
|
12
12
|
</head>
|
|
13
13
|
<body>
|
|
14
14
|
<div id="root"></div>
|
package/package.json
CHANGED
package/scripts/mcp-server.js
CHANGED
|
@@ -67,7 +67,7 @@ const server = new McpServer({ name: 'autosnippet', version: '1.0.0' });
|
|
|
67
67
|
server.registerTool(
|
|
68
68
|
'autosnippet_open_create',
|
|
69
69
|
{
|
|
70
|
-
description: '
|
|
70
|
+
description: '打开浏览器并导航到 Dashboard 新建 Recipe 页(Use Copied Code 流程)。等价于 Xcode 中 // as:create 复制后保存触发的跳转。用户需先将要提交的代码复制到剪贴板,调用后页面会读取剪贴板并填充。可选 path 用于头文件解析(如 Sources/MyMod/Foo.m)。Dashboard 需已运行于 localhost:3000(若未运行,先在终端 asd ui)。',
|
|
71
71
|
inputSchema: {
|
|
72
72
|
path: z.string().optional().describe('相对路径,用于头文件解析,如 Sources/MyMod/Foo.m')
|
|
73
73
|
}
|
|
@@ -83,7 +83,7 @@ server.registerTool(
|
|
|
83
83
|
};
|
|
84
84
|
} catch (e) {
|
|
85
85
|
return {
|
|
86
|
-
content: [{ type: 'text', text: `打开失败: ${e.message}。请确认 asd ui
|
|
86
|
+
content: [{ type: 'text', text: `打开失败: ${e.message}。请确认 Dashboard 已运行(终端执行 asd ui),或手动打开 http://localhost:3000。` }]
|
|
87
87
|
};
|
|
88
88
|
}
|
|
89
89
|
}
|
|
@@ -11,7 +11,7 @@ This skill tells the agent how to **submit module usage code** (that Cursor has
|
|
|
11
11
|
|
|
12
12
|
1. **Goal**: When you (Cursor) have **finished writing or refining** module usage code, or the user says "把这段提交到 web / 加入知识库", guide them to **submit that code to the Dashboard** so it becomes a **Recipe** in `Knowledge/recipes/`.
|
|
13
13
|
2. **Do not modify Knowledge directly**: Agent **must not** create or modify any files under `Knowledge/recipes/` or `Knowledge/snippets/`. All Recipe and Snippet changes must be submitted via Dashboard Web and saved after human review.
|
|
14
|
-
3. **Primary flow**: Code is ready (in editor or clipboard) → user opens
|
|
14
|
+
3. **Primary flow**: Code is ready (in editor or clipboard) → user opens browser to **`http://localhost:3000`**(Dashboard 需已运行)→ in the Dashboard click **New Recipe** → **Use Copied Code** (paste the code) → AI fills title/summary/trigger/headers → **user reviews and approves** → user **saves** → Recipe is added to the knowledge base.
|
|
15
15
|
4. **Alternative (in editor)**: User adds **`// as:create`** in the source file, copies the code (or keeps the code you just wrote), saves the file → **watch** (from `asd watch` or `asd ui`) opens the Dashboard with current file path and clipboard → user completes "Use Copied Code" in the web, **reviews**, and saves → added to knowledge base.
|
|
16
16
|
5. **Project root** = directory with `AutoSnippetRoot.boxspec.json`. All commands run from the project root.
|
|
17
17
|
|
|
@@ -26,15 +26,17 @@ This skill tells the agent how to **submit module usage code** (that Cursor has
|
|
|
26
26
|
- **Code scenario**: Usage code is in current file or clipboard. If not copied, prompt user to copy the code block you provide.
|
|
27
27
|
- **Agent-drafted Recipe scenario**: If you have generated a full Recipe (frontmatter, Snippet, Usage Guide), **prefer writing to draft file** for user to copy (see "When full copy is difficult" below). Or output in copyable format in chat, guide user to copy → Dashboard → Use Copied Code → paste → review → save. Do not write to `Knowledge/recipes/` or `Knowledge/snippets/`.
|
|
28
28
|
|
|
29
|
-
### Step 2:
|
|
29
|
+
### Step 2: Open the web (Dashboard) in browser
|
|
30
30
|
|
|
31
|
-
-
|
|
32
|
-
-
|
|
31
|
+
- **Preferred**: Call MCP **`autosnippet_open_create`** to open the page.
|
|
32
|
+
- **If MCP fails or browser doesn't open**: Run in terminal: `open "http://localhost:3000/?action=create&source=clipboard"` (macOS). This opens the browser directly.
|
|
33
|
+
- **Manual fallback**: User opens **`http://localhost:3000`** in browser (Dashboard 需已运行;若未运行,先执行 `asd ui`).
|
|
33
34
|
|
|
34
35
|
### Step 3: Submit via Dashboard
|
|
35
36
|
|
|
36
|
-
1. **If MCP is configured**:
|
|
37
|
-
2. **
|
|
37
|
+
1. **If MCP is configured**: Call **`autosnippet_open_create`** to open Dashboard New Recipe page. Page reads clipboard and fills. Optional: pass current file `path` for header resolution.
|
|
38
|
+
2. **If MCP doesn't open browser**: Run terminal command `open "http://localhost:3000/?action=create&source=clipboard"` (macOS) to open the browser.
|
|
39
|
+
3. **Manual fallback**: User opens **`http://localhost:3000`** in browser → **New Recipe** → **Use Copied Code** → paste.
|
|
38
40
|
3. Pasted code: **Full Recipe MD** (with `---` frontmatter, `## Snippet / Code Reference`, `## AI Context / Usage Guide`) is parsed directly, **no AI rewrite**. Plain code still goes through AI analysis and fill.
|
|
39
41
|
4. **User reviews and approves** — 人工审核 title/summary/category/trigger 及内容,确认无误后再保存。
|
|
40
42
|
5. User **saves** → Recipe is written to **`Knowledge/recipes/`** — i.e. **added to the knowledge base**.
|
|
@@ -73,22 +75,24 @@ All of these **submit through the web (Dashboard)** and result in content in **`
|
|
|
73
75
|
|
|
74
76
|
| User / Cursor situation | Action |
|
|
75
77
|
|-------------------------|--------|
|
|
76
|
-
| "把这段提交到 web / 加入知识库" (code just written) |
|
|
78
|
+
| "把这段提交到 web / 加入知识库" (code just written) | 1) 提示用户复制代码;2) 调用 **`autosnippet_open_create`**;3) 若浏览器未打开,运行 `open "http://localhost:3000/?action=create&source=clipboard"`;4) 用户粘贴并保存。 |
|
|
77
79
|
| Agent 起草了 Recipe/Snippet 内容 | **Prefer**: Write to `_draft_recipe.md` (project root) → user opens, copies all → call **`autosnippet_open_create`** or manual Dashboard → Use Copied Code → paste → review → save. |
|
|
78
80
|
| Code in current file, want to open web from editor | **MCP**:`autosnippet_open_create`(传 path)。或 Add **`// as:create`**, copy, save; ensure **`asd watch`** / **`asd ui`** running. |
|
|
79
|
-
| Code already in a file (path known) | **`
|
|
81
|
+
| Code already in a file (path known) | 打开 **`http://localhost:3000`** → New Recipe → enter path → **Scan File** → review → save. |
|
|
80
82
|
| Agent 起草内容无法完整复制 | Write to `_draft_recipe.md` → user Scan File or open & copy → Dashboard → review → save. |
|
|
81
|
-
| Batch from Target | **`asd ais <Target>`** → **`
|
|
83
|
+
| Batch from Target | **`asd ais <Target>`** → 打开 **`http://localhost:3000`** → **Candidates** → approve. |
|
|
82
84
|
|
|
83
85
|
---
|
|
84
86
|
|
|
85
|
-
## MCP Tools (when
|
|
87
|
+
## MCP Tools (when Dashboard is running on localhost:3000)
|
|
86
88
|
|
|
87
89
|
| Tool | Use |
|
|
88
90
|
|------|-----|
|
|
89
91
|
| `autosnippet_context_search` | On-demand semantic search of knowledge base; pass `query`, `limit?` |
|
|
90
92
|
| `autosnippet_open_create` | Open Dashboard New Recipe page (copy→jump); equivalent to Xcode `// as:create`. Optional `path` for header resolution |
|
|
91
93
|
|
|
94
|
+
**Fallback when MCP doesn't open browser**: Run in terminal: `open "http://localhost:3000/?action=create&source=clipboard"` (macOS). Agent should try this if `autosnippet_open_create` returns but the browser did not open.
|
|
95
|
+
|
|
92
96
|
---
|
|
93
97
|
|
|
94
98
|
## Relation to other skills
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
/*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-red-800:oklch(44.4% .177 26.899);--color-orange-50:oklch(98% .016 73.684);--color-orange-100:oklch(95.4% .038 75.164);--color-orange-600:oklch(64.6% .222 41.116);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-700:oklch(55.5% .163 48.998);--color-emerald-50:oklch(97.9% .021 166.113);--color-emerald-100:oklch(95% .052 163.051);--color-emerald-600:oklch(59.6% .145 163.225);--color-cyan-50:oklch(98.4% .019 200.873);--color-cyan-100:oklch(95.6% .045 203.388);--color-cyan-600:oklch(60.9% .126 221.723);--color-blue-50:oklch(97% .014 254.604);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-200:oklch(88.2% .059 254.128);--color-blue-300:oklch(80.9% .105 251.813);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-indigo-50:oklch(96.2% .018 272.314);--color-indigo-100:oklch(93% .034 272.788);--color-indigo-600:oklch(51.1% .262 276.966);--color-purple-50:oklch(97.7% .014 308.299);--color-purple-100:oklch(94.6% .033 307.174);--color-purple-600:oklch(55.8% .288 302.321);--color-pink-50:oklch(97.1% .014 343.198);--color-pink-100:oklch(94.8% .028 342.258);--color-pink-600:oklch(59.2% .249 .584);--color-slate-50:oklch(98.4% .003 247.858);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-200:oklch(92.9% .013 255.508);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-500:oklch(55.4% .046 257.417);--color-slate-600:oklch(44.6% .043 257.281);--color-slate-700:oklch(37.2% .044 257.287);--color-slate-800:oklch(27.9% .041 260.031);--color-slate-900:oklch(20.8% .042 265.755);--color-white:#fff;--spacing:.25rem;--container-md:28rem;--container-lg:32rem;--container-2xl:42rem;--container-3xl:48rem;--container-6xl:72rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75/1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-wider:.05em;--tracking-widest:.1em;--leading-relaxed:1.625;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--ease-out:cubic-bezier(0,0,.2,1);--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--blur-sm:8px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.inset-0{inset:calc(var(--spacing)*0)}.top-0\.5{top:calc(var(--spacing)*.5)}.top-1\/2{top:50%}.top-4{top:calc(var(--spacing)*4)}.top-full{top:100%}.right-0{right:calc(var(--spacing)*0)}.right-0\.5{right:calc(var(--spacing)*.5)}.right-4{right:calc(var(--spacing)*4)}.left-0\.5{left:calc(var(--spacing)*.5)}.left-3{left:calc(var(--spacing)*3)}.z-10{z-index:10}.z-50{z-index:50}.m-auto{margin:auto}.mx-auto{margin-inline:auto}.my-3{margin-block:calc(var(--spacing)*3)}.mt-0\.5{margin-top:calc(var(--spacing)*.5)}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-1\.5{margin-top:calc(var(--spacing)*1.5)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-3{margin-top:calc(var(--spacing)*3)}.mt-4{margin-top:calc(var(--spacing)*4)}.mr-4{margin-right:calc(var(--spacing)*4)}.mb-0\.5{margin-bottom:calc(var(--spacing)*.5)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-3{margin-bottom:calc(var(--spacing)*3)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.mb-6{margin-bottom:calc(var(--spacing)*6)}.mb-8{margin-bottom:calc(var(--spacing)*8)}.ml-1{margin-left:calc(var(--spacing)*1)}.ml-2{margin-left:calc(var(--spacing)*2)}.ml-4{margin-left:calc(var(--spacing)*4)}.ml-auto{margin-left:auto}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-6{-webkit-line-clamp:6;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.flex{display:flex}.grid{display:grid}.h-1\.5{height:calc(var(--spacing)*1.5)}.h-2\.5{height:calc(var(--spacing)*2.5)}.h-3{height:calc(var(--spacing)*3)}.h-4{height:calc(var(--spacing)*4)}.h-8{height:calc(var(--spacing)*8)}.h-10{height:calc(var(--spacing)*10)}.h-16{height:calc(var(--spacing)*16)}.h-64{height:calc(var(--spacing)*64)}.h-\[85vh\]{height:85vh}.h-full{height:100%}.h-screen{height:100vh}.max-h-32{max-height:calc(var(--spacing)*32)}.max-h-60{max-height:calc(var(--spacing)*60)}.max-h-\[85vh\]{max-height:85vh}.max-h-\[90vh\]{max-height:90vh}.max-h-\[280px\]{max-height:280px}.min-h-0{min-height:calc(var(--spacing)*0)}.min-h-\[100px\]{min-height:100px}.min-h-\[320px\]{min-height:320px}.min-h-\[400px\]{min-height:400px}.min-h-\[480px\]{min-height:480px}.w-1\.5{width:calc(var(--spacing)*1.5)}.w-3{width:calc(var(--spacing)*3)}.w-8{width:calc(var(--spacing)*8)}.w-10{width:calc(var(--spacing)*10)}.w-16{width:calc(var(--spacing)*16)}.w-64{width:calc(var(--spacing)*64)}.w-72{width:calc(var(--spacing)*72)}.w-80{width:calc(var(--spacing)*80)}.w-96{width:calc(var(--spacing)*96)}.w-\[512px\]{width:512px}.w-fit{width:fit-content}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-3xl{max-width:var(--container-3xl)}.max-w-6xl{max-width:var(--container-6xl)}.max-w-\[80\%\]{max-width:80%}.max-w-\[85\%\]{max-width:85%}.max-w-\[1400px\]{max-width:1400px}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-none{max-width:none}.min-w-\[200px\]{min-width:200px}.flex-1{flex:1}.shrink-0{flex-shrink:0}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x)var(--tw-translate-y)}.scale-105{--tw-scale-x:105%;--tw-scale-y:105%;--tw-scale-z:105%;scale:var(--tw-scale-x)var(--tw-scale-y)}.rotate-180{rotate:180deg}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize-none{resize:none}.list-inside{list-style-position:inside}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-start{justify-content:flex-start}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.gap-6{gap:calc(var(--spacing)*6)}.gap-8{gap:calc(var(--spacing)*8)}:where(.space-y-0\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*.5)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*.5)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*3)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*3)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*6)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*6)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*8)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*8)*calc(1 - var(--tw-space-y-reverse)))}.gap-x-8{column-gap:calc(var(--spacing)*8)}.gap-y-4{row-gap:calc(var(--spacing)*4)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-4{border-style:var(--tw-border-style);border-width:4px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-l-4{border-left-style:var(--tw-border-style);border-left-width:4px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-none{--tw-border-style:none;border-style:none}.border-amber-100{border-color:var(--color-amber-100)}.border-amber-200{border-color:var(--color-amber-200)}.border-blue-100{border-color:var(--color-blue-100)}.border-blue-200{border-color:var(--color-blue-200)}.border-blue-600{border-color:var(--color-blue-600)}.border-cyan-100{border-color:var(--color-cyan-100)}.border-emerald-100{border-color:var(--color-emerald-100)}.border-indigo-100{border-color:var(--color-indigo-100)}.border-orange-100{border-color:var(--color-orange-100)}.border-pink-100{border-color:var(--color-pink-100)}.border-purple-100{border-color:var(--color-purple-100)}.border-red-200{border-color:var(--color-red-200)}.border-slate-100{border-color:var(--color-slate-100)}.border-slate-200{border-color:var(--color-slate-200)}.border-transparent{border-color:#0000}.border-t-blue-600{border-top-color:var(--color-blue-600)}.border-t-transparent{border-top-color:#0000}.bg-amber-50{background-color:var(--color-amber-50)}.bg-amber-600{background-color:var(--color-amber-600)}.bg-blue-50{background-color:var(--color-blue-50)}.bg-blue-100{background-color:var(--color-blue-100)}.bg-blue-600{background-color:var(--color-blue-600)}.bg-cyan-50{background-color:var(--color-cyan-50)}.bg-emerald-50{background-color:var(--color-emerald-50)}.bg-indigo-50{background-color:var(--color-indigo-50)}.bg-orange-50{background-color:var(--color-orange-50)}.bg-pink-50{background-color:var(--color-pink-50)}.bg-purple-50{background-color:var(--color-purple-50)}.bg-red-50{background-color:var(--color-red-50)}.bg-red-100{background-color:var(--color-red-100)}.bg-slate-50{background-color:var(--color-slate-50)}.bg-slate-50\/50{background-color:#f8fafc80}@supports (color:color-mix(in lab,red,red)){.bg-slate-50\/50{background-color:color-mix(in oklab,var(--color-slate-50)50%,transparent)}}.bg-slate-100{background-color:var(--color-slate-100)}.bg-slate-200{background-color:var(--color-slate-200)}.bg-slate-300{background-color:var(--color-slate-300)}.bg-slate-900{background-color:var(--color-slate-900)}.bg-slate-900\/50{background-color:#0f172b80}@supports (color:color-mix(in lab,red,red)){.bg-slate-900\/50{background-color:color-mix(in oklab,var(--color-slate-900)50%,transparent)}}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.bg-white\/90{background-color:#ffffffe6}@supports (color:color-mix(in lab,red,red)){.bg-white\/90{background-color:color-mix(in oklab,var(--color-white)90%,transparent)}}.p-1{padding:calc(var(--spacing)*1)}.p-1\.5{padding:calc(var(--spacing)*1.5)}.p-2{padding:calc(var(--spacing)*2)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.p-5{padding:calc(var(--spacing)*5)}.p-6{padding:calc(var(--spacing)*6)}.p-8{padding:calc(var(--spacing)*8)}.px-1{padding-inline:calc(var(--spacing)*1)}.px-1\.5{padding-inline:calc(var(--spacing)*1.5)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-5{padding-inline:calc(var(--spacing)*5)}.px-6{padding-inline:calc(var(--spacing)*6)}.px-8{padding-inline:calc(var(--spacing)*8)}.py-0\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.py-2\.5{padding-block:calc(var(--spacing)*2.5)}.py-3{padding-block:calc(var(--spacing)*3)}.py-8{padding-block:calc(var(--spacing)*8)}.py-12{padding-block:calc(var(--spacing)*12)}.pr-1{padding-right:calc(var(--spacing)*1)}.pr-2{padding-right:calc(var(--spacing)*2)}.pr-4{padding-right:calc(var(--spacing)*4)}.pr-12{padding-right:calc(var(--spacing)*12)}.pb-2{padding-bottom:calc(var(--spacing)*2)}.pb-3{padding-bottom:calc(var(--spacing)*3)}.pl-0{padding-left:calc(var(--spacing)*0)}.pl-3{padding-left:calc(var(--spacing)*3)}.pl-4{padding-left:calc(var(--spacing)*4)}.pl-6{padding-left:calc(var(--spacing)*6)}.pl-10{padding-left:calc(var(--spacing)*10)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[8px\]{font-size:8px}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-amber-500{color:var(--color-amber-500)}.text-amber-600{color:var(--color-amber-600)}.text-amber-700{color:var(--color-amber-700)}.text-blue-400{color:var(--color-blue-400)}.text-blue-500{color:var(--color-blue-500)}.text-blue-600{color:var(--color-blue-600)}.text-blue-700{color:var(--color-blue-700)}.text-cyan-600{color:var(--color-cyan-600)}.text-emerald-600{color:var(--color-emerald-600)}.text-indigo-600{color:var(--color-indigo-600)}.text-orange-600{color:var(--color-orange-600)}.text-pink-600{color:var(--color-pink-600)}.text-purple-600{color:var(--color-purple-600)}.text-red-700{color:var(--color-red-700)}.text-red-800{color:var(--color-red-800)}.text-slate-100{color:var(--color-slate-100)}.text-slate-300{color:var(--color-slate-300)}.text-slate-400{color:var(--color-slate-400)}.text-slate-500{color:var(--color-slate-500)}.text-slate-600{color:var(--color-slate-600)}.text-slate-700{color:var(--color-slate-700)}.text-slate-800{color:var(--color-slate-800)}.text-slate-900{color:var(--color-slate-900)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.italic{font-style:italic}.opacity-0{opacity:0}.opacity-20{opacity:.2}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-80{opacity:.8}.opacity-90{opacity:.9}.opacity-100{opacity:1}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-1{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-blue-200{--tw-ring-color:var(--color-blue-200)}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.backdrop-blur-\[2px\]{--tw-backdrop-blur:blur(2px);-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-shadow{transition-property:box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-500{--tw-duration:.5s;transition-duration:.5s}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.outline-none{--tw-outline-style:none;outline-style:none}@media(hover:hover){.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}}.first\:mt-0:first-child{margin-top:calc(var(--spacing)*0)}.last\:mb-0:last-child{margin-bottom:calc(var(--spacing)*0)}.last\:border-0:last-child{border-style:var(--tw-border-style);border-width:0}.last\:pb-0:last-child{padding-bottom:calc(var(--spacing)*0)}@media(hover:hover){.hover\:border-blue-300:hover{border-color:var(--color-blue-300)}.hover\:border-slate-200:hover{border-color:var(--color-slate-200)}.hover\:bg-amber-700:hover{background-color:var(--color-amber-700)}.hover\:bg-blue-50:hover{background-color:var(--color-blue-50)}.hover\:bg-blue-50\/50:hover{background-color:#eff6ff80}@supports (color:color-mix(in lab,red,red)){.hover\:bg-blue-50\/50:hover{background-color:color-mix(in oklab,var(--color-blue-50)50%,transparent)}}.hover\:bg-blue-100:hover{background-color:var(--color-blue-100)}.hover\:bg-blue-700:hover{background-color:var(--color-blue-700)}.hover\:bg-red-50:hover{background-color:var(--color-red-50)}.hover\:bg-red-200:hover{background-color:var(--color-red-200)}.hover\:bg-slate-50:hover{background-color:var(--color-slate-50)}.hover\:bg-slate-100:hover{background-color:var(--color-slate-100)}.hover\:bg-slate-200:hover{background-color:var(--color-slate-200)}.hover\:bg-slate-800:hover{background-color:var(--color-slate-800)}.hover\:bg-white:hover{background-color:var(--color-white)}.hover\:text-blue-600:hover{color:var(--color-blue-600)}.hover\:text-blue-700:hover{color:var(--color-blue-700)}.hover\:text-red-500:hover{color:var(--color-red-500)}.hover\:text-red-600:hover{color:var(--color-red-600)}.hover\:text-slate-600:hover{color:var(--color-slate-600)}.hover\:text-slate-700:hover{color:var(--color-slate-700)}.hover\:underline:hover{text-decoration-line:underline}.hover\:shadow-md:hover{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}}.focus\:border-blue-500:focus{border-color:var(--color-blue-500)}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-blue-500:focus{--tw-ring-color:var(--color-blue-500)}.focus\:ring-blue-500\/10:focus{--tw-ring-color:#3080ff1a}@supports (color:color-mix(in lab,red,red)){.focus\:ring-blue-500\/10:focus{--tw-ring-color:color-mix(in oklab,var(--color-blue-500)10%,transparent)}}.focus\:ring-blue-500\/20:focus{--tw-ring-color:#3080ff33}@supports (color:color-mix(in lab,red,red)){.focus\:ring-blue-500\/20:focus{--tw-ring-color:color-mix(in oklab,var(--color-blue-500)20%,transparent)}}.active\:scale-95:active{--tw-scale-x:95%;--tw-scale-y:95%;--tw-scale-z:95%;scale:var(--tw-scale-x)var(--tw-scale-y)}.disabled\:bg-slate-300:disabled{background-color:var(--color-slate-300)}.disabled\:opacity-50:disabled{opacity:.5}@media(min-width:48rem){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(min-width:64rem){.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}}.no-scrollbar::-webkit-scrollbar{display:none}.no-scrollbar{-ms-overflow-style:none;scrollbar-width:none}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}
|