autosnippet 3.0.10 → 3.0.13
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/cli.js +64 -1
- package/config/default.json +9 -0
- package/dashboard/dist/assets/{index-I2ySoCmF.js → index-Bnm26ulL.js} +47 -47
- package/dashboard/dist/index.html +1 -1
- package/lib/cli/SetupService.js +92 -5
- package/lib/cli/UpgradeService.js +14 -5
- package/lib/core/discovery/GenericDiscoverer.js +4 -28
- package/lib/external/mcp/handlers/bootstrap/base-dimensions.js +246 -0
- package/lib/external/mcp/handlers/bootstrap/pipeline/checkpoint.js +80 -0
- package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-configs.js +275 -0
- package/lib/external/mcp/handlers/bootstrap/pipeline/noAiFallback.js +600 -0
- package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +125 -342
- package/lib/external/mcp/handlers/bootstrap/refine.js +362 -0
- package/lib/external/mcp/handlers/bootstrap.js +6 -590
- package/lib/external/mcp/handlers/browse.js +119 -9
- package/lib/external/mcp/handlers/guard.js +25 -6
- package/lib/external/mcp/handlers/search.js +56 -24
- package/lib/http/routes/guardRules.js +9 -17
- package/lib/injection/ServiceContainer.js +12 -3
- package/lib/platform/ios/xcode/XcodeImportResolver.js +434 -0
- package/lib/platform/ios/xcode/XcodeIntegration.js +40 -659
- package/lib/platform/ios/xcode/XcodeWriteUtils.js +220 -0
- package/lib/service/chat/ChatAgent.js +39 -418
- package/lib/service/chat/ChatAgentPrompts.js +149 -0
- package/lib/service/chat/ChatAgentTasks.js +297 -0
- package/lib/service/chat/tools/_shared.js +61 -0
- package/lib/service/chat/tools/ai-analysis.js +284 -0
- package/lib/service/chat/tools/ast-graph.js +681 -0
- package/lib/service/chat/tools/composite.js +496 -0
- package/lib/service/chat/tools/guard.js +265 -0
- package/lib/service/chat/tools/index.js +250 -0
- package/lib/service/chat/tools/infrastructure.js +222 -0
- package/lib/service/chat/tools/knowledge-graph.js +234 -0
- package/lib/service/chat/tools/lifecycle.js +469 -0
- package/lib/service/chat/tools/project-access.js +923 -0
- package/lib/service/chat/tools/query.js +264 -0
- package/lib/service/chat/tools.js +14 -3994
- package/lib/service/cursor/AgentInstructionsGenerator.js +395 -0
- package/lib/service/cursor/CursorDeliveryPipeline.js +70 -11
- package/lib/service/cursor/FileProtection.js +116 -0
- package/lib/service/cursor/KnowledgeCompressor.js +61 -11
- package/lib/service/cursor/SkillsSyncer.js +5 -3
- package/lib/service/cursor/TopicClassifier.js +19 -3
- package/lib/service/guard/ExclusionManager.js +26 -2
- package/lib/service/guard/GuardCheckEngine.js +38 -370
- package/lib/service/guard/GuardCodeChecks.js +362 -0
- package/lib/service/guard/GuardCrossFileChecks.js +307 -0
- package/lib/service/guard/GuardPatternUtils.js +180 -0
- package/lib/service/guard/GuardService.js +80 -38
- package/lib/service/module/ModuleService.js +1 -0
- package/lib/service/search/SearchEngine.js +10 -2
- package/lib/service/wiki/WikiGenerator.js +226 -1532
- package/lib/service/wiki/WikiRenderers.js +1878 -0
- package/lib/service/wiki/WikiUtils.js +907 -0
- package/lib/shared/LanguageService.js +299 -0
- package/package.json +1 -1
|
@@ -11,8 +11,12 @@
|
|
|
11
11
|
* const lang = LanguageService.inferLang('App.swift'); // 'swift'
|
|
12
12
|
* const display = LanguageService.displayName('swift'); // 'Swift'
|
|
13
13
|
* const primary = LanguageService.detectPrimary(langStats); // 'typescript'
|
|
14
|
+
* const langs = LanguageService.detectProjectLanguages('/path/to/project');
|
|
14
15
|
*/
|
|
15
16
|
|
|
17
|
+
import { existsSync, readdirSync } from 'node:fs';
|
|
18
|
+
import { join } from 'node:path';
|
|
19
|
+
|
|
16
20
|
// ═══════════════════════════════════════════════════════════
|
|
17
21
|
// 1) 文件扩展名 → 规范化语言 ID
|
|
18
22
|
// ═══════════════════════════════════════════════════════════
|
|
@@ -193,6 +197,105 @@ const SOURCE_CODE_EXTS = Object.freeze(
|
|
|
193
197
|
])
|
|
194
198
|
);
|
|
195
199
|
|
|
200
|
+
// ═══════════════════════════════════════════════════════════
|
|
201
|
+
// 5.5) 语言别名映射 — 将常见缩写/变体归一化为规范 ID
|
|
202
|
+
// ═══════════════════════════════════════════════════════════
|
|
203
|
+
|
|
204
|
+
/** @type {Readonly<Record<string, string>>} */
|
|
205
|
+
const LANG_ALIASES = Object.freeze({
|
|
206
|
+
// Objective-C variants
|
|
207
|
+
objc: 'objectivec',
|
|
208
|
+
'objective-c': 'objectivec',
|
|
209
|
+
'obj-c': 'objectivec',
|
|
210
|
+
// TypeScript
|
|
211
|
+
ts: 'typescript',
|
|
212
|
+
tsx: 'typescript',
|
|
213
|
+
// JavaScript
|
|
214
|
+
js: 'javascript',
|
|
215
|
+
jsx: 'javascript',
|
|
216
|
+
// C++
|
|
217
|
+
'c++': 'cpp',
|
|
218
|
+
cxx: 'cpp',
|
|
219
|
+
// C#
|
|
220
|
+
'c#': 'csharp',
|
|
221
|
+
cs: 'csharp',
|
|
222
|
+
// Python
|
|
223
|
+
py: 'python',
|
|
224
|
+
python3: 'python',
|
|
225
|
+
// Kotlin
|
|
226
|
+
kt: 'kotlin',
|
|
227
|
+
// Rust
|
|
228
|
+
rs: 'rust',
|
|
229
|
+
// Go
|
|
230
|
+
golang: 'go',
|
|
231
|
+
// Ruby
|
|
232
|
+
rb: 'ruby',
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// ═══════════════════════════════════════════════════════════
|
|
236
|
+
// 6) 生态系统/Discoverer ID → 对应编程语言 ID 数组
|
|
237
|
+
// ═══════════════════════════════════════════════════════════
|
|
238
|
+
|
|
239
|
+
/** @type {Readonly<Record<string, readonly string[]>>} */
|
|
240
|
+
const ECO_TO_LANGS = Object.freeze({
|
|
241
|
+
spm: Object.freeze(['swift', 'objectivec']),
|
|
242
|
+
node: Object.freeze(['javascript', 'typescript']),
|
|
243
|
+
go: Object.freeze(['go']),
|
|
244
|
+
jvm: Object.freeze(['java', 'kotlin']),
|
|
245
|
+
python: Object.freeze(['python']),
|
|
246
|
+
dart: Object.freeze(['dart']),
|
|
247
|
+
rust: Object.freeze(['rust']),
|
|
248
|
+
dotnet: Object.freeze(['csharp']),
|
|
249
|
+
ruby: Object.freeze(['ruby']),
|
|
250
|
+
generic: Object.freeze([]),
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
// ═══════════════════════════════════════════════════════════
|
|
254
|
+
// 7) 构建系统标志文件 → 生态系统映射(项目级语言检测的核心数据)
|
|
255
|
+
// ═══════════════════════════════════════════════════════════
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* @typedef {{ file: string, eco: string, buildTool: string }} BuildSystemMarker
|
|
259
|
+
* @type {ReadonlyArray<BuildSystemMarker>}
|
|
260
|
+
*/
|
|
261
|
+
const BUILD_SYSTEM_MARKERS = Object.freeze([
|
|
262
|
+
// Apple / iOS
|
|
263
|
+
{ file: 'Package.swift', eco: 'spm', buildTool: 'SPM' },
|
|
264
|
+
{ file: 'Podfile', eco: 'spm', buildTool: 'CocoaPods' },
|
|
265
|
+
// JS / TS (lock files before package.json to detect specific tool)
|
|
266
|
+
{ file: 'yarn.lock', eco: 'node', buildTool: 'Yarn' },
|
|
267
|
+
{ file: 'pnpm-lock.yaml', eco: 'node', buildTool: 'pnpm' },
|
|
268
|
+
{ file: 'package.json', eco: 'node', buildTool: 'npm' },
|
|
269
|
+
// Python
|
|
270
|
+
{ file: 'Pipfile', eco: 'python', buildTool: 'Pipenv' },
|
|
271
|
+
{ file: 'pyproject.toml', eco: 'python', buildTool: 'Poetry' },
|
|
272
|
+
{ file: 'setup.py', eco: 'python', buildTool: 'setuptools' },
|
|
273
|
+
{ file: 'requirements.txt', eco: 'python', buildTool: 'pip' },
|
|
274
|
+
// Go
|
|
275
|
+
{ file: 'go.mod', eco: 'go', buildTool: 'Go Modules' },
|
|
276
|
+
// Rust
|
|
277
|
+
{ file: 'Cargo.toml', eco: 'rust', buildTool: 'Cargo' },
|
|
278
|
+
// JVM
|
|
279
|
+
{ file: 'pom.xml', eco: 'jvm', buildTool: 'Maven' },
|
|
280
|
+
{ file: 'build.gradle', eco: 'jvm', buildTool: 'Gradle' },
|
|
281
|
+
{ file: 'build.gradle.kts', eco: 'jvm', buildTool: 'Gradle (Kotlin)' },
|
|
282
|
+
// Dart / Flutter
|
|
283
|
+
{ file: 'pubspec.yaml', eco: 'dart', buildTool: 'Flutter' },
|
|
284
|
+
{ file: 'melos.yaml', eco: 'dart', buildTool: 'Melos' },
|
|
285
|
+
// C# / .NET
|
|
286
|
+
{ file: '*.csproj', eco: 'dotnet', buildTool: '.NET' },
|
|
287
|
+
{ file: '*.sln', eco: 'dotnet', buildTool: '.NET' },
|
|
288
|
+
// Ruby
|
|
289
|
+
{ file: 'Gemfile', eco: 'ruby', buildTool: 'Bundler' },
|
|
290
|
+
]);
|
|
291
|
+
|
|
292
|
+
/** 扫描目录时跳过的标准目录(性能优化) */
|
|
293
|
+
const SCAN_SKIP_DIRS = Object.freeze(new Set([
|
|
294
|
+
'.git', 'node_modules', '.build', 'build', 'dist', 'target', 'out',
|
|
295
|
+
'vendor', '.cache', 'Pods', 'DerivedData', '__pycache__', '.venv', 'venv',
|
|
296
|
+
'.gradle', 'Carthage', '.fvm', '.dart_tool', '.cargo',
|
|
297
|
+
]));
|
|
298
|
+
|
|
196
299
|
// ═══════════════════════════════════════════════════════════
|
|
197
300
|
// LanguageService — 静态单例
|
|
198
301
|
// ═══════════════════════════════════════════════════════════
|
|
@@ -206,6 +309,7 @@ export class LanguageService {
|
|
|
206
309
|
* @returns {string} 语言 ID,如 'swift', 'typescript', 'python', 'unknown'
|
|
207
310
|
*/
|
|
208
311
|
static inferLang(filename) {
|
|
312
|
+
if (!filename || typeof filename !== 'string') return 'unknown';
|
|
209
313
|
const dot = filename.lastIndexOf('.');
|
|
210
314
|
if (dot === -1) {
|
|
211
315
|
return 'unknown';
|
|
@@ -220,9 +324,45 @@ export class LanguageService {
|
|
|
220
324
|
* @returns {string}
|
|
221
325
|
*/
|
|
222
326
|
static langFromExt(ext) {
|
|
327
|
+
if (!ext || typeof ext !== 'string') return 'unknown';
|
|
223
328
|
return EXT_TO_LANG[ext.toLowerCase()] || 'unknown';
|
|
224
329
|
}
|
|
225
330
|
|
|
331
|
+
// ─── 别名归一化 ───────────────────────────────
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* 将语言 ID 别名/缩写归一化为规范 ID
|
|
335
|
+
*
|
|
336
|
+
* 示例:
|
|
337
|
+
* normalize('objc') → 'objectivec'
|
|
338
|
+
* normalize('ts') → 'typescript'
|
|
339
|
+
* normalize('golang') → 'go'
|
|
340
|
+
* normalize('swift') → 'swift' (已是规范 ID)
|
|
341
|
+
* normalize('unknown') → 'unknown'
|
|
342
|
+
*
|
|
343
|
+
* @param {string} langId - 语言 ID(可能是别名)
|
|
344
|
+
* @returns {string} 规范化语言 ID
|
|
345
|
+
*/
|
|
346
|
+
static normalize(langId) {
|
|
347
|
+
if (!langId || typeof langId !== 'string') return 'unknown';
|
|
348
|
+
const lower = langId.toLowerCase().trim();
|
|
349
|
+
if (KNOWN_PROGRAMMING_LANGS.has(lower)) return lower;
|
|
350
|
+
return LANG_ALIASES[lower] || lower;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* 将规范语言 ID 转为 Guard 兼容 ID
|
|
355
|
+
*
|
|
356
|
+
* Guard 内置规则使用 'objc' 而非 'objectivec'。
|
|
357
|
+
* 其他语言 ID 不变。
|
|
358
|
+
*
|
|
359
|
+
* @param {string} langId
|
|
360
|
+
* @returns {string}
|
|
361
|
+
*/
|
|
362
|
+
static toGuardLangId(langId) {
|
|
363
|
+
return langId === 'objectivec' ? 'objc' : langId;
|
|
364
|
+
}
|
|
365
|
+
|
|
226
366
|
// ─── 显示名 ────────────────────────────────────
|
|
227
367
|
|
|
228
368
|
/**
|
|
@@ -394,6 +534,165 @@ export class LanguageService {
|
|
|
394
534
|
}
|
|
395
535
|
return null;
|
|
396
536
|
}
|
|
537
|
+
|
|
538
|
+
// ─── 生态系统 / 项目级语言检测 ────────────────
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* 获取语言别名映射表(不可变)
|
|
542
|
+
* @returns {Readonly<Record<string, string>>}
|
|
543
|
+
*/
|
|
544
|
+
static get langAliases() {
|
|
545
|
+
return LANG_ALIASES;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* 获取 ECO_TO_LANGS 映射(不可变)
|
|
550
|
+
* @returns {Readonly<Record<string, readonly string[]>>}
|
|
551
|
+
*/
|
|
552
|
+
static get ecoToLangs() {
|
|
553
|
+
return ECO_TO_LANGS;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/**
|
|
557
|
+
* 获取 BUILD_SYSTEM_MARKERS(不可变)
|
|
558
|
+
* @returns {ReadonlyArray<BuildSystemMarker>}
|
|
559
|
+
*/
|
|
560
|
+
static get buildSystemMarkers() {
|
|
561
|
+
return BUILD_SYSTEM_MARKERS;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* 获取 SCAN_SKIP_DIRS(不可变)
|
|
566
|
+
* @returns {ReadonlySet<string>}
|
|
567
|
+
*/
|
|
568
|
+
static get scanSkipDirs() {
|
|
569
|
+
return SCAN_SKIP_DIRS;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* 根据生态系统/Discoverer ID 获取对应的语言 ID 数组
|
|
574
|
+
* @param {string} ecoId - 如 'spm', 'node', 'rust', 'dart'
|
|
575
|
+
* @returns {readonly string[]}
|
|
576
|
+
*/
|
|
577
|
+
static langsForEco(ecoId) {
|
|
578
|
+
return ECO_TO_LANGS[ecoId] || [];
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* 检测构建系统标志文件 — 纯数据匹配,不访问文件系统
|
|
583
|
+
*
|
|
584
|
+
* @param {string[]} entryNames - 目录内文件/目录名列表
|
|
585
|
+
* @returns {Array<{ eco: string, buildTool: string }>}
|
|
586
|
+
*/
|
|
587
|
+
static matchBuildMarkers(entryNames) {
|
|
588
|
+
if (!Array.isArray(entryNames) || entryNames.length === 0) return [];
|
|
589
|
+
const nameSet = new Set(entryNames);
|
|
590
|
+
const results = [];
|
|
591
|
+
const seenEco = new Set();
|
|
592
|
+
|
|
593
|
+
for (const marker of BUILD_SYSTEM_MARKERS) {
|
|
594
|
+
if (seenEco.has(marker.eco)) continue;
|
|
595
|
+
const isGlob = marker.file.startsWith('*');
|
|
596
|
+
const matched = isGlob
|
|
597
|
+
? entryNames.some((n) => n.endsWith(marker.file.slice(1)))
|
|
598
|
+
: nameSet.has(marker.file);
|
|
599
|
+
if (matched) {
|
|
600
|
+
results.push({ eco: marker.eco, buildTool: marker.buildTool });
|
|
601
|
+
seenEco.add(marker.eco);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
return results;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* 检测项目使用的编程语言 — 统一入口
|
|
609
|
+
*
|
|
610
|
+
* 策略(按优先级):
|
|
611
|
+
* 1. 若传入 discovererIds(来自 ModuleService),直接映射为语言
|
|
612
|
+
* 2. 否则扫描项目目录的构建系统标记文件(支持 monorepo 多层扫描)
|
|
613
|
+
*
|
|
614
|
+
* @param {string} projectRoot - 项目根目录绝对路径
|
|
615
|
+
* @param {object} [opts]
|
|
616
|
+
* @param {string[]} [opts.discovererIds] - ModuleService 检测到的生态 ID
|
|
617
|
+
* @param {number} [opts.maxDepth=2] - 最大扫描深度:0=仅根目录,1=+子目录,2=+孙目录
|
|
618
|
+
* @returns {string[]} 规范化语言 ID 数组(如 ['rust', 'dart'])
|
|
619
|
+
*/
|
|
620
|
+
static detectProjectLanguages(projectRoot, opts = {}) {
|
|
621
|
+
if (!projectRoot || typeof projectRoot !== 'string') return [];
|
|
622
|
+
const { discovererIds, maxDepth = 2 } = opts;
|
|
623
|
+
|
|
624
|
+
// ── Path 1: 从 Discoverer ID 映射 ──
|
|
625
|
+
if (discovererIds && discovererIds.length > 0) {
|
|
626
|
+
const nonGeneric = discovererIds.filter((id) => id !== 'generic');
|
|
627
|
+
if (nonGeneric.length > 0) {
|
|
628
|
+
const langSet = new Set();
|
|
629
|
+
for (const did of nonGeneric) {
|
|
630
|
+
for (const lang of ECO_TO_LANGS[did] || []) langSet.add(lang);
|
|
631
|
+
}
|
|
632
|
+
if (langSet.size > 0) return [...langSet];
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
// ── Path 2: 扫描构建系统标记文件 ──
|
|
637
|
+
const seenEco = new Set();
|
|
638
|
+
|
|
639
|
+
const scanDir = (dir) => {
|
|
640
|
+
try {
|
|
641
|
+
for (const marker of BUILD_SYSTEM_MARKERS) {
|
|
642
|
+
if (seenEco.has(marker.eco)) continue;
|
|
643
|
+
const isGlob = marker.file.startsWith('*');
|
|
644
|
+
let matched = false;
|
|
645
|
+
if (isGlob) {
|
|
646
|
+
try {
|
|
647
|
+
const suffix = marker.file.slice(1);
|
|
648
|
+
matched = readdirSync(dir).some((n) => n.endsWith(suffix));
|
|
649
|
+
} catch { /* skip */ }
|
|
650
|
+
} else {
|
|
651
|
+
matched = existsSync(join(dir, marker.file));
|
|
652
|
+
}
|
|
653
|
+
if (matched) seenEco.add(marker.eco);
|
|
654
|
+
}
|
|
655
|
+
} catch { /* skip unreadable dir */ }
|
|
656
|
+
};
|
|
657
|
+
|
|
658
|
+
// Level 0: 项目根目录
|
|
659
|
+
scanDir(projectRoot);
|
|
660
|
+
|
|
661
|
+
// Level 1..maxDepth: 子目录(支持 monorepo)
|
|
662
|
+
if (seenEco.size === 0 && maxDepth >= 1) {
|
|
663
|
+
/** @type {Array<[string, number]>} */
|
|
664
|
+
const queue = [[projectRoot, 0]];
|
|
665
|
+
while (queue.length > 0) {
|
|
666
|
+
const [dir, depth] = queue.shift();
|
|
667
|
+
if (depth >= maxDepth) continue;
|
|
668
|
+
try {
|
|
669
|
+
for (const ent of readdirSync(dir, { withFileTypes: true })) {
|
|
670
|
+
if (!ent.isDirectory() || ent.name.startsWith('.') || SCAN_SKIP_DIRS.has(ent.name)) continue;
|
|
671
|
+
const sub = join(dir, ent.name);
|
|
672
|
+
scanDir(sub);
|
|
673
|
+
if (depth + 1 < maxDepth) queue.push([sub, depth + 1]);
|
|
674
|
+
}
|
|
675
|
+
} catch { /* skip */ }
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
// ── 将生态 ID 转为语言 ID ──
|
|
680
|
+
const langSet = new Set();
|
|
681
|
+
for (const eco of seenEco) {
|
|
682
|
+
for (const lang of ECO_TO_LANGS[eco] || []) langSet.add(lang);
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
// ── 启发式: node 与其他生态共存时,JS/TS 通常只是构建工具,去掉 ──
|
|
686
|
+
if (seenEco.size > 1 && seenEco.has('node')) {
|
|
687
|
+
const hasOther = [...seenEco].some((e) => e !== 'node');
|
|
688
|
+
if (hasOther) {
|
|
689
|
+
langSet.delete('javascript');
|
|
690
|
+
langSet.delete('typescript');
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
return [...langSet];
|
|
695
|
+
}
|
|
397
696
|
}
|
|
398
697
|
|
|
399
698
|
export default LanguageService;
|