autosnippet 3.0.13 → 3.1.1
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/bin/api-server.js +2 -0
- package/bin/cli.js +24 -19
- package/config/default.json +1 -1
- package/lib/bootstrap.js +4 -4
- package/lib/cli/SetupService.js +29 -29
- package/lib/cli/UpgradeService.js +3 -2
- package/lib/core/AstAnalyzer.js +1 -1
- package/lib/core/ast/ensure-grammars.js +1 -1
- package/lib/core/ast/index.js +62 -11
- package/lib/core/ast/lang-dart.js +27 -21
- package/lib/core/ast/lang-go.js +6 -20
- package/lib/core/ast/lang-rust.js +53 -28
- package/lib/core/ast/parser-init.js +9 -5
- package/lib/core/discovery/DartDiscoverer.js +4 -10
- package/lib/core/discovery/GoDiscoverer.js +45 -25
- package/lib/core/discovery/NodeDiscoverer.js +1 -3
- package/lib/core/discovery/PythonDiscoverer.js +7 -1
- package/lib/core/discovery/RustDiscoverer.js +111 -38
- package/lib/core/discovery/index.js +2 -2
- package/lib/core/enhancement/django-enhancement.js +10 -4
- package/lib/core/enhancement/fastapi-enhancement.js +16 -9
- package/lib/core/enhancement/go-grpc-enhancement.js +2 -1
- package/lib/core/enhancement/go-web-enhancement.js +3 -6
- package/lib/core/enhancement/ml-enhancement.js +6 -3
- package/lib/core/enhancement/nextjs-enhancement.js +17 -7
- package/lib/core/enhancement/node-server-enhancement.js +4 -2
- package/lib/core/enhancement/react-enhancement.js +6 -3
- package/lib/core/enhancement/rust-tokio-enhancement.js +6 -2
- package/lib/core/enhancement/rust-web-enhancement.js +13 -7
- package/lib/core/enhancement/vue-enhancement.js +10 -5
- package/lib/external/ai/AiFactory.js +3 -1
- package/lib/external/ai/AiProvider.js +3 -1
- package/lib/external/mcp/McpServer.js +2 -0
- package/lib/external/mcp/handlers/bootstrap/base-dimensions.js +1 -2
- package/lib/external/mcp/handlers/bootstrap/pipeline/checkpoint.js +7 -1
- package/lib/external/mcp/handlers/bootstrap/pipeline/noAiFallback.js +55 -26
- package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +8 -8
- package/lib/external/mcp/handlers/bootstrap/refine.js +3 -1
- package/lib/external/mcp/handlers/bootstrap.js +4 -10
- package/lib/external/mcp/handlers/browse.js +6 -2
- package/lib/external/mcp/handlers/guard.js +6 -2
- package/lib/external/mcp/handlers/skill.js +6 -2
- package/lib/http/HttpServer.js +1 -1
- package/lib/http/routes/candidates.js +3 -1
- package/lib/http/routes/extract.js +4 -5
- package/lib/http/routes/guardRules.js +1 -1
- package/lib/http/routes/modules.js +9 -3
- package/lib/http/routes/skills.js +54 -6
- package/lib/http/routes/violations.js +4 -3
- package/lib/infrastructure/external/ClipboardManager.js +24 -7
- package/lib/infrastructure/external/NativeUi.js +3 -1
- package/lib/infrastructure/external/OpenBrowser.js +1 -0
- package/lib/infrastructure/external/XcodeAutomation.js +5 -5
- package/lib/infrastructure/vector/IndexingPipeline.js +14 -5
- package/lib/injection/ServiceContainer.js +34 -11
- package/lib/platform/ios/index.js +20 -25
- package/lib/platform/ios/routes/spm.js +6 -3
- package/lib/platform/ios/snippet/PlaceholderConverter.js +6 -2
- package/lib/platform/ios/snippet/XcodeCodec.js +4 -2
- package/lib/platform/ios/spm/SpmDiscoverer.js +1 -1
- package/lib/platform/ios/spm/SpmService.js +3 -1
- package/lib/platform/ios/xcode/XcodeIntegration.js +10 -12
- package/lib/platform/ios/xcode/XcodeWriteUtils.js +6 -1
- package/lib/service/automation/FileWatcher.js +1 -3
- package/lib/service/automation/handlers/CreateHandler.js +3 -5
- package/lib/service/automation/handlers/GuardHandler.js +11 -32
- package/lib/service/automation/handlers/SearchHandler.js +9 -9
- package/lib/service/chat/CandidateGuardrail.js +11 -6
- package/lib/service/chat/ChatAgent.js +31 -22
- package/lib/service/chat/HandoffProtocol.js +5 -2
- package/lib/service/chat/tools/composite.js +3 -2
- package/lib/service/chat/tools/index.js +60 -71
- package/lib/service/chat/tools/infrastructure.js +9 -4
- package/lib/service/chat/tools/lifecycle.js +22 -5
- package/lib/service/chat/tools/project-access.js +5 -9
- package/lib/service/chat/tools.js +1 -2
- package/lib/service/cursor/AgentInstructionsGenerator.js +33 -15
- package/lib/service/cursor/CursorDeliveryPipeline.js +2 -1
- package/lib/service/cursor/KnowledgeCompressor.js +16 -7
- package/lib/service/guard/ComplianceReporter.js +5 -2
- package/lib/service/guard/GuardCheckEngine.js +53 -26
- package/lib/service/guard/GuardCodeChecks.js +217 -188
- package/lib/service/guard/GuardCrossFileChecks.js +203 -184
- package/lib/service/guard/GuardPatternUtils.js +17 -10
- package/lib/service/module/ModuleService.js +180 -56
- package/lib/service/recipe/RecipeCandidateValidator.js +11 -8
- package/lib/service/snippet/SnippetFactory.js +3 -3
- package/lib/service/snippet/SnippetInstaller.js +35 -11
- package/lib/service/snippet/codecs/VSCodeCodec.js +2 -2
- package/lib/service/wiki/WikiGenerator.js +67 -40
- package/lib/service/wiki/WikiRenderers.js +105 -80
- package/lib/service/wiki/WikiUtils.js +217 -80
- package/lib/shared/LanguageService.js +111 -53
- package/lib/shared/PathGuard.js +0 -8
- package/package.json +3 -9
- package/scripts/bench-real-projects.mjs +29 -29
- package/scripts/generate-recipe-drafts.js +17 -27
- package/scripts/init-snippets.js +43 -24
- package/scripts/install-vscode-copilot.js +3 -19
- package/scripts/setup-mcp-config.js +0 -4
package/scripts/init-snippets.js
CHANGED
|
@@ -26,6 +26,7 @@ const TRIGGER_SNIPPETS = [
|
|
|
26
26
|
title: 'AutoSnippet: Search (Long)',
|
|
27
27
|
summary: 'Search and insert Recipe/Snippet from knowledge base',
|
|
28
28
|
xcodeContent: '// as:search <#keyword#>',
|
|
29
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: VSCode snippet placeholder syntax
|
|
29
30
|
vscodeBody: ['// as:search ${1:keyword}'],
|
|
30
31
|
},
|
|
31
32
|
{
|
|
@@ -34,6 +35,7 @@ const TRIGGER_SNIPPETS = [
|
|
|
34
35
|
title: 'AutoSnippet: Create Recipe',
|
|
35
36
|
summary: 'Create new Recipe (Dashboard or clipboard/file)',
|
|
36
37
|
xcodeContent: '// as:create <#-c or -f#>',
|
|
38
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: VSCode snippet placeholder syntax
|
|
37
39
|
vscodeBody: ['// as:create ${1:-c or -f}'],
|
|
38
40
|
},
|
|
39
41
|
{
|
|
@@ -42,6 +44,7 @@ const TRIGGER_SNIPPETS = [
|
|
|
42
44
|
title: 'AutoSnippet: Audit Code',
|
|
43
45
|
summary: 'AI code review against knowledge base',
|
|
44
46
|
xcodeContent: '// as:audit <#keyword or scope (file/target/project)#>',
|
|
47
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: VSCode snippet placeholder syntax
|
|
45
48
|
vscodeBody: ['// as:audit ${1:keyword or scope (file/target/project)}'],
|
|
46
49
|
},
|
|
47
50
|
];
|
|
@@ -54,7 +57,9 @@ class XcodeInitializer {
|
|
|
54
57
|
}
|
|
55
58
|
|
|
56
59
|
isAvailable() {
|
|
57
|
-
if (process.platform !== 'darwin')
|
|
60
|
+
if (process.platform !== 'darwin') {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
58
63
|
try {
|
|
59
64
|
execSync('xcode-select -p', { stdio: 'ignore' });
|
|
60
65
|
return true;
|
|
@@ -76,7 +81,7 @@ class XcodeInitializer {
|
|
|
76
81
|
}
|
|
77
82
|
|
|
78
83
|
generatePlist(snippet) {
|
|
79
|
-
const
|
|
84
|
+
const escapeXml = (s) =>
|
|
80
85
|
String(s || '')
|
|
81
86
|
.replace(/&/g, '&')
|
|
82
87
|
.replace(/</g, '<')
|
|
@@ -89,21 +94,21 @@ class XcodeInitializer {
|
|
|
89
94
|
<plist version="1.0">
|
|
90
95
|
<dict>
|
|
91
96
|
<key>IDECodeSnippetCompletionPrefix</key>
|
|
92
|
-
<string>${
|
|
97
|
+
<string>${escapeXml(snippet.shortcut)}</string>
|
|
93
98
|
<key>IDECodeSnippetCompletionScopes</key>
|
|
94
99
|
<array>
|
|
95
100
|
<string>All</string>
|
|
96
101
|
</array>
|
|
97
102
|
<key>IDECodeSnippetContents</key>
|
|
98
|
-
<string>${
|
|
103
|
+
<string>${escapeXml(snippet.xcodeContent)}</string>
|
|
99
104
|
<key>IDECodeSnippetIdentifier</key>
|
|
100
|
-
<string>${
|
|
105
|
+
<string>${escapeXml(snippet.id)}</string>
|
|
101
106
|
<key>IDECodeSnippetLanguage</key>
|
|
102
107
|
<string>Xcode.SourceCodeLanguage.Generic</string>
|
|
103
108
|
<key>IDECodeSnippetSummary</key>
|
|
104
|
-
<string>${
|
|
109
|
+
<string>${escapeXml(snippet.summary)}</string>
|
|
105
110
|
<key>IDECodeSnippetTitle</key>
|
|
106
|
-
<string>${
|
|
111
|
+
<string>${escapeXml(snippet.title)}</string>
|
|
107
112
|
<key>IDECodeSnippetUserSnippet</key>
|
|
108
113
|
<true/>
|
|
109
114
|
<key>IDECodeSnippetVersion</key>
|
|
@@ -113,8 +118,12 @@ class XcodeInitializer {
|
|
|
113
118
|
}
|
|
114
119
|
|
|
115
120
|
init() {
|
|
116
|
-
if (!this.isAvailable())
|
|
117
|
-
|
|
121
|
+
if (!this.isAvailable()) {
|
|
122
|
+
return { skipped: true, reason: 'Xcode not available' };
|
|
123
|
+
}
|
|
124
|
+
if (!this.ensureDir()) {
|
|
125
|
+
return { skipped: true, reason: 'Cannot create snippets dir' };
|
|
126
|
+
}
|
|
118
127
|
|
|
119
128
|
let count = 0;
|
|
120
129
|
for (const snippet of TRIGGER_SNIPPETS) {
|
|
@@ -126,7 +135,9 @@ class XcodeInitializer {
|
|
|
126
135
|
}
|
|
127
136
|
|
|
128
137
|
list() {
|
|
129
|
-
if (!fs.existsSync(this.snippetsDir))
|
|
138
|
+
if (!fs.existsSync(this.snippetsDir)) {
|
|
139
|
+
return [];
|
|
140
|
+
}
|
|
130
141
|
return fs
|
|
131
142
|
.readdirSync(this.snippetsDir)
|
|
132
143
|
.filter((f) => f.startsWith('com.autosnippet') && f.endsWith('.codesnippet'));
|
|
@@ -174,7 +185,9 @@ class VSCodeInitializer {
|
|
|
174
185
|
}
|
|
175
186
|
|
|
176
187
|
init() {
|
|
177
|
-
if (!this.ensureDir())
|
|
188
|
+
if (!this.ensureDir()) {
|
|
189
|
+
return { skipped: true, reason: 'Cannot create .vscode dir' };
|
|
190
|
+
}
|
|
178
191
|
|
|
179
192
|
const bundle = {};
|
|
180
193
|
for (const snippet of TRIGGER_SNIPPETS) {
|
|
@@ -186,13 +199,15 @@ class VSCodeInitializer {
|
|
|
186
199
|
}
|
|
187
200
|
|
|
188
201
|
const filePath = path.join(this.vscodeDir, this.filename);
|
|
189
|
-
fs.writeFileSync(filePath, JSON.stringify(bundle, null, 2)
|
|
202
|
+
fs.writeFileSync(filePath, `${JSON.stringify(bundle, null, 2)}\n`, 'utf-8');
|
|
190
203
|
return { success: true, count: TRIGGER_SNIPPETS.length, path: filePath };
|
|
191
204
|
}
|
|
192
205
|
|
|
193
206
|
list() {
|
|
194
207
|
const filePath = path.join(this.vscodeDir, this.filename);
|
|
195
|
-
if (!fs.existsSync(filePath))
|
|
208
|
+
if (!fs.existsSync(filePath)) {
|
|
209
|
+
return [];
|
|
210
|
+
}
|
|
196
211
|
try {
|
|
197
212
|
const content = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
198
213
|
return Object.keys(content);
|
|
@@ -239,15 +254,23 @@ export class SnippetInitializer {
|
|
|
239
254
|
|
|
240
255
|
list(target = 'all') {
|
|
241
256
|
const result = {};
|
|
242
|
-
if (target === 'all' || target === 'xcode')
|
|
243
|
-
|
|
257
|
+
if (target === 'all' || target === 'xcode') {
|
|
258
|
+
result.xcode = this.xcode.list();
|
|
259
|
+
}
|
|
260
|
+
if (target === 'all' || target === 'vscode') {
|
|
261
|
+
result.vscode = this.vscode.list();
|
|
262
|
+
}
|
|
244
263
|
return result;
|
|
245
264
|
}
|
|
246
265
|
|
|
247
266
|
remove(target = 'all') {
|
|
248
267
|
const result = {};
|
|
249
|
-
if (target === 'all' || target === 'xcode')
|
|
250
|
-
|
|
268
|
+
if (target === 'all' || target === 'xcode') {
|
|
269
|
+
result.xcode = this.xcode.remove();
|
|
270
|
+
}
|
|
271
|
+
if (target === 'all' || target === 'vscode') {
|
|
272
|
+
result.vscode = this.vscode.remove();
|
|
273
|
+
}
|
|
251
274
|
return result;
|
|
252
275
|
}
|
|
253
276
|
}
|
|
@@ -273,22 +296,18 @@ async function main() {
|
|
|
273
296
|
|
|
274
297
|
switch (command) {
|
|
275
298
|
case 'init': {
|
|
276
|
-
const
|
|
277
|
-
console.log('✅ Snippets initialized:', JSON.stringify(result, null, 2));
|
|
299
|
+
const _result = await init.initialize(target);
|
|
278
300
|
break;
|
|
279
301
|
}
|
|
280
302
|
case 'list': {
|
|
281
|
-
const
|
|
282
|
-
console.log('📋 Installed snippets:', JSON.stringify(result, null, 2));
|
|
303
|
+
const _result = init.list(target);
|
|
283
304
|
break;
|
|
284
305
|
}
|
|
285
306
|
case 'remove': {
|
|
286
|
-
const
|
|
287
|
-
console.log('🗑️ Snippets removed:', JSON.stringify(result, null, 2));
|
|
307
|
+
const _result = init.remove(target);
|
|
288
308
|
break;
|
|
289
309
|
}
|
|
290
310
|
case 'help':
|
|
291
|
-
console.log(`Usage: init-snippets.js [init|list|remove] [--target=xcode|vscode|all]`);
|
|
292
311
|
break;
|
|
293
312
|
default:
|
|
294
313
|
console.error(`Unknown command: ${command}`);
|
|
@@ -30,7 +30,6 @@ const __dirname = dirname(__filename);
|
|
|
30
30
|
|
|
31
31
|
import fs from 'node:fs';
|
|
32
32
|
import { createRequire } from 'node:module';
|
|
33
|
-
import os from 'node:os';
|
|
34
33
|
import path from 'node:path';
|
|
35
34
|
|
|
36
35
|
const require = createRequire(import.meta.url);
|
|
@@ -46,7 +45,6 @@ const isAutoSnippetRepo =
|
|
|
46
45
|
|
|
47
46
|
// 默认只做工作区配置,不做全局配置
|
|
48
47
|
// 如果在 AutoSnippet 仓库内执行且未明确指定 --path,跳过所有配置
|
|
49
|
-
const configGlobal = args.global && !isAutoSnippetRepo;
|
|
50
48
|
const configWorkspace = !args.global && !isAutoSnippetRepo && (args.path || !isAutoSnippetRepo);
|
|
51
49
|
const skipVerify = args['skip-verify'];
|
|
52
50
|
const isQuiet = args.quiet || process.env.ASD_QUIET === 'true';
|
|
@@ -71,22 +69,6 @@ function error(msg) {
|
|
|
71
69
|
|
|
72
70
|
// ============ 助手函数 ============
|
|
73
71
|
|
|
74
|
-
function getVSCodeSettingsPath(isGlobal = true) {
|
|
75
|
-
const platform = os.platform();
|
|
76
|
-
|
|
77
|
-
if (isGlobal) {
|
|
78
|
-
if (platform === 'darwin') {
|
|
79
|
-
return path.join(os.homedir(), 'Library/Application Support/Code/User/settings.json');
|
|
80
|
-
} else if (platform === 'win32') {
|
|
81
|
-
return path.join(process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming'), 'Code/User/settings.json');
|
|
82
|
-
} else {
|
|
83
|
-
return path.join(os.homedir(), '.config/Code/User/settings.json');
|
|
84
|
-
}
|
|
85
|
-
} else {
|
|
86
|
-
return path.join(projectPath, '.vscode/settings.json');
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
72
|
function readJsonFile(filePath, defaultValue = {}) {
|
|
91
73
|
if (!fs.existsSync(filePath)) {
|
|
92
74
|
return defaultValue;
|
|
@@ -154,7 +136,9 @@ function configureVSCodeSettings() {
|
|
|
154
136
|
if (fs.existsSync(mcpConfigPath)) {
|
|
155
137
|
try {
|
|
156
138
|
config = JSON.parse(fs.readFileSync(mcpConfigPath, 'utf8'));
|
|
157
|
-
} catch {
|
|
139
|
+
} catch {
|
|
140
|
+
/* ignore */
|
|
141
|
+
}
|
|
158
142
|
}
|
|
159
143
|
|
|
160
144
|
if (!config.servers) {
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
|
|
11
11
|
import fs from 'node:fs';
|
|
12
12
|
import { createRequire } from 'node:module';
|
|
13
|
-
import os from 'node:os';
|
|
14
13
|
import path from 'node:path';
|
|
15
14
|
|
|
16
15
|
const require = createRequire(import.meta.url);
|
|
@@ -50,8 +49,6 @@ if (!fs.existsSync(mcpServerPath)) {
|
|
|
50
49
|
|
|
51
50
|
// ============ 编辑器配置 ============
|
|
52
51
|
|
|
53
|
-
let settingsPath; // 全局声明,供后面使用
|
|
54
|
-
|
|
55
52
|
if (isVSCode) {
|
|
56
53
|
configureVSCode();
|
|
57
54
|
} else if (isCursor) {
|
|
@@ -105,7 +102,6 @@ function configureVSCode() {
|
|
|
105
102
|
}
|
|
106
103
|
process.exit(1);
|
|
107
104
|
}
|
|
108
|
-
|
|
109
105
|
}
|
|
110
106
|
|
|
111
107
|
function configureCursor() {
|