autosnippet 3.3.6 → 3.3.8

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.
Files changed (275) hide show
  1. package/README.md +1 -0
  2. package/dashboard/dist/assets/icons-BMNb0V6L.js +1 -0
  3. package/dashboard/dist/assets/index-DHJ1Dj7u.css +1 -0
  4. package/dashboard/dist/assets/index-DV8biUkH.js +112 -0
  5. package/dashboard/dist/index.html +3 -3
  6. package/dist/bin/cli.js +8 -4
  7. package/dist/lib/agent/AgentRuntime.d.ts +2 -2
  8. package/dist/lib/agent/AgentRuntime.js +26 -18
  9. package/dist/lib/agent/core/ChatAgentPrompts.js +57 -21
  10. package/dist/lib/agent/core/LoopContext.d.ts +1 -0
  11. package/dist/lib/agent/core/ToolExecutionPipeline.js +13 -0
  12. package/dist/lib/agent/domain/ChatAgentTasks.js +4 -0
  13. package/dist/lib/agent/forced-summary.js +7 -2
  14. package/dist/lib/agent/memory/ActiveContext.d.ts +0 -2
  15. package/dist/lib/agent/memory/ActiveContext.js +0 -2
  16. package/dist/lib/agent/memory/MemoryEmbeddingStore.d.ts +49 -0
  17. package/dist/lib/agent/memory/MemoryEmbeddingStore.js +159 -0
  18. package/dist/lib/agent/memory/MemoryRetriever.d.ts +2 -0
  19. package/dist/lib/agent/memory/MemoryRetriever.js +25 -11
  20. package/dist/lib/agent/memory/MemoryStore.d.ts +8 -41
  21. package/dist/lib/agent/memory/MemoryStore.js +196 -261
  22. package/dist/lib/agent/memory/PersistentMemory.d.ts +2 -0
  23. package/dist/lib/agent/memory/PersistentMemory.js +4 -5
  24. package/dist/lib/agent/memory/SessionStore.d.ts +0 -2
  25. package/dist/lib/agent/memory/SessionStore.js +0 -2
  26. package/dist/lib/agent/tools/ast-graph.js +21 -19
  27. package/dist/lib/agent/tools/infrastructure.js +3 -2
  28. package/dist/lib/agent/tools/project-access.d.ts +2 -2
  29. package/dist/lib/agent/tools/project-access.js +5 -4
  30. package/dist/lib/bootstrap.js +2 -1
  31. package/dist/lib/cli/AiScanService.js +8 -21
  32. package/dist/lib/cli/KnowledgeSyncService.d.ts +7 -37
  33. package/dist/lib/cli/KnowledgeSyncService.js +23 -51
  34. package/dist/lib/core/ast/ProjectGraph.js +5 -27
  35. package/dist/lib/core/discovery/ConfigWatcher.d.ts +64 -0
  36. package/dist/lib/core/discovery/ConfigWatcher.js +336 -0
  37. package/dist/lib/core/discovery/CustomConfigDiscoverer.d.ts +28 -0
  38. package/dist/lib/core/discovery/CustomConfigDiscoverer.js +1303 -0
  39. package/dist/lib/core/discovery/DiscovererPreference.d.ts +44 -0
  40. package/dist/lib/core/discovery/DiscovererPreference.js +141 -0
  41. package/dist/lib/core/discovery/DiscovererRegistry.d.ts +10 -1
  42. package/dist/lib/core/discovery/DiscovererRegistry.js +42 -2
  43. package/dist/lib/core/discovery/ProjectDiscoverer.d.ts +19 -0
  44. package/dist/lib/core/discovery/index.d.ts +2 -0
  45. package/dist/lib/core/discovery/index.js +4 -0
  46. package/dist/lib/core/discovery/parsers/CMakeParser.d.ts +32 -0
  47. package/dist/lib/core/discovery/parsers/CMakeParser.js +148 -0
  48. package/dist/lib/core/discovery/parsers/GradleDslParser.d.ts +43 -0
  49. package/dist/lib/core/discovery/parsers/GradleDslParser.js +171 -0
  50. package/dist/lib/core/discovery/parsers/JsonConfigParser.d.ts +45 -0
  51. package/dist/lib/core/discovery/parsers/JsonConfigParser.js +122 -0
  52. package/dist/lib/core/discovery/parsers/RubyDslParser.d.ts +49 -0
  53. package/dist/lib/core/discovery/parsers/RubyDslParser.js +282 -0
  54. package/dist/lib/core/discovery/parsers/StarlarkParser.d.ts +33 -0
  55. package/dist/lib/core/discovery/parsers/StarlarkParser.js +229 -0
  56. package/dist/lib/core/discovery/parsers/YamlConfigParser.d.ts +37 -0
  57. package/dist/lib/core/discovery/parsers/YamlConfigParser.js +212 -0
  58. package/dist/lib/domain/dimension/DimensionRegistry.d.ts +0 -2
  59. package/dist/lib/domain/dimension/DimensionRegistry.js +0 -2
  60. package/dist/lib/domain/dimension/DimensionSop.js +44 -33
  61. package/dist/lib/domain/dimension/UnifiedDimension.d.ts +0 -2
  62. package/dist/lib/domain/dimension/UnifiedDimension.js +0 -2
  63. package/dist/lib/domain/knowledge/KnowledgeEntry.d.ts +7 -1
  64. package/dist/lib/domain/knowledge/KnowledgeEntry.js +17 -3
  65. package/dist/lib/domain/knowledge/Lifecycle.d.ts +26 -0
  66. package/dist/lib/domain/knowledge/Lifecycle.js +42 -0
  67. package/dist/lib/domain/knowledge/index.d.ts +2 -1
  68. package/dist/lib/domain/knowledge/index.js +1 -1
  69. package/dist/lib/external/ai/AiProvider.d.ts +12 -0
  70. package/dist/lib/external/ai/AiProvider.js +24 -0
  71. package/dist/lib/external/ai/AiProviderManager.d.ts +101 -0
  72. package/dist/lib/external/ai/AiProviderManager.js +193 -0
  73. package/dist/lib/external/ai/providers/ClaudeProvider.js +11 -0
  74. package/dist/lib/external/ai/providers/GoogleGeminiProvider.js +18 -0
  75. package/dist/lib/external/ai/providers/MockProvider.d.ts +21 -3
  76. package/dist/lib/external/ai/providers/MockProvider.js +290 -14
  77. package/dist/lib/external/ai/providers/OpenAiProvider.js +16 -0
  78. package/dist/lib/external/lark/LarkTransport.d.ts +5 -1
  79. package/dist/lib/external/lark/LarkTransport.js +10 -2
  80. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.d.ts +2 -1
  81. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.js +102 -153
  82. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/mock-pipeline.d.ts +20 -0
  83. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/mock-pipeline.js +432 -0
  84. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +49 -24
  85. package/dist/lib/external/mcp/handlers/bootstrap/refine.js +8 -0
  86. package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.d.ts +1 -1
  87. package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +41 -37
  88. package/dist/lib/external/mcp/handlers/bootstrap-external.d.ts +9 -0
  89. package/dist/lib/external/mcp/handlers/bootstrap-external.js +3 -1
  90. package/dist/lib/external/mcp/handlers/bootstrap-internal.js +2 -0
  91. package/dist/lib/external/mcp/handlers/consolidated.js +2 -1
  92. package/dist/lib/external/mcp/handlers/dimension-complete-external.js +9 -4
  93. package/dist/lib/external/mcp/handlers/evolve-external.d.ts +1 -0
  94. package/dist/lib/external/mcp/handlers/evolve-external.js +18 -18
  95. package/dist/lib/external/mcp/handlers/guard.js +15 -24
  96. package/dist/lib/external/mcp/handlers/knowledge.js +5 -4
  97. package/dist/lib/external/mcp/handlers/panorama.js +9 -9
  98. package/dist/lib/external/mcp/handlers/rescan-external.js +7 -6
  99. package/dist/lib/external/mcp/handlers/rescan-internal.js +9 -5
  100. package/dist/lib/external/mcp/handlers/search.js +3 -1
  101. package/dist/lib/external/mcp/handlers/skill.js +4 -4
  102. package/dist/lib/external/mcp/handlers/structure.js +8 -12
  103. package/dist/lib/external/mcp/handlers/system.js +10 -34
  104. package/dist/lib/http/routes/ai.js +109 -30
  105. package/dist/lib/http/routes/candidates.js +11 -4
  106. package/dist/lib/http/routes/commands.js +10 -1
  107. package/dist/lib/http/routes/guardReport.js +3 -5
  108. package/dist/lib/http/routes/health.js +11 -0
  109. package/dist/lib/http/routes/modules.js +27 -0
  110. package/dist/lib/http/routes/panorama.js +12 -12
  111. package/dist/lib/http/routes/recipes.js +66 -8
  112. package/dist/lib/http/routes/remote.js +3 -13
  113. package/dist/lib/http/routes/search.js +11 -8
  114. package/dist/lib/http/utils/routeHelpers.js +2 -1
  115. package/dist/lib/infrastructure/audit/AuditLogger.d.ts +20 -3
  116. package/dist/lib/infrastructure/audit/AuditStore.d.ts +28 -29
  117. package/dist/lib/infrastructure/audit/AuditStore.js +81 -88
  118. package/dist/lib/infrastructure/database/drizzle/schema.d.ts +180 -2
  119. package/dist/lib/infrastructure/database/drizzle/schema.js +23 -3
  120. package/dist/lib/injection/ServiceContainer.d.ts +6 -5
  121. package/dist/lib/injection/ServiceContainer.js +18 -31
  122. package/dist/lib/injection/ServiceMap.d.ts +22 -0
  123. package/dist/lib/injection/modules/AiModule.d.ts +6 -9
  124. package/dist/lib/injection/modules/AiModule.js +82 -39
  125. package/dist/lib/injection/modules/AppModule.js +2 -1
  126. package/dist/lib/injection/modules/GuardModule.js +5 -5
  127. package/dist/lib/injection/modules/InfraModule.js +60 -0
  128. package/dist/lib/injection/modules/KnowledgeModule.js +86 -51
  129. package/dist/lib/injection/modules/PanoramaModule.js +16 -10
  130. package/dist/lib/injection/modules/VectorModule.js +3 -0
  131. package/dist/lib/repository/audit/AuditRepository.d.ts +107 -0
  132. package/dist/lib/repository/audit/AuditRepository.js +272 -0
  133. package/dist/lib/repository/base/RepositoryBase.d.ts +46 -0
  134. package/dist/lib/repository/base/RepositoryBase.js +32 -0
  135. package/dist/lib/repository/bootstrap/BootstrapRepository.d.ts +94 -0
  136. package/dist/lib/repository/bootstrap/BootstrapRepository.js +246 -0
  137. package/dist/lib/repository/code/CodeEntityRepository.d.ts +91 -0
  138. package/dist/lib/repository/code/CodeEntityRepository.js +361 -0
  139. package/dist/lib/repository/delivery/DeliveryRepoAdapter.d.ts +39 -0
  140. package/dist/lib/repository/delivery/DeliveryRepoAdapter.js +23 -0
  141. package/dist/lib/repository/evolution/LifecycleEventRepository.d.ts +51 -0
  142. package/dist/lib/repository/evolution/LifecycleEventRepository.js +119 -0
  143. package/dist/lib/repository/evolution/ProposalRepository.d.ts +9 -12
  144. package/dist/lib/repository/evolution/ProposalRepository.js +114 -57
  145. package/dist/lib/repository/guard/GuardViolationRepository.d.ts +104 -0
  146. package/dist/lib/repository/guard/GuardViolationRepository.js +217 -0
  147. package/dist/lib/repository/knowledge/KnowledgeEdgeRepository.d.ts +129 -0
  148. package/dist/lib/repository/knowledge/KnowledgeEdgeRepository.js +475 -0
  149. package/dist/lib/repository/knowledge/KnowledgeFileStore.d.ts +39 -0
  150. package/dist/lib/repository/knowledge/KnowledgeFileStore.js +12 -0
  151. package/dist/lib/repository/knowledge/KnowledgeRepository.impl.d.ts +295 -11
  152. package/dist/lib/repository/knowledge/KnowledgeRepository.impl.js +608 -13
  153. package/dist/lib/repository/knowledge/KnowledgeUnitOfWork.d.ts +61 -0
  154. package/dist/lib/repository/knowledge/KnowledgeUnitOfWork.js +156 -0
  155. package/dist/lib/repository/memory/MemoryRepository.d.ts +90 -0
  156. package/dist/lib/repository/memory/MemoryRepository.js +260 -0
  157. package/dist/lib/repository/search/SearchRepoAdapter.d.ts +92 -0
  158. package/dist/lib/repository/search/SearchRepoAdapter.js +124 -0
  159. package/dist/lib/repository/session/SessionRepository.d.ts +46 -0
  160. package/dist/lib/repository/session/SessionRepository.js +110 -0
  161. package/dist/lib/repository/sourceref/RecipeSourceRefRepository.d.ts +66 -0
  162. package/dist/lib/repository/sourceref/RecipeSourceRefRepository.js +182 -0
  163. package/dist/lib/repository/sync/SyncRepoAdapter.d.ts +58 -0
  164. package/dist/lib/repository/sync/SyncRepoAdapter.js +58 -0
  165. package/dist/lib/service/bootstrap/UiStartupTasks.js +5 -6
  166. package/dist/lib/service/bootstrap/bootstrap-event-types.d.ts +0 -1
  167. package/dist/lib/service/bootstrap/bootstrap-event-types.js +0 -1
  168. package/dist/lib/service/cleanup/CleanupService.d.ts +54 -7
  169. package/dist/lib/service/cleanup/CleanupService.js +291 -40
  170. package/dist/lib/service/delivery/CursorDeliveryPipeline.js +6 -8
  171. package/dist/lib/service/evolution/ConsolidationAdvisor.d.ts +4 -9
  172. package/dist/lib/service/evolution/ConsolidationAdvisor.js +34 -70
  173. package/dist/lib/service/evolution/ContentPatcher.d.ts +4 -12
  174. package/dist/lib/service/evolution/ContentPatcher.js +48 -19
  175. package/dist/lib/service/evolution/ContradictionDetector.d.ts +3 -7
  176. package/dist/lib/service/evolution/ContradictionDetector.js +17 -24
  177. package/dist/lib/service/evolution/DecayDetector.d.ts +10 -9
  178. package/dist/lib/service/evolution/DecayDetector.js +63 -57
  179. package/dist/lib/service/evolution/EnhancementSuggester.d.ts +3 -9
  180. package/dist/lib/service/evolution/EnhancementSuggester.js +42 -86
  181. package/dist/lib/service/evolution/KnowledgeMetabolism.d.ts +4 -4
  182. package/dist/lib/service/evolution/KnowledgeMetabolism.js +102 -71
  183. package/dist/lib/service/evolution/ProposalExecutor.d.ts +5 -12
  184. package/dist/lib/service/evolution/ProposalExecutor.js +64 -69
  185. package/dist/lib/service/evolution/RecipeLifecycleSupervisor.d.ts +9 -14
  186. package/dist/lib/service/evolution/RecipeLifecycleSupervisor.js +94 -155
  187. package/dist/lib/service/evolution/RecipeRelevanceAuditor.d.ts +4 -1
  188. package/dist/lib/service/evolution/RecipeRelevanceAuditor.js +50 -49
  189. package/dist/lib/service/evolution/RedundancyAnalyzer.d.ts +3 -7
  190. package/dist/lib/service/evolution/RedundancyAnalyzer.js +15 -22
  191. package/dist/lib/service/evolution/StagingManager.d.ts +6 -15
  192. package/dist/lib/service/evolution/StagingManager.js +37 -95
  193. package/dist/lib/service/evolution/createSupersedeProposal.d.ts +1 -1
  194. package/dist/lib/service/evolution/createSupersedeProposal.js +7 -8
  195. package/dist/lib/service/guard/CoverageAnalyzer.d.ts +3 -7
  196. package/dist/lib/service/guard/CoverageAnalyzer.js +9 -11
  197. package/dist/lib/service/guard/GuardCheckEngine.d.ts +3 -0
  198. package/dist/lib/service/guard/GuardCheckEngine.js +14 -22
  199. package/dist/lib/service/guard/ReverseGuard.d.ts +4 -7
  200. package/dist/lib/service/guard/ReverseGuard.js +21 -31
  201. package/dist/lib/service/guard/ViolationsStore.d.ts +15 -21
  202. package/dist/lib/service/guard/ViolationsStore.js +75 -69
  203. package/dist/lib/service/knowledge/CodeEntityGraph.d.ts +45 -63
  204. package/dist/lib/service/knowledge/CodeEntityGraph.js +418 -496
  205. package/dist/lib/service/knowledge/ConfidenceRouter.js +18 -9
  206. package/dist/lib/service/knowledge/KnowledgeFileWriter.d.ts +2 -1
  207. package/dist/lib/service/knowledge/KnowledgeGraphService.d.ts +18 -60
  208. package/dist/lib/service/knowledge/KnowledgeGraphService.js +58 -109
  209. package/dist/lib/service/knowledge/KnowledgeService.d.ts +15 -1
  210. package/dist/lib/service/knowledge/KnowledgeService.js +97 -46
  211. package/dist/lib/service/knowledge/RecipeProductionGateway.d.ts +0 -2
  212. package/dist/lib/service/knowledge/RecipeProductionGateway.js +0 -2
  213. package/dist/lib/service/knowledge/SourceRefReconciler.d.ts +5 -13
  214. package/dist/lib/service/knowledge/SourceRefReconciler.js +58 -78
  215. package/dist/lib/service/module/ModuleService.js +10 -19
  216. package/dist/lib/service/panorama/CouplingAnalyzer.d.ts +14 -3
  217. package/dist/lib/service/panorama/CouplingAnalyzer.js +137 -32
  218. package/dist/lib/service/panorama/DimensionAnalyzer.d.ts +7 -4
  219. package/dist/lib/service/panorama/DimensionAnalyzer.js +94 -33
  220. package/dist/lib/service/panorama/LayerInferrer.d.ts +16 -1
  221. package/dist/lib/service/panorama/LayerInferrer.js +118 -1
  222. package/dist/lib/service/panorama/ModuleDiscoverer.d.ts +14 -4
  223. package/dist/lib/service/panorama/ModuleDiscoverer.js +209 -61
  224. package/dist/lib/service/panorama/PanoramaAggregator.d.ts +15 -4
  225. package/dist/lib/service/panorama/PanoramaAggregator.js +128 -62
  226. package/dist/lib/service/panorama/PanoramaScanner.d.ts +5 -1
  227. package/dist/lib/service/panorama/PanoramaScanner.js +60 -31
  228. package/dist/lib/service/panorama/PanoramaService.d.ts +11 -8
  229. package/dist/lib/service/panorama/PanoramaService.js +49 -69
  230. package/dist/lib/service/panorama/PanoramaTypes.d.ts +41 -0
  231. package/dist/lib/service/panorama/RoleRefiner.d.ts +10 -5
  232. package/dist/lib/service/panorama/RoleRefiner.js +92 -282
  233. package/dist/lib/service/panorama/TechStackProfiler.d.ts +13 -0
  234. package/dist/lib/service/panorama/TechStackProfiler.js +79 -0
  235. package/dist/lib/service/quality/QualityScorer.d.ts +45 -26
  236. package/dist/lib/service/quality/QualityScorer.js +157 -83
  237. package/dist/lib/service/search/SearchEngine.d.ts +1 -0
  238. package/dist/lib/service/search/SearchEngine.js +32 -37
  239. package/dist/lib/service/signal/HitRecorder.js +5 -5
  240. package/dist/lib/service/skills/RuleRecallStrategy.js +7 -3
  241. package/dist/lib/service/skills/SignalCollector.d.ts +6 -8
  242. package/dist/lib/service/skills/SignalCollector.js +34 -60
  243. package/dist/lib/service/skills/SkillAdvisor.d.ts +7 -13
  244. package/dist/lib/service/skills/SkillAdvisor.js +30 -79
  245. package/dist/lib/service/vector/ContextualEnricher.d.ts +1 -0
  246. package/dist/lib/service/vector/ContextualEnricher.js +4 -0
  247. package/dist/lib/service/vector/SyncCoordinator.d.ts +3 -1
  248. package/dist/lib/service/vector/SyncCoordinator.js +25 -3
  249. package/dist/lib/service/vector/VectorService.d.ts +2 -0
  250. package/dist/lib/service/vector/VectorService.js +3 -0
  251. package/dist/lib/service/wiki/WikiGenerator.js +1 -1
  252. package/dist/lib/shared/LanguageProfiles.d.ts +109 -0
  253. package/dist/lib/shared/LanguageProfiles.js +939 -0
  254. package/dist/lib/shared/LanguageService.d.ts +6 -0
  255. package/dist/lib/shared/LanguageService.js +19 -0
  256. package/dist/lib/shared/constants.d.ts +19 -19
  257. package/dist/lib/shared/constants.js +10 -10
  258. package/dist/lib/shared/developer-identity.d.ts +18 -0
  259. package/dist/lib/shared/developer-identity.js +62 -0
  260. package/dist/lib/shared/schemas/http-requests.d.ts +8 -17
  261. package/dist/lib/shared/schemas/http-requests.js +9 -6
  262. package/dist/lib/shared/schemas/mcp-tools.d.ts +1 -1
  263. package/dist/lib/types/knowledge-wire.d.ts +1 -0
  264. package/dist/lib/types/project-snapshot-builder.d.ts +0 -1
  265. package/dist/lib/types/project-snapshot-builder.js +0 -1
  266. package/dist/lib/types/project-snapshot.d.ts +0 -1
  267. package/dist/lib/types/project-snapshot.js +0 -1
  268. package/dist/lib/types/snapshot-views.d.ts +0 -2
  269. package/dist/lib/types/snapshot-views.js +0 -1
  270. package/package.json +2 -1
  271. package/dashboard/dist/assets/icons-D1aVZYFW.js +0 -1
  272. package/dashboard/dist/assets/index-CxHOu8Hd.css +0 -1
  273. package/dashboard/dist/assets/index-DDdAOpYT.js +0 -128
  274. package/dist/lib/repository/base/BaseRepository.d.ts +0 -53
  275. package/dist/lib/repository/base/BaseRepository.js +0 -226
