# Adds JavaDoc to impl package - documentation only $ErrorActionPreference = 'Stop' $utf8 = [System.Text.UTF8Encoding]::new($false) $ImplDir = 'd:/ylrz_saas_new/java/fs-service/src/main/java/com/fs/company/service/workflow/impl' $WorkflowDir = 'd:/ylrz_saas_new/java/fs-service/src/main/java/com/fs/company/service/workflow' $CallerLabel = '调用方' $MainCallerLabel = '主要调用方' $ClassDesc = @{ LobsterEvolutionEngineImpl = '龙虾进化引擎实现:单轮对话从上下文组装到 AI 生成、质量评分、合规与敏感词过滤的完整流水线。' LobsterWorkflowExecutorImpl = '龙虾工作流执行器实现:实例生命周期管理、节点推进、消息投递与进化引擎集成。' DynamicNodeExecutorImpl = '动态节点执行器实现:按节点类型注册 handler,执行枚举节点与 AI 兜底逻辑。' ContextAssemblerImpl = '上下文组装器实现:并行加载画像、知识库、历史、变量等多源上下文供 AI 使用。' SummaryGeneratorImpl = '对话摘要生成器实现:实例/全局摘要、变量抽取与异步摘要更新。' LobsterE2eTestServiceImpl = '龙虾端到端测试服务实现:工作流 E2E 跑批、单步推进与多轮对话测试。' VariableStoreImpl = '工作流变量存储实现:内存 + Redis + 数据库三级读写,供实例运行时变量持久化。' MultiTurnDialogueManagerImpl = '多轮对话管理器实现:多轮信息收集节点的轮次控制、变量抽取与完成判定。' QualityScoringServiceImpl = '质量评分服务实现:多维度 AI 回复评分、规则引擎校正与带反馈重生成。' SensitiveWordServiceImpl = '敏感词过滤服务实现:租户级敏感词检测、替换与高风险词处置。' ComplianceServiceImpl = '合规检查服务实现:AI 回复合规性校验与分级安全话术替换。' ConditionEvaluatorImpl = '条件表达式求值器实现:工作流分支节点的条件判断。' DynamicNodeAdjusterImpl = '动态节点调节器实现:基于语义分析的路由决策与转人工判定。' DynamicNodeImplServiceImpl = '动态节点实现管理服务:节点 handler 注册与配置 CRUD。' DuplicateReplyDetector = '重复回复检测器:防止工作流对同一客户重复发送相同内容。' FactDecayScheduler = '事实衰减定时任务:清理过期用户事实与沟通习惯缓存。' LobsterBillingServiceImpl = '龙虾计费服务实现:租户余额、Token 消耗记录与统计汇总。' LobsterConversationSummaryServiceImpl = '对话摘要查询服务实现:管理端摘要列表与详情。' LobsterEventAuditServiceImpl = '事件审计服务实现:进化/学习事件的人工审核流转。' LobsterEvolutionSuggestionServiceImpl = '进化建议服务实现:AI 进化建议列表、审核与指标统计。' LobsterInstanceStatsServiceImpl = '实例统计服务实现:工作流实例运行指标汇总。' LobsterIntegrationTestServiceImpl = '集成测试服务实现:引擎组件冒烟测试与节点类型验证。' LobsterLearningCorpusServiceImpl = '学习语料服务实现:租户学习语料查询。' LobsterModelConfigServiceImpl = '模型配置服务实现:租户级 LLM 路由与质量检查模型配置。' LobsterNodeTypeServiceImpl = '节点类型注册服务实现:工作流节点类型元数据缓存与 CRUD。' LobsterPromptServiceImpl = '系统 Prompt 管理服务实现:引擎 Prompt 与系统 Prompt CRUD。' LobsterSalesCorpusServiceImpl = '销冠语料服务实现:销冠对话导入、分析与场景查询。' LobsterTestScenarioServiceImpl = '测试场景服务实现:E2E 测试场景 CRUD 与定时跑批。' MultiModelWorkflowGeneratorImpl = '多模型工作流生成器实现:AI 自动生成/迭代优化工作流 JSON。' NodePromptServiceImpl = '节点 Prompt 绑定服务实现:节点与 Prompt 模板的关联保存。' OutputQualityCheckerImpl = '输出质量检查器实现:生成内容的基础质量校验与纠正。' PendingAuditKnowledgeServiceImpl = '待审核知识服务实现:低质量问答入库审核与晋升知识库。' ProfileEnrichmentService = '用户画像富化服务:基于行为数据异步更新客户画像。' PromptManagerImpl = 'Prompt 管理器实现:节点/全局 Prompt 读取与持久化。' QualityScoreRuleEngine = '质量评分规则引擎:静态规则校正、创意场景加分与合规否决。' ReplaceWordServiceImpl = '违禁词/易错词替换服务实现:按租户加载替换词表并应用。' SemanticTakeoverDetectorImpl = '语义接管检测器实现:检测客户要求转人工或 AI 主动转接意图。' ToolCallFrameworkImpl = '工具调用框架实现:解析 AI 工具调用并执行订单/SMS 等内置工具。' VariableSubstitutionEngineImpl = '变量替换引擎实现:模板占位符替换与变量抽取。' WorkflowTemplateAdminServiceImpl = '工作流模板管理服务实现:模板列表、节点保存与发布查询。' } $Callers = @{ LobsterWorkflowExecutor = @('LobsterInboundService','WorkflowTriggerScheduler','LobsterTaskDispatchService','LobsterWorkflowExecController','LobsterTravelValidationServiceImpl') LobsterEvolutionEngine = @('LobsterWorkflowExecutorImpl','LobsterQwEvolutionBridge','LobsterTravelValidationServiceImpl','LobsterPayWorkflowBridge') DynamicNodeExecutor = @('LobsterWorkflowExecutorImpl','LobsterTravelValidationServiceImpl','LobsterEngineController','LobsterAdminController','LobsterIntegrationTestServiceImpl') ContextAssembler = @('LobsterEvolutionEngineImpl','MultiTurnDialogueManagerImpl','ChannelPluginService') SummaryGenerator = @('LobsterEvolutionEngineImpl','ContextAssemblerImpl','MultiTurnDialogueManagerImpl','LobsterTravelValidationServiceImpl','LobsterEngineHealthService') VariableStore = @('LobsterEvolutionEngineImpl','LobsterWorkflowExecutorImpl','TriggerOrchestratorImpl','LobsterScheduleService','ContextAssemblerImpl') MultiTurnDialogueManager = @('LobsterEvolutionEngineImpl','LobsterWorkflowExecutorImpl') QualityScoringService = @('LobsterEvolutionEngineImpl','DynamicNodeExecutorImpl','LobsterTravelValidationServiceImpl','LobsterE2eTestServiceImpl','TenantLearningEngineImpl') SensitiveWordService = @('LobsterEvolutionEngineImpl','MultiTurnDialogueManagerImpl','LobsterTravelValidationServiceImpl','LobsterCompanyConfigService','LobsterEngineHealthService') LobsterE2eTestService = @('LobsterE2eController','LobsterAdminController','LobsterTravelValidationServiceImpl','LobsterTestScenarioServiceImpl') ComplianceService = @('LobsterEvolutionEngineImpl','MultiTurnDialogueManagerImpl','LobsterWorkflowExecController') ConditionEvaluator = @('LobsterWorkflowExecutorImpl') DynamicNodeAdjuster = @('LobsterEvolutionEngineImpl') PromptManager = @('LobsterEvolutionEngineImpl','LobsterWorkflowExecutorImpl','DynamicNodeExecutorImpl','MultiTurnDialogueManagerImpl') ToolCallFramework = @('LobsterEvolutionEngineImpl') ReplaceWordService = @('LobsterEvolutionEngineImpl','LobsterCompanyConfigService') VariableSubstitutionEngine = @('LobsterWorkflowExecutorImpl','LobsterEvolutionEngineImpl') SemanticTakeoverDetector = @('DynamicNodeAdjusterImpl','LobsterInboundReplyOrchestrator') OutputQualityChecker = @('DynamicNodeExecutorImpl') MultiModelWorkflowGenerator = @('LobsterIntegrationTestServiceImpl','LobsterAdminController') PendingAuditKnowledgeService = @('TenantLearningEngineImpl','LobsterLearningPersistenceService') ProfileEnrichmentService = @('LobsterEvolutionEngineImpl') QualityScoreRuleEngine = @('QualityScoringServiceImpl') DuplicateReplyDetector = @('LobsterWorkflowExecutorImpl') FactDecayScheduler = @('Spring 定时调度') LobsterBillingServiceImpl = @('LobsterAdminController','LobsterPlatformAdminController','LobsterTokenStatsController') LobsterIntegrationTestServiceImpl = @('LobsterEngineController','LobsterAdminController') WorkflowTemplateAdminServiceImpl = @('LobsterAdminController') ILobsterSalesCorpusService = @('LobsterAdminController','LobsterSalesCorpusController','LobsterPlatformAdminController') ILobsterEvolutionSuggestionService = @('LobsterAdminController') ILobsterInstanceStatsService = @('LobsterAdminController') ILobsterPromptService = @('LobsterPromptController') LobsterModelConfigService = @('LobsterAdminController','LobsterModelRouteController') LobsterNodeTypeService = @('LobsterIntegrationTestServiceImpl','DynamicNodeExecutorImpl') LobsterTestScenarioService = @('LobsterE2eController','LobsterAdminController') DynamicNodeImplService = @('LobsterE2eController','LobsterAdminController') INodePromptService = @('WorkflowTemplateAdminServiceImpl') ILobsterEventAuditService = @('LobsterEventAuditController','LobsterAdminController') ILobsterConversationSummaryService = @('LobsterAdminController') ILobsterLearningCorpusService = @('LobsterAdminController') } function Get-Callers([string]$ClassName) { $keys = @($ClassName, ($ClassName -replace 'Impl$','')) if (-not $keys[1].StartsWith('I')) { $keys += 'I' + $keys[1] } foreach ($k in $keys) { if ($Callers.ContainsKey($k)) { return $Callers[$k] } } return @('Spring 容器注入调用') } function Format-Callers([string[]]$list) { return (($list | ForEach-Object { "{@code $_}" }) -join '、') } function Parse-InterfaceMethods([string]$ClassName) { $iface = $ClassName -replace 'Impl$','' $files = @( (Join-Path $WorkflowDir "$iface.java"), (Join-Path $WorkflowDir "I$iface.java") ) $methods = @{} foreach ($f in $files) { if (-not (Test-Path $f)) { continue } $text = [System.IO.File]::ReadAllText($f, $utf8) $matches = [regex]::Matches($text, '/\*\*([\s\S]*?)\*/\s*(?:@[\w.]+\s*)*[\w<>,\[\]\s.?]+\s+(\w+)\s*\([^)]*\)\s*;') foreach ($m in $matches) { $lines = $m.Groups[1].Value -split "`n" | ForEach-Object { $_ -replace '^\s*\*\s?','' } | Where-Object { $_ -and $_ -notmatch '^\s*@(param|return)' } if ($lines.Count -gt 0) { $methods[$m.Groups[2].Value] = $lines[0].Trim() } } } return $methods } function Method-Purpose([string]$ClassName, [string]$MethodName, $ifaceMethods) { if ($ifaceMethods.ContainsKey($MethodName)) { return $ifaceMethods[$MethodName] } $map = @{ init='初始化组件(注册 handler、加载缓存等)。' evolve='执行单轮对话进化流水线,生成 AI 回复及下一节点。' enrichWithDynamicNode='AI 动态生成并插入个性化工作流节点。' learnCustomerHabit='从本轮交互学习客户沟通习惯并写入 habit 表。' startWorkflow='启动新的工作流实例并执行首节点。' executeNextNode='接收客户回复并推进工作流到下一节点。' execute='执行指定类型的动态节点 handler。' processDialogue='处理多轮对话节点的一轮交互。' scoreWithRetry='质量评分并在不达标时带反馈重生成。' filterSensitiveWords='过滤文本中的敏感词并替换。' enrichProfile='多渠道融合 CRM/标签/交互数据并写入用户画像表。' detectTakeover='检测客户是否要求转人工接管。' detectAITransfer='检测 AI 是否应主动转接人工。' cleanupExpiredFacts='定时清理过期事实与习惯数据。' } if ($map.ContainsKey($MethodName)) { return $map[$MethodName] } if ($MethodName.StartsWith('get') -and $MethodName.Length -gt 3) { return "获取$($MethodName.Substring(3))。" } if ($MethodName.StartsWith('is') -and $MethodName.Length -gt 2) { return "判断是否$($MethodName.Substring(2))。" } if ($MethodName.StartsWith('list')) { return "查询$($MethodName.Substring(4))列表。" } return "$MethodName 的公共入口。" } function Has-JavadocBefore { param([Parameter(Mandatory)][AllowEmptyCollection()][string[]]$Lines, [Parameter(Mandatory)][int]$Idx) if ($null -eq $Lines -or $Lines.Count -eq 0 -or $Idx -le 0) { return $false } $j = $Idx - 1 while ($j -ge 0 -and $Lines[$j].Trim() -eq '') { $j-- } if ($j -ge 0 -and $Lines[$j].Trim().EndsWith('*/')) { return $true } return $false } function Has-CallerInJavadoc { param([Parameter(Mandatory)][AllowEmptyCollection()][string[]]$Lines, [Parameter(Mandatory)][int]$Idx) if ($null -eq $Lines -or $Lines.Count -eq 0 -or $Idx -le 0) { return $false } $j = $Idx - 1 while ($j -ge 0) { $t = $Lines[$j].Trim() if ($t.StartsWith('/**')) { break } if ($t.Contains($CallerLabel)) { return $true } $j-- } return $false } function Make-MethodDoc([string]$ClassName, [string]$MethodName, $ifaceMethods, [string]$indent) { $purpose = Method-Purpose $ClassName $MethodName $ifaceMethods $callers = Format-Callers (Get-Callers $ClassName) return @( "$indent/**", "$indent * $purpose", "$indent *
${CallerLabel}:$callers。", "$indent */" ) } function Make-ClassDoc([string]$ClassName) { $desc = if ($ClassDesc.ContainsKey($ClassName)) { $ClassDesc[$ClassName] } else { "$ClassName:workflow impl 包 Spring 服务实现。" } $callers = Format-Callers (Get-Callers $ClassName) return @( '/**', " * $desc", " *
${MainCallerLabel}:$callers。", ' */' ) } function Process-File([string]$FilePath) { $className = [System.IO.Path]::GetFileNameWithoutExtension($FilePath) if ($className -eq 'package-info') { return $false } $lines = [System.Collections.Generic.List[string]]::new() [System.IO.File]::ReadAllLines($FilePath, $utf8) | ForEach-Object { [void]$lines.Add($_) } $ifaceMethods = Parse-InterfaceMethods $className $classIdx = -1 for ($i = 0; $i -lt $lines.Count; $i++) { if ($lines[$i] -match "public\s+(?:final\s+)?class\s+$className\b") { $classIdx = $i; break } } if ($classIdx -lt 0) { return $false } $modified = $false $hasClassDoc = $false $j = $classIdx - 1 while ($j -ge 0 -and ($lines[$j].Trim().StartsWith('@') -or $lines[$j].Trim() -eq '')) { $j-- } if ($j -ge 0 -and ($lines[$j].Trim().StartsWith('/**') -or $lines[$j].Trim().EndsWith('*/'))) { $hasClassDoc = $true } $lineArr = @($lines.ToArray()) if (-not $hasClassDoc) { $insertAt = $classIdx while ($insertAt -gt 0 -and ($lines[$insertAt-1].Trim().StartsWith('@') -or $lines[$insertAt-1].Trim() -eq '')) { $insertAt-- } $doc = Make-ClassDoc $className for ($d = $doc.Count - 1; $d -ge 0; $d--) { $lines.Insert($insertAt, $doc[$d]) } $classIdx += $doc.Count $modified = $true } elseif (-not (Has-CallerInJavadoc -Lines $lineArr -Idx $classIdx)) { $j = $classIdx - 1 while ($j -ge 0 -and ($lines[$j].Trim().StartsWith('@') -or $lines[$j].Trim() -eq '')) { $j-- } if ($j -ge 0 -and $lines[$j].Trim() -eq '*/') { $callers = Format-Callers (Get-Callers $className) $lines.Insert($j, " *
${MainCallerLabel}:$callers。") $modified = $true } } $lineArr = @($lines.ToArray()) $out = [System.Collections.Generic.List[string]]::new() $skipUntil = -1 for ($i = 0; $i -lt $lines.Count; $i++) { if ($i -le $skipUntil) { continue } $line = $lines[$i] $stripped = $line.Trim() if ($stripped -eq '@Override' -and ($i+1) -lt $lines.Count -and $lines[$i+1].Trim() -match '^public\s+') { if (-not (Has-JavadocBefore -Lines $lineArr -Idx $i)) { $mm = [regex]::Match($lines[$i+1], '\b(\w+)\s*\(') if ($mm.Success) { $indent = if ($line -match '^(\s*)') { $Matches[1] } else { ' ' } Make-MethodDoc $className $mm.Groups[1].Value $ifaceMethods $indent | ForEach-Object { [void]$out.Add($_) } $modified = $true } } elseif (-not (Has-CallerInJavadoc -Lines $lineArr -Idx $i)) { $j = $i - 1 while ($j -ge 0 -and $lines[$j].Trim() -ne '*/') { $j-- } if ($j -ge 0) { $indent = if ($lines[$j] -match '^(\s*)') { $Matches[1] } else { ' ' } $callers = Format-Callers (Get-Callers $className) [void]$out.Insert($out.Count, "$indent *
${CallerLabel}:$callers。") $modified = $true } } [void]$out.Add($line) continue } if ($stripped -match '^public\s+(?!class\b|interface\b|enum\b|static\s+class\b)' -and -not $stripped.StartsWith('@')) { if (-not (Has-JavadocBefore -Lines $lineArr -Idx $i)) { $combined = $stripped $k = $i while ($combined -notmatch '[;{]' -and $k+1 -lt $lines.Count) { $k++; $combined += ' ' + $lines[$k].Trim() } $mm = [regex]::Match($combined, '\b(\w+)\s*\(') if ($mm.Success -and $mm.Groups[1].Value -notin @('if','for','while','switch','catch')) { $indent = if ($line -match '^(\s*)') { $Matches[1] } else { ' ' } Make-MethodDoc $className $mm.Groups[1].Value $ifaceMethods $indent | ForEach-Object { [void]$out.Add($_) } $modified = $true } } elseif (-not (Has-CallerInJavadoc -Lines $lineArr -Idx $i)) { $j = $i - 1 while ($j -ge 0 -and $lines[$j].Trim() -ne '*/') { $j-- } if ($j -ge 0) { $indent = if ($lines[$j] -match '^(\s*)') { $Matches[1] } else { ' ' } $callers = Format-Callers (Get-Callers $className) [void]$out.Insert($out.Count, "$indent *
${CallerLabel}:$callers。") $modified = $true } } } [void]$out.Add($line) } if ($modified) { [System.IO.File]::WriteAllLines($FilePath, $out, $utf8) } return $modified } $modified = @() if ($MyInvocation.InvocationName -ne '.') { Get-ChildItem $ImplDir -Filter *.java | Sort-Object Name | ForEach-Object { if (Process-File $_.FullName) { $modified += $_.Name Write-Host "MODIFIED: $($_.Name)" } else { Write-Host "SKIP: $($_.Name)" } } Write-Host "Total modified: $($modified.Count)" }