add_impl_javadoc.ps1 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. # Adds JavaDoc to impl package - documentation only
  2. $ErrorActionPreference = 'Stop'
  3. $utf8 = [System.Text.UTF8Encoding]::new($false)
  4. $ImplDir = 'd:/ylrz_saas_new/java/fs-service/src/main/java/com/fs/company/service/workflow/impl'
  5. $WorkflowDir = 'd:/ylrz_saas_new/java/fs-service/src/main/java/com/fs/company/service/workflow'
  6. $CallerLabel = '调用方'
  7. $MainCallerLabel = '主要调用方'
  8. $ClassDesc = @{
  9. LobsterEvolutionEngineImpl = '龙虾进化引擎实现:单轮对话从上下文组装到 AI 生成、质量评分、合规与敏感词过滤的完整流水线。'
  10. LobsterWorkflowExecutorImpl = '龙虾工作流执行器实现:实例生命周期管理、节点推进、消息投递与进化引擎集成。'
  11. DynamicNodeExecutorImpl = '动态节点执行器实现:按节点类型注册 handler,执行枚举节点与 AI 兜底逻辑。'
  12. ContextAssemblerImpl = '上下文组装器实现:并行加载画像、知识库、历史、变量等多源上下文供 AI 使用。'
  13. SummaryGeneratorImpl = '对话摘要生成器实现:实例/全局摘要、变量抽取与异步摘要更新。'
  14. LobsterE2eTestServiceImpl = '龙虾端到端测试服务实现:工作流 E2E 跑批、单步推进与多轮对话测试。'
  15. VariableStoreImpl = '工作流变量存储实现:内存 + Redis + 数据库三级读写,供实例运行时变量持久化。'
  16. MultiTurnDialogueManagerImpl = '多轮对话管理器实现:多轮信息收集节点的轮次控制、变量抽取与完成判定。'
  17. QualityScoringServiceImpl = '质量评分服务实现:多维度 AI 回复评分、规则引擎校正与带反馈重生成。'
  18. SensitiveWordServiceImpl = '敏感词过滤服务实现:租户级敏感词检测、替换与高风险词处置。'
  19. ComplianceServiceImpl = '合规检查服务实现:AI 回复合规性校验与分级安全话术替换。'
  20. ConditionEvaluatorImpl = '条件表达式求值器实现:工作流分支节点的条件判断。'
  21. DynamicNodeAdjusterImpl = '动态节点调节器实现:基于语义分析的路由决策与转人工判定。'
  22. DynamicNodeImplServiceImpl = '动态节点实现管理服务:节点 handler 注册与配置 CRUD。'
  23. DuplicateReplyDetector = '重复回复检测器:防止工作流对同一客户重复发送相同内容。'
  24. FactDecayScheduler = '事实衰减定时任务:清理过期用户事实与沟通习惯缓存。'
  25. LobsterBillingServiceImpl = '龙虾计费服务实现:租户余额、Token 消耗记录与统计汇总。'
  26. LobsterConversationSummaryServiceImpl = '对话摘要查询服务实现:管理端摘要列表与详情。'
  27. LobsterEventAuditServiceImpl = '事件审计服务实现:进化/学习事件的人工审核流转。'
  28. LobsterEvolutionSuggestionServiceImpl = '进化建议服务实现:AI 进化建议列表、审核与指标统计。'
  29. LobsterInstanceStatsServiceImpl = '实例统计服务实现:工作流实例运行指标汇总。'
  30. LobsterIntegrationTestServiceImpl = '集成测试服务实现:引擎组件冒烟测试与节点类型验证。'
  31. LobsterLearningCorpusServiceImpl = '学习语料服务实现:租户学习语料查询。'
  32. LobsterModelConfigServiceImpl = '模型配置服务实现:租户级 LLM 路由与质量检查模型配置。'
  33. LobsterNodeTypeServiceImpl = '节点类型注册服务实现:工作流节点类型元数据缓存与 CRUD。'
  34. LobsterPromptServiceImpl = '系统 Prompt 管理服务实现:引擎 Prompt 与系统 Prompt CRUD。'
  35. LobsterSalesCorpusServiceImpl = '销冠语料服务实现:销冠对话导入、分析与场景查询。'
  36. LobsterTestScenarioServiceImpl = '测试场景服务实现:E2E 测试场景 CRUD 与定时跑批。'
  37. MultiModelWorkflowGeneratorImpl = '多模型工作流生成器实现:AI 自动生成/迭代优化工作流 JSON。'
  38. NodePromptServiceImpl = '节点 Prompt 绑定服务实现:节点与 Prompt 模板的关联保存。'
  39. OutputQualityCheckerImpl = '输出质量检查器实现:生成内容的基础质量校验与纠正。'
  40. PendingAuditKnowledgeServiceImpl = '待审核知识服务实现:低质量问答入库审核与晋升知识库。'
  41. ProfileEnrichmentService = '用户画像富化服务:基于行为数据异步更新客户画像。'
  42. PromptManagerImpl = 'Prompt 管理器实现:节点/全局 Prompt 读取与持久化。'
  43. QualityScoreRuleEngine = '质量评分规则引擎:静态规则校正、创意场景加分与合规否决。'
  44. ReplaceWordServiceImpl = '违禁词/易错词替换服务实现:按租户加载替换词表并应用。'
  45. SemanticTakeoverDetectorImpl = '语义接管检测器实现:检测客户要求转人工或 AI 主动转接意图。'
  46. ToolCallFrameworkImpl = '工具调用框架实现:解析 AI 工具调用并执行订单/SMS 等内置工具。'
  47. VariableSubstitutionEngineImpl = '变量替换引擎实现:模板占位符替换与变量抽取。'
  48. WorkflowTemplateAdminServiceImpl = '工作流模板管理服务实现:模板列表、节点保存与发布查询。'
  49. }
  50. $Callers = @{
  51. LobsterWorkflowExecutor = @('LobsterInboundService','WorkflowTriggerScheduler','LobsterTaskDispatchService','LobsterWorkflowExecController','LobsterTravelValidationServiceImpl')
  52. LobsterEvolutionEngine = @('LobsterWorkflowExecutorImpl','LobsterQwEvolutionBridge','LobsterTravelValidationServiceImpl','LobsterPayWorkflowBridge')
  53. DynamicNodeExecutor = @('LobsterWorkflowExecutorImpl','LobsterTravelValidationServiceImpl','LobsterEngineController','LobsterAdminController','LobsterIntegrationTestServiceImpl')
  54. ContextAssembler = @('LobsterEvolutionEngineImpl','MultiTurnDialogueManagerImpl','ChannelPluginService')
  55. SummaryGenerator = @('LobsterEvolutionEngineImpl','ContextAssemblerImpl','MultiTurnDialogueManagerImpl','LobsterTravelValidationServiceImpl','LobsterEngineHealthService')
  56. VariableStore = @('LobsterEvolutionEngineImpl','LobsterWorkflowExecutorImpl','TriggerOrchestratorImpl','LobsterScheduleService','ContextAssemblerImpl')
  57. MultiTurnDialogueManager = @('LobsterEvolutionEngineImpl','LobsterWorkflowExecutorImpl')
  58. QualityScoringService = @('LobsterEvolutionEngineImpl','DynamicNodeExecutorImpl','LobsterTravelValidationServiceImpl','LobsterE2eTestServiceImpl','TenantLearningEngineImpl')
  59. SensitiveWordService = @('LobsterEvolutionEngineImpl','MultiTurnDialogueManagerImpl','LobsterTravelValidationServiceImpl','LobsterCompanyConfigService','LobsterEngineHealthService')
  60. LobsterE2eTestService = @('LobsterE2eController','LobsterAdminController','LobsterTravelValidationServiceImpl','LobsterTestScenarioServiceImpl')
  61. ComplianceService = @('LobsterEvolutionEngineImpl','MultiTurnDialogueManagerImpl','LobsterWorkflowExecController')
  62. ConditionEvaluator = @('LobsterWorkflowExecutorImpl')
  63. DynamicNodeAdjuster = @('LobsterEvolutionEngineImpl')
  64. PromptManager = @('LobsterEvolutionEngineImpl','LobsterWorkflowExecutorImpl','DynamicNodeExecutorImpl','MultiTurnDialogueManagerImpl')
  65. ToolCallFramework = @('LobsterEvolutionEngineImpl')
  66. ReplaceWordService = @('LobsterEvolutionEngineImpl','LobsterCompanyConfigService')
  67. VariableSubstitutionEngine = @('LobsterWorkflowExecutorImpl','LobsterEvolutionEngineImpl')
  68. SemanticTakeoverDetector = @('DynamicNodeAdjusterImpl','LobsterInboundReplyOrchestrator')
  69. OutputQualityChecker = @('DynamicNodeExecutorImpl')
  70. MultiModelWorkflowGenerator = @('LobsterIntegrationTestServiceImpl','LobsterAdminController')
  71. PendingAuditKnowledgeService = @('TenantLearningEngineImpl','LobsterLearningPersistenceService')
  72. ProfileEnrichmentService = @('LobsterEvolutionEngineImpl')
  73. QualityScoreRuleEngine = @('QualityScoringServiceImpl')
  74. DuplicateReplyDetector = @('LobsterWorkflowExecutorImpl')
  75. FactDecayScheduler = @('Spring 定时调度')
  76. LobsterBillingServiceImpl = @('LobsterAdminController','LobsterPlatformAdminController','LobsterTokenStatsController')
  77. LobsterIntegrationTestServiceImpl = @('LobsterEngineController','LobsterAdminController')
  78. WorkflowTemplateAdminServiceImpl = @('LobsterAdminController')
  79. ILobsterSalesCorpusService = @('LobsterAdminController','LobsterSalesCorpusController','LobsterPlatformAdminController')
  80. ILobsterEvolutionSuggestionService = @('LobsterAdminController')
  81. ILobsterInstanceStatsService = @('LobsterAdminController')
  82. ILobsterPromptService = @('LobsterPromptController')
  83. LobsterModelConfigService = @('LobsterAdminController','LobsterModelRouteController')
  84. LobsterNodeTypeService = @('LobsterIntegrationTestServiceImpl','DynamicNodeExecutorImpl')
  85. LobsterTestScenarioService = @('LobsterE2eController','LobsterAdminController')
  86. DynamicNodeImplService = @('LobsterE2eController','LobsterAdminController')
  87. INodePromptService = @('WorkflowTemplateAdminServiceImpl')
  88. ILobsterEventAuditService = @('LobsterEventAuditController','LobsterAdminController')
  89. ILobsterConversationSummaryService = @('LobsterAdminController')
  90. ILobsterLearningCorpusService = @('LobsterAdminController')
  91. }
  92. function Get-Callers([string]$ClassName) {
  93. $keys = @($ClassName, ($ClassName -replace 'Impl$',''))
  94. if (-not $keys[1].StartsWith('I')) { $keys += 'I' + $keys[1] }
  95. foreach ($k in $keys) {
  96. if ($Callers.ContainsKey($k)) { return $Callers[$k] }
  97. }
  98. return @('Spring 容器注入调用')
  99. }
  100. function Format-Callers([string[]]$list) {
  101. return (($list | ForEach-Object { "{@code $_}" }) -join '、')
  102. }
  103. function Parse-InterfaceMethods([string]$ClassName) {
  104. $iface = $ClassName -replace 'Impl$',''
  105. $files = @(
  106. (Join-Path $WorkflowDir "$iface.java"),
  107. (Join-Path $WorkflowDir "I$iface.java")
  108. )
  109. $methods = @{}
  110. foreach ($f in $files) {
  111. if (-not (Test-Path $f)) { continue }
  112. $text = [System.IO.File]::ReadAllText($f, $utf8)
  113. $matches = [regex]::Matches($text, '/\*\*([\s\S]*?)\*/\s*(?:@[\w.]+\s*)*[\w<>,\[\]\s.?]+\s+(\w+)\s*\([^)]*\)\s*;')
  114. foreach ($m in $matches) {
  115. $lines = $m.Groups[1].Value -split "`n" | ForEach-Object { $_ -replace '^\s*\*\s?','' } | Where-Object { $_ -and $_ -notmatch '^\s*@(param|return)' }
  116. if ($lines.Count -gt 0) { $methods[$m.Groups[2].Value] = $lines[0].Trim() }
  117. }
  118. }
  119. return $methods
  120. }
  121. function Method-Purpose([string]$ClassName, [string]$MethodName, $ifaceMethods) {
  122. if ($ifaceMethods.ContainsKey($MethodName)) { return $ifaceMethods[$MethodName] }
  123. $map = @{
  124. init='初始化组件(注册 handler、加载缓存等)。'
  125. evolve='执行单轮对话进化流水线,生成 AI 回复及下一节点。'
  126. enrichWithDynamicNode='AI 动态生成并插入个性化工作流节点。'
  127. learnCustomerHabit='从本轮交互学习客户沟通习惯并写入 habit 表。'
  128. startWorkflow='启动新的工作流实例并执行首节点。'
  129. executeNextNode='接收客户回复并推进工作流到下一节点。'
  130. execute='执行指定类型的动态节点 handler。'
  131. processDialogue='处理多轮对话节点的一轮交互。'
  132. scoreWithRetry='质量评分并在不达标时带反馈重生成。'
  133. filterSensitiveWords='过滤文本中的敏感词并替换。'
  134. enrichProfile='多渠道融合 CRM/标签/交互数据并写入用户画像表。'
  135. detectTakeover='检测客户是否要求转人工接管。'
  136. detectAITransfer='检测 AI 是否应主动转接人工。'
  137. cleanupExpiredFacts='定时清理过期事实与习惯数据。'
  138. }
  139. if ($map.ContainsKey($MethodName)) { return $map[$MethodName] }
  140. if ($MethodName.StartsWith('get') -and $MethodName.Length -gt 3) { return "获取$($MethodName.Substring(3))。" }
  141. if ($MethodName.StartsWith('is') -and $MethodName.Length -gt 2) { return "判断是否$($MethodName.Substring(2))。" }
  142. if ($MethodName.StartsWith('list')) { return "查询$($MethodName.Substring(4))列表。" }
  143. return "$MethodName 的公共入口。"
  144. }
  145. function Has-JavadocBefore {
  146. param([Parameter(Mandatory)][AllowEmptyCollection()][string[]]$Lines, [Parameter(Mandatory)][int]$Idx)
  147. if ($null -eq $Lines -or $Lines.Count -eq 0 -or $Idx -le 0) { return $false }
  148. $j = $Idx - 1
  149. while ($j -ge 0 -and $Lines[$j].Trim() -eq '') { $j-- }
  150. if ($j -ge 0 -and $Lines[$j].Trim().EndsWith('*/')) { return $true }
  151. return $false
  152. }
  153. function Has-CallerInJavadoc {
  154. param([Parameter(Mandatory)][AllowEmptyCollection()][string[]]$Lines, [Parameter(Mandatory)][int]$Idx)
  155. if ($null -eq $Lines -or $Lines.Count -eq 0 -or $Idx -le 0) { return $false }
  156. $j = $Idx - 1
  157. while ($j -ge 0) {
  158. $t = $Lines[$j].Trim()
  159. if ($t.StartsWith('/**')) { break }
  160. if ($t.Contains($CallerLabel)) { return $true }
  161. $j--
  162. }
  163. return $false
  164. }
  165. function Make-MethodDoc([string]$ClassName, [string]$MethodName, $ifaceMethods, [string]$indent) {
  166. $purpose = Method-Purpose $ClassName $MethodName $ifaceMethods
  167. $callers = Format-Callers (Get-Callers $ClassName)
  168. return @(
  169. "$indent/**",
  170. "$indent * $purpose",
  171. "$indent * <p>${CallerLabel}:$callers。",
  172. "$indent */"
  173. )
  174. }
  175. function Make-ClassDoc([string]$ClassName) {
  176. $desc = if ($ClassDesc.ContainsKey($ClassName)) { $ClassDesc[$ClassName] } else { "$ClassName:workflow impl 包 Spring 服务实现。" }
  177. $callers = Format-Callers (Get-Callers $ClassName)
  178. return @(
  179. '/**',
  180. " * $desc",
  181. " * <p>${MainCallerLabel}:$callers。",
  182. ' */'
  183. )
  184. }
  185. function Process-File([string]$FilePath) {
  186. $className = [System.IO.Path]::GetFileNameWithoutExtension($FilePath)
  187. if ($className -eq 'package-info') { return $false }
  188. $lines = [System.Collections.Generic.List[string]]::new()
  189. [System.IO.File]::ReadAllLines($FilePath, $utf8) | ForEach-Object { [void]$lines.Add($_) }
  190. $ifaceMethods = Parse-InterfaceMethods $className
  191. $classIdx = -1
  192. for ($i = 0; $i -lt $lines.Count; $i++) {
  193. if ($lines[$i] -match "public\s+(?:final\s+)?class\s+$className\b") { $classIdx = $i; break }
  194. }
  195. if ($classIdx -lt 0) { return $false }
  196. $modified = $false
  197. $hasClassDoc = $false
  198. $j = $classIdx - 1
  199. while ($j -ge 0 -and ($lines[$j].Trim().StartsWith('@') -or $lines[$j].Trim() -eq '')) { $j-- }
  200. if ($j -ge 0 -and ($lines[$j].Trim().StartsWith('/**') -or $lines[$j].Trim().EndsWith('*/'))) { $hasClassDoc = $true }
  201. $lineArr = @($lines.ToArray())
  202. if (-not $hasClassDoc) {
  203. $insertAt = $classIdx
  204. while ($insertAt -gt 0 -and ($lines[$insertAt-1].Trim().StartsWith('@') -or $lines[$insertAt-1].Trim() -eq '')) { $insertAt-- }
  205. $doc = Make-ClassDoc $className
  206. for ($d = $doc.Count - 1; $d -ge 0; $d--) { $lines.Insert($insertAt, $doc[$d]) }
  207. $classIdx += $doc.Count
  208. $modified = $true
  209. } elseif (-not (Has-CallerInJavadoc -Lines $lineArr -Idx $classIdx)) {
  210. $j = $classIdx - 1
  211. while ($j -ge 0 -and ($lines[$j].Trim().StartsWith('@') -or $lines[$j].Trim() -eq '')) { $j-- }
  212. if ($j -ge 0 -and $lines[$j].Trim() -eq '*/') {
  213. $callers = Format-Callers (Get-Callers $className)
  214. $lines.Insert($j, " * <p>${MainCallerLabel}:$callers。")
  215. $modified = $true
  216. }
  217. }
  218. $lineArr = @($lines.ToArray())
  219. $out = [System.Collections.Generic.List[string]]::new()
  220. $skipUntil = -1
  221. for ($i = 0; $i -lt $lines.Count; $i++) {
  222. if ($i -le $skipUntil) { continue }
  223. $line = $lines[$i]
  224. $stripped = $line.Trim()
  225. if ($stripped -eq '@Override' -and ($i+1) -lt $lines.Count -and $lines[$i+1].Trim() -match '^public\s+') {
  226. if (-not (Has-JavadocBefore -Lines $lineArr -Idx $i)) {
  227. $mm = [regex]::Match($lines[$i+1], '\b(\w+)\s*\(')
  228. if ($mm.Success) {
  229. $indent = if ($line -match '^(\s*)') { $Matches[1] } else { ' ' }
  230. Make-MethodDoc $className $mm.Groups[1].Value $ifaceMethods $indent | ForEach-Object { [void]$out.Add($_) }
  231. $modified = $true
  232. }
  233. } elseif (-not (Has-CallerInJavadoc -Lines $lineArr -Idx $i)) {
  234. $j = $i - 1
  235. while ($j -ge 0 -and $lines[$j].Trim() -ne '*/') { $j-- }
  236. if ($j -ge 0) {
  237. $indent = if ($lines[$j] -match '^(\s*)') { $Matches[1] } else { ' ' }
  238. $callers = Format-Callers (Get-Callers $className)
  239. [void]$out.Insert($out.Count, "$indent * <p>${CallerLabel}:$callers。")
  240. $modified = $true
  241. }
  242. }
  243. [void]$out.Add($line)
  244. continue
  245. }
  246. if ($stripped -match '^public\s+(?!class\b|interface\b|enum\b|static\s+class\b)' -and -not $stripped.StartsWith('@')) {
  247. if (-not (Has-JavadocBefore -Lines $lineArr -Idx $i)) {
  248. $combined = $stripped
  249. $k = $i
  250. while ($combined -notmatch '[;{]' -and $k+1 -lt $lines.Count) { $k++; $combined += ' ' + $lines[$k].Trim() }
  251. $mm = [regex]::Match($combined, '\b(\w+)\s*\(')
  252. if ($mm.Success -and $mm.Groups[1].Value -notin @('if','for','while','switch','catch')) {
  253. $indent = if ($line -match '^(\s*)') { $Matches[1] } else { ' ' }
  254. Make-MethodDoc $className $mm.Groups[1].Value $ifaceMethods $indent | ForEach-Object { [void]$out.Add($_) }
  255. $modified = $true
  256. }
  257. } elseif (-not (Has-CallerInJavadoc -Lines $lineArr -Idx $i)) {
  258. $j = $i - 1
  259. while ($j -ge 0 -and $lines[$j].Trim() -ne '*/') { $j-- }
  260. if ($j -ge 0) {
  261. $indent = if ($lines[$j] -match '^(\s*)') { $Matches[1] } else { ' ' }
  262. $callers = Format-Callers (Get-Callers $className)
  263. [void]$out.Insert($out.Count, "$indent * <p>${CallerLabel}:$callers。")
  264. $modified = $true
  265. }
  266. }
  267. }
  268. [void]$out.Add($line)
  269. }
  270. if ($modified) {
  271. [System.IO.File]::WriteAllLines($FilePath, $out, $utf8)
  272. }
  273. return $modified
  274. }
  275. $modified = @()
  276. if ($MyInvocation.InvocationName -ne '.') {
  277. Get-ChildItem $ImplDir -Filter *.java | Sort-Object Name | ForEach-Object {
  278. if (Process-File $_.FullName) {
  279. $modified += $_.Name
  280. Write-Host "MODIFIED: $($_.Name)"
  281. } else {
  282. Write-Host "SKIP: $($_.Name)"
  283. }
  284. }
  285. Write-Host "Total modified: $($modified.Count)"
  286. }