@@ -4,15 +4,17 @@
4
4
  * 所有表定义从 migration 001-003 忠实翻译。
5
5
  * DB 列名与 migration 保持一致;实体映射由 repository 层处理。
6
6
  *
7
- * 表清单 (16):
7
+ * 表清单 (15):
8
8
  * 001: knowledge_entries, knowledge_edges, guard_violations, audit_logs,
9
9
  * sessions, token_usage, semantic_memories, bootstrap_snapshots,
10
10
  * bootstrap_dim_files, code_entities
11
- * 002: tasks, task_dependencies, task_events
12
11
  * 003: remote_commands
13
12
  * 004: evolution_proposals (+ knowledge_entries.staging_deadline)
13
+ * 005: recipe_source_refs
14
14
  * 内联: remote_state
15
15
  * 内部: schema_migrations
16
+ *
17
+ * 注: Task 系统为纯内存 + JSONL 信号架构,不使用数据库表。
16
18
  */
17
19
  export declare const schemaMigrations: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
18
20
  name: "schema_migrations";
@@ -3411,3 +3413,179 @@ export declare const recipeSourceRefs: import("drizzle-orm/sqlite-core").SQLiteT
3411
3413
  };
3412
3414
  dialect: "sqlite";
3413
3415
  }>;
3416
+ export declare const lifecycleTransitionEvents: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
3417
+ name: "lifecycle_transition_events";
3418
+ schema: undefined;
3419
+ columns: {
3420
+ id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3421
+ name: "id";
3422
+ tableName: "lifecycle_transition_events";
3423
+ dataType: "string";
3424
+ columnType: "SQLiteText";
3425
+ data: string;
3426
+ driverParam: string;
3427
+ notNull: true;
3428
+ hasDefault: false;
3429
+ isPrimaryKey: true;
3430
+ isAutoincrement: false;
3431
+ hasRuntimeDefault: false;
3432
+ enumValues: [string, ...string[]];
3433
+ baseColumn: never;
3434
+ identity: undefined;
3435
+ generated: undefined;
3436
+ }, {}, {
3437
+ length: number | undefined;
3438
+ }>;
3439
+ recipeId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3440
+ name: "recipe_id";
3441
+ tableName: "lifecycle_transition_events";
3442
+ dataType: "string";
3443
+ columnType: "SQLiteText";
3444
+ data: string;
3445
+ driverParam: string;
3446
+ notNull: true;
3447
+ hasDefault: false;
3448
+ isPrimaryKey: false;
3449
+ isAutoincrement: false;
3450
+ hasRuntimeDefault: false;
3451
+ enumValues: [string, ...string[]];
3452
+ baseColumn: never;
3453
+ identity: undefined;
3454
+ generated: undefined;
3455
+ }, {}, {
3456
+ length: number | undefined;
3457
+ }>;
3458
+ fromState: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3459
+ name: "from_state";
3460
+ tableName: "lifecycle_transition_events";
3461
+ dataType: "string";
3462
+ columnType: "SQLiteText";
3463
+ data: string;
3464
+ driverParam: string;
3465
+ notNull: true;
3466
+ hasDefault: false;
3467
+ isPrimaryKey: false;
3468
+ isAutoincrement: false;
3469
+ hasRuntimeDefault: false;
3470
+ enumValues: [string, ...string[]];
3471
+ baseColumn: never;
3472
+ identity: undefined;
3473
+ generated: undefined;
3474
+ }, {}, {
3475
+ length: number | undefined;
3476
+ }>;
3477
+ toState: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3478
+ name: "to_state";
3479
+ tableName: "lifecycle_transition_events";
3480
+ dataType: "string";
3481
+ columnType: "SQLiteText";
3482
+ data: string;
3483
+ driverParam: string;
3484
+ notNull: true;
3485
+ hasDefault: false;
3486
+ isPrimaryKey: false;
3487
+ isAutoincrement: false;
3488
+ hasRuntimeDefault: false;
3489
+ enumValues: [string, ...string[]];
3490
+ baseColumn: never;
3491
+ identity: undefined;
3492
+ generated: undefined;
3493
+ }, {}, {
3494
+ length: number | undefined;
3495
+ }>;
3496
+ trigger: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3497
+ name: "trigger";
3498
+ tableName: "lifecycle_transition_events";
3499
+ dataType: "string";
3500
+ columnType: "SQLiteText";
3501
+ data: string;
3502
+ driverParam: string;
3503
+ notNull: true;
3504
+ hasDefault: false;
3505
+ isPrimaryKey: false;
3506
+ isAutoincrement: false;
3507
+ hasRuntimeDefault: false;
3508
+ enumValues: [string, ...string[]];
3509
+ baseColumn: never;
3510
+ identity: undefined;
3511
+ generated: undefined;
3512
+ }, {}, {
3513
+ length: number | undefined;
3514
+ }>;
3515
+ operatorId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3516
+ name: "operator_id";
3517
+ tableName: "lifecycle_transition_events";
3518
+ dataType: "string";
3519
+ columnType: "SQLiteText";
3520
+ data: string;
3521
+ driverParam: string;
3522
+ notNull: true;
3523
+ hasDefault: true;
3524
+ isPrimaryKey: false;
3525
+ isAutoincrement: false;
3526
+ hasRuntimeDefault: false;
3527
+ enumValues: [string, ...string[]];
3528
+ baseColumn: never;
3529
+ identity: undefined;
3530
+ generated: undefined;
3531
+ }, {}, {
3532
+ length: number | undefined;
3533
+ }>;
3534
+ evidenceJson: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3535
+ name: "evidence_json";
3536
+ tableName: "lifecycle_transition_events";
3537
+ dataType: "string";
3538
+ columnType: "SQLiteText";
3539
+ data: string;
3540
+ driverParam: string;
3541
+ notNull: false;
3542
+ hasDefault: false;
3543
+ isPrimaryKey: false;
3544
+ isAutoincrement: false;
3545
+ hasRuntimeDefault: false;
3546
+ enumValues: [string, ...string[]];
3547
+ baseColumn: never;
3548
+ identity: undefined;
3549
+ generated: undefined;
3550
+ }, {}, {
3551
+ length: number | undefined;
3552
+ }>;
3553
+ proposalId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3554
+ name: "proposal_id";
3555
+ tableName: "lifecycle_transition_events";
3556
+ dataType: "string";
3557
+ columnType: "SQLiteText";
3558
+ data: string;
3559
+ driverParam: string;
3560
+ notNull: false;
3561
+ hasDefault: false;
3562
+ isPrimaryKey: false;
3563
+ isAutoincrement: false;
3564
+ hasRuntimeDefault: false;
3565
+ enumValues: [string, ...string[]];
3566
+ baseColumn: never;
3567
+ identity: undefined;
3568
+ generated: undefined;
3569
+ }, {}, {
3570
+ length: number | undefined;
3571
+ }>;
3572
+ createdAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3573
+ name: "created_at";
3574
+ tableName: "lifecycle_transition_events";
3575
+ dataType: "number";
3576
+ columnType: "SQLiteInteger";
3577
+ data: number;
3578
+ driverParam: number;
3579
+ notNull: true;
3580
+ hasDefault: false;
3581
+ isPrimaryKey: false;
3582
+ isAutoincrement: false;
3583
+ hasRuntimeDefault: false;
3584
+ enumValues: undefined;
3585
+ baseColumn: never;
3586
+ identity: undefined;
3587
+ generated: undefined;
3588
+ }, {}, {}>;
3589
+ };
3590
+ dialect: "sqlite";
3591
+ }>;
@@ -4,17 +4,19 @@
4
4
  * 所有表定义从 migration 001-003 忠实翻译。
