autosnippet 1.4.7 → 1.5.0
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 +22 -6
- package/bin/ui.js +29 -2
- package/dashboard/dist/assets/{index-CdoJx4Qh.js → index-4u3vg5wW.js} +11 -11
- package/dashboard/dist/index.html +1 -1
- package/lib/infra/nativeUi.js +1 -1
- package/lib/infra/openBrowser.js +1 -1
- package/package.json +5 -3
- package/resources/native-ui/README.md +29 -0
- package/resources/native-ui/main.swift +433 -0
- package/scripts/build-native-ui.js +2 -2
- package/scripts/cursor-rules/autosnippet-conventions.mdc +23 -0
- package/scripts/ensure-parse-package.js +5 -24
- package/scripts/install-cursor-skill.js +21 -2
- package/scripts/mcp-server.js +96 -12
- package/skills/autosnippet-batch-scan/SKILL.md +53 -0
- package/skills/autosnippet-when/SKILL.md +3 -1
- /package/{bin → resources}/openChrome.applescript +0 -0
package/README.md
CHANGED
|
@@ -39,7 +39,7 @@ asd ui # 启动 Dashboard(建议常驻)
|
|
|
39
39
|
|
|
40
40
|
1. **组建知识库**:`asd ais <Target>` 或 `asd ais --all` → Dashboard Candidates 审核 → Recipe 入库
|
|
41
41
|
2. **依赖关系**:`asd spm-map` 或 Dashboard 刷新
|
|
42
|
-
3. **Cursor 集成**:`asd install:cursor-skill --mcp`(安装 Skills + MCP,需 `asd ui` 运行)
|
|
42
|
+
3. **Cursor 集成**:`asd install:cursor-skill --mcp`(安装 Skills + Cursor 规则 `.cursor/rules/` + MCP,需 `asd ui` 运行)
|
|
43
43
|
4. **语义索引**:`asd ui` 启动时自动 embed;也可手动 `asd embed`
|
|
44
44
|
|
|
45
45
|
### 闭环
|
|
@@ -76,11 +76,17 @@ asd ui # 启动 Dashboard(建议常驻)
|
|
|
76
76
|
| `asd ais [Target]` | AI 扫描 Target → Candidates |
|
|
77
77
|
| `asd search [keyword] --copy` | 搜索并复制第一条到剪贴板 |
|
|
78
78
|
| `asd search [keyword] --pick` | 交互选择后复制/插入 |
|
|
79
|
-
| `asd install:cursor-skill --mcp` | 安装 Skills
|
|
79
|
+
| `asd install:cursor-skill --mcp` | 安装 Skills、Cursor 规则(`.cursor/rules/*.mdc`)并配置 MCP(需 `asd ui` 运行) |
|
|
80
80
|
| `asd install:full` | 全量安装;`--parser` 含 Swift 解析器;`--lancedb` 仅 LanceDB |
|
|
81
81
|
| `asd embed` | 手动构建语义向量索引(`asd ui` 启动时也会自动执行) |
|
|
82
82
|
| `asd spm-map` | 刷新 SPM 依赖映射(依赖关系图数据来源) |
|
|
83
83
|
|
|
84
|
+
### 用 Cursor 做批量扫描
|
|
85
|
+
|
|
86
|
+
除 `asd ais [Target]`(项目内 AI)外,可用 **Cursor 作为批量扫描工具**:在 Cursor 里让 Agent 通过 **MCP 工具**(`autosnippet_get_targets` → `autosnippet_get_target_files` → 按文件提取 → `autosnippet_submit_candidates`)扫描指定 Target,用 Cursor 模型提取候选并提交到 Dashboard,再到 **Candidates** 页审核入库。
|
|
87
|
+
|
|
88
|
+
简单一句:「扫描 BDNetwork ,生产 Recipes 到候选」。AutoSnippet 将所有能力都通过语义交给 Cursor 了。
|
|
89
|
+
|
|
84
90
|
## 全量安装与可选依赖
|
|
85
91
|
|
|
86
92
|
克隆或需完整能力时,**任意目录**执行:
|
|
@@ -93,19 +99,30 @@ asd install:full --lancedb # 仅安装 LanceDB(向量检索更快)
|
|
|
93
99
|
|
|
94
100
|
**Swift 解析器**:默认回退 `dump-package`;`--parser` 构建 ParsePackage 后 SPM 解析更准确,需本机已装 Swift。
|
|
95
101
|
|
|
102
|
+
### Postinstall 脚本说明(npm install 时)
|
|
103
|
+
|
|
104
|
+
`npm install` 会执行以下**可选**脚本,均为本包内本地构建,**不访问网络、不执行动态代码**:
|
|
105
|
+
|
|
106
|
+
| 脚本 | 作用 |
|
|
107
|
+
|------|------|
|
|
108
|
+
| `scripts/ensure-parse-package.js` | 仅当 `ASD_BUILD_SWIFT_PARSER=1` 时构建 Swift 解析器并打印「正在安装…」;否则打印跳过说明并退出。 |
|
|
109
|
+
| `scripts/build-native-ui.js` | 仅在 macOS 上用本机 Swift 编译 `resources/native-ui/main.swift` → `resources/native-ui/native-ui`;失败则静默跳过。 |
|
|
110
|
+
|
|
111
|
+
未安装或跳过不影响核心功能。详见 [npm lifecycle scripts](https://docs.npmjs.com/cli/v10/using-npm/scripts#life-cycle-scripts)。
|
|
112
|
+
|
|
96
113
|
## 配置
|
|
97
114
|
|
|
98
115
|
- **AI**:项目根 `.env`,设置 `ASD_GOOGLE_API_KEY` 等(见 `.env.example`)。可选 `ASD_AI_PROVIDER`、代理等。
|
|
99
116
|
- **LanceDB**:`asd install:full --lancedb`,在 boxspec 的 `context.storage.adapter` 中配置 `"lance"`。
|
|
100
|
-
- **Native UI**(可选):macOS 上 `npm install` 会尝试构建 `
|
|
117
|
+
- **Native UI**(可选):macOS 上 `npm install` 会尝试构建 `resources/native-ui/native-ui`(需本机 Swift);未构建时回退到 AppleScript/inquirer,功能正常。
|
|
101
118
|
|
|
102
119
|
## Recipe 格式
|
|
103
120
|
|
|
104
121
|
完整 Recipe 为 Markdown 文件,需包含:
|
|
105
122
|
|
|
106
123
|
- **Frontmatter**(`---` 包裹的 YAML):`title`、`trigger` 必填;可选 `category`、`language`、`headers` 等
|
|
107
|
-
-
|
|
108
|
-
-
|
|
124
|
+
- **Snippet / Code Reference**:下接代码块,供 Snippet 与检索使用
|
|
125
|
+
- **AI Context / Usage Guide**:使用说明,供 AI 与 Guard 检索
|
|
109
126
|
|
|
110
127
|
## 术语
|
|
111
128
|
|
|
@@ -114,7 +131,6 @@ asd install:full --lancedb # 仅安装 LanceDB(向量检索更快)
|
|
|
114
131
|
- **项目根**:含 `AutoSnippetRoot.boxspec.json` 的目录
|
|
115
132
|
|
|
116
133
|
**详细介绍**:启动 `asd ui` 后访问 Dashboard → **使用说明** 页;或参阅 [使用文档](docs/使用文档.md)(含 Skills 一览、AI 配置、闭环详解等)。
|
|
117
|
-
**发布流程**:CI 与 npm 发布见 [发布流程](docs/发布流程.md)(打 tag `v*` 触发自动发布)。
|
|
118
134
|
|
|
119
135
|
---
|
|
120
136
|
|
package/bin/ui.js
CHANGED
|
@@ -787,10 +787,20 @@ function launch(projectRoot, port = 3000, options = {}) {
|
|
|
787
787
|
}
|
|
788
788
|
});
|
|
789
789
|
|
|
790
|
-
// API: 获取 Target 将要扫描的文件列表(不调用 AI)
|
|
790
|
+
// API: 获取 Target 将要扫描的文件列表(不调用 AI)。支持 body.target 或 body.targetName(按名称查 target)
|
|
791
791
|
app.post('/api/spm/target-files', async (req, res) => {
|
|
792
792
|
try {
|
|
793
|
-
|
|
793
|
+
let target = req.body?.target;
|
|
794
|
+
if (!target && req.body?.targetName) {
|
|
795
|
+
const targets = await targetScanner.listAllTargets(projectRoot);
|
|
796
|
+
target = targets.find(t => t.name === req.body.targetName);
|
|
797
|
+
if (!target) {
|
|
798
|
+
return res.status(404).json({ error: `未找到 Target: ${req.body.targetName}` });
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
if (!target) {
|
|
802
|
+
return res.status(400).json({ error: '需要 body.target 或 body.targetName' });
|
|
803
|
+
}
|
|
794
804
|
const files = await targetScanner.getTargetFilesContent(target);
|
|
795
805
|
const scannedFiles = files.map(f => ({
|
|
796
806
|
name: f.name,
|
|
@@ -842,6 +852,23 @@ function launch(projectRoot, port = 3000, options = {}) {
|
|
|
842
852
|
}
|
|
843
853
|
});
|
|
844
854
|
|
|
855
|
+
// API: 追加候选(供 Cursor/MCP 批量扫描:Cursor AI 提取后提交,无需项目内 AI)
|
|
856
|
+
app.post('/api/candidates/append', async (req, res) => {
|
|
857
|
+
try {
|
|
858
|
+
const { targetName, items, source, expiresInHours } = req.body;
|
|
859
|
+
if (!targetName || !Array.isArray(items) || items.length === 0) {
|
|
860
|
+
return res.status(400).json({ error: '需要 targetName 与 items(数组,至少一条)' });
|
|
861
|
+
}
|
|
862
|
+
const safeSource = (source && typeof source === 'string') ? source : 'cursor-scan';
|
|
863
|
+
const hours = typeof expiresInHours === 'number' ? expiresInHours : 24;
|
|
864
|
+
await candidateService.appendCandidates(projectRoot, String(targetName), items, safeSource, hours);
|
|
865
|
+
res.json({ ok: true, count: items.length, targetName: String(targetName) });
|
|
866
|
+
} catch (err) {
|
|
867
|
+
console.error(`[API Error]`, err);
|
|
868
|
+
res.status(500).json({ error: err.message });
|
|
869
|
+
}
|
|
870
|
+
});
|
|
871
|
+
|
|
845
872
|
// API: 删除候选内容
|
|
846
873
|
app.post('/api/candidates/delete', async (req, res) => {
|
|
847
874
|
try {
|