autosnippet 1.6.1 → 1.6.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 +4 -7
- package/bin/api-server.js +84 -0
- package/bin/asd-cli.js +3 -2
- package/bin/cli-commands.js +169 -16
- package/bin/dashboard/routes/search.js +194 -27
- package/bin/dashboard/routes/spm.js +44 -12
- package/bin/dashboard-server.js +17 -4
- package/checksums.json +4 -4
- package/dashboard/dist/assets/index-BvG0go78.css +1 -0
- package/dashboard/dist/assets/index-xYTasTfI.js +54 -0
- package/dashboard/dist/assets/{markdown-DqCR-tTD.js → markdown-C9NwMkin.js} +1 -1
- package/dashboard/dist/assets/{vendor-DcWukCsG.js → vendor-lTi5QT2P.js} +64 -69
- package/dashboard/dist/index.html +4 -4
- package/lib/agent/Agent.js +402 -0
- package/lib/agent/ResultFusion.js +33 -0
- package/lib/agent/Task.js +337 -0
- package/lib/agent/UserPreferenceManager.js +5 -0
- package/lib/ai/providers/OpenAiProvider.js +29 -11
- package/lib/api/APIGateway.js +689 -0
- package/lib/application/services/ContextServiceCompat.js +73 -30
- package/lib/application/services/IntelligentServiceLayer.js +172 -7
- package/lib/application/services/SearchServiceV2.js +198 -41
- package/lib/automation/ActionPipeline.js +13 -0
- package/lib/automation/AutomationOrchestrator.js +23 -0
- package/lib/automation/ContextCollector.js +10 -0
- package/lib/automation/OutputApplier.js +10 -0
- package/lib/automation/TriggerResolver.js +13 -0
- package/lib/business/metrics/MetricsHub.js +442 -0
- package/lib/business/recipe/RecipeHub.js +460 -0
- package/lib/business/search/SearchHub.js +484 -0
- package/lib/cli/candidateCommand.js +143 -0
- package/lib/cli/embedCommand.js +47 -0
- package/lib/cli/searchCommand.js +138 -0
- package/lib/cli/statusCommand.js +256 -0
- package/lib/infrastructure/cache/CacheHub.js +243 -0
- package/lib/infrastructure/error/ErrorManager.js +453 -0
- package/lib/infrastructure/external/OpenBrowser.js +14 -1
- package/lib/infrastructure/external/spm/DepFixer.js +164 -0
- package/lib/infrastructure/external/spm/DepGraphAnalyzer.js +98 -0
- package/lib/infrastructure/external/spm/DepGraphService.js +208 -0
- package/lib/infrastructure/external/spm/DepPolicyEngine.js +49 -0
- package/lib/infrastructure/external/spm/DepReport.js +10 -0
- package/lib/infrastructure/external/spm/SpmDepsServiceV2.js +219 -194
- package/lib/infrastructure/external/spm/spmDepGraphPatch.js +4 -0
- package/lib/infrastructure/external/spm/spmDepMapUpdater.js +10 -0
- package/lib/infrastructure/logging/LogFactory.js +160 -0
- package/lib/infrastructure/notification/ClipboardManager.js +137 -0
- package/lib/infrastructure/notification/NativeUi.js +71 -6
- package/lib/infrastructure/notification/Notifier.js +52 -0
- package/lib/infrastructure/paths/PathFinder.js +19 -110
- package/lib/infrastructure/paths/ProjectStructure.js +222 -0
- package/lib/infrastructure/process/ProcessHub.js +452 -0
- package/lib/injection/DirectiveParserV2.js +33 -17
- package/lib/injection/ImportDecisionEngine.js +39 -0
- package/lib/injection/ImportWriterV2.js +210 -5
- package/lib/injection/ModuleResolverV2.js +93 -17
- package/lib/injection/injectionService.js +172 -21
- package/lib/rateLimit.js +10 -2
- package/lib/search/indexer.js +6 -1
- package/lib/search/rankingEngine.js +11 -2
- package/lib/search/recallEngine.js +5 -1
- package/lib/search/unifiedSearch.js +245 -0
- package/lib/watch/DirectiveDetector.js +1 -1
- package/lib/watch/FileWatchService.js +31 -0
- package/lib/watch/handlers/AlinkHandler.js +14 -0
- package/lib/watch/handlers/CreateHandler.js +72 -4
- package/lib/watch/handlers/DraftHandler.js +14 -0
- package/lib/watch/handlers/GuardHandler.js +14 -0
- package/lib/watch/handlers/HeaderHandler.js +14 -0
- package/lib/watch/handlers/SearchHandler.js +901 -43
- package/lib/writeGuard.js +10 -15
- package/package.json +6 -3
- package/recipes/README.md +2 -2
- package/resources/native-ui/main.swift +169 -30
- package/scripts/cursor-rules/autosnippet-conventions.mdc +9 -8
- package/scripts/generate-checksums.js +16 -0
- package/scripts/generate-recipe-drafts.js +151 -0
- package/scripts/init-xcode-snippets.js +310 -0
- package/scripts/install-cursor-skill.js +13 -20
- package/scripts/install-full.js +2 -11
- package/scripts/random-search-test.js +142 -0
- package/scripts/recipe-migration-diagnose.js +0 -11
- package/scripts/test-ai-failure-handling.js +79 -0
- package/scripts/test-google-models.js +85 -0
- package/scripts/test-hybrid-comprehensive.js +120 -0
- package/scripts/test-hybrid-search.js +54 -0
- package/scripts/test-search-modes.js +364 -0
- package/scripts/test-sentence-search.js +80 -0
- package/skills/autosnippet-concepts/SKILL.md +2 -2
- package/skills/autosnippet-create/SKILL.md +1 -1
- package/skills/autosnippet-dep-graph/SKILL.md +1 -1
- package/skills/autosnippet-recipes/SKILL.md +2 -2
- package/dashboard/dist/assets/index-DIIxAaTf.js +0 -54
- package/dashboard/dist/assets/index-DnrK_geI.css +0 -1
package/README.md
CHANGED
|
@@ -83,7 +83,7 @@ asd ui # 启动 Dashboard + watch
|
|
|
83
83
|
|
|
84
84
|
| 命令 | 说明 |
|
|
85
85
|
|------|------|
|
|
86
|
-
| `asd setup` | 初始化项目根(创建
|
|
86
|
+
| `asd setup` | 初始化项目根(创建 AutoSnippet/AutoSnippet.boxspec.json) |
|
|
87
87
|
| `asd ui` | 启动 Dashboard + watch |
|
|
88
88
|
| `asd status` | 环境自检(含项目根、AI、索引、Dashboard/Watch、Native UI) |
|
|
89
89
|
| `asd create --clipboard` | 从剪贴板创建 Recipe/Snippet |
|
|
@@ -93,7 +93,7 @@ asd ui # 启动 Dashboard + watch
|
|
|
93
93
|
| `asd search [keyword] --copy` | 搜索并复制第一条到剪贴板 |
|
|
94
94
|
| `asd search [keyword] --pick` | 交互选择后复制/插入 |
|
|
95
95
|
| `asd install:cursor-skill --mcp` | 安装 Skills、Cursor 规则(`.cursor/rules/*.mdc`)并配置 MCP。配置时可运行;MCP 工具使用时需 `asd ui` 已启动 |
|
|
96
|
-
| `asd install:full` | 全量安装;`--parser` 含 Swift
|
|
96
|
+
| `asd install:full` | 全量安装;`--parser` 含 Swift 解析器 |
|
|
97
97
|
| `asd embed` | 手动构建语义向量索引(`asd ui` 启动时也会自动执行) |
|
|
98
98
|
| `asd spm-map` | 刷新 SPM 依赖映射(依赖关系图数据来源) |
|
|
99
99
|
|
|
@@ -139,10 +139,7 @@ npm run build:parser # 构建 ParsePackage(需本机已安装 Swift)
|
|
|
139
139
|
| **项目根** | 含 `AutoSnippetRoot.boxspec.json` 的目录 |
|
|
140
140
|
| **Target** | SPM 模块/编译单元;`asd ais <Target>` 扫描该 Target 下的源码提取候选 |
|
|
141
141
|
|
|
142
|
-
**详细介绍**:启动 `asd ui` 后访问 Dashboard → **使用说明**
|
|
143
|
-
- 📖 **[完整使用说明书](docs/USER_MANUAL.md)**:15,000 字详细文档,涵盖从入门到高级的所有功能
|
|
144
|
-
- 📝 **[使用文档](docs/使用文档.md)**:简明版使用说明(含 Skills 一览、AI 配置、闭环详解等)
|
|
145
|
-
- ⚙️ **[npm 脚本参考](docs/NPM_SCRIPTS_REFERENCE.md)**:所有 npm 命令详细说明和使用示例
|
|
142
|
+
**详细介绍**:启动 `asd ui` 后访问 Dashboard → **使用说明** 页;
|
|
146
143
|
|
|
147
144
|
## AutoSnippet 目录与 Git
|
|
148
145
|
|
|
@@ -152,7 +149,7 @@ AutoSnippet 下各路径与版本控制的关系建议如下(可按项目需
|
|
|
152
149
|
|------|------|------|
|
|
153
150
|
| **AutoSnippet/recipes/** | Recipe 的 Markdown 文件 | **Git 子仓库**:单独建远程仓库并 `git submodule add <url> AutoSnippet/recipes`,用于权限拦截(仅能 push 子仓库的人可保存/上传 Recipe)。详见 [权限设置说明](docs/权限设置说明.md) 中「只把 AutoSnippet/recipes 作为子仓库」。 |
|
|
154
151
|
| **AutoSnippet/.autosnippet/** | Guard 规则、违反记录、candidates、recipe-stats、context 配置等 | **跟随主仓库 Git**:规则与配置建议提交到主仓库,便于团队共享。 |
|
|
155
|
-
| **AutoSnippet/.autosnippet/context/index/** | 语义向量索引(embed 生成) | **不跟随 Git**:体积大、机器相关,建议加入 `.gitignore`(如 `AutoSnippet/.autosnippet/context/index
|
|
152
|
+
| **AutoSnippet/.autosnippet/context/index/** | 语义向量索引(embed 生成) | **不跟随 Git**:体积大、机器相关,建议加入 `.gitignore`(如 `AutoSnippet/.autosnippet/context/index/`)。 |
|
|
156
153
|
| **AutoSnippet/.autosnippet/candidates/**(若存在) | 候选数据等 | 视需要:若仅本地缓存可不提交;若团队共享可跟随主仓库或单独子仓库。 |
|
|
157
154
|
| **AutoSnippet/AutoSnippet.spmmap.json**(若存在) | SPM 依赖映射 | **跟随主仓库 Git**:便于依赖关系图一致。 |
|
|
158
155
|
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Server 启动脚本
|
|
3
|
+
*
|
|
4
|
+
* 用法:
|
|
5
|
+
* node bin/api-server.js [options]
|
|
6
|
+
*
|
|
7
|
+
* 选项:
|
|
8
|
+
* --port <port> API 服务器端口 (默认: 8080)
|
|
9
|
+
* --host <host> API 服务器主机 (默认: localhost)
|
|
10
|
+
* --config <path> 配置文件路径
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const { APIGateway } = require('../lib/api/APIGateway');
|
|
14
|
+
const { Agent } = require('../lib/agent/Agent');
|
|
15
|
+
const { RecipeHub } = require('../lib/business/recipe/RecipeHub');
|
|
16
|
+
const { SearchHub } = require('../lib/business/search/SearchHub');
|
|
17
|
+
const { MetricsHub } = require('../lib/business/metrics/MetricsHub');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 解析命令行参数
|
|
21
|
+
*/
|
|
22
|
+
function parseArgs() {
|
|
23
|
+
const args = process.argv.slice(2);
|
|
24
|
+
const options = {
|
|
25
|
+
port: 8080,
|
|
26
|
+
host: 'localhost',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
for (let i = 0; i < args.length; i++) {
|
|
30
|
+
if (args[i] === '--port') {
|
|
31
|
+
options.port = parseInt(args[++i], 10);
|
|
32
|
+
} else if (args[i] === '--host') {
|
|
33
|
+
options.host = args[++i];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return options;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* 启动 API 服务器
|
|
42
|
+
*/
|
|
43
|
+
async function startServer() {
|
|
44
|
+
const options = parseArgs();
|
|
45
|
+
|
|
46
|
+
// 创建 Agent
|
|
47
|
+
const agent = new Agent({ name: 'APIAgent' });
|
|
48
|
+
|
|
49
|
+
// 注册 Hub
|
|
50
|
+
agent.registerHub('recipe', new RecipeHub());
|
|
51
|
+
agent.registerHub('search', new SearchHub());
|
|
52
|
+
agent.registerHub('metric', new MetricsHub());
|
|
53
|
+
|
|
54
|
+
// 创建 API Gateway
|
|
55
|
+
const gateway = new APIGateway(agent, {
|
|
56
|
+
port: options.port,
|
|
57
|
+
host: options.host,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// 启动服务器
|
|
61
|
+
try {
|
|
62
|
+
await gateway.start();
|
|
63
|
+
console.log(`✨ API 服务器运行中...`);
|
|
64
|
+
console.log(`📝 API 文档: http://${options.host}:${options.port}/api/docs`);
|
|
65
|
+
console.log(`🏥 健康检查: http://${options.host}:${options.port}/api/health`);
|
|
66
|
+
console.log(`\n按 Ctrl+C 停止服务器`);
|
|
67
|
+
} catch (error) {
|
|
68
|
+
console.error('❌ 启动服务器失败:', error);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// 处理信号
|
|
73
|
+
process.on('SIGINT', async () => {
|
|
74
|
+
console.log('\n🛑 停止服务器...');
|
|
75
|
+
await gateway.stop();
|
|
76
|
+
console.log('✅ 服务器已停止');
|
|
77
|
+
process.exit(0);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
startServer().catch(error => {
|
|
82
|
+
console.error('Fatal error:', error);
|
|
83
|
+
process.exit(1);
|
|
84
|
+
});
|
package/bin/asd-cli.js
CHANGED
|
@@ -23,10 +23,11 @@ const fs = require('fs');
|
|
|
23
23
|
const path = require('path');
|
|
24
24
|
|
|
25
25
|
// 入口校验:包内存在 checksums.json 且未经过 asd-verify(无 ASD_VERIFIED)时,可拒跑或警告,避免绕过完整性校验直接运行 node bin/asd-cli.js
|
|
26
|
+
// 开发环境可设 ASD_SKIP_CHECKSUMS=1 或 ASD_SKIP_ENTRY_CHECK=1 来跳过检查
|
|
26
27
|
const pkgRoot = path.join(__dirname, '..');
|
|
27
28
|
const checksumsPath = path.join(pkgRoot, 'checksums.json');
|
|
28
|
-
if (fs.existsSync(checksumsPath) && process.env.ASD_VERIFIED !== '1') {
|
|
29
|
-
const msg = 'asd: 未经过完整性校验入口(请使用 asd 命令,勿直接运行 node bin/asd-cli.js)。开发/调试可设 ASD_SKIP_ENTRY_CHECK=1 跳过。';
|
|
29
|
+
if (fs.existsSync(checksumsPath) && process.env.ASD_VERIFIED !== '1' && process.env.ASD_SKIP_CHECKSUMS !== '1') {
|
|
30
|
+
const msg = 'asd: 未经过完整性校验入口(请使用 asd 命令,勿直接运行 node bin/asd-cli.js)。开发/调试可设 ASD_SKIP_CHECKSUMS=1 或 ASD_SKIP_ENTRY_CHECK=1 跳过。';
|
|
30
31
|
if (process.env.ASD_STRICT_ENTRY === '1') {
|
|
31
32
|
console.error(msg);
|
|
32
33
|
process.exit(1);
|
package/bin/cli-commands.js
CHANGED
|
@@ -17,9 +17,10 @@ const create = require('./create-snippet.js');
|
|
|
17
17
|
const watch = require('../lib/watch/fileWatcher.js');
|
|
18
18
|
const cache = require('../lib/infrastructure/cache/CacheStore.js');
|
|
19
19
|
const pjson = require('../package.json');
|
|
20
|
+
const swiftParserClient = require('../lib/infrastructure/external/spm/swiftParserClient');
|
|
20
21
|
|
|
21
22
|
function registerCommands(cmd, ctx) {
|
|
22
|
-
const { CMD_PATH, findPath, install, create, watch, cache, helpers, inquirer, fs, execSync, pjson } = ctx;
|
|
23
|
+
const { CMD_PATH, findPath, install, create, watch, cache, helpers, inquirer, fs, execSync, pjson, spmDepMapUpdater } = ctx;
|
|
23
24
|
|
|
24
25
|
// 配置 version 选项
|
|
25
26
|
cmd.version(pjson.version, '-v, --version', 'output the current version');
|
|
@@ -129,8 +130,8 @@ function registerCommands(cmd, ctx) {
|
|
|
129
130
|
}
|
|
130
131
|
}
|
|
131
132
|
|
|
132
|
-
// Step 4: 安装依赖和配置工具链
|
|
133
|
-
|
|
133
|
+
// Step 4: 安装依赖和配置工具链
|
|
134
|
+
console.log('🔧 步骤 4/5:安装依赖和配置工具链...\n');
|
|
134
135
|
|
|
135
136
|
// 查找 asd 安装位置(全局或本地)
|
|
136
137
|
let asdPath;
|
|
@@ -229,6 +230,33 @@ function registerCommands(cmd, ctx) {
|
|
|
229
230
|
}
|
|
230
231
|
}
|
|
231
232
|
|
|
233
|
+
// Step 5: 生成 spmmap(依赖 Swift 解析器)
|
|
234
|
+
console.log('🧭 步骤 5/5:生成依赖图 AutoSnippet.spmmap.json...');
|
|
235
|
+
const parserBin = swiftParserClient.getParserBin(projectRoot);
|
|
236
|
+
if (!parserBin) {
|
|
237
|
+
console.warn('⚠️ 未检测到 Swift 解析器(ParsePackage),已跳过 spmmap 生成。');
|
|
238
|
+
console.warn(' 请先安装解析器:asd install:full --parser');
|
|
239
|
+
console.warn(' 安装完成后请重新执行:asd setup\n');
|
|
240
|
+
} else {
|
|
241
|
+
try {
|
|
242
|
+
const result = await spmDepMapUpdater.updateSpmDepMap(projectRoot, {
|
|
243
|
+
aggressive: true,
|
|
244
|
+
requireParser: true
|
|
245
|
+
});
|
|
246
|
+
if (result && result.ok) {
|
|
247
|
+
console.log('✅ spmmap 已生成/更新\n');
|
|
248
|
+
} else if (result && result.reason === 'parserMissing') {
|
|
249
|
+
console.warn('⚠️ 未检测到 Swift 解析器(ParsePackage),已跳过 spmmap 生成。');
|
|
250
|
+
console.warn(' 请先安装解析器:asd install:full --parser');
|
|
251
|
+
console.warn(' 安装完成后请重新执行:asd setup\n');
|
|
252
|
+
} else {
|
|
253
|
+
console.warn('⚠️ spmmap 生成失败,请检查 Package.swift 或解析器状态\n');
|
|
254
|
+
}
|
|
255
|
+
} catch (err) {
|
|
256
|
+
console.warn(`⚠️ spmmap 生成失败:${err.message}\n`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
232
260
|
console.log('\n========================================');
|
|
233
261
|
console.log('✅ 工作空间初始化完成!');
|
|
234
262
|
console.log('========================================\n');
|
|
@@ -236,10 +264,27 @@ function registerCommands(cmd, ctx) {
|
|
|
236
264
|
console.log('📁 Recipe 目录: AutoSnippet/recipes/');
|
|
237
265
|
console.log('⚙️ VSCode MCP: .vscode/settings.json');
|
|
238
266
|
console.log('⚙️ Cursor MCP: .cursor/mcp.json\n');
|
|
239
|
-
|
|
240
|
-
|
|
267
|
+
|
|
268
|
+
// Step 6: 初始化 Xcode Snippets(仅在 macOS)
|
|
269
|
+
if (process.platform === 'darwin') {
|
|
270
|
+
console.log('🚀 步骤 6/6:初始化 Xcode Snippets...');
|
|
271
|
+
try {
|
|
272
|
+
const { initialize: initXcodeSnippets } = require('../scripts/init-xcode-snippets.js');
|
|
273
|
+
const success = await initXcodeSnippets();
|
|
274
|
+
if (success) {
|
|
275
|
+
console.log('✅ Xcode Snippets 已添加\n');
|
|
276
|
+
}
|
|
277
|
+
} catch (err) {
|
|
278
|
+
console.warn(`⚠️ Xcode Snippets 初始化失败:${err.message}`);
|
|
279
|
+
console.warn(' 可稍后手动运行:npm run init:snippets\n');
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
console.log('🎯 后续步骤:');
|
|
284
|
+
console.log(' 1. 重启编辑器 (VSCode/Cursor/Xcode)');
|
|
241
285
|
console.log(' 2. 测试 MCP: @autosnippet search');
|
|
242
|
-
console.log(' 3.
|
|
286
|
+
console.log(' 3. 在 Xcode 中输入 "ass" 尝试 Snippet');
|
|
287
|
+
console.log(' 4. 启动面板: asd ui\n');
|
|
243
288
|
});
|
|
244
289
|
|
|
245
290
|
|
|
@@ -393,11 +438,26 @@ function registerCommands(cmd, ctx) {
|
|
|
393
438
|
.option('-s, --skip-spm', 'skip SPM scanning')
|
|
394
439
|
.description('recognize that Snippet automatically injects dependency header files')
|
|
395
440
|
.action((options) => {
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
441
|
+
// 使用异步版本来确保得到结果或超时
|
|
442
|
+
const timeoutId = setTimeout(() => {
|
|
443
|
+
console.error('❌ 未找到 AutoSnippet.boxspec.json 配置文件');
|
|
444
|
+
console.error(' 请在包含 AutoSnippet.boxspec.json 的目录或其子目录中运行此命令');
|
|
445
|
+
console.error(' 或使用 asd init 初始化项目');
|
|
446
|
+
process.exit(1);
|
|
447
|
+
}, 3000);
|
|
448
|
+
|
|
449
|
+
getSpecFile(function (specFile) {
|
|
450
|
+
clearTimeout(timeoutId);
|
|
451
|
+
if (!specFile) {
|
|
452
|
+
console.error('❌ Watch 启动失败:未找到 AutoSnippet.boxspec.json 配置文件');
|
|
453
|
+
process.exit(1);
|
|
454
|
+
}
|
|
455
|
+
const args = {
|
|
456
|
+
skipSpm: options.skipSpm || false,
|
|
457
|
+
projectRoot: CMD_PATH,
|
|
458
|
+
};
|
|
459
|
+
watch.watchFileChange(specFile, CMD_PATH, args);
|
|
460
|
+
});
|
|
401
461
|
});
|
|
402
462
|
|
|
403
463
|
// spm-map 命令
|
|
@@ -422,14 +482,14 @@ function registerCommands(cmd, ctx) {
|
|
|
422
482
|
}
|
|
423
483
|
});
|
|
424
484
|
|
|
425
|
-
// ui 命令 - 启动 Dashboard Web
|
|
485
|
+
// ui 命令 - 启动 Dashboard Web 界面(自动包含 watch 功能)
|
|
426
486
|
cmd
|
|
427
487
|
.command('ui')
|
|
428
488
|
.option('-p, --port <port>', 'specify port (default: 3000)', '3000')
|
|
429
489
|
.option('--no-open', 'do not open browser automatically')
|
|
430
490
|
.option('-b, --force-build', 'force rebuild dashboard frontend')
|
|
431
491
|
.option('-d, --dir <directory>', 'specify AutoSnippet project directory (default: current directory)')
|
|
432
|
-
.description('start AutoSnippet Dashboard web interface')
|
|
492
|
+
.description('start AutoSnippet Dashboard web interface (includes file watcher)')
|
|
433
493
|
.action(async (options) => {
|
|
434
494
|
const ui = ctx.ui;
|
|
435
495
|
if (!ui || typeof ui.launch !== 'function') {
|
|
@@ -441,6 +501,13 @@ function registerCommands(cmd, ctx) {
|
|
|
441
501
|
const port = parseInt(options.port, 10);
|
|
442
502
|
// 使用 -d 选项指定的目录,或 ASD_CWD 环境变量,或当前目录
|
|
443
503
|
const projectRoot = options.dir || process.env.ASD_CWD || CMD_PATH;
|
|
504
|
+
|
|
505
|
+
// 提示用户 watch 功能已包含
|
|
506
|
+
const isDebugMode = process.env.ASD_DEBUG_WATCH === '1' || process.env.ASD_DEBUG_SEARCH === '1';
|
|
507
|
+
if (isDebugMode) {
|
|
508
|
+
console.log('💡 调试模式已启用,将显示文件监听日志');
|
|
509
|
+
}
|
|
510
|
+
|
|
444
511
|
await ui.launch(projectRoot, port, {
|
|
445
512
|
forceBuild: options.forceBuild || false,
|
|
446
513
|
openBrowser: options.open !== false,
|
|
@@ -450,19 +517,105 @@ function registerCommands(cmd, ctx) {
|
|
|
450
517
|
}
|
|
451
518
|
});
|
|
452
519
|
|
|
520
|
+
// status 命令 - 环境自检
|
|
521
|
+
cmd
|
|
522
|
+
.command('status')
|
|
523
|
+
.description('check AutoSnippet environment (project root, AI, index, Dashboard, Native UI)')
|
|
524
|
+
.action(async () => {
|
|
525
|
+
const { runStatus } = require('../lib/cli/statusCommand');
|
|
526
|
+
const projectRoot = CMD_PATH;
|
|
527
|
+
await runStatus(projectRoot);
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
// search 命令 - 搜索知识库
|
|
531
|
+
cmd
|
|
532
|
+
.command('search <keyword>')
|
|
533
|
+
.alias('s')
|
|
534
|
+
.option('--copy', 'copy first result to clipboard')
|
|
535
|
+
.option('--pick', 'interactive selection')
|
|
536
|
+
.option('-m, --semantic', 'use semantic search (requires embed)')
|
|
537
|
+
.option('--without-agent', 'disable intelligent agent enhancement')
|
|
538
|
+
.option('--session <id>', 'specify session ID for agent personalization')
|
|
539
|
+
.description('search Recipes and Snippets')
|
|
540
|
+
.action(async (keyword, options) => {
|
|
541
|
+
const { runSearch } = require('../lib/cli/searchCommand');
|
|
542
|
+
const projectRoot = CMD_PATH;
|
|
543
|
+
await runSearch(projectRoot, keyword, options);
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
// embed 命令 - 构建语义索引
|
|
547
|
+
cmd
|
|
548
|
+
.command('embed')
|
|
549
|
+
.option('--clear', 'clear and rebuild index')
|
|
550
|
+
.description('build semantic vector index for Recipes')
|
|
551
|
+
.action(async (options) => {
|
|
552
|
+
const { runEmbed } = require('../lib/cli/embedCommand');
|
|
553
|
+
const projectRoot = CMD_PATH;
|
|
554
|
+
await runEmbed(projectRoot, options);
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
// candidate 命令 - 从剪贴板创建候选
|
|
558
|
+
cmd
|
|
559
|
+
.command('candidate')
|
|
560
|
+
.option('-t, --title <title>', 'candidate title')
|
|
561
|
+
.option('-c, --category <category>', 'candidate category')
|
|
562
|
+
.description('create candidate from clipboard')
|
|
563
|
+
.action(async (options) => {
|
|
564
|
+
const { runCandidate } = require('../lib/cli/candidateCommand');
|
|
565
|
+
const projectRoot = CMD_PATH;
|
|
566
|
+
await runCandidate(projectRoot, options);
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
// install:full 命令 - 全量安装
|
|
570
|
+
cmd
|
|
571
|
+
.command('install:full')
|
|
572
|
+
.option('--parser', 'install Swift parser')
|
|
573
|
+
.description('install all optional dependencies')
|
|
574
|
+
.action(async (options) => {
|
|
575
|
+
const { execSync } = require('child_process');
|
|
576
|
+
const path = require('path');
|
|
577
|
+
const rootDir = path.join(__dirname, '..');
|
|
578
|
+
const scriptPath = path.join(rootDir, 'scripts/install-full.js');
|
|
579
|
+
|
|
580
|
+
const env = { ...process.env };
|
|
581
|
+
if (options.parser) env.ASD_INSTALL_PARSER = '1';
|
|
582
|
+
|
|
583
|
+
try {
|
|
584
|
+
execSync(`node "${scriptPath}"`, {
|
|
585
|
+
stdio: 'inherit',
|
|
586
|
+
env,
|
|
587
|
+
cwd: rootDir
|
|
588
|
+
});
|
|
589
|
+
} catch (err) {
|
|
590
|
+
console.error('❌ 安装失败');
|
|
591
|
+
process.exit(1);
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
|
|
453
595
|
cmd.addHelpText('after', `
|
|
454
596
|
|
|
455
597
|
Examples:
|
|
456
598
|
asd setup # 初始化工作空间
|
|
599
|
+
asd status # 环境自检
|
|
457
600
|
asd install # 安装依赖/skills/MCP
|
|
458
601
|
asd extract # 同步 snippets 到 Xcode
|
|
459
602
|
asd create # 创建 snippet
|
|
460
|
-
asd watch #
|
|
461
|
-
asd ui # 启动 Dashboard
|
|
603
|
+
asd watch # 监听文件变化(单独运行)
|
|
604
|
+
asd ui # 启动 Dashboard(自动包含 watch)
|
|
605
|
+
asd search <keyword> # 搜索知识库
|
|
606
|
+
asd embed # 构建语义索引
|
|
607
|
+
asd candidate # 从剪贴板创建候选
|
|
608
|
+
|
|
609
|
+
Advanced:
|
|
462
610
|
asd ui -d /path/to/AutoSnippet # 启动 Dashboard,操作指定项目
|
|
611
|
+
asd install:full --parser # 全量安装 + Swift 解析器
|
|
612
|
+
|
|
613
|
+
Debug modes:
|
|
614
|
+
ASD_DEBUG_WATCH=1 asd ui # Dashboard + 文件监听日志
|
|
615
|
+
ASD_DEBUG_SEARCH=1 asd ui # Dashboard + 搜索调试日志
|
|
463
616
|
|
|
464
617
|
Notes:
|
|
465
|
-
- 老命令仍可用:i/c/e/u/w 只是别名,不会破坏现有脚本。
|
|
618
|
+
- 老命令仍可用:i/c/e/u/w/s 只是别名,不会破坏现有脚本。
|
|
466
619
|
- 在非 AutoSnippet 目录中,使用 -d 或 ASD_CWD 环境变量指定项目路径。
|
|
467
620
|
`);
|
|
468
621
|
}
|