autosnippet 3.0.11 → 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
|
@@ -59,9 +59,12 @@ import {
|
|
|
59
59
|
} from './bootstrap/skills.js';
|
|
60
60
|
import { buildLanguageExtension, detectPrimaryLanguage, inferLang } from './LanguageExtensions.js';
|
|
61
61
|
import { inferFilePriority, inferTargetRole } from './TargetClassifier.js';
|
|
62
|
+
import { baseDimensions, resolveActiveDimensions } from './bootstrap/base-dimensions.js';
|
|
63
|
+
import { bootstrapRefine } from './bootstrap/refine.js';
|
|
62
64
|
|
|
63
65
|
// Re-export for external consumers
|
|
64
66
|
export { loadBootstrapSkills };
|
|
67
|
+
export { bootstrapRefine };
|
|
65
68
|
|
|
66
69
|
/**
|
|
67
70
|
* bootstrapKnowledge — 一键初始化知识库 (Skill-aware)
|
|
@@ -501,220 +504,13 @@ export async function bootstrapKnowledge(ctx, args) {
|
|
|
501
504
|
};
|
|
502
505
|
|
|
503
506
|
// 9 维度定义(Phase 4 响应 + Phase 5 候选创建共用)
|
|
504
|
-
//
|
|
505
|
-
// 注意:anti-pattern 已移除 — 代码问题由 Guard 独立处理,bootstrap 不做错误检测
|
|
506
|
-
//
|
|
507
|
-
// 执行顺序优化(v5.1):
|
|
508
|
-
// ⑧ ⑨ 提前到 ⑥ 前面执行 → deep-scan / category-scan 的中间结果
|
|
509
|
-
// 通过 PipelineContext 缓存,供 project-profile 复用,避免重复扫描
|
|
510
|
-
const baseDimensions = [
|
|
511
|
-
// ── 通用维度(所有语言共享)──────────────────────────────────
|
|
512
|
-
|
|
513
|
-
// ① 代码规范(Dual: Skill + Candidate)
|
|
514
|
-
{
|
|
515
|
-
id: 'code-standard',
|
|
516
|
-
label: '代码规范',
|
|
517
|
-
guide:
|
|
518
|
-
'命名约定(类名前缀/方法签名风格/API 命名)、注释风格(语言/格式/MARK 分段)、文件组织规范',
|
|
519
|
-
knowledgeTypes: ['code-standard', 'code-style'],
|
|
520
|
-
skillWorthy: true,
|
|
521
|
-
dualOutput: true,
|
|
522
|
-
skillMeta: {
|
|
523
|
-
name: 'project-code-standard',
|
|
524
|
-
description:
|
|
525
|
-
'Project coding standards and naming conventions (auto-generated by bootstrap)',
|
|
526
|
-
},
|
|
527
|
-
},
|
|
528
|
-
// ② 代码模式(Candidate)
|
|
529
|
-
{
|
|
530
|
-
id: 'code-pattern',
|
|
531
|
-
label: '设计模式与代码惯例',
|
|
532
|
-
guide: '单例/委托/Category·Extension/工厂/Builder/观察者/Coordinator 模式、继承关系',
|
|
533
|
-
knowledgeTypes: ['code-pattern', 'code-relation', 'inheritance'],
|
|
534
|
-
},
|
|
535
|
-
// ③ 架构模式(Dual: Skill + Candidate)
|
|
536
|
-
{
|
|
537
|
-
id: 'architecture',
|
|
538
|
-
label: '架构模式',
|
|
539
|
-
guide: '分层架构、模块职责与边界、依赖图、导入约束规则',
|
|
540
|
-
knowledgeTypes: ['architecture', 'module-dependency', 'boundary-constraint'],
|
|
541
|
-
skillWorthy: true,
|
|
542
|
-
dualOutput: true,
|
|
543
|
-
skillMeta: {
|
|
544
|
-
name: 'project-architecture',
|
|
545
|
-
description:
|
|
546
|
-
'Project architecture layers, module boundaries and dependency graph (auto-generated by bootstrap)',
|
|
547
|
-
},
|
|
548
|
-
},
|
|
549
|
-
// ④ 最佳实践(Candidate)
|
|
550
|
-
{
|
|
551
|
-
id: 'best-practice',
|
|
552
|
-
label: '最佳实践',
|
|
553
|
-
guide: '错误处理、并发安全、内存管理、日志规范、测试模式',
|
|
554
|
-
knowledgeTypes: ['best-practice'],
|
|
555
|
-
},
|
|
556
|
-
// ⑤ 事件与数据流(Candidate)
|
|
557
|
-
{
|
|
558
|
-
id: 'event-and-data-flow',
|
|
559
|
-
label: '事件与数据流',
|
|
560
|
-
guide:
|
|
561
|
-
'事件传播(Delegate/Notification/Block·Closure/Target-Action)、数据状态管理(KVO/属性观察/响应式/持久化)',
|
|
562
|
-
knowledgeTypes: ['call-chain', 'data-flow'],
|
|
563
|
-
},
|
|
564
|
-
// ⑥ 项目特征(Dual: Skill + Candidate)
|
|
565
|
-
{
|
|
566
|
-
id: 'project-profile',
|
|
567
|
-
label: '项目特征',
|
|
568
|
-
guide:
|
|
569
|
-
'技术栈、目录结构、三方依赖枚举与用途、Extension/Category 分类聚合、自定义基类层级与全局定义(宏/typealias/PCH)、系统事件 hook 与生命周期入口、基础设施服务注册表、Runtime 与语言互操作',
|
|
570
|
-
knowledgeTypes: ['architecture'],
|
|
571
|
-
skillWorthy: true,
|
|
572
|
-
dualOutput: true,
|
|
573
|
-
skillMeta: {
|
|
574
|
-
name: 'project-profile',
|
|
575
|
-
description:
|
|
576
|
-
'Project tech stack, module structure, third-party dependencies, base extensions/classes, event hooks, infrastructure services, and runtime/interop features (auto-generated by bootstrap)',
|
|
577
|
-
},
|
|
578
|
-
},
|
|
579
|
-
// ⑦ Agent 开发注意事项(Skill)
|
|
580
|
-
{
|
|
581
|
-
id: 'agent-guidelines',
|
|
582
|
-
label: 'Agent开发注意事项',
|
|
583
|
-
guide:
|
|
584
|
-
'三大核心原则(严谨性/深度特征挖掘/完整性)、命名强制、线程安全、内存约束、已废弃 API 标记、架构约束注释、TODO/FIXME',
|
|
585
|
-
knowledgeTypes: ['boundary-constraint', 'code-standard'],
|
|
586
|
-
skillWorthy: true,
|
|
587
|
-
skillMeta: {
|
|
588
|
-
name: 'project-agent-guidelines',
|
|
589
|
-
description:
|
|
590
|
-
'Mandatory coding rules, deprecated APIs and agent constraints for this project (auto-generated by bootstrap)',
|
|
591
|
-
},
|
|
592
|
-
},
|
|
593
|
-
|
|
594
|
-
// ── 语言条件维度(按 conditions 过滤)──────────────────────
|
|
595
|
-
|
|
596
|
-
// ⑧ ObjC/Swift 深度扫描
|
|
597
|
-
{
|
|
598
|
-
id: 'objc-deep-scan',
|
|
599
|
-
label: '深度扫描(常量/Hook)',
|
|
600
|
-
guide:
|
|
601
|
-
'全量扫描 #define 值宏/函数宏、extern/static 常量、Method Swizzling hook 对(Agent 必须使用项目常量,修改被 hook 方法前必须查阅 hook 清单)',
|
|
602
|
-
knowledgeTypes: ['code-standard', 'code-pattern'],
|
|
603
|
-
conditions: { languages: ['objectivec', 'swift'] },
|
|
604
|
-
skillWorthy: true,
|
|
605
|
-
dualOutput: true,
|
|
606
|
-
skillMeta: {
|
|
607
|
-
name: 'project-objc-deep-scan',
|
|
608
|
-
description:
|
|
609
|
-
'Project #define macros, static constants, and Method Swizzling hooks (auto-generated by bootstrap)',
|
|
610
|
-
},
|
|
611
|
-
},
|
|
612
|
-
// ⑨ Foundation/UIKit Category/Extension 专项扫描
|
|
613
|
-
{
|
|
614
|
-
id: 'category-scan',
|
|
615
|
-
label: '基础类分类方法扫描',
|
|
616
|
-
guide:
|
|
617
|
-
'Foundation/UIKit Category/Extension 逐方法清单(含完整实现代码与项目使用频次),仅扫描基础类分类、不含业务代码(Agent 遇到同等功能必须使用项目已有分类方法,禁止重复实现)',
|
|
618
|
-
knowledgeTypes: ['code-standard', 'code-pattern'],
|
|
619
|
-
conditions: { languages: ['objectivec', 'swift'] },
|
|
620
|
-
skillWorthy: true,
|
|
621
|
-
dualOutput: true,
|
|
622
|
-
skillMeta: {
|
|
623
|
-
name: 'project-category-scan',
|
|
624
|
-
description:
|
|
625
|
-
'Foundation/UIKit Category and Extension methods with implementations and usage patterns — base classes only, no business code (auto-generated by bootstrap)',
|
|
626
|
-
},
|
|
627
|
-
},
|
|
628
|
-
|
|
629
|
-
// ⑩ TS/JS 模块导出分析
|
|
630
|
-
{
|
|
631
|
-
id: 'module-export-scan',
|
|
632
|
-
label: '模块导出分析',
|
|
633
|
-
guide: 'barrel export 结构、re-export 链路、public API surface、tree-shaking 合规性',
|
|
634
|
-
knowledgeTypes: ['code-standard', 'architecture'],
|
|
635
|
-
conditions: { languages: ['typescript', 'javascript'] },
|
|
636
|
-
skillWorthy: true,
|
|
637
|
-
dualOutput: true,
|
|
638
|
-
skillMeta: {
|
|
639
|
-
name: 'project-module-exports',
|
|
640
|
-
description: 'Module export structure and public API surface (auto-generated by bootstrap)',
|
|
641
|
-
},
|
|
642
|
-
},
|
|
643
|
-
// ⑪ TS/JS 框架约定扫描
|
|
644
|
-
{
|
|
645
|
-
id: 'framework-convention-scan',
|
|
646
|
-
label: '框架约定扫描',
|
|
647
|
-
guide: '组件目录结构、状态管理约定、路由约定、样式约定、数据获取模式',
|
|
648
|
-
knowledgeTypes: ['code-standard', 'architecture'],
|
|
649
|
-
conditions: {
|
|
650
|
-
languages: ['typescript', 'javascript'],
|
|
651
|
-
frameworks: ['react', 'vue', 'angular', 'nextjs', 'nuxt'],
|
|
652
|
-
},
|
|
653
|
-
skillWorthy: true,
|
|
654
|
-
dualOutput: true,
|
|
655
|
-
skillMeta: {
|
|
656
|
-
name: 'project-framework-conventions',
|
|
657
|
-
description: 'Framework-specific conventions and patterns (auto-generated by bootstrap)',
|
|
658
|
-
},
|
|
659
|
-
},
|
|
660
|
-
|
|
661
|
-
// ⑫ Python 包结构分析
|
|
662
|
-
{
|
|
663
|
-
id: 'python-package-scan',
|
|
664
|
-
label: 'Python 包结构分析',
|
|
665
|
-
guide:
|
|
666
|
-
'__init__.py 导出策略、相对/绝对导入风格、type hints 覆盖率、decorator 使用模式、__all__ 定义',
|
|
667
|
-
knowledgeTypes: ['code-standard', 'architecture'],
|
|
668
|
-
conditions: { languages: ['python'] },
|
|
669
|
-
skillWorthy: true,
|
|
670
|
-
dualOutput: true,
|
|
671
|
-
skillMeta: {
|
|
672
|
-
name: 'project-python-structure',
|
|
673
|
-
description:
|
|
674
|
-
'Python package structure, import patterns and type hint coverage (auto-generated by bootstrap)',
|
|
675
|
-
},
|
|
676
|
-
},
|
|
677
|
-
|
|
678
|
-
// ⑬ Java/Kotlin 注解扫描
|
|
679
|
-
{
|
|
680
|
-
id: 'jvm-annotation-scan',
|
|
681
|
-
label: '注解/Annotation 扫描',
|
|
682
|
-
guide:
|
|
683
|
-
'DI 注解(@Inject/@Autowired/@Component)、ORM 注解(@Entity/@Table)、API 注解(@RestController/@RequestMapping)、自定义注解、元编程模式',
|
|
684
|
-
knowledgeTypes: ['code-pattern', 'architecture'],
|
|
685
|
-
conditions: { languages: ['java', 'kotlin'] },
|
|
686
|
-
skillWorthy: true,
|
|
687
|
-
dualOutput: true,
|
|
688
|
-
skillMeta: {
|
|
689
|
-
name: 'project-jvm-annotations',
|
|
690
|
-
description:
|
|
691
|
-
'Annotation/DI usage patterns and meta-programming (auto-generated by bootstrap)',
|
|
692
|
-
},
|
|
693
|
-
},
|
|
694
|
-
|
|
695
|
-
// ⑭ Go 模块结构分析
|
|
696
|
-
{
|
|
697
|
-
id: 'go-module-scan',
|
|
698
|
-
label: 'Go 模块结构分析',
|
|
699
|
-
guide:
|
|
700
|
-
'go.mod 依赖图、internal 包隔离边界、cmd/ 入口点枚举、build tags/constraints、interface 分布与实现关系、init() 函数清单',
|
|
701
|
-
knowledgeTypes: ['architecture', 'code-pattern'],
|
|
702
|
-
conditions: { languages: ['go'] },
|
|
703
|
-
skillWorthy: true,
|
|
704
|
-
dualOutput: true,
|
|
705
|
-
skillMeta: {
|
|
706
|
-
name: 'project-go-module-structure',
|
|
707
|
-
description:
|
|
708
|
-
'Go module structure, internal packages, build tags and interface distribution (auto-generated by bootstrap)',
|
|
709
|
-
},
|
|
710
|
-
},
|
|
711
|
-
];
|
|
507
|
+
// → 从 bootstrap/base-dimensions.js 导入
|
|
712
508
|
|
|
713
509
|
// ── 根据项目主语言和框架过滤条件维度 ──────────────────────
|
|
714
510
|
const detectedFrameworks = allTargets
|
|
715
511
|
.map((t) => (typeof t === 'object' ? t.framework : null))
|
|
716
512
|
.filter(Boolean);
|
|
717
|
-
const activeDimensions =
|
|
513
|
+
const activeDimensions = resolveActiveDimensions(
|
|
718
514
|
baseDimensions,
|
|
719
515
|
primaryLang,
|
|
720
516
|
detectedFrameworks
|
|
@@ -1041,384 +837,4 @@ export async function bootstrapKnowledge(ctx, args) {
|
|
|
1041
837
|
});
|
|
1042
838
|
}
|
|
1043
839
|
|
|
1044
|
-
|
|
1045
|
-
* bootstrapRefine — Phase 6 AI 润色
|
|
1046
|
-
*
|
|
1047
|
-
* 对 Bootstrap Phase 5 产出的知识条目进行 AI 二次精炼:
|
|
1048
|
-
* - 改善模板化描述 → 更自然精准
|
|
1049
|
-
* - 补充高阶架构洞察
|
|
1050
|
-
* - 推断并填充 relations 关联
|
|
1051
|
-
* - 调整 confidence 评分
|
|
1052
|
-
*
|
|
1053
|
-
* @param {object} ctx MCP context { container, logger }
|
|
1054
|
-
* @param {object} args { candidateIds?: string[], userPrompt?: string, dryRun?: boolean }
|
|
1055
|
-
*/
|
|
1056
|
-
export async function bootstrapRefine(ctx, args) {
|
|
1057
|
-
const t0 = Date.now();
|
|
1058
|
-
const knowledgeService = ctx.container.get('knowledgeService');
|
|
1059
|
-
const aiProvider = ctx.container.get('aiProvider');
|
|
1060
|
-
|
|
1061
|
-
if (!aiProvider) {
|
|
1062
|
-
return envelope({
|
|
1063
|
-
success: false,
|
|
1064
|
-
message: 'AI provider not configured',
|
|
1065
|
-
errorCode: 'MISSING_AI_PROVIDER',
|
|
1066
|
-
});
|
|
1067
|
-
}
|
|
1068
|
-
|
|
1069
|
-
// 接入 BootstrapTaskManager 双通道推送 refine:* 事件
|
|
1070
|
-
let onProgress = null;
|
|
1071
|
-
try {
|
|
1072
|
-
const taskManager = ctx.container.get('bootstrapTaskManager');
|
|
1073
|
-
onProgress = (eventName, data) => taskManager.emitProgress(eventName, data);
|
|
1074
|
-
} catch {
|
|
1075
|
-
/* optional */
|
|
1076
|
-
}
|
|
1077
|
-
|
|
1078
|
-
// 1. 收集待润色条目
|
|
1079
|
-
let entries;
|
|
1080
|
-
if (args.candidateIds?.length) {
|
|
1081
|
-
entries = [];
|
|
1082
|
-
for (const id of args.candidateIds) {
|
|
1083
|
-
const e = await knowledgeService.get(id);
|
|
1084
|
-
if (e) {
|
|
1085
|
-
entries.push(typeof e.toJSON === 'function' ? e.toJSON() : e);
|
|
1086
|
-
}
|
|
1087
|
-
}
|
|
1088
|
-
} else {
|
|
1089
|
-
const result = await knowledgeService.list(
|
|
1090
|
-
{ lifecycle: 'pending', source: 'bootstrap' },
|
|
1091
|
-
{ page: 1, pageSize: 200 }
|
|
1092
|
-
);
|
|
1093
|
-
entries = (result.items || []).map((e) => (typeof e.toJSON === 'function' ? e.toJSON() : e));
|
|
1094
|
-
}
|
|
1095
|
-
|
|
1096
|
-
if (entries.length === 0) {
|
|
1097
|
-
return envelope({
|
|
1098
|
-
success: true,
|
|
1099
|
-
data: { refined: 0, total: 0, errors: [], results: [] },
|
|
1100
|
-
meta: { tool: 'autosnippet_bootstrap', responseTimeMs: Date.now() - t0 },
|
|
1101
|
-
});
|
|
1102
|
-
}
|
|
1103
|
-
|
|
1104
|
-
onProgress?.('refine:started', { total: entries.length, candidateIds: entries.map((e) => e.id) });
|
|
1105
|
-
|
|
1106
|
-
// 2. 收集已发布 Recipe 标题(关联关系只能指向已发布 Recipe,不能在候选之间互关联)
|
|
1107
|
-
let publishedTitles = [];
|
|
1108
|
-
try {
|
|
1109
|
-
const published = await knowledgeService.list(
|
|
1110
|
-
{ lifecycle: 'active' },
|
|
1111
|
-
{ page: 1, pageSize: 200 }
|
|
1112
|
-
);
|
|
1113
|
-
publishedTitles = (published.items || []).map((e) => e.title).filter(Boolean);
|
|
1114
|
-
} catch { /* ignore */ }
|
|
1115
|
-
|
|
1116
|
-
// 3. 逐条 AI 润色
|
|
1117
|
-
const results = [];
|
|
1118
|
-
const errors = [];
|
|
1119
|
-
let refined = 0;
|
|
1120
|
-
let processed = 0;
|
|
1121
|
-
|
|
1122
|
-
for (const entry of entries) {
|
|
1123
|
-
processed++;
|
|
1124
|
-
onProgress?.('refine:item-started', {
|
|
1125
|
-
candidateId: entry.id,
|
|
1126
|
-
title: entry.title,
|
|
1127
|
-
current: processed,
|
|
1128
|
-
total: entries.length,
|
|
1129
|
-
progress: Math.round(((processed - 1) / entries.length) * 100),
|
|
1130
|
-
});
|
|
1131
|
-
|
|
1132
|
-
try {
|
|
1133
|
-
const before = {
|
|
1134
|
-
title: entry.title || '',
|
|
1135
|
-
description: entry.description || '',
|
|
1136
|
-
pattern: entry.content?.pattern || '',
|
|
1137
|
-
markdown: entry.content?.markdown || '',
|
|
1138
|
-
rationale: entry.content?.rationale || '',
|
|
1139
|
-
tags: entry.tags || [],
|
|
1140
|
-
confidence: entry.reasoning?.confidence ?? 0.6,
|
|
1141
|
-
relations: entry.relations || {},
|
|
1142
|
-
aiInsight: entry.aiInsight || null,
|
|
1143
|
-
agentNotes: entry.agentNotes || null,
|
|
1144
|
-
};
|
|
1145
|
-
|
|
1146
|
-
const refineInstruction = args.userPrompt
|
|
1147
|
-
? args.userPrompt
|
|
1148
|
-
: '请改善描述使其更专业简洁,补充高阶架构洞察';
|
|
1149
|
-
|
|
1150
|
-
const prompt = `你是一位高级代码知识管理专家。请改进以下知识条目。
|
|
1151
|
-
|
|
1152
|
-
## ⭐ JSON key 规范(最高优先级)
|
|
1153
|
-
|
|
1154
|
-
返回的 JSON 必须且只能使用以下 9 个 key,大小写必须完全一致:
|
|
1155
|
-
|
|
1156
|
-
description → 摘要(string)
|
|
1157
|
-
pattern → 代码/标准用法(string)
|
|
1158
|
-
markdown → Markdown 文档(string)
|
|
1159
|
-
rationale → 设计原理(string)
|
|
1160
|
-
tags → 标签(string[])
|
|
1161
|
-
confidence → 置信度(number 0.0–1.0)
|
|
1162
|
-
aiInsight → AI 洞察(string | null)
|
|
1163
|
-
agentNotes → Agent 笔记(string[] | null)
|
|
1164
|
-
relations → 关联关系(object)
|
|
1165
|
-
|
|
1166
|
-
## 当前条目信息
|
|
1167
|
-
|
|
1168
|
-
标题: ${before.title}
|
|
1169
|
-
类型: ${entry.knowledgeType || '未知'}
|
|
1170
|
-
语言: ${entry.language || '未知'}
|
|
1171
|
-
|
|
1172
|
-
【description】摘要
|
|
1173
|
-
${before.description || '(空)'}
|
|
1174
|
-
|
|
1175
|
-
【pattern】代码/标准用法
|
|
1176
|
-
${(before.pattern || '(空)').substring(0, 2000)}
|
|
1177
|
-
|
|
1178
|
-
【markdown】Markdown 文档
|
|
1179
|
-
${(before.markdown || '(空)').substring(0, 2000)}
|
|
1180
|
-
|
|
1181
|
-
【rationale】设计原理
|
|
1182
|
-
${before.rationale || '(空)'}
|
|
1183
|
-
|
|
1184
|
-
【tags】标签
|
|
1185
|
-
${JSON.stringify(before.tags)}
|
|
1186
|
-
|
|
1187
|
-
【confidence】置信度
|
|
1188
|
-
${before.confidence}
|
|
1189
|
-
|
|
1190
|
-
【relations】关联关系
|
|
1191
|
-
${JSON.stringify(before.relations)}
|
|
1192
|
-
|
|
1193
|
-
【aiInsight】AI 洞察
|
|
1194
|
-
${before.aiInsight || '(空)'}
|
|
1195
|
-
|
|
1196
|
-
【agentNotes】Agent 笔记
|
|
1197
|
-
${JSON.stringify(before.agentNotes || [])}
|
|
1198
|
-
|
|
1199
|
-
${publishedTitles.length > 0 ? `已发布的 Recipe: ${publishedTitles.slice(0, 20).join(', ')}` : '(尚无已发布的 Recipe)'}
|
|
1200
|
-
|
|
1201
|
-
## 润色指令
|
|
1202
|
-
|
|
1203
|
-
${refineInstruction}
|
|
1204
|
-
|
|
1205
|
-
## 约束
|
|
1206
|
-
|
|
1207
|
-
1. 只修改需要改进的字段,未涉及的必须原样返回。
|
|
1208
|
-
2. tags 采用合并策略(保留原有 + 补充新建议),不要删除已有标签。
|
|
1209
|
-
3. relations 为 object 格式,key 为关系类型(如 inherits/implements/calls/depends_on/extends/related),value 为 string[]。
|
|
1210
|
-
4. relations 只能指向已发布的 Recipe,不能在候选之间建立关联。如果没有已发布的 Recipe,relations 应保持为空 {}。
|
|
1211
|
-
5. 每个 key 都必须存在,key 名称必须与上述完全一致。
|
|
1212
|
-
|
|
1213
|
-
仅返回 JSON,不要添加任何其他文字或代码块标记。`;
|
|
1214
|
-
|
|
1215
|
-
const parsed = await aiProvider.chatWithStructuredOutput(prompt, { temperature: 0.3 });
|
|
1216
|
-
|
|
1217
|
-
if (!parsed) {
|
|
1218
|
-
errors.push({ id: entry.id, title: entry.title, error: 'AI returned no valid JSON' });
|
|
1219
|
-
onProgress?.('refine:item-failed', {
|
|
1220
|
-
candidateId: entry.id,
|
|
1221
|
-
title: entry.title,
|
|
1222
|
-
error: 'No valid JSON',
|
|
1223
|
-
current: processed,
|
|
1224
|
-
total: entries.length,
|
|
1225
|
-
progress: Math.round((processed / entries.length) * 100),
|
|
1226
|
-
});
|
|
1227
|
-
continue;
|
|
1228
|
-
}
|
|
1229
|
-
|
|
1230
|
-
if (args.dryRun) {
|
|
1231
|
-
results.push({ id: entry.id, title: entry.title, preview: parsed });
|
|
1232
|
-
onProgress?.('refine:item-completed', {
|
|
1233
|
-
candidateId: entry.id,
|
|
1234
|
-
title: entry.title,
|
|
1235
|
-
refined: false,
|
|
1236
|
-
current: processed,
|
|
1237
|
-
total: entries.length,
|
|
1238
|
-
progress: Math.round((processed / entries.length) * 100),
|
|
1239
|
-
});
|
|
1240
|
-
continue;
|
|
1241
|
-
}
|
|
1242
|
-
|
|
1243
|
-
// ─── key 别名归一化(与 candidates.js 保持一致) ───
|
|
1244
|
-
const KEY_ALIASES = {
|
|
1245
|
-
summary: 'description',
|
|
1246
|
-
desc: 'description',
|
|
1247
|
-
content: 'pattern',
|
|
1248
|
-
design: 'rationale',
|
|
1249
|
-
designRationale: 'rationale',
|
|
1250
|
-
markdownDoc: 'markdown',
|
|
1251
|
-
doc: 'markdown',
|
|
1252
|
-
tag: 'tags',
|
|
1253
|
-
label: 'tags',
|
|
1254
|
-
labels: 'tags',
|
|
1255
|
-
score: 'confidence',
|
|
1256
|
-
ai_insight: 'aiInsight',
|
|
1257
|
-
insight: 'aiInsight',
|
|
1258
|
-
aiinsight: 'aiInsight',
|
|
1259
|
-
agent_notes: 'agentNotes',
|
|
1260
|
-
notes: 'agentNotes',
|
|
1261
|
-
agentnotes: 'agentNotes',
|
|
1262
|
-
relation: 'relations',
|
|
1263
|
-
};
|
|
1264
|
-
const VALID_KEYS = new Set([
|
|
1265
|
-
'description',
|
|
1266
|
-
'pattern',
|
|
1267
|
-
'markdown',
|
|
1268
|
-
'rationale',
|
|
1269
|
-
'tags',
|
|
1270
|
-
'confidence',
|
|
1271
|
-
'aiInsight',
|
|
1272
|
-
'agentNotes',
|
|
1273
|
-
'relations',
|
|
1274
|
-
]);
|
|
1275
|
-
const normalized = {};
|
|
1276
|
-
for (const [key, value] of Object.entries(parsed)) {
|
|
1277
|
-
if (VALID_KEYS.has(key)) {
|
|
1278
|
-
normalized[key] = value;
|
|
1279
|
-
} else {
|
|
1280
|
-
const mapped = KEY_ALIASES[key] || KEY_ALIASES[key.toLowerCase?.()];
|
|
1281
|
-
if (mapped && !(mapped in normalized)) {
|
|
1282
|
-
normalized[mapped] = value;
|
|
1283
|
-
}
|
|
1284
|
-
}
|
|
1285
|
-
}
|
|
1286
|
-
for (const k of VALID_KEYS) {
|
|
1287
|
-
if (!(k in normalized)) {
|
|
1288
|
-
normalized[k] = before[k];
|
|
1289
|
-
}
|
|
1290
|
-
}
|
|
1291
|
-
|
|
1292
|
-
// 构建更新数据
|
|
1293
|
-
const updateData = {};
|
|
1294
|
-
let changed = false;
|
|
1295
|
-
|
|
1296
|
-
if (normalized.description != null && normalized.description !== before.description) {
|
|
1297
|
-
updateData.description = normalized.description;
|
|
1298
|
-
changed = true;
|
|
1299
|
-
}
|
|
1300
|
-
// tags 采用合并策略
|
|
1301
|
-
if (normalized.tags != null && Array.isArray(normalized.tags)) {
|
|
1302
|
-
const merged = [...new Set([...(before.tags || []), ...normalized.tags])];
|
|
1303
|
-
if (JSON.stringify(merged) !== JSON.stringify(before.tags)) {
|
|
1304
|
-
updateData.tags = merged;
|
|
1305
|
-
changed = true;
|
|
1306
|
-
}
|
|
1307
|
-
}
|
|
1308
|
-
if (
|
|
1309
|
-
typeof normalized.confidence === 'number' &&
|
|
1310
|
-
normalized.confidence !== before.confidence
|
|
1311
|
-
) {
|
|
1312
|
-
updateData.reasoning = { ...(entry.reasoning || {}), confidence: normalized.confidence };
|
|
1313
|
-
changed = true;
|
|
1314
|
-
}
|
|
1315
|
-
if (normalized.aiInsight != null && normalized.aiInsight !== before.aiInsight) {
|
|
1316
|
-
updateData.aiInsight = normalized.aiInsight;
|
|
1317
|
-
changed = true;
|
|
1318
|
-
}
|
|
1319
|
-
if (normalized.agentNotes !== undefined) {
|
|
1320
|
-
const newNotes = JSON.stringify(normalized.agentNotes);
|
|
1321
|
-
if (newNotes !== JSON.stringify(before.agentNotes)) {
|
|
1322
|
-
updateData.agentNotes = normalized.agentNotes;
|
|
1323
|
-
changed = true;
|
|
1324
|
-
}
|
|
1325
|
-
}
|
|
1326
|
-
if (normalized.relations !== undefined) {
|
|
1327
|
-
const newRels = JSON.stringify(normalized.relations);
|
|
1328
|
-
if (newRels !== JSON.stringify(before.relations)) {
|
|
1329
|
-
updateData.relations = normalized.relations;
|
|
1330
|
-
changed = true;
|
|
1331
|
-
}
|
|
1332
|
-
}
|
|
1333
|
-
// content 嵌套写入
|
|
1334
|
-
const contentPatch = { ...(entry.content || {}) };
|
|
1335
|
-
let contentChanged = false;
|
|
1336
|
-
if (normalized.pattern != null && normalized.pattern !== before.pattern) {
|
|
1337
|
-
contentPatch.pattern = normalized.pattern;
|
|
1338
|
-
contentChanged = true;
|
|
1339
|
-
}
|
|
1340
|
-
if (normalized.markdown != null && normalized.markdown !== before.markdown) {
|
|
1341
|
-
contentPatch.markdown = normalized.markdown;
|
|
1342
|
-
contentChanged = true;
|
|
1343
|
-
}
|
|
1344
|
-
if (normalized.rationale != null && normalized.rationale !== before.rationale) {
|
|
1345
|
-
contentPatch.rationale = normalized.rationale;
|
|
1346
|
-
contentChanged = true;
|
|
1347
|
-
}
|
|
1348
|
-
if (contentChanged) {
|
|
1349
|
-
updateData.content = contentPatch;
|
|
1350
|
-
changed = true;
|
|
1351
|
-
}
|
|
1352
|
-
|
|
1353
|
-
if (changed) {
|
|
1354
|
-
await knowledgeService.update(entry.id, updateData);
|
|
1355
|
-
refined++;
|
|
1356
|
-
}
|
|
1357
|
-
|
|
1358
|
-
results.push({
|
|
1359
|
-
id: entry.id,
|
|
1360
|
-
title: entry.title,
|
|
1361
|
-
refined: changed,
|
|
1362
|
-
fields: Object.keys(parsed),
|
|
1363
|
-
});
|
|
1364
|
-
onProgress?.('refine:item-completed', {
|
|
1365
|
-
candidateId: entry.id,
|
|
1366
|
-
title: entry.title,
|
|
1367
|
-
refined: changed,
|
|
1368
|
-
current: processed,
|
|
1369
|
-
total: entries.length,
|
|
1370
|
-
progress: Math.round((processed / entries.length) * 100),
|
|
1371
|
-
refinedSoFar: refined,
|
|
1372
|
-
});
|
|
1373
|
-
} catch (err) {
|
|
1374
|
-
errors.push({ id: entry.id, title: entry.title, error: err.message });
|
|
1375
|
-
onProgress?.('refine:item-failed', {
|
|
1376
|
-
candidateId: entry.id,
|
|
1377
|
-
title: entry.title,
|
|
1378
|
-
error: err.message,
|
|
1379
|
-
current: processed,
|
|
1380
|
-
total: entries.length,
|
|
1381
|
-
progress: Math.round((processed / entries.length) * 100),
|
|
1382
|
-
});
|
|
1383
|
-
}
|
|
1384
|
-
}
|
|
1385
|
-
|
|
1386
|
-
onProgress?.('refine:completed', { total: entries.length, refined, failed: errors.length });
|
|
1387
|
-
|
|
1388
|
-
return envelope({
|
|
1389
|
-
success: true,
|
|
1390
|
-
data: {
|
|
1391
|
-
refined,
|
|
1392
|
-
total: entries.length,
|
|
1393
|
-
errors,
|
|
1394
|
-
results,
|
|
1395
|
-
message: `Phase 6 AI 润色完成: ${refined}/${entries.length} 条知识条目已更新${args.dryRun ? '(预览模式)' : ''}`,
|
|
1396
|
-
},
|
|
1397
|
-
meta: { tool: 'autosnippet_bootstrap', responseTimeMs: Date.now() - t0 },
|
|
1398
|
-
});
|
|
1399
|
-
}
|
|
1400
|
-
|
|
1401
|
-
// ══════════════════════════════════════════════════════════════════
|
|
1402
|
-
// 内部辅助 — 维度条件化
|
|
1403
|
-
// ══════════════════════════════════════════════════════════════════
|
|
1404
|
-
|
|
1405
|
-
/**
|
|
1406
|
-
* 根据项目主语言和检测到的框架过滤条件维度
|
|
1407
|
-
* @param {Array} allDimensions 所有维度定义(含 conditions 字段)
|
|
1408
|
-
* @param {string} primaryLang 主语言
|
|
1409
|
-
* @param {string[]} detectedFrameworks 检测到的框架
|
|
1410
|
-
* @returns {Array} 适用的维度列表
|
|
1411
|
-
*/
|
|
1412
|
-
function _resolveActiveDimensions(allDimensions, primaryLang, detectedFrameworks = []) {
|
|
1413
|
-
return allDimensions.filter((dim) => {
|
|
1414
|
-
if (!dim.conditions) {
|
|
1415
|
-
return true; // 无条件 → 通用维度
|
|
1416
|
-
}
|
|
1417
|
-
const langMatch = !dim.conditions.languages || dim.conditions.languages.includes(primaryLang);
|
|
1418
|
-
const fwMatch =
|
|
1419
|
-
!dim.conditions.frameworks ||
|
|
1420
|
-
dim.conditions.frameworks.some((f) => detectedFrameworks.includes(f));
|
|
1421
|
-
// languages 必须匹配;frameworks 为可选增强(有 frameworks 条件时必须至少命中一个)
|
|
1422
|
-
return langMatch && (dim.conditions.frameworks ? fwMatch : true);
|
|
1423
|
-
});
|
|
1424
|
-
}
|
|
840
|
+
// bootstrapRefine → 已提取到 bootstrap/refine.js(通过顶部 re-export)
|