5
5
  * DB 列名与 migration 保持一致;实体映射由 repository 层处理。
6
6
  *
7
- * 表清单 (16):
7
+ * 表清单 (15):
8
8
  * 001: knowledge_entries, knowledge_edges, guard_violations, audit_logs,
9
9
  * sessions, token_usage, semantic_memories, bootstrap_snapshots,
10
10
  * bootstrap_dim_files, code_entities
11
- * 002: tasks, task_dependencies, task_events
12
11
  * 003: remote_commands
13
12
  * 004: evolution_proposals (+ knowledge_entries.staging_deadline)
13
+ * 005: recipe_source_refs
14
14
  * 内联: remote_state
15
15
  * 内部: schema_migrations
16
+ *
17
+ * 注: Task 系统为纯内存 + JSONL 信号架构,不使用数据库表。
16
18
  */
17
- import { index, integer, real, sqliteTable, text, uniqueIndex } from 'drizzle-orm/sqlite-core';
19
+ import { index, integer, real, sqliteTable, text, uniqueIndex, } from 'drizzle-orm/sqlite-core';
18
20
  // ═══════════════════════════════════════════════════════════════
19
21
  // 内部 — schema_migrations
20
22
  // ═══════════════════════════════════════════════════════════════
@@ -339,3 +341,21 @@ export const recipeSourceRefs = sqliteTable('recipe_source_refs', {
339
341
  newPath: text('new_path'),
340
342
  verifiedAt: integer('verified_at').notNull(),
341
343
  }, (table) => [index('idx_rsr_path').on(table.sourcePath), index('idx_rsr_status').on(table.status)]);
