@ohos-cpf/3rdloop 0.0.1

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 (389) hide show
  1. package/README.md +425 -0
  2. package/bin/3rdloop.mjs +48 -0
  3. package/lib/cli.js +741 -0
  4. package/lib/config.js +318 -0
  5. package/lib/doctor.js +114 -0
  6. package/lib/exit-codes.js +31 -0
  7. package/lib/opencode.js +156 -0
  8. package/lib/orch.js +427 -0
  9. package/lib/queries.js +264 -0
  10. package/lib/runner.js +979 -0
  11. package/lib/step.js +326 -0
  12. package/lib/ui.js +223 -0
  13. package/lib/workflow.js +291 -0
  14. package/lib/workflows.js +132 -0
  15. package/package.json +50 -0
  16. package/vendor/Server/Agent/SkillSelector/README.md +344 -0
  17. package/vendor/Server/Agent/SkillSelector/core/Agent.js +207 -0
  18. package/vendor/Server/Agent/SkillSelector/index.js +14 -0
  19. package/vendor/Server/Agent/SkillSelector/llm/llmClient.js +313 -0
  20. package/vendor/Server/Agent/SkillSelector/llm/prompts.js +161 -0
  21. package/vendor/Server/Agent/SkillSelector/llm/reactSteps.js +144 -0
  22. package/vendor/Server/Agent/SkillSelector/matcher/fuzzyMatcher.js +433 -0
  23. package/vendor/Server/Agent/SkillSelector/scanner/skillScanner.js +382 -0
  24. package/vendor/Server/Agent/SkillSelector/types.js +63 -0
  25. package/vendor/Server/Agent/SkillSelector/utils/actionWords.js +60 -0
  26. package/vendor/Server/Brain/AnalysisStrategies.js +422 -0
  27. package/vendor/Server/Brain/Brain.js +686 -0
  28. package/vendor/Server/Brain/DecompositionStrategies.js +621 -0
  29. package/vendor/Server/Brain/PlanPersistence.js +196 -0
  30. package/vendor/Server/Brain/SkillExecutor.js +251 -0
  31. package/vendor/Server/Brain/index.js +11 -0
  32. package/vendor/Server/CLI/cli.js +243 -0
  33. package/vendor/Server/CLI/opencode/index.js +804 -0
  34. package/vendor/Server/CLI/opencode.js +5 -0
  35. package/vendor/Server/DbUse/MessageArchive.js +61 -0
  36. package/vendor/Server/DbUse/StorageManager.js +107 -0
  37. package/vendor/Server/DbUse/adapters/BaseAdapter.js +94 -0
  38. package/vendor/Server/DbUse/adapters/FileAdapter.js +138 -0
  39. package/vendor/Server/DbUse/adapters/JsonAdapter.js +138 -0
  40. package/vendor/Server/DbUse/adapters/JsonlAdapter.js +114 -0
  41. package/vendor/Server/DbUse/adapters/SqliteAdapter.js +157 -0
  42. package/vendor/Server/DbUse/index.js +160 -0
  43. package/vendor/Server/DbUse/stores/SessionStore.js +279 -0
  44. package/vendor/Server/DbUse/stores/TaskExecutionStore.js +133 -0
  45. package/vendor/Server/DbUse/stores/TaskRegistryStore.js +262 -0
  46. package/vendor/Server/DbUse/stores/TaskStepStore.js +279 -0
  47. package/vendor/Server/FlexRunner/FlexRunner.js +1759 -0
  48. package/vendor/Server/FlexRunner/index.js +12 -0
  49. package/vendor/Server/Knowledge/KnowledgeImporter.js +523 -0
  50. package/vendor/Server/Knowledge/KnowledgeManager.js +341 -0
  51. package/vendor/Server/Knowledge/index.js +33 -0
  52. package/vendor/Server/LoopEngine/LoopEngine.js +1133 -0
  53. package/vendor/Server/LoopEngine/index.js +11 -0
  54. package/vendor/Server/Orchestrator/Orchestrator.js +1425 -0
  55. package/vendor/Server/Orchestrator/StepNode.js +312 -0
  56. package/vendor/Server/Orchestrator/index.js +13 -0
  57. package/vendor/Server/Routes/controllers/BrainController.js +241 -0
  58. package/vendor/Server/Routes/controllers/FlexRunnerController.js +1125 -0
  59. package/vendor/Server/Routes/controllers/HealthController.js +44 -0
  60. package/vendor/Server/Routes/controllers/KnowledgeImportController.js +355 -0
  61. package/vendor/Server/Routes/controllers/LoopEngineController.js +788 -0
  62. package/vendor/Server/Routes/controllers/OrchestratorController.js +911 -0
  63. package/vendor/Server/Routes/controllers/StatsController.js +57 -0
  64. package/vendor/Server/Routes/controllers/StreamController.js +67 -0
  65. package/vendor/Server/Routes/library/logger.js +179 -0
  66. package/vendor/Server/Routes/library/zipArchive.js +172 -0
  67. package/vendor/Server/Routes/router/Router.js +204 -0
  68. package/vendor/Server/Routes/routes/brain.js +47 -0
  69. package/vendor/Server/Routes/routes/flexrunner.js +72 -0
  70. package/vendor/Server/Routes/routes/health.js +28 -0
  71. package/vendor/Server/Routes/routes/index.js +57 -0
  72. package/vendor/Server/Routes/routes/knowledge.js +55 -0
  73. package/vendor/Server/Routes/routes/loopengine.js +58 -0
  74. package/vendor/Server/Routes/routes/orchestrator.js +61 -0
  75. package/vendor/Server/Routes/routes/registry.js +98 -0
  76. package/vendor/Server/Routes/routes/stats.js +23 -0
  77. package/vendor/Server/Routes/routes/stream.js +30 -0
  78. package/vendor/Server/Routes/server.js +202 -0
  79. package/vendor/Server/Routes/sse/SseHub.js +308 -0
  80. package/vendor/Server/Skills/acceptance-check/SKILL.md +174 -0
  81. package/vendor/Server/Skills/acceptance-check/references/PHASE1_ARTIFACT_COLLECTION.md +52 -0
  82. package/vendor/Server/Skills/acceptance-check/references/PHASE2_CRITERIA_EVALUATION.md +77 -0
  83. package/vendor/Server/Skills/arkts-code-check/SKILL.md +314 -0
  84. package/vendor/Server/Skills/arkts-code-check/references/CODE_CHECK_GUIDE.md +160 -0
  85. package/vendor/Server/Skills/arkts-code-check/references/FILE_TYPE_GUIDE.md +29 -0
  86. package/vendor/Server/Skills/arkts-code-check/references/PHASE1_INFO_COLLECTION.md +222 -0
  87. package/vendor/Server/Skills/arkts-code-check/references/REPORT_TEMPLATE.md +220 -0
  88. package/vendor/Server/Skills/arkts-library-compile-validate/SKILL.md +329 -0
  89. package/vendor/Server/Skills/arkts-library-compile-validate/scripts/build.ps1 +93 -0
  90. package/vendor/Server/Skills/arkts-library-compile-validate/scripts/code-linter.cjs +433 -0
  91. package/vendor/Server/Skills/arkts-library-compile-validate/scripts/migrate.cjs +851 -0
  92. package/vendor/Server/Skills/arkts-library-compile-validate/scripts/ohpm-switch.cjs +789 -0
  93. package/vendor/Server/Skills/arkts-library-demo-code/SKILL.md +291 -0
  94. package/vendor/Server/Skills/arkts-library-demo-code/references/API_SIGNATURE_CHECKS.md +68 -0
  95. package/vendor/Server/Skills/arkts-library-demo-code/references/BUILD_VALIDATION.md +184 -0
  96. package/vendor/Server/Skills/arkts-library-demo-code/references/CODE_STANDARDS.md +337 -0
  97. package/vendor/Server/Skills/arkts-library-demo-code/references/EXAMPLES.md +400 -0
  98. package/vendor/Server/Skills/arkts-library-demo-code/references/SYSTEM_API_LOOKUP.md +99 -0
  99. package/vendor/Server/Skills/arkts-library-demo-code/references/TEMPLATE.md +544 -0
  100. package/vendor/Server/Skills/arkts-library-demo-code/scripts/build.ps1 +93 -0
  101. package/vendor/Server/Skills/arkts-library-demo-code/scripts/code-linter.cjs +433 -0
  102. package/vendor/Server/Skills/arkts-library-demo-code/scripts/migrate.cjs +851 -0
  103. package/vendor/Server/Skills/arkts-library-demo-code/scripts/ohpm-switch.cjs +789 -0
  104. package/vendor/Server/Skills/arkts-library-demo-coverage/SKILL.md +174 -0
  105. package/vendor/Server/Skills/arkts-library-demo-scenario/SKILL.md +321 -0
  106. package/vendor/Server/Skills/arkts-library-demo-scenario/references/EXAMPLES.md +100 -0
  107. package/vendor/Server/Skills/arkts-library-demo-scenario/references/TEMPLATE.md +185 -0
  108. package/vendor/Server/Skills/arkts-library-documentation-quality-check/SKILL.md +234 -0
  109. package/vendor/Server/Skills/arkts-library-documentation-quality-check/assets/REPORT_TEMPLATE.md +103 -0
  110. package/vendor/Server/Skills/arkts-library-documentation-quality-check/references/CHECK_DIMENSIONS.md +89 -0
  111. package/vendor/Server/Skills/arkts-library-documentation-quality-check/references/COMPLIANCE_CHECKLIST.md +62 -0
  112. package/vendor/Server/Skills/arkts-library-documentation-quality-check/references/KB_QUERY_GUIDE.md +108 -0
  113. package/vendor/Server/Skills/arkts-library-documentation-quality-check/references/MCP_TOOL_DISCOVERY.md +124 -0
  114. package/vendor/Server/Skills/arkts-library-documentation-quality-check/references/REPORT_TEMPLATE.md +90 -0
  115. package/vendor/Server/Skills/arkts-library-documentation-quality-check/references/SCORING_FORMULA.md +57 -0
  116. package/vendor/Server/Skills/arkts-library-documentation-quality-check/scripts/validate-skill.cjs +259 -0
  117. package/vendor/Server/Skills/arkts-library-interface-spec/SKILL.md +97 -0
  118. package/vendor/Server/Skills/arkts-library-memory-leak-check/SKILL.md +392 -0
  119. package/vendor/Server/Skills/arkts-library-source-clone/SKILL.md +113 -0
  120. package/vendor/Server/Skills/arkts-library-stability-check/SKILL.md +313 -0
  121. package/vendor/Server/Skills/arkts-library-stability-check/assets/REPORT_TEMPLATE.md +154 -0
  122. package/vendor/Server/Skills/arkts-library-stability-check/references/CHECKLIST.md +166 -0
  123. package/vendor/Server/Skills/arkts-library-stability-check/references/CODE_EXAMPLES.md +309 -0
  124. package/vendor/Server/Skills/arkts-library-stability-check/references/SCORING_RULES.md +90 -0
  125. package/vendor/Server/Skills/arkts-library-stability-check/scripts/validate-skill.cjs +282 -0
  126. package/vendor/Server/Skills/arkts-library-test-coverage-check/SKILL.md +361 -0
  127. package/vendor/Server/Skills/arkts-library-test-coverage-check/assets/REPORT_TEMPLATE.md +146 -0
  128. package/vendor/Server/Skills/arkts-library-test-coverage-check/references/CHECKLIST.md +253 -0
  129. package/vendor/Server/Skills/arkts-library-test-coverage-check/references/MCP_TOOL_USAGE.md +115 -0
  130. package/vendor/Server/Skills/arkts-library-test-coverage-check/scripts/validate-skill.cjs +263 -0
  131. package/vendor/Server/Skills/arkts-library-xts-code/SKILL.md +455 -0
  132. package/vendor/Server/Skills/arkts-library-xts-code/assets/report-template.md +60 -0
  133. package/vendor/Server/Skills/arkts-library-xts-code/references/ACCESS_MODIFIER_PRECHECK.md +76 -0
  134. package/vendor/Server/Skills/arkts-library-xts-code/references/BUILD_VERIFICATION.md +200 -0
  135. package/vendor/Server/Skills/arkts-library-xts-code/references/CODE_STANDARDS.md +519 -0
  136. package/vendor/Server/Skills/arkts-library-xts-code/references/SUBAGENT_PROMPT_TEMPLATE.md +276 -0
  137. package/vendor/Server/Skills/arkts-library-xts-code/references/SYSTEM_API_LOOKUP.md +93 -0
  138. package/vendor/Server/Skills/arkts-library-xts-code/references/XTS_TEMPLATE.md +767 -0
  139. package/vendor/Server/Skills/arkts-library-xts-code/scripts/build.ps1 +93 -0
  140. package/vendor/Server/Skills/arkts-library-xts-code/scripts/code-linter.cjs +433 -0
  141. package/vendor/Server/Skills/arkts-library-xts-code/scripts/migrate.cjs +851 -0
  142. package/vendor/Server/Skills/arkts-library-xts-code/scripts/ohpm-switch.cjs +789 -0
  143. package/vendor/Server/Skills/arkts-library-xts-code/scripts/precheck-access-modifiers.cjs +221 -0
  144. package/vendor/Server/Skills/arkts-library-xts-code-fix/SKILL.md +229 -0
  145. package/vendor/Server/Skills/arkts-library-xts-coverage/SKILL.md +97 -0
  146. package/vendor/Server/Skills/arkts-library-xts-doc/SKILL.md +194 -0
  147. package/vendor/Server/Skills/arkts-library-xts-doc/references/EXAMPLES.md +576 -0
  148. package/vendor/Server/Skills/arkts-library-xts-doc/references/TEMPLATE.md +575 -0
  149. package/vendor/Server/Skills/arkts-library-xts-doc/references/TESTABILITY_GUIDE.md +182 -0
  150. package/vendor/Server/Skills/arkts-library-xts-execution/SKILL.md +491 -0
  151. package/vendor/Server/Skills/arkts-library-xts-execution/references/error-fixing-examples.md +217 -0
  152. package/vendor/Server/Skills/arkts-library-xts-execution/scripts/build.ps1 +93 -0
  153. package/vendor/Server/Skills/arkts-library-xts-execution/scripts/code-linter.cjs +433 -0
  154. package/vendor/Server/Skills/arkts-library-xts-execution/scripts/migrate.cjs +851 -0
  155. package/vendor/Server/Skills/arkts-library-xts-execution/scripts/ohpm-switch.cjs +789 -0
  156. package/vendor/Server/Skills/flutter-code-check/SKILL.md +299 -0
  157. package/vendor/Server/Skills/flutter-code-check/assets/OUTPUT_TEMPLATE.md +312 -0
  158. package/vendor/Server/Skills/flutter-code-check/references/CHECKLIST.md +190 -0
  159. package/vendor/Server/Skills/flutter-code-check/references/PLATFORMS.md +134 -0
  160. package/vendor/Server/Skills/flutter-code-check/scripts/validate-skill.cjs +259 -0
  161. package/vendor/Server/Skills/flutter-interface/README.md +75 -0
  162. package/vendor/Server/Skills/flutter-interface/SKILL.md +291 -0
  163. package/vendor/Server/Skills/flutter-interface/references/EXAMPLES.md +336 -0
  164. package/vendor/Server/Skills/flutter-interface/references/GIT_CLONE_GUIDE.md +190 -0
  165. package/vendor/Server/Skills/flutter-interface/references/SCRIPT_REFERENCE.md +258 -0
  166. package/vendor/Server/Skills/flutter-interface/references/TEMPLATE.md +254 -0
  167. package/vendor/Server/Skills/flutter-library-consistency-check/SKILL.md +518 -0
  168. package/vendor/Server/Skills/flutter-library-consistency-check/references/CHECKLIST.md +382 -0
  169. package/vendor/Server/Skills/flutter-library-consistency-check/references/FUNCTION_COMPARISON_GUIDE.md +342 -0
  170. package/vendor/Server/Skills/flutter-library-consistency-check/references/PLATFORM_LIMITATION_GUIDE.md +71 -0
  171. package/vendor/Server/Skills/flutter-library-documentation-quality-check/SKILL.md +519 -0
  172. package/vendor/Server/Skills/flutter-library-documentation-quality-check/references/CHECKLIST.md +407 -0
  173. package/vendor/Server/Skills/flutter-library-memory-leak-check/SKILL.md +653 -0
  174. package/vendor/Server/Skills/flutter-library-memory-leak-check/references/CHECKLIST.md +397 -0
  175. package/vendor/Server/Skills/flutter-library-stability-check/SKILL.md +745 -0
  176. package/vendor/Server/Skills/flutter-library-stability-check/references/CHECKLIST.md +721 -0
  177. package/vendor/Server/Skills/flutter-library-test-coverage-check/SKILL.md +414 -0
  178. package/vendor/Server/Skills/flutter-library-test-coverage-check/assets/REPORT_TEMPLATE.md +150 -0
  179. package/vendor/Server/Skills/flutter-library-test-coverage-check/references/CHECKLIST.md +304 -0
  180. package/vendor/Server/Skills/flutter-library-test-coverage-check/references/SCORING_RULES.md +265 -0
  181. package/vendor/Server/Skills/flutter-library-test-coverage-check/references/SCRIPT_USAGE.md +286 -0
  182. package/vendor/Server/Skills/knowledge-import/SKILL.md +383 -0
  183. package/vendor/Server/Skills/knowledge-import/references/MCP_TOOL_USAGE.md +165 -0
  184. package/vendor/Server/Skills/knowledge-import/references/SKILL_LOCATOR_GUIDE.md +91 -0
  185. package/vendor/Server/Skills/knowledge-import/references/SKILL_OPTIMIZATION_GUIDE.md +127 -0
  186. package/vendor/Server/Skills/ohos-lib-pr-push/SKILL.md +301 -0
  187. package/vendor/Server/Skills/ohos-lib-pr-push/assets/PR_ISSUE_TEMPLATE.md +105 -0
  188. package/vendor/Server/Skills/ohos-lib-pr-push/references/GITCODE_API.md +127 -0
  189. package/vendor/Server/Skills/ohos-lib-pr-push/scripts/gitcode-api.cjs +208 -0
  190. package/vendor/Server/Skills/rn-code-check/SKILL.md +321 -0
  191. package/vendor/Server/Skills/rn-code-check/references/API-GUIDE.md +235 -0
  192. package/vendor/Server/Skills/rn-code-check/references/CHECKLIST.md +189 -0
  193. package/vendor/Server/Skills/rn-code-check/references/REPORT-TEMPLATE.md +247 -0
  194. package/vendor/Server/Skills/rn-lib-add-example/SKILL.md +198 -0
  195. package/vendor/Server/Skills/rn-lib-add-example/references/APP_RENAME_GUIDE.md +40 -0
  196. package/vendor/Server/Skills/rn-lib-add-example/references/SHELL_ADAPTATION_CHECKLIST.md +78 -0
  197. package/vendor/Server/Skills/rn-lib-add-example/references/TEMPLATE_REPO_GUIDE.md +70 -0
  198. package/vendor/Server/Skills/rn-lib-add-example/references/VERIFICATION_GUIDE.md +47 -0
  199. package/vendor/Server/Skills/rn-lib-add-example/scripts/create-example.cjs +252 -0
  200. package/vendor/Server/Skills/rn-lib-update-doc/SKILL.md +176 -0
  201. package/vendor/Server/Skills/rn-lib-update-doc/config.json +5 -0
  202. package/vendor/Server/Skills/rn-lib-update-doc/references/changelog-template.md +35 -0
  203. package/vendor/Server/Skills/rn-lib-update-doc/references/format-diff.md +137 -0
  204. package/vendor/Server/Skills/rn-lib-update-doc/references/link-registry.json +33 -0
  205. package/vendor/Server/Skills/rn-lib-update-doc/references/model-0.4.2-overview.md +40 -0
  206. package/vendor/Server/Skills/rn-lib-update-doc/references/model-0.4.2.md +429 -0
  207. package/vendor/Server/Skills/rn-lib-update-doc/scripts/detect-readme-format.cjs +105 -0
  208. package/vendor/Server/Skills/rn-lib-update-doc/scripts/find-usage-doc.cjs +90 -0
  209. package/vendor/Server/Skills/rn-lib-update-doc/scripts/link-verify.cjs +213 -0
  210. package/vendor/Server/Skills/rn-lib-update-doc/scripts/normalize-changelog.cjs +73 -0
  211. package/vendor/Server/Skills/rn-lib-update-doc/scripts/normalize-package-meta.cjs +258 -0
  212. package/vendor/Server/Skills/rn-lib-update-doc/scripts/normalize-readme-links.cjs +341 -0
  213. package/vendor/Server/Skills/rn-lib-update-doc/scripts/resolve-usage-docs.cjs +67 -0
  214. package/vendor/Server/Skills/rn-library-consistency-check/SKILL.md +299 -0
  215. package/vendor/Server/Skills/rn-library-consistency-check/assets/REPORT_TEMPLATE.md +293 -0
  216. package/vendor/Server/Skills/rn-library-consistency-check/references/ARKTS_COMPONENT_CHECK_GUIDE.md +857 -0
  217. package/vendor/Server/Skills/rn-library-consistency-check/references/ARKTS_TURBOMODULE_CHECK_GUIDE.md +856 -0
  218. package/vendor/Server/Skills/rn-library-consistency-check/references/CHECKLIST.md +157 -0
  219. package/vendor/Server/Skills/rn-library-consistency-check/references/CPP_COMPONENT_CHECK_GUIDE.md +801 -0
  220. package/vendor/Server/Skills/rn-library-consistency-check/references/CPP_TURBOMODULE_CHECK_GUIDE.md +684 -0
  221. package/vendor/Server/Skills/rn-library-consistency-check/references/FUNCTION_COMPARISON_GUIDE.md +233 -0
  222. package/vendor/Server/Skills/rn-library-consistency-check/references/NATIVE_COMPONENT_IDENTIFICATION.md +1373 -0
  223. package/vendor/Server/Skills/rn-library-consistency-check/references/SCORING_STANDARD.md +220 -0
  224. package/vendor/Server/Skills/rn-library-consistency-check/scripts/validate-skill.py +245 -0
  225. package/vendor/Server/Skills/rn-library-documentation-quality-check/SKILL.md +263 -0
  226. package/vendor/Server/Skills/rn-library-documentation-quality-check/assets/MODEL.md +414 -0
  227. package/vendor/Server/Skills/rn-library-documentation-quality-check/assets/MODEL_en.md +413 -0
  228. package/vendor/Server/Skills/rn-library-documentation-quality-check/assets/REPORT_TEMPLATE.md +311 -0
  229. package/vendor/Server/Skills/rn-library-documentation-quality-check/references/CHECK_CHECKLIST.md +355 -0
  230. package/vendor/Server/Skills/rn-library-documentation-quality-check/references/CROSS_VALIDATION_GUIDE.md +115 -0
  231. package/vendor/Server/Skills/rn-library-documentation-quality-check/references/DOC_COLLECTION_GUIDE.md +139 -0
  232. package/vendor/Server/Skills/rn-library-documentation-quality-check/references/EXAMPLES.md +586 -0
  233. package/vendor/Server/Skills/rn-library-documentation-quality-check/references/GOTCHAS.md +57 -0
  234. package/vendor/Server/Skills/rn-library-documentation-quality-check/scripts/validate-skill.py +259 -0
  235. package/vendor/Server/Skills/rn-library-interface-analyzer/SKILL.md +301 -0
  236. package/vendor/Server/Skills/rn-library-interface-analyzer/assets/REPORT_TEMPLATE.md +148 -0
  237. package/vendor/Server/Skills/rn-library-interface-analyzer/references/DOC_ANNOTATION_GUIDE.md +118 -0
  238. package/vendor/Server/Skills/rn-library-interface-analyzer/references/SCRIPT_USAGE_GUIDE.md +168 -0
  239. package/vendor/Server/Skills/rn-library-interface-analyzer/references/URL_PARSING_RULES.md +176 -0
  240. package/vendor/Server/Skills/rn-library-issue-generalizer/SKILL.md +274 -0
  241. package/vendor/Server/Skills/rn-library-issue-generalizer/assets/case-template.md +45 -0
  242. package/vendor/Server/Skills/rn-library-issue-generalizer/assets/rule-template.md +25 -0
  243. package/vendor/Server/Skills/rn-library-issue-generalizer/references/PR_FETCH_GUIDE.md +61 -0
  244. package/vendor/Server/Skills/rn-library-issue-generalizer/references/RULE_TEMPLATE_GUIDE.md +165 -0
  245. package/vendor/Server/Skills/rn-library-issue-generalizer/scripts/fetch-pr-info.py +239 -0
  246. package/vendor/Server/Skills/rn-library-known-issue-check/SKILL.md +263 -0
  247. package/vendor/Server/Skills/rn-library-known-issue-check/assets/REPORT_TEMPLATE.md +96 -0
  248. package/vendor/Server/Skills/rn-library-known-issue-check/references/COMPLIANCE_CHECKLIST.md +58 -0
  249. package/vendor/Server/Skills/rn-library-known-issue-check/references/INSPECTION_GUIDE.md +99 -0
  250. package/vendor/Server/Skills/rn-library-known-issue-check/references/PRESCREEN_GUIDE.md +64 -0
  251. package/vendor/Server/Skills/rn-library-known-issue-check/references/SOURCE_PREP_GUIDE.md +75 -0
  252. package/vendor/Server/Skills/rn-library-known-issue-check/scripts/validate-known-issue-report.py +164 -0
  253. package/vendor/Server/Skills/rn-library-memory-leak-check/SKILL.md +339 -0
  254. package/vendor/Server/Skills/rn-library-memory-leak-check/assets/REPORT_TEMPLATE.md +83 -0
  255. package/vendor/Server/Skills/rn-library-memory-leak-check/references/CHECKLIST.md +859 -0
  256. package/vendor/Server/Skills/rn-library-memory-leak-check/references/HARMONY_CODE_PATTERNS.md +122 -0
  257. package/vendor/Server/Skills/rn-library-memory-leak-check/scripts/scan_harmony_code.py +279 -0
  258. package/vendor/Server/Skills/rn-library-stability-check/SKILL.md +273 -0
  259. package/vendor/Server/Skills/rn-library-stability-check/assets/REPORT_TEMPLATE.md +129 -0
  260. package/vendor/Server/Skills/rn-library-stability-check/references/CHECKLIST.md +581 -0
  261. package/vendor/Server/Skills/rn-library-stability-check/references/SCORING_RULES.md +138 -0
  262. package/vendor/Server/Skills/rn-library-stability-check/scripts/scan-harmony-code.py +168 -0
  263. package/vendor/Server/Skills/rn-library-test-coverage-check/SKILL.md +506 -0
  264. package/vendor/Server/Skills/rn-library-test-coverage-check/references/CHECKLIST.md +280 -0
  265. package/vendor/Server/Skills/rn-library-test-coverage-check/references/DEMO_LOCATION.md +221 -0
  266. package/vendor/Server/Skills/rn-library-test-coverage-check/references/REPORT_TEMPLATE.md +209 -0
  267. package/vendor/Server/Skills/rn-library-test-coverage-check/references/SCRIPT_USAGE.md +325 -0
  268. package/vendor/Server/Skills/rn-ohos-xts-generator/SKILL.md +279 -0
  269. package/vendor/Server/Skills/rn-ohos-xts-generator/assets/TEST_FILE_TEMPLATES.md +404 -0
  270. package/vendor/Server/Skills/rn-ohos-xts-generator/references/BUILD_TROUBLESHOOTING.md +185 -0
  271. package/vendor/Server/Skills/rn-ohos-xts-generator/references/BUILD_WORKFLOW.md +265 -0
  272. package/vendor/Server/Skills/rn-ohos-xts-generator/references/COMMON_CONFIG.md +189 -0
  273. package/vendor/Server/Skills/rn-ohos-xts-generator/references/CONFIG_GUIDE.md +203 -0
  274. package/vendor/Server/Skills/rn-ohos-xts-generator/references/COVERAGE_ANALYZER.md +147 -0
  275. package/vendor/Server/Skills/rn-ohos-xts-generator/references/DESIGN_DOC_GUIDE.md +148 -0
  276. package/vendor/Server/Skills/rn-ohos-xts-generator/references/GENERATION_FLOW.md +165 -0
  277. package/vendor/Server/Skills/rn-ohos-xts-generator/references/GENERATION_STRATEGY.md +195 -0
  278. package/vendor/Server/Skills/rn-ohos-xts-generator/references/HARMONY_SCANNER.md +249 -0
  279. package/vendor/Server/Skills/rn-ohos-xts-generator/references/JEST_FRAMEWORK.md +235 -0
  280. package/vendor/Server/Skills/rn-ohos-xts-generator/references/PLATFORM_COMPAT.md +161 -0
  281. package/vendor/Server/Skills/rn-ohos-xts-generator/references/RN_TEST_PATTERNS.md +413 -0
  282. package/vendor/Server/Skills/rn-ohos-xts-generator/references/SOURCE_PARSER.md +235 -0
  283. package/vendor/Server/Skills/rn-ohos-xts-generator/references/TEST_CONVENTIONS.md +245 -0
  284. package/vendor/Server/Skills/rn-ohos-xts-generator/references/TROUBLESHOOTING.md +282 -0
  285. package/vendor/Server/Skills/rn-ohos-xts-generator/references/USAGE_GUIDE.md +251 -0
  286. package/vendor/Server/Skills/rnoh-cptf-api-test/SKILL.md +469 -0
  287. package/vendor/Server/Skills/rnoh-cptf-api-test/assets/CPTF_TEST_TEMPLATE.md +310 -0
  288. package/vendor/Server/Skills/rnoh-cptf-api-test/assets/DEMO_PAGE_TEMPLATE.md +303 -0
  289. package/vendor/Server/Skills/rnoh-cptf-api-test/references/CPTF_TEST_GENERATION_GUIDE.md +421 -0
  290. package/vendor/Server/Skills/rnoh-cptf-api-test/references/DEMO_GENERATION_GUIDE.md +358 -0
  291. package/vendor/Server/Skills/rnoh-cptf-api-test/references/QUALITY_CHECKLIST.md +114 -0
  292. package/vendor/Server/Skills/rnoh-cptf-api-test/references/SPEC_PARSING_GUIDE.md +274 -0
  293. package/vendor/Server/Skills/rnoh-cptf-api-test/scripts/validate-rnoh-cptf-api-test.sh +185 -0
  294. package/vendor/Server/Skills/rnoh-cptf-demo-test/SKILL.md +191 -0
  295. package/vendor/Server/Skills/rnoh-cptf-demo-test/assets/TEST_TEMPLATE.md +216 -0
  296. package/vendor/Server/Skills/rnoh-cptf-demo-test/references/CPTF_SETUP.md +107 -0
  297. package/vendor/Server/Skills/rnoh-cptf-demo-test/references/DEMO_ANALYSIS.md +120 -0
  298. package/vendor/Server/Skills/rnoh-cptf-demo-test/scripts/validate-rnoh-cptf-test.sh +108 -0
  299. package/vendor/Server/Skills/rnoh-cptf-test-run/SKILL.md +237 -0
  300. package/vendor/Server/Skills/rnoh-cptf-test-run/references/DEBUG_PLAYBOOK.md +261 -0
  301. package/vendor/Server/Skills/rnoh-cptf-test-run/scripts/validate-run-env.sh +112 -0
  302. package/vendor/Server/Skills/rnoh-lib-code-adapt/SKILL.md +498 -0
  303. package/vendor/Server/Skills/rnoh-lib-code-adapt/references/adapt-checklist.md +270 -0
  304. package/vendor/Server/Skills/rnoh-lib-code-adapt/references/api-migration-checklist.md +164 -0
  305. package/vendor/Server/Skills/rnoh-lib-code-adapt/references/common-compile-errors.md +556 -0
  306. package/vendor/Server/Skills/rnoh-lib-code-adapt/references/deveco-cli-tools.md +459 -0
  307. package/vendor/Server/Skills/rnoh-lib-code-adapt/references/edge-cases.md +65 -0
  308. package/vendor/Server/Skills/rnoh-lib-code-adapt/references/har-tgz-build.md +512 -0
  309. package/vendor/Server/Skills/rnoh-lib-code-adapt/references/version-compat-matrix.md +132 -0
  310. package/vendor/Server/Skills/rnoh-lib-code-adapt/scripts/auto-integrate.sh +424 -0
  311. package/vendor/Server/Skills/rnoh-lib-demo-coverage/SKILL.md +137 -0
  312. package/vendor/Server/Skills/rnoh-lib-demo-create/SKILL.md +306 -0
  313. package/vendor/Server/Skills/rnoh-lib-demo-create/assets/DEMO_PAGE_TEMPLATE.md +485 -0
  314. package/vendor/Server/Skills/rnoh-lib-demo-create/assets/INDEX_TEMPLATE.md +172 -0
  315. package/vendor/Server/Skills/rnoh-lib-demo-create/references/DEMO_CODE_RULES.md +422 -0
  316. package/vendor/Server/Skills/rnoh-lib-demo-create/references/QUALITY_CHECKLIST.md +95 -0
  317. package/vendor/Server/Skills/rnoh-lib-demo-create/references/SOURCE_EXPLORATION.md +169 -0
  318. package/vendor/Server/Skills/rnoh-lib-demo-doc/SKILL.md +554 -0
  319. package/vendor/Server/Skills/rnoh-lib-demo-doc/assets/DEMO_DOC_TEMPLATE.md +106 -0
  320. package/vendor/Server/Skills/rnoh-lib-demo-doc/references/COVERAGE_INCREMENTAL.md +216 -0
  321. package/vendor/Server/Skills/rnoh-lib-demo-doc/references/DEMO_DESIGN_RULES.md +413 -0
  322. package/vendor/Server/Skills/rnoh-lib-demo-doc/references/OUTPUT_FORMAT.md +269 -0
  323. package/vendor/Server/Skills/rnoh-lib-demo-doc/references/QUALITY_CHECKLIST.md +98 -0
  324. package/vendor/Server/Skills/rnoh-lib-func-test/SKILL.md +337 -0
  325. package/vendor/Server/Skills/rnoh-lib-rnt-search/SKILL.md +722 -0
  326. package/vendor/Server/Skills/rnoh-lib-rnt-search/assets/PORT_REPORT_TEMPLATE.md +219 -0
  327. package/vendor/Server/Skills/rnoh-lib-rnt-search/references/DEMO_PORTING_GUIDE.md +345 -0
  328. package/vendor/Server/Skills/rnoh-lib-rnt-search/references/PORT_VERIFICATION.md +269 -0
  329. package/vendor/Server/Skills/rnoh-lib-rnt-search/references/RNT_PROJECT_STRUCTURE.md +173 -0
  330. package/vendor/Server/Skills/rnoh-lib-rnt-search/scripts/analyze-demo-deps.cjs +267 -0
  331. package/vendor/Server/Skills/rnoh-lib-rnt-search/scripts/detect-rnoh-version.cjs +174 -0
  332. package/vendor/Server/Skills/rnoh-lib-rnt-search/scripts/find-rnt-demo.sh +111 -0
  333. package/vendor/Server/Skills/rnoh-lib-rnt-search/scripts/port-demo.sh +186 -0
  334. package/vendor/Server/Skills/rnoh-lib-rnt-search/scripts/read-lib-meta.cjs +150 -0
  335. package/vendor/Server/Skills/rnoh-lib-test-align/SKILL.md +296 -0
  336. package/vendor/Server/Skills/rnoh-lib-test-align/references/jest-troubleshooting.md +371 -0
  337. package/vendor/Server/Skills/rnoh-lib-test-align/references/port-test-demo-guide.md +212 -0
  338. package/vendor/Server/Skills/rnoh-lib-test-align/references/runtime-troubleshooting.md +345 -0
  339. package/vendor/Server/Skills/rnoh-lib-test-align/references/unit-test-template.md +223 -0
  340. package/vendor/Server/Skills/rnoh-lib-test-align/scripts/port-test-demo.sh +1053 -0
  341. package/vendor/Server/Skills/rnoh-lib-version-diff/SKILL.md +255 -0
  342. package/vendor/Server/Skills/rnoh-lib-version-diff/references/OHOS_ADAPTATION.md +77 -0
  343. package/vendor/Server/Skills/rnoh-lib-version-diff/references/OHOS_API_LOOKUP.md +224 -0
  344. package/vendor/Server/Skills/rnoh-lib-version-diff/references/script-reference.md +174 -0
  345. package/vendor/Server/Skills/rnoh-lib-version-diff/scripts/detect-upstream-version.js +967 -0
  346. package/vendor/Server/Skills/rnoh-lib-version-diff/scripts/generate-diff.js +1798 -0
  347. package/vendor/Server/Skills/rnoh-lib-version-diff/scripts/package.json +5 -0
  348. package/vendor/Server/Skills/rnoh-lib-version-diff/templates/report-template.md +137 -0
  349. package/vendor/Server/Skills/rnoh-lib-xts-coverage/SKILL.md +145 -0
  350. package/vendor/Server/Skills/skill-generator/SKILL.md +365 -0
  351. package/vendor/Server/Skills/skill-generator/assets/SKILL_TEMPLATE.md +183 -0
  352. package/vendor/Server/Skills/skill-generator/references/COMPLIANCE_CHECKLIST.md +82 -0
  353. package/vendor/Server/Skills/skill-generator/references/KB_QUERY_GUIDE.md +110 -0
  354. package/vendor/Server/Skills/skill-generator/references/MCP_TOOL_DISCOVERY.md +122 -0
  355. package/vendor/Server/Skills/skill-generator/references/SKILL_SPEC.md +121 -0
  356. package/vendor/Server/Skills/skill-generator/scripts/validate-skill.cjs +259 -0
  357. package/vendor/Server/Skills/task-analysis/SKILL.md +234 -0
  358. package/vendor/Server/Skills/task-analysis/assets/OUTPUT_EXAMPLES.md +160 -0
  359. package/vendor/Server/Skills/task-analysis/references/ACCEPTANCE_CRITERIA_GUIDE.md +190 -0
  360. package/vendor/Server/Skills/task-analysis/references/ANALYSIS_SCHEMA.md +224 -0
  361. package/vendor/Server/Skills/task-analysis/references/INTEGRATION_CONTEXT.md +162 -0
  362. package/vendor/Server/Skills/task-analysis/references/LESSONS_LEARNED.md +55 -0
  363. package/vendor/Server/Skills/task-analysis/references/REPLAN_CONTEXT_GUIDE.md +126 -0
  364. package/vendor/Server/Skills/task-analysis/scripts/validate-analysis-output.sh +256 -0
  365. package/vendor/Server/Skills/task-decomposition/SKILL.md +529 -0
  366. package/vendor/Server/Skills/task-decomposition/assets/OUTPUT_EXAMPLES.md +451 -0
  367. package/vendor/Server/Skills/task-decomposition/references/ACCEPTANCE_CRITERIA_GUIDE.md +179 -0
  368. package/vendor/Server/Skills/task-decomposition/references/DEPENDENCY_GRAPH_GUIDE.md +152 -0
  369. package/vendor/Server/Skills/task-decomposition/references/INTEGRATION_CONTEXT.md +175 -0
  370. package/vendor/Server/Skills/task-decomposition/references/REPLAN_CONTEXT_GUIDE.md +195 -0
  371. package/vendor/Server/Skills/task-decomposition/references/TASK_DECOMPOSITION_TEMPLATES.md +226 -0
  372. package/vendor/Server/Skills/task-decomposition/scripts/list-available-skills.cjs +263 -0
  373. package/vendor/Server/Skills/task-decomposition/scripts/skill-blacklist.json +29 -0
  374. package/vendor/Server/Skills/task-decomposition/scripts/validate-decomposition-output.cjs +376 -0
  375. package/vendor/Server/Skills/task-decomposition/scripts/validate-param-consistency.cjs +259 -0
  376. package/vendor/Server/Skills/task-decomposition/scripts/validate-specified-skills.cjs +216 -0
  377. package/vendor/Server/Skills/task-decomposition/scripts/validate-step-graph.cjs +425 -0
  378. package/vendor/Server/Skills/tpc-cpp-check/SKILL.md +427 -0
  379. package/vendor/Server/Skills/tpc-cpp-check/references/CHECKLIST.md +214 -0
  380. package/vendor/Server/Skills/tpc-cpp-check/references/HPKBUILD_GUIDE.md +235 -0
  381. package/vendor/Server/Skills/tpc-cpp-check/references/REPORT_TEMPLATE.md +250 -0
  382. package/vendor/Server/TestCheck/TestCheck.js +775 -0
  383. package/vendor/Server/TestCheck/index.js +11 -0
  384. package/vendor/Server/library/McpToolGuide.js +280 -0
  385. package/vendor/Server/library/StatsService.js +127 -0
  386. package/vendor/Server/library/cstTime.js +16 -0
  387. package/vendor/Server/package.json +17 -0
  388. package/vendor/VERSION +3 -0
  389. package/workflows/pr-check.mjs +106 -0
@@ -0,0 +1,911 @@
1
+ /**
2
+ * OrchestratorController —— 编排器 HTTP 接口控制器
3
+ *
4
+ * 职责:封装 Orchestrator 的 HTTP 接口,供前端进行任务编排和进度查看。
5
+ * 不感知 HTTP 层细节,只接收 RequestContext / ResponseContext。
6
+ *
7
+ * 管理多个 Orchestrator 实例(按 taskId 区分),支持:
8
+ * - 加载任务定义
9
+ * - 启动 / 暂停 / 恢复 / 终止编排
10
+ * - 查询编排进度
11
+ * - 查询步骤执行细节(实时消息 / 会话内容)
12
+ * - 修改未执行步骤的配置
13
+ *
14
+ * 与 FlexRunnerController 的区别:
15
+ * - FlexRunnerController 管理单个步骤的执行
16
+ * - OrchestratorController 管理多步骤的编排调度
17
+ */
18
+
19
+ import path from 'node:path';
20
+ import fs from 'node:fs';
21
+ import { Orchestrator, OrchestratorStatus } from '../../Orchestrator/Orchestrator.js';
22
+ import { StorageManager } from '../../DbUse/index.js';
23
+
24
+ /**
25
+ * OrchestratorController
26
+ */
27
+ class OrchestratorController {
28
+ /**
29
+ * @param {object} [deps] - 共享依赖
30
+ * @param {object} [deps.sseHub] - SseHub 实例
31
+ * @param {object} [deps.storage] - 存储门面
32
+ * @param {function} [deps.flexRunnerFactory] - FlexRunner 工厂(测试用)
33
+ * @param {string} [deps.skillDirectory] - 默认 SKILL 根目录(taskDef 未指定 skillDirectory 时兜底)
34
+ */
35
+ constructor(deps = {}) {
36
+ this.sseHub = deps.sseHub || null;
37
+ this.storage = deps.storage || null;
38
+ this.flexRunnerFactory = deps.flexRunnerFactory || null;
39
+ this.skillDirectory = deps.skillDirectory || '';
40
+
41
+ /** @type {Map<string, Orchestrator>} key = taskId */
42
+ this._orchestrators = new Map();
43
+ }
44
+
45
+ // ─── 辅助方法 ──────────────────────────────────────────────────────
46
+
47
+ /**
48
+ * 获取任务注册表(懒初始化)。
49
+ * @returns {import('../../DbUse/stores/TaskRegistryStore.js').default|null}
50
+ * @private
51
+ */
52
+ _getRegistry() {
53
+ if (!this.storage) return null;
54
+ try {
55
+ return this.storage.taskRegistryStore();
56
+ } catch {
57
+ return null;
58
+ }
59
+ }
60
+
61
+ /**
62
+ * 注册任务摘要到注册表。
63
+ * @param {object} entry
64
+ * @returns {Promise<void>}
65
+ * @private
66
+ */
67
+ async _registerTask(entry) {
68
+ const registry = this._getRegistry();
69
+ if (!registry) return;
70
+ try {
71
+ await registry.upsert(entry);
72
+ } catch (err) {
73
+ console.warn(`[OrchestratorController] 注册任务摘要失败: ${err.message}`);
74
+ }
75
+ }
76
+
77
+ /**
78
+ * 任务终态时回写注册表:status + 结构化指标。
79
+ *
80
+ * metrics 来自步骤的 meta .json 旁车文件(通用键值对,如 mergeLevel / score),
81
+ * 存入 task_registry.metadata JSON 列,后端不解释键语义。
82
+ * 多步骤时合并各步骤 metrics(后完成的覆盖同名字段)。
83
+ *
84
+ * @param {string} taskId
85
+ * @param {Orchestrator} orch - 已到终态的编排器实例
86
+ * @returns {Promise<void>}
87
+ * @private
88
+ */
89
+ async _patchRegistryFinalState(taskId, orch) {
90
+ const registry = this._getRegistry();
91
+ if (!registry) return;
92
+
93
+ const progress = orch.getProgress();
94
+
95
+ // 合并各步骤 metrics(通用键值对,后写覆盖同名)
96
+ let metrics = null;
97
+ for (const s of (progress.steps || [])) {
98
+ if (s.metrics && typeof s.metrics === 'object') {
99
+ metrics = { ...(metrics || {}), ...s.metrics };
100
+ }
101
+ }
102
+
103
+ const patch = { status: progress.status || 'completed' };
104
+ if (metrics) {
105
+ // 与已有 metadata 合并(保留 load 时写入的其他摘要字段,如 stepCount)
106
+ const existing = await registry.get(taskId);
107
+ const existingMeta = existing && existing.metadata && typeof existing.metadata === 'object'
108
+ ? existing.metadata
109
+ : {};
110
+ patch.metadata = { ...existingMeta, ...metrics };
111
+ }
112
+
113
+ await registry.patch(taskId, patch);
114
+ }
115
+
116
+ /**
117
+ * 获取已有实例,不存在则报错。
118
+ */
119
+ _getOrchestrator(taskId) {
120
+ const orch = this._orchestrators.get(taskId);
121
+ if (!orch) {
122
+ throw new Error(`未找到编排任务: taskId=${taskId},请先加载任务`);
123
+ }
124
+ return orch;
125
+ }
126
+
127
+ /**
128
+ * 创建新的 Orchestrator 实例。
129
+ */
130
+ _createOrchestrator() {
131
+ return new Orchestrator({
132
+ sseHub: this.sseHub,
133
+ storage: this.storage,
134
+ flexRunnerFactory: this.flexRunnerFactory
135
+ });
136
+ }
137
+
138
+ /**
139
+ * 释放指定任务编排器持有的重型引用,并(可选)从内存移除编排器实例。
140
+ *
141
+ * 调用 `orch.dispose()` 置空各步骤节点的 `_runner`,使 FlexRunner / CLIController /
142
+ * SkillSelector Agent / LLMClient / Storage 可被 GC 回收。保留磁盘持久化与
143
+ * Orchestrator 的轻量元信息(getProgress / getStepInfo 仍可用)。
144
+ *
145
+ * @param {string} taskId - 任务 ID
146
+ * @param {object} [opts]
147
+ * @param {boolean} [opts.removeInstance=false] - 是否同时从内存 Map 移除编排器实例
148
+ * @returns {boolean} 是否找到并处理了该任务
149
+ */
150
+ disposeOrchestrator(taskId, opts = {}) {
151
+ const { removeInstance = false } = opts;
152
+ const orch = this._orchestrators.get(taskId);
153
+ if (!orch) return false;
154
+
155
+ try {
156
+ orch.dispose();
157
+ } catch (err) {
158
+ console.warn(`[OrchestratorController] dispose 失败: taskId=${taskId}, error=${err.message}`);
159
+ }
160
+
161
+ if (removeInstance) {
162
+ this._orchestrators.delete(taskId);
163
+ }
164
+ return true;
165
+ }
166
+
167
+ // ─── 供 FlexRunnerController 跨域查询 ──────────────────────────────
168
+
169
+ /**
170
+ * 获取编排器中某步骤关联的 FlexRunner 实例。
171
+ *
172
+ * 编排执行时,Orchestrator 在步骤节点上创建 FlexRunner 并挂载到 node._runner。
173
+ * 此方法供 FlexRunnerController 查找由编排器创建(而非通过 /api/flexrunner/init 注册)的实例,
174
+ * 使前端的对话/控制/文件操作能正确路由到编排执行中的实例。
175
+ *
176
+ * @param {string} taskId
177
+ * @param {string|number} stepId
178
+ * @returns {object|null} FlexRunner 实例(可能为 null 表示步骤未执行或已结束且实例未存活)
179
+ */
180
+ getStepRunner(taskId, stepId) {
181
+ let orch;
182
+ try {
183
+ orch = this._getOrchestrator(taskId);
184
+ } catch {
185
+ return null;
186
+ }
187
+ const node = orch.getNode(stepId);
188
+ if (!node) return null;
189
+ return node._runner || null;
190
+ }
191
+
192
+ /**
193
+ * 获取编排器中某步骤的元信息(即使 FlexRunner 实例已不可用)。
194
+ *
195
+ * 用于步骤执行结束后,前端仍能查询到步骤的最终状态、sessionId、resultPath 等。
196
+ *
197
+ * @param {string} taskId
198
+ * @param {string|number} stepId
199
+ * @returns {object|null} 步骤的 JSON 快照
200
+ */
201
+ getStepInfo(taskId, stepId) {
202
+ let orch;
203
+ try {
204
+ orch = this._getOrchestrator(taskId);
205
+ } catch {
206
+ return null;
207
+ }
208
+ const node = orch.getNode(stepId);
209
+ if (!node) return null;
210
+ return node.toJSON();
211
+ }
212
+
213
+ /**
214
+ * 按大循环轮次从磁盘读取历史步骤的元信息。
215
+ *
216
+ * 当用户查看历史轮次的编排详情时,内存中只有最新轮次的编排器实例,
217
+ * 历史轮次的编排状态持久化在 orchestration_loop{N}.json 中。
218
+ * 此方法从磁盘读取对应轮次的编排快照,提取指定 stepId 的步骤信息(含 sessionId)。
219
+ *
220
+ * @param {string} taskId
221
+ * @param {string|number} stepId
222
+ * @param {number} loop - 大循环轮次(0-based)
223
+ * @returns {Promise<object|null>} 步骤的 JSON 快照
224
+ */
225
+ async getStepInfoByLoop(taskId, stepId, loop) {
226
+ if (!this.storage) return null;
227
+ try {
228
+ const state = await this.storage.json('task').read(`${taskId}/orchestration_loop${loop}`);
229
+ if (!state || !Array.isArray(state.steps)) return null;
230
+ const sid = String(stepId);
231
+ return state.steps.find(s => String(s.stepId) === sid) || null;
232
+ } catch (err) {
233
+ console.warn(`[OrchestratorController] 读取轮次步骤信息失败: taskId=${taskId}, loop=${loop}, stepId=${stepId}, ${err.message}`);
234
+ return null;
235
+ }
236
+ }
237
+
238
+ /**
239
+ * 获取编排器中某任务的所有步骤元信息列表。
240
+ *
241
+ * @param {string} taskId
242
+ * @returns {object[]} 步骤 JSON 快照数组(空数组表示任务不存在或无步骤)
243
+ */
244
+ getTaskSteps(taskId) {
245
+ let orch;
246
+ try {
247
+ orch = this._getOrchestrator(taskId);
248
+ } catch {
249
+ return [];
250
+ }
251
+ const progress = orch.getProgress();
252
+ return progress.steps || [];
253
+ }
254
+
255
+ // ─── HTTP Handlers ─────────────────────────────────────────────────
256
+
257
+ /**
258
+ * POST /api/orchestrator/load
259
+ * 加载任务定义 JSON,创建编排器实例
260
+ *
261
+ * Body: {
262
+ * taskId, taskDir, skillDirectory,
263
+ * steps: [{ stepId, taskDescription, dependId, nextStepId, failStepId, maxRetries, ... }]
264
+ * }
265
+ */
266
+ async load(req, res) {
267
+ const body = req.body || {};
268
+ const { taskId } = body;
269
+
270
+ if (!taskId) {
271
+ return res.error(400, 'taskId 为必填项');
272
+ }
273
+ if (!Array.isArray(body.steps) || body.steps.length === 0) {
274
+ return res.error(400, 'steps 为必填项且不能为空');
275
+ }
276
+
277
+ try {
278
+ // 若已存在同 taskId 的实例,先终止旧的
279
+ const existing = this._orchestrators.get(taskId);
280
+ if (existing && existing.status === OrchestratorStatus.RUNNING) {
281
+ await existing.abort();
282
+ }
283
+
284
+ const orch = this._createOrchestrator();
285
+ // taskDef 未指定 skillDirectory 时,用服务端默认 SKILL 根目录兜底
286
+ // (保证 specifiedSkill / SkillSelector 自动匹配有根目录可解析)
287
+ if (!body.skillDirectory && this.skillDirectory) {
288
+ body.skillDirectory = this.skillDirectory;
289
+ }
290
+ await orch.loadTask(body);
291
+
292
+ this._orchestrators.set(taskId, orch);
293
+
294
+ // 注册任务摘要到注册表(SQLite),供历史列表分页查询
295
+ const firstStep = body.steps[0] || {};
296
+ this._registerTask({
297
+ taskId,
298
+ taskType: 'orchestrator',
299
+ status: 'loaded',
300
+ title: (firstStep.taskDescription || body.title || '').slice(0, 200),
301
+ description: body.title || firstStep.taskDescription || '',
302
+ createdAt: new Date().toISOString(),
303
+ metadata: { stepCount: body.steps.length }
304
+ });
305
+
306
+ res.json({
307
+ status: 'ok',
308
+ message: `编排任务已加载: taskId=${taskId}`,
309
+ orchestrator: orch.getProgress()
310
+ });
311
+ } catch (err) {
312
+ res.error(400, err.message);
313
+ }
314
+ }
315
+
316
+ /**
317
+ * POST /api/orchestrator/start
318
+ * 启动编排执行
319
+ *
320
+ * Body: { taskId }
321
+ */
322
+ async start(req, res) {
323
+ const body = req.body || {};
324
+ const { taskId } = body;
325
+
326
+ let orch;
327
+ try {
328
+ orch = this._getOrchestrator(taskId);
329
+ } catch (err) {
330
+ return res.error(404, err.message);
331
+ }
332
+
333
+ if (orch.status !== OrchestratorStatus.LOADED) {
334
+ return res.error(409, `当前状态为 ${orch.status},需先加载任务`);
335
+ }
336
+
337
+ // 异步启动,不阻塞 HTTP 响应
338
+ orch.start()
339
+ .catch(err => {
340
+ console.error(`[OrchestratorController] taskId=${taskId} 执行异常:`, err.message);
341
+ })
342
+ .finally(() => {
343
+ // 终态回写注册表:status + 结构化指标(metrics 存入通用 metadata 列,后端不解释键)
344
+ // 使历史列表一次 SQL 即可拿到真实状态与等级,前端无需逐任务调 progress
345
+ this._patchRegistryFinalState(taskId, orch).catch(err => {
346
+ console.warn(`[OrchestratorController] 注册表终态回写失败: taskId=${taskId}, ${err.message}`);
347
+ });
348
+ });
349
+
350
+ res.json({
351
+ status: 'ok',
352
+ message: `编排任务已启动: taskId=${taskId}`,
353
+ progress: orch.getProgress()
354
+ });
355
+ }
356
+
357
+ /**
358
+ * POST /api/orchestrator/pause
359
+ * 暂停编排执行
360
+ *
361
+ * Body: { taskId }
362
+ */
363
+ async pause(req, res) {
364
+ const body = req.body || {};
365
+ const { taskId } = body;
366
+
367
+ let orch;
368
+ try {
369
+ orch = this._getOrchestrator(taskId);
370
+ } catch (err) {
371
+ return res.error(404, err.message);
372
+ }
373
+
374
+ const ok = await orch.pause();
375
+ res.json({
376
+ status: ok ? 'ok' : 'error',
377
+ message: ok ? '编排已暂停' : '暂停失败(可能未在运行中)',
378
+ progress: orch.getProgress()
379
+ });
380
+ }
381
+
382
+ /**
383
+ * POST /api/orchestrator/resume
384
+ * 恢复编排执行
385
+ *
386
+ * Body: { taskId }
387
+ */
388
+ async resume(req, res) {
389
+ const body = req.body || {};
390
+ const { taskId } = body;
391
+
392
+ let orch;
393
+ try {
394
+ orch = this._getOrchestrator(taskId);
395
+ } catch (err) {
396
+ return res.error(404, err.message);
397
+ }
398
+
399
+ const ok = await orch.resume();
400
+ res.json({
401
+ status: ok ? 'ok' : 'error',
402
+ message: ok ? '编排已恢复' : '恢复失败(可能未在运行中)',
403
+ progress: orch.getProgress()
404
+ });
405
+ }
406
+
407
+ /**
408
+ * POST /api/orchestrator/abort
409
+ * 终止编排执行
410
+ *
411
+ * Body: { taskId }
412
+ */
413
+ async abort(req, res) {
414
+ const body = req.body || {};
415
+ const { taskId } = body;
416
+
417
+ let orch;
418
+ try {
419
+ orch = this._getOrchestrator(taskId);
420
+ } catch (err) {
421
+ return res.error(404, err.message);
422
+ }
423
+
424
+ const ok = await orch.abort();
425
+ res.json({
426
+ status: ok ? 'ok' : 'error',
427
+ message: ok ? '编排已终止' : '终止失败(可能未在运行中)',
428
+ progress: orch.getProgress()
429
+ });
430
+ }
431
+
432
+ /**
433
+ * GET /api/orchestrator/progress?taskId=xxx[&loop=N]
434
+ * 查询编排进度(全部步骤状态汇总)
435
+ *
436
+ * - 不传 loop:返回最新编排状态(内存实例或 orchestration.json 快照)
437
+ * - 传 loop=N:返回第 N 轮编排状态(从 orchestration_loopN.json 读取)
438
+ *
439
+ * 如果内存中没有该任务实例,尝试从磁盘恢复。
440
+ */
441
+ async progress(req, res) {
442
+ const { taskId } = req.query;
443
+ if (!taskId) return res.error(400, 'taskId 为必填项');
444
+
445
+ // ── 指定轮次:从磁盘读取 orchestration_loop{N}.json ──
446
+ const loopParam = req.query.loop;
447
+ if (loopParam != null && loopParam !== '') {
448
+ const loopNum = Number(loopParam);
449
+ if (this.storage) {
450
+ try {
451
+ const state = await this.storage.json('task').read(`${taskId}/orchestration_loop${loopNum}`);
452
+ if (state) {
453
+ return res.json({ status: 'ok', progress: state });
454
+ }
455
+ return res.error(404, `未找到第 ${loopNum} 轮编排状态: taskId=${taskId}`);
456
+ } catch (err) {
457
+ console.warn(`[OrchestratorController] 读取轮次编排状态失败: loop=${loopNum}, ${err.message}`);
458
+ return res.error(404, `未找到第 ${loopNum} 轮编排状态: taskId=${taskId}`);
459
+ }
460
+ }
461
+ return res.error(404, `未找到第 ${loopNum} 轮编排状态: taskId=${taskId}`);
462
+ }
463
+
464
+ // ── 默认:返回最新编排状态 ──
465
+ let orch;
466
+ try {
467
+ orch = this._getOrchestrator(taskId);
468
+ } catch (_) {
469
+ // 内存中不存在,尝试从磁盘恢复(只读响应,不写入内存 Map——
470
+ // 避免前端翻阅大量历史任务时 Orchestrator 实例无限驻留内存)。
471
+ // queryOnly:任务可能是另一进程(如 CLI)正在执行的编排,RUNNING 状态
472
+ // 原样返回,不做"重启中断→FAILED"标记,避免前端误报"检视失败"。
473
+ if (this.storage) {
474
+ try {
475
+ const state = await this.storage.json('task').read(`${taskId}/orchestration`);
476
+ if (state) {
477
+ orch = this._createOrchestrator();
478
+ await orch.restoreState(state, { queryOnly: true });
479
+ }
480
+ } catch (err) {
481
+ console.warn(`[OrchestratorController] 恢复失败: ${err.message}`);
482
+ }
483
+ }
484
+ if (!orch) {
485
+ return res.error(404, `未找到编排任务: taskId=${taskId}`);
486
+ }
487
+ }
488
+
489
+ res.json({
490
+ status: 'ok',
491
+ progress: orch.getProgress()
492
+ });
493
+ }
494
+
495
+ /**
496
+ * GET /api/orchestrator/step-detail?taskId=xxx&stepId=yyy&detailType=live
497
+ * 查询单个步骤的执行细节
498
+ *
499
+ * Query:
500
+ * taskId - 任务 ID
501
+ * stepId - 步骤 ID
502
+ * detailType - 'live' | 'session' | 'status'(默认 live)
503
+ */
504
+ async stepDetail(req, res) {
505
+ const { taskId } = req.query;
506
+ const stepId = req.query.stepId;
507
+ const detailType = req.query.detailType || 'live';
508
+
509
+ if (!taskId || !stepId) {
510
+ return res.error(400, 'taskId 和 stepId 为必填项');
511
+ }
512
+
513
+ let orch;
514
+ try {
515
+ orch = this._getOrchestrator(taskId);
516
+ } catch (err) {
517
+ return res.error(404, err.message);
518
+ }
519
+
520
+ try {
521
+ const detail = await orch.getStepDetail(stepId, detailType);
522
+ res.json({ status: 'ok', detail });
523
+ } catch (err) {
524
+ res.error(404, err.message);
525
+ }
526
+ }
527
+
528
+ /**
529
+ * POST /api/orchestrator/update-step
530
+ * 修改未执行步骤的配置
531
+ *
532
+ * Body: {
533
+ * taskId, stepId,
534
+ * taskDescription?, dependId?, nextStepId?, failStepId?,
535
+ * maxRetries?, skillDirectory?, taskDir?, inputReport?
536
+ * }
537
+ */
538
+ async updateStep(req, res) {
539
+ const body = req.body || {};
540
+ const { taskId, stepId } = body;
541
+
542
+ if (!taskId || stepId == null) {
543
+ return res.error(400, 'taskId 和 stepId 为必填项');
544
+ }
545
+
546
+ let orch;
547
+ try {
548
+ orch = this._getOrchestrator(taskId);
549
+ } catch (err) {
550
+ return res.error(404, err.message);
551
+ }
552
+
553
+ // 提取可修改字段(排除 taskId/stepId)
554
+ const patch = { ...body };
555
+ delete patch.taskId;
556
+ delete patch.stepId;
557
+
558
+ try {
559
+ const ok = orch.updateStepConfig(stepId, patch);
560
+ res.json({
561
+ status: ok ? 'ok' : 'error',
562
+ message: ok
563
+ ? `步骤 ${stepId} 配置已修改`
564
+ : `步骤 ${stepId} 当前状态不允许修改配置`,
565
+ progress: orch.getProgress()
566
+ });
567
+ } catch (err) {
568
+ res.error(400, err.message);
569
+ }
570
+ }
571
+
572
+ /**
573
+ * GET /api/orchestrator/tasks
574
+ * 列出所有编排任务(合并内存实例 + 磁盘持久化记录)
575
+ *
576
+ * Query:
577
+ * page - 页码(默认 1)
578
+ * pageSize - 每页条数(默认 20,最大 100)
579
+ * taskIdPrefix - 可选,按 taskId 前缀过滤(如 'fluttercheck_' / 'codecheck_'),
580
+ * 供各功能面板历史列表独立分页,避免混合任务挤占页容量
581
+ */
582
+ async tasks(req, res) {
583
+ const query = req.query || {};
584
+ const page = Math.max(1, parseInt(query.page, 10) || 1);
585
+ const pageSize = Math.min(100, Math.max(1, parseInt(query.pageSize, 10) || 20));
586
+ const taskIdPrefix = query.taskIdPrefix || null;
587
+
588
+ // ── 优先方案:从注册表分页查询 ──
589
+ const registry = this._getRegistry();
590
+ if (registry) {
591
+ try {
592
+ const result = await registry.listPage({
593
+ page,
594
+ pageSize,
595
+ taskType: 'orchestrator',
596
+ taskIdPrefix
597
+ });
598
+
599
+ // 合并内存中活跃任务的状态
600
+ const mergedTasks = result.tasks.map(t => {
601
+ const orch = this._orchestrators.get(t.task_id);
602
+ if (orch) {
603
+ const progress = orch.getProgress();
604
+ return { ...t, taskId: t.task_id, status: progress.status || t.status };
605
+ }
606
+ return { ...t, taskId: t.task_id };
607
+ });
608
+
609
+ // 第一页补充「活跃但尚未落库」的任务:
610
+ // 仅当任务处于非终态(active: idle/loaded/running)且不在注册表全量 ID 集合中时
611
+ // 才补全。此前用「不在本页 existingIds 中」判断会误把 OFFSET 之外的其他页历史
612
+ // 终态任务(restoreFromDisk 常驻内存)补进首页,导致跨页重复 + 最早任务置顶。
613
+ if (page === 1) {
614
+ const registryIds = new Set(
615
+ await registry.listIds({ taskType: 'orchestrator', taskIdPrefix })
616
+ );
617
+ const activeStatuses = ['idle', 'loaded', 'running'];
618
+ for (const [taskId, orch] of this._orchestrators) {
619
+ if (taskIdPrefix && !taskId.startsWith(taskIdPrefix)) continue;
620
+ const progress = orch.getProgress();
621
+ if (!activeStatuses.includes(progress.status)) continue;
622
+ if (registryIds.has(taskId)) continue;
623
+ mergedTasks.unshift({
624
+ task_id: taskId,
625
+ task_type: 'orchestrator',
626
+ status: progress.status || 'loaded',
627
+ title: (progress.taskDescription || '').slice(0, 200),
628
+ description: progress.taskDescription || '',
629
+ created_at: progress.startTime || new Date().toISOString(),
630
+ metadata: null,
631
+ taskId
632
+ });
633
+ }
634
+ }
635
+
636
+ return res.json({
637
+ status: 'ok',
638
+ tasks: mergedTasks,
639
+ total: result.total,
640
+ page: result.page,
641
+ pageSize: result.pageSize,
642
+ totalPages: result.totalPages
643
+ });
644
+ } catch (err) {
645
+ console.warn('[OrchestratorController] 注册表查询失败,降级到磁盘扫描:', err.message);
646
+ }
647
+ }
648
+
649
+ // ── 降级方案:内存 + 磁盘扫描 ──
650
+ const list = [];
651
+ const seenTaskIds = new Set();
652
+
653
+ for (const orch of this._orchestrators.values()) {
654
+ list.push(orch.getProgress());
655
+ seenTaskIds.add(orch.taskId);
656
+ }
657
+
658
+ if (this.storage) {
659
+ const persistedIds = this._listPersistedTaskIds();
660
+ for (const taskId of persistedIds) {
661
+ if (seenTaskIds.has(taskId)) continue;
662
+ try {
663
+ const state = await this.storage.json('task').read(`${taskId}/orchestration`);
664
+ if (state) {
665
+ list.push(state);
666
+ seenTaskIds.add(taskId);
667
+ }
668
+ } catch (err) {
669
+ console.warn(`[OrchestratorController] 读取任务状态失败: taskId=${taskId}, error=${err.message}`);
670
+ }
671
+ }
672
+ }
673
+
674
+ // 降级也做分页
675
+ list.sort((a, b) => ((b.startTime || '') > (a.startTime || '') ? 1 : -1));
676
+ const total = list.length;
677
+ const totalPages = Math.max(1, Math.ceil(total / pageSize));
678
+ const offset = (page - 1) * pageSize;
679
+ const paged = list.slice(offset, offset + pageSize);
680
+
681
+ res.json({
682
+ status: 'ok',
683
+ tasks: paged,
684
+ total,
685
+ page,
686
+ pageSize,
687
+ totalPages
688
+ });
689
+ }
690
+
691
+ /**
692
+ * DELETE /api/orchestrator/task?taskId=xxx
693
+ * 移除一个编排任务实例(同时删除持久化文件)
694
+ */
695
+ async removeTask(req, res) {
696
+ const { taskId } = req.query;
697
+ const orch = this._orchestrators.get(taskId);
698
+
699
+ // 如果正在运行,先终止
700
+ if (orch && orch.status === OrchestratorStatus.RUNNING) {
701
+ await orch.abort();
702
+ }
703
+
704
+ // 先释放重型引用,再从内存移除
705
+ const existed = this.disposeOrchestrator(taskId, { removeInstance: true });
706
+
707
+ // 同时删除持久化文件
708
+ let diskRemoved = false;
709
+ if (this.storage) {
710
+ try {
711
+ diskRemoved = await this.storage.json('task').delete(`${taskId}/orchestration`);
712
+ } catch (err) {
713
+ console.warn(`[OrchestratorController] 删除持久化文件失败: ${err.message}`);
714
+ }
715
+ }
716
+
717
+ res.json({
718
+ status: 'ok',
719
+ removed: existed || diskRemoved,
720
+ message: (existed || diskRemoved) ? '编排任务已移除' : '任务不存在'
721
+ });
722
+ }
723
+
724
+ // ─── 持久化恢复 ──────────────────────────────────────────────────
725
+
726
+ /**
727
+ * 扫描 db/task/ 目录,列出有 orchestration.json 的 taskId 列表。
728
+ * @returns {string[]}
729
+ * @private
730
+ */
731
+ _listPersistedTaskIds() {
732
+ if (!this.storage) return [];
733
+ try {
734
+ const rootDir = this.storage.manager.rootDir;
735
+ const taskDir = path.join(rootDir, 'task');
736
+ if (!fs.existsSync(taskDir)) return [];
737
+ const entries = fs.readdirSync(taskDir, { withFileTypes: true });
738
+ const ids = [];
739
+ for (const entry of entries) {
740
+ if (entry.isDirectory()) {
741
+ const orchFile = path.join(taskDir, entry.name, 'orchestration.json');
742
+ if (fs.existsSync(orchFile)) {
743
+ ids.push(entry.name);
744
+ }
745
+ }
746
+ }
747
+ return ids;
748
+ } catch (err) {
749
+ console.warn('[OrchestratorController] _listPersistedTaskIds 失败:', err.message);
750
+ return [];
751
+ }
752
+ }
753
+
754
+ /**
755
+ * 从磁盘恢复所有持久化的编排任务到内存。
756
+ *
757
+ * 服务重启时调用。对每个 db/task/{taskId}/orchestration.json:
758
+ * - 创建 Orchestrator 实例并 restoreState
759
+ * - RUNNING 状态会被标记为 FAILED(执行中断)
760
+ * - 其他状态原样恢复
761
+ * - 恢复后回写注册表:进程死亡导致 start().finally() 中的终态回写未执行,
762
+ * registry 停留在 loaded/running 的记录修正为恢复后的终态(含 metrics、
763
+ * interrupted 标记);未入库的老任务补录摘要。
764
+ *
765
+ * @returns {Promise<{restored: string[], failed: string[]}>}
766
+ */
767
+ async restoreFromDisk() {
768
+ const restored = [];
769
+ const failed = [];
770
+
771
+ if (!this.storage) {
772
+ console.warn('[OrchestratorController] storage 未注入,跳过恢复');
773
+ return { restored, failed };
774
+ }
775
+
776
+ const persistedIds = this._listPersistedTaskIds();
777
+ console.log(`[OrchestratorController] 发现 ${persistedIds.length} 个持久化编排任务`);
778
+
779
+ for (const taskId of persistedIds) {
780
+ try {
781
+ const state = await this.storage.json('task').read(`${taskId}/orchestration`);
782
+ if (!state) {
783
+ console.warn(`[OrchestratorController] orchestration.json 为空: taskId=${taskId}`);
784
+ failed.push(taskId);
785
+ continue;
786
+ }
787
+
788
+ const wasRunning = state.status === 'running';
789
+ const orch = this._createOrchestrator();
790
+ await orch.restoreState(state);
791
+ this._orchestrators.set(taskId, orch);
792
+ restored.push(taskId);
793
+
794
+ // 恢复后修正注册表(非终态 → 终态;未入库 → 补录)
795
+ await this._patchRegistryAfterRestore(taskId, orch, state, { wasRunning });
796
+ } catch (err) {
797
+ // JSON 损坏、字段缺失等情况下标记为 failed,不中断其他任务的恢复
798
+ const isJsonError = err instanceof SyntaxError;
799
+ console.error(
800
+ `[OrchestratorController] 恢复失败: taskId=${taskId}, ` +
801
+ `type=${isJsonError ? 'JSON损坏' : '其他错误'}, error=${err.message}`
802
+ );
803
+ failed.push(taskId);
804
+ }
805
+ }
806
+
807
+ return { restored, failed };
808
+ }
809
+
810
+ /**
811
+ * 服务重启恢复后,回写任务注册表。
812
+ *
813
+ * 仅修正"非终态"记录(running/loaded)——进程死亡导致 start().finally() 中
814
+ * 的 _patchRegistryFinalState 未执行,这些记录停留在启动时的状态。
815
+ * 已是终态(completed/failed/aborted/passed/...)的真实历史不覆盖。
816
+ *
817
+ * @param {string} taskId
818
+ * @param {Orchestrator} orch - 恢复后的编排器实例(RUNNING 已转 FAILED)
819
+ * @param {object} state - orchestration.json 原始快照(含 steps[].taskDescription/metrics)
820
+ * @param {object} [opts]
821
+ * @param {boolean} [opts.wasRunning] - 崩溃前是否处于 running 状态
822
+ * @returns {Promise<void>}
823
+ * @private
824
+ */
825
+ async _patchRegistryAfterRestore(taskId, orch, state, opts = {}) {
826
+ const registry = this._getRegistry();
827
+ if (!registry) return;
828
+
829
+ try {
830
+ const existing = await registry.get(taskId);
831
+ // 终态记录是真实历史,不覆盖
832
+ if (existing && !['running', 'loaded'].includes(existing.status)) return;
833
+
834
+ const progress = orch.getProgress();
835
+
836
+ // 合并各步骤 metrics(与 _patchRegistryFinalState 相同语义:后完成覆盖同名)
837
+ let metrics = null;
838
+ for (const s of (progress.steps || [])) {
839
+ if (s.metrics && typeof s.metrics === 'object') {
840
+ metrics = { ...(metrics || {}), ...s.metrics };
841
+ }
842
+ }
843
+
844
+ const existingMeta = existing?.metadata && typeof existing.metadata === 'object'
845
+ ? existing.metadata
846
+ : {};
847
+ const metadata = { ...existingMeta, ...(metrics || {}) };
848
+ if (opts.wasRunning) {
849
+ metadata.interrupted = true;
850
+ metadata.interruptedReason = '服务重启导致执行中断';
851
+ }
852
+
853
+ const status = progress.status || 'failed';
854
+ const firstStep = (state.steps || [])[0] || {};
855
+
856
+ if (!existing) {
857
+ // 老任务未入库(TaskRegistryStore 上线前创建):补录摘要,保留原始创建时间
858
+ await registry.upsert({
859
+ taskId,
860
+ taskType: 'orchestrator',
861
+ status,
862
+ title: (firstStep.taskDescription || taskId).slice(0, 200),
863
+ description: firstStep.taskDescription || '',
864
+ createdAt: state.startTime || new Date().toISOString(),
865
+ metadata
866
+ });
867
+ } else {
868
+ await registry.patch(taskId, { status, metadata });
869
+ }
870
+ console.log(
871
+ `[OrchestratorController] 注册表已修正: taskId=${taskId}, ` +
872
+ `${existing ? existing.status : '(未入库)'} → ${status}`
873
+ );
874
+ } catch (err) {
875
+ console.warn(`[OrchestratorController] 恢复后回写注册表失败: taskId=${taskId}, ${err.message}`);
876
+ }
877
+ }
878
+
879
+ /**
880
+ * GET /api/orchestrator/step-history?taskId=xxx
881
+ * 查询任务的步骤执行历史(SQLite,db/TaskStep/store.db)。
882
+ *
883
+ * 数据来源为 TaskStepStore,每次执行尝试(attempt)一条记录:
884
+ * 含状态流转(running/completed/error)、起止时间、耗时、sessionId、
885
+ * resultPath、metrics 等。服务重启后依然完整可查。
886
+ */
887
+ async stepHistory(req, res) {
888
+ const { taskId } = req.query;
889
+ if (!taskId) {
890
+ return res.error(400, 'taskId 为必填项');
891
+ }
892
+ if (!this.storage) {
893
+ return res.error(500, 'storage 未初始化');
894
+ }
895
+
896
+ try {
897
+ const store = this.storage.taskStepStore();
898
+ const steps = await store.listByTask(taskId);
899
+ res.json({
900
+ status: 'ok',
901
+ taskId,
902
+ total: steps.length,
903
+ steps
904
+ });
905
+ } catch (err) {
906
+ res.error(500, `查询步骤历史失败: ${err.message}`);
907
+ }
908
+ }
909
+ }
910
+
911
+ export default OrchestratorController;