344
+ // ═══════════════════════════════════════════════════════════════
345
+ // 18. lifecycle_transition_events — Recipe 生命周期转移事件 (migration 006)
346
+ // ═══════════════════════════════════════════════════════════════
347
+ export const lifecycleTransitionEvents = sqliteTable('lifecycle_transition_events', {
348
+ id: text('id').primaryKey(),
349
+ recipeId: text('recipe_id').notNull(),
350
+ fromState: text('from_state').notNull(),
351
+ toState: text('to_state').notNull(),
352
+ trigger: text('trigger').notNull(),
353
+ operatorId: text('operator_id').notNull().default('system'),
354
+ evidenceJson: text('evidence_json'),
355
+ proposalId: text('proposal_id'),
356
+ createdAt: integer('created_at').notNull(),
357
+ }, (table) => [
358
+ index('idx_lte_recipe_id').on(table.recipeId),
359
+ index('idx_lte_created_at').on(table.createdAt),
360
+ index('idx_lte_trigger').on(table.trigger),
361
+ ]);
@@ -32,11 +32,12 @@ export declare class ServiceContainer {
32
32
  /**
33
33
  * 热重载 AI Provider(API Key 变更后调用,无需重启进程)
34
34
  *
35
- * 流程:
36
- * 1. 替换 singletons.aiProvider
37
- * 2. 重新创建 _embedProvider(如果主 provider 不支持 embedding)
38
- * 3. 清除已缓存的依赖 AI 的 singleton(SearchEngine 等),
39
- * 下次 get() 时会用新 provider 重新创建
35
+ * 委托给 AiProviderManager.switchProvider() — 原子操作:
36
+ * 1. 替换 provider 引用 + DI 数据管道同步
37
+ * 2. Token 追踪 AOP 重新挂载
38
+ * 3. Embedding fallback 重建
39
+ * 4. 清除已缓存的依赖 AI singleton(SearchEngine 等)
40
+ * 5. 监听器回调通知
40
41
  */
41
42
  reloadAiProvider(newProvider: Record<string, unknown> | null): void;
42
43
  /** 获取当前默认 UI 语言偏好 */
@@ -9,6 +9,7 @@ import { CacheCoordinator } from '../infrastructure/cache/CacheCoordinator.js';
9
9
  import { GraphCache } from '../infrastructure/cache/GraphCache.js';
10
10
  // ─── P3: Infrastructure ──────────────────────────────
11
11
  import Logger from '../infrastructure/logging/Logger.js';
12
+ import { unwrapRawDb } from '../repository/search/SearchRepoAdapter.js';
12
13
  import * as AgentModule from './modules/AgentModule.js';
13
14
  import * as AiModule from './modules/AiModule.js';
14
15
  import * as AppModule from './modules/AppModule.js';
@@ -147,36 +148,20 @@ export class ServiceContainer {
147
148
  /**
148
149
  * 热重载 AI Provider(API Key 变更后调用,无需重启进程)
149
150
  *
150
- * 流程:
151
- * 1. 替换 singletons.aiProvider
152
- * 2. 重新创建 _embedProvider(如果主 provider 不支持 embedding)
153
- * 3. 清除已缓存的依赖 AI 的 singleton(SearchEngine 等),
154
- * 下次 get() 时会用新 provider 重新创建
151
+ * 委托给 AiProviderManager.switchProvider() — 原子操作:
152
+ * 1. 替换 provider 引用 + DI 数据管道同步
153
+ * 2. Token 追踪 AOP 重新挂载
154
+ * 3. Embedding fallback 重建
155
+ * 4. 清除已缓存的依赖 AI singleton(SearchEngine 等)
156
+ * 5. 监听器回调通知
155
157
  */
156
158
  reloadAiProvider(newProvider) {
157
- const old = this.singletons.aiProvider;
158
- this.singletons.aiProvider = newProvider;
159
- // 重新创建 embedding fallback provider(委托 AiModule)
160
- this.singletons._embedProvider = null;
161
- if (newProvider &&
162
- typeof newProvider.supportsEmbedding === 'function' &&
163
- !newProvider.supportsEmbedding()) {
164
- AiModule.initEmbeddingFallback(this);
159
+ if (!newProvider) {
160
+ this.logger.warn('[ServiceContainer] reloadAiProvider called with null — ignored');
161
+ return;
165
162
  }
166
- // 清除持有旧 aiProvider 引用的 singleton 缓存
167
- // 下次调用 container.get() 时会使用新 provider 重建
168
- const cleared = [];
169
- for (const key of this._aiDependentSingletons || []) {
170
- if (this.singletons[key]) {
171
- this.singletons[key] = null;
172
- cleared.push(key);
173
- }
174
- }
175
- this.logger.info('AI provider hot-reloaded', {
176
- old: old?.constructor?.name || 'none',
177
- new: newProvider?.constructor?.name || 'none',
178
- clearedSingletons: cleared,
179
- });
163
+ const manager = this.singletons._aiProviderManager;
164
+ manager.switchProvider(newProvider);
180
165
  }
181
166
  // ─── 跨进程缓存协调 ─────
182
167
  /**
@@ -193,7 +178,9 @@ export class ServiceContainer {
193
178
  #initCacheCoordinator() {
194
179
  try {
195
180
  const db = this.singletons.database;
196
- const rawDb = db?.getDb ? db.getDb() : null;
181
+ const rawDb = db
182
+ ? unwrapRawDb(db)
183
+ : null;
197
184
  if (!rawDb) {
198
185
  return;
199
186
  }
@@ -316,7 +303,7 @@ export class ServiceContainer {
316
303
  if (changedPaths.length === 0 && deletedPaths.length === 0) {
317
304
  // 完全命中
318
305
  this.singletons.projectGraph = graph;
319
- this.logger.info(`[ServiceContainer] ProjectGraph ⚡ 缓存命中 (${graph.getOverview()?.totalClasses} classes, ` +
306
+ this.logger.info(`[ServiceContainer] ProjectGraph ⚡ 缓存命中 (${(await graph.getOverview())?.totalClasses} classes, ` +
320
307
  `${Date.now() - startTime}ms)`);
321
308
  return graph;
322
309
  }
@@ -325,7 +312,7 @@ export class ServiceContainer {
325
312
  this.singletons.projectGraph = graph;
326
313
  // 写回缓存
327
314
  cache.save('project-graph', graph.toJSON(), { fileHashes: newHashes });
328
- const overview = graph.getOverview();
315
+ const overview = (await graph.getOverview());
329
316
  this.logger.info(`[ServiceContainer] ProjectGraph 增量更新: +${diff.added} ~${diff.updated} -${diff.deleted} ` +
330
317
  `(${overview.totalClasses} classes, ${Date.now() - startTime}ms)`);
331
318
  return graph;
@@ -333,7 +320,7 @@ export class ServiceContainer {
333
320
  // ── 无缓存,全量构建 ──
334
321
  const graph = await ProjectGraph.build(projectRoot, options);
335
322
  this.singletons.projectGraph = graph;
336
- const overview = graph.getOverview();
323
+ const overview = (await graph.getOverview());
337
324
  // 计算文件 hash 并写入缓存
338
325
  const currentFiles = this.#collectSourceFilePaths(projectRoot, options);
339
326
  const fileHashes = cache.computeFileHashes(currentFiles, projectRoot);
@@ -14,6 +14,7 @@ import type ProjectGraph from '../core/ast/ProjectGraph.js';
14
14
  import type Constitution from '../core/constitution/Constitution.js';
15
15
  import type Gateway from '../core/gateway/Gateway.js';
16
16
  import type { AiProvider } from '../external/ai/AiProvider.js';
17
+ import type { AiProviderManager } from '../external/ai/AiProviderManager.js';
17
18
  import type AuditLogger from '../infrastructure/audit/AuditLogger.js';
18
19
  import type AuditStore from '../infrastructure/audit/AuditStore.js';
19
20
  import type { CacheCoordinator } from '../infrastructure/cache/CacheCoordinator.js';
@@ -23,7 +24,17 @@ import type Logger from '../infrastructure/logging/Logger.js';
23
24
  import type { SignalBus } from '../infrastructure/signal/SignalBus.js';
24
25
  import type { IndexingPipeline } from '../infrastructure/vector/IndexingPipeline.js';
25
26
  import type { VectorStore } from '../infrastructure/vector/VectorStore.js';
27
+ import type { AuditRepositoryImpl } from '../repository/audit/AuditRepository.js';
28
+ import type { BootstrapRepositoryImpl } from '../repository/bootstrap/BootstrapRepository.js';
29
+ import type { CodeEntityRepositoryImpl } from '../repository/code/CodeEntityRepository.js';
30
+ import type { ProposalRepository } from '../repository/evolution/ProposalRepository.js';
31
+ import type { GuardViolationRepositoryImpl } from '../repository/guard/GuardViolationRepository.js';
32
+ import type { KnowledgeEdgeRepositoryImpl } from '../repository/knowledge/KnowledgeEdgeRepository.js';
26
33
  import type { KnowledgeRepositoryImpl } from '../repository/knowledge/KnowledgeRepository.impl.js';
34
+ import type { MemoryRepositoryImpl } from '../repository/memory/MemoryRepository.js';
35
+ import type { RemoteCommandRepository } from '../repository/remote/RemoteCommandRepository.js';
36
+ import type { SessionRepositoryImpl } from '../repository/session/SessionRepository.js';
37
+ import type { RecipeSourceRefRepositoryImpl } from '../repository/sourceref/RecipeSourceRefRepository.js';
27
38
  import type { TokenUsageStore } from '../repository/token/TokenUsageStore.js';
28
39
  import type { BootstrapTaskManager } from '../service/bootstrap/BootstrapTaskManager.js';
29
40
  import type { CursorDeliveryPipeline } from '../service/delivery/CursorDeliveryPipeline.js';
@@ -73,6 +84,16 @@ export interface ServiceMap {
73
84
  eventBus: EventBus;
74
85
  bootstrapTaskManager: BootstrapTaskManager;
75
86
  knowledgeRepository: KnowledgeRepositoryImpl;
87
+ knowledgeEdgeRepository: KnowledgeEdgeRepositoryImpl;
88
+ codeEntityRepository: CodeEntityRepositoryImpl;
89
+ bootstrapRepository: BootstrapRepositoryImpl;
90
+ guardViolationRepository: GuardViolationRepositoryImpl;
91
+ auditRepository: AuditRepositoryImpl;
92
+ memoryRepository: MemoryRepositoryImpl;
93
+ sessionRepository: SessionRepositoryImpl;
94
+ proposalRepository: ProposalRepository;
95
+ remoteCommandRepository: RemoteCommandRepository;
96
+ recipeSourceRefRepository: RecipeSourceRefRepositoryImpl;
76
97
  knowledgeFileWriter: KnowledgeFileWriter;
77
98
  knowledgeSyncService: KnowledgeSyncService;
78
99
  qualityScorer: QualityScorer;
@@ -98,6 +119,7 @@ export interface ServiceMap {
98
119
  dimensionCopy: typeof DimensionCopy;
99
120
  constitution: Constitution | null;
100
121
  aiProvider: AiProvider | null;
122
+ aiProviderManager: AiProviderManager;
101
123
  projectGraph: ProjectGraph | null;
102
124
  vectorService: VectorService;
103
125
  contextualEnricher: ContextualEnricher | null;
@@ -6,6 +6,7 @@
6
6
  *
7
7
  * 职责:
8
8
  * - AI Provider 自动探测与创建
9
+ * - AiProviderManager 统一管理层
9
10
  * - Embedding fallback provider 管理
10
11
  * - AiFactory 实例注入
11
12
  *
@@ -17,19 +18,15 @@ import type { ServiceContainer } from '../ServiceContainer.js';
17
18
  *
18
19
  * 1. 动态导入 AiFactory
19
20
  * 2. 自动探测可用 AI Provider
20
- * 3. 创建 Embedding fallback(若主 provider 不支持 embedding)
21
+ * 3. 创建 AiProviderManager(统一管理层)
22
+ * 4. 绑定 Token 追踪、Embedding fallback、DI 级联清理
21
23
  */
22
24
  export declare function initialize(c: ServiceContainer): Promise<void>;
23
- /**
24
- * 创建/刷新 Embedding fallback provider
25
- *
26
- * 若主 provider 不支持 embedding(如 Claude),尝试从其他可用 provider 创建备用。
27
- */
28
- export declare function initEmbeddingFallback(c: ServiceContainer): void;
29
25
  /**
30
26
  * 注册 AI 相关的服务到容器
31
27
  *
32
- * 当前 AI Provider 和 AiFactory 通过 singletons 直接管理,
33
- * 此方法注册便于其他模块通过 container.get() 获取的快捷服务。
28
+ * - 标记 AI 模块就绪
29
+ * - 注册 aiProviderManager 服务
30
+ * - 延迟注入 TokenRecorder(tokenUsageStore 此时已可用)
34
31
  */
35
32
  export declare function register(c: ServiceContainer): void;
@@ -6,17 +6,20 @@
6
6
  *
7
7
  * 职责:
8
8
  * - AI Provider 自动探测与创建
9
+ * - AiProviderManager 统一管理层
9
10
  * - Embedding fallback provider 管理
10
11
  * - AiFactory 实例注入
11
12
  *
12
13
  * @module AiModule
13
14
  */
15
+ import { AiProviderManager } from '../../external/ai/AiProviderManager.js';
14
16
  /**
15
17
  * 初始化 AI Provider(在模块注册前调用)
16
18
  *
17
19
  * 1. 动态导入 AiFactory
18
20
  * 2. 自动探测可用 AI Provider
19
- * 3. 创建 Embedding fallback(若主 provider 不支持 embedding)
21
+ * 3. 创建 AiProviderManager(统一管理层)
22
+ * 4. 绑定 Token 追踪、Embedding fallback、DI 级联清理
20
23
  */
21
24
  export async function initialize(c) {
22
25
  const logger = c.logger;
@@ -43,56 +46,96 @@ export async function initialize(c) {
43
46
  c.singletons.aiProvider = null;
44
47
  }
45
48
  }
46
- // Embedding fallback provider
47
- initEmbeddingFallback(c);
49
+ // ── 创建 AiProviderManager(统一管理层)──
50
+ const manager = new AiProviderManager(c.singletons.aiProvider || { name: 'mock', model: 'mock-fallback' });
51
+ c.singletons._aiProviderManager = manager;
52
+ // 绑定: DI 数据管道同步(切换时更新 singletons 中的 provider 引用,供工厂函数读取)
53
+ manager._bindDiSync((provider, embed) => {
54
+ c.singletons.aiProvider = provider;
55
+ c.singletons._embedProvider = embed;
56
+ });
57
+ // 绑定: DI 级联清理回调
58
+ manager._bindDependentClearer(() => {
59
+ const cleared = [];
60
+ for (const key of c._aiDependentSingletons || []) {
61
+ if (c.singletons[key]) {
62
+ c.singletons[key] = null;
63
+ cleared.push(key);
64
+ }
65
+ }
66
+ return cleared;
67
+ });
68
+ // 绑定: Embedding fallback 初始化器
69
+ manager._bindEmbedFallbackInit((currentProvider) => {
70
+ return createEmbedFallback(c, currentProvider);
71
+ });
72
+ // Token 追踪 AOP(manager 自身已在构造时 wire,此处延迟注入 recorder)
73
+ // recorder 注入放到 register() 之后(tokenUsageStore 需先注册)
74
+ // Embedding fallback: manager 的 embedFallbackInit 回调已绑定,初始化时主动触发一次
75
+ const initialEmbed = createEmbedFallback(c, c.singletons.aiProvider);
76
+ if (initialEmbed) {
77
+ manager.setEmbedProvider(initialEmbed);
78
+ c.singletons._embedProvider = initialEmbed;
79
+ }
48
80
  }
49
81
  /**
50
- * 创建/刷新 Embedding fallback provider
51
- *
52
- * 若主 provider 不支持 embedding(如 Claude),尝试从其他可用 provider 创建备用。
82
+ * 纯函数: 尝试为给定 provider 创建 Embedding fallback
83
+ * 被 initEmbeddingFallback() 和 AiProviderManager 的 embedFallbackInit 回调共用
53
84
  */
54
- export function initEmbeddingFallback(c) {
55
- const currentProvider = c.singletons.aiProvider;
56
- if ((currentProvider &&
57
- typeof currentProvider
58
- .supportsEmbedding !== 'function') ||
59
- (currentProvider &&
60
- !currentProvider.supportsEmbedding?.())) {
61
- try {
62
- const aiFactory = (c.singletons._aiFactory || {});
63
- const providerName = (currentProvider?.name || '').replace('-', '');
64
- const fbCandidates = typeof aiFactory.getAvailableFallbacks === 'function'
65
- ? aiFactory.getAvailableFallbacks(providerName)
66
- : [];
67
- for (const fb of fbCandidates) {
68
- try {
69
- const fbProvider = aiFactory.createProvider({ provider: fb });
70
- if (typeof fbProvider.supportsEmbedding === 'function' &&
71
- fbProvider.supportsEmbedding()) {
72
- c.singletons._embedProvider = fbProvider;
73
- c.logger.info('Embedding fallback provider created', { provider: fb });
74
- break;
75
- }
76
- }
77
- catch {
78
- /* skip */
85
+ function createEmbedFallback(c, currentProvider) {
86
+ if (!currentProvider ||
87
+ (typeof currentProvider.supportsEmbedding === 'function' && currentProvider.supportsEmbedding())) {
88
+ return null; // 主 provider 已支持 embedding,无需 fallback
89
+ }
90
+ try {
91
+ const aiFactory = (c.singletons._aiFactory || {});
92
+ const providerName = (currentProvider.name || '').replace('-', '');
93
+ const fbCandidates = typeof aiFactory.getAvailableFallbacks === 'function'
94
+ ? aiFactory.getAvailableFallbacks(providerName)
95
+ : [];
96
+ for (const fb of fbCandidates) {
97
+ try {
98
+ const fbProvider = aiFactory.createProvider?.({ provider: fb });
99
+ if (fbProvider &&
100
+ typeof fbProvider.supportsEmbedding === 'function' &&
101
+ fbProvider.supportsEmbedding()) {
102
+ c.logger.info('Embedding fallback provider created', { provider: fb });
103
+ return fbProvider;
79
104
  }
80
105
  }
81
- }
82
- catch {
83
- /* no embed fallback available */
106
+ catch {
107
+ /* skip */
108
+ }
84
109
  }
85
110
  }
111
+ catch {
112
+ /* no embed fallback available */
113
+ }
114
+ return null;
86
115
  }
87
116
  /**
88
117
  * 注册 AI 相关的服务到容器
89
118
  *
90
- * 当前 AI Provider 和 AiFactory 通过 singletons 直接管理,
91
- * 此方法注册便于其他模块通过 container.get() 获取的快捷服务。
119
+ * - 标记 AI 模块就绪
120
+ * - 注册 aiProviderManager 服务
121
+ * - 延迟注入 TokenRecorder(tokenUsageStore 此时已可用)
92
122
  */
93
123
  export function register(c) {
94
- // aiProvider 和 _aiFactory 已通过 initialize() 写入 singletons
95
- // KnowledgeModule 中已注册 'aiProvider' 的 register 工厂
96
- // 此处仅标记 AI 模块已就绪
97
124
  c.singletons._aiModuleReady = true;
125
+ // 注册 aiProviderManager(消费者通过 container.get('aiProviderManager') 获取)
126
+ c.register('aiProviderManager', () => c.singletons._aiProviderManager);
127
+ // 延迟注入 TokenRecorder 到 manager(tokenUsageStore 在 AppModule 中注册)
128
+ const manager = c.singletons._aiProviderManager;
129
+ const containerRef = c;
130
+ manager.setTokenRecorder({
131
+ record(r) {
132
+ try {
133
+ const store = containerRef.get('tokenUsageStore');
134
+ store.record(r);
135
+ }
136
+ catch {
137
+ /* tokenUsageStore not available yet */
138
+ }
139
+ },
140
+ });
98
141
  }
@@ -8,6 +8,7 @@
8
8
  * - primeSearchPipeline (for prime multi-query search — no DB dependency)
9
9
  */
10
10
  import { resolveProjectRoot } from '#shared/resolveProjectRoot.js';
11
+ import { unwrapRawDb } from '../../repository/search/SearchRepoAdapter.js';
11
12
  import { TokenUsageStore } from '../../repository/token/TokenUsageStore.js';
12
13
  import { CursorDeliveryPipeline } from '../../service/delivery/CursorDeliveryPipeline.js';
13
14
  import { RecipeExtractor } from '../../service/knowledge/RecipeExtractor.js';
@@ -29,7 +30,7 @@ export function register(c) {
29
30
  });
30
31
  c.singleton('tokenUsageStore', (ct) => {
31
32
  const db = ct.get('database');
32
- return new TokenUsageStore(db.getDb(), db.getDrizzle());
33
+ return new TokenUsageStore(unwrapRawDb(db), db.getDrizzle());
33
34
  });
34
35
  // ═══ Module ═══
35
36
  c.singleton('moduleService', (ct) => {
@@ -9,6 +9,7 @@
9
9
  import fs from 'node:fs';
10
10
  import path from 'node:path';
11
11
  import { resolveProjectRoot } from '#shared/resolveProjectRoot.js';
12
+ import { unwrapRawDb } from '../../repository/search/SearchRepoAdapter.js';
12
13
  import { ComplianceReporter } from '../../service/guard/ComplianceReporter.js';
13
14
  import { CoverageAnalyzer } from '../../service/guard/CoverageAnalyzer.js';
14
15
  import { ExclusionManager } from '../../service/guard/ExclusionManager.js';
@@ -66,6 +67,7 @@ export function register(c) {
66
67
  return new GuardCheckEngine(ct.get('database'), {
67
68
  guardConfig: merged,
68
69
  signalBus: ct.singletons.signalBus || undefined,
70
+ knowledgeRepo: ct.get('knowledgeRepository'),
69
71
  });
70
72
  });
71
73
  c.singleton('exclusionManager', (ct) => {
@@ -80,7 +82,7 @@ export function register(c) {
80
82
  });
81
83
  c.singleton('violationsStore', (ct) => {
82
84
  const db = ct.get('database');
83
- return new ViolationsStore(db.getDb(), db.getDrizzle());
85
+ return new ViolationsStore(unwrapRawDb(db), db.getDrizzle());
84
86
  });
85
87
  c.singleton('complianceReporter', (ct) => {
86
88
  const config = ct.singletons._config || {};
@@ -91,13 +93,11 @@ export function register(c) {
91
93
  signalBus: ct.singletons.signalBus || undefined,
92
94
  }));
93
95
  c.singleton('reverseGuard', (ct) => {
94
- const db = ct.get('database');
95
- return new ReverseGuard(db.getDb(), {
96
+ return new ReverseGuard(ct.get('knowledgeRepository'), ct.get('codeEntityRepository'), ct.get('recipeSourceRefRepository'), {
96
97
  signalBus: ct.singletons.signalBus || undefined,
97
98
  });
98
99
  });
99
100
  c.singleton('coverageAnalyzer', (ct) => {
100
- const db = ct.get('database');
101
101
  let ruleLearner;
102
102
  try {
103
103
  ruleLearner = { ruleLearner: ct.get('ruleLearner') };
@@ -105,6 +105,6 @@ export function register(c) {
105
105
  catch {
106
106
  /* ruleLearner not yet available */
107
107
  }
108
- return new CoverageAnalyzer(db.getDb(), ruleLearner);
108
+ return new CoverageAnalyzer(ct.get('knowledgeRepository'), ct.get('guardViolationRepository'), ruleLearner);
109
109
  });
110
110
  }