foxclaw 0.1.0 → 0.1.3

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 (514) hide show
  1. package/README.md +54 -29
  2. package/bin/foxclaw.cjs +51 -0
  3. package/index.js +4 -10
  4. package/package.json +46 -38
  5. package/python/.dockerignore +35 -0
  6. package/python/.env.example +173 -0
  7. package/python/.gitattributes +46 -0
  8. package/python/.github/workflows/ci.yml +167 -0
  9. package/python/.github/workflows/release.yml +183 -0
  10. package/python/CHANGELOG.md +57 -0
  11. package/python/CHANGELOG_CN.md +57 -0
  12. package/python/Dockerfile +64 -0
  13. package/python/LICENSE +21 -0
  14. package/python/MANIFEST.in +14 -0
  15. package/python/README.md +201 -0
  16. package/python/README_CN.md +336 -0
  17. package/python/bench/bm25_audit.py +186 -0
  18. package/python/bench/bm25_regression.py +177 -0
  19. package/python/bench/bm25_stress.py +155 -0
  20. package/python/bench/cd_audit.py +215 -0
  21. package/python/bench/chaos.py +140 -0
  22. package/python/bench/concurrency.py +103 -0
  23. package/python/bench/e2e_real_models.py +94 -0
  24. package/python/bench/llm_retry_test.py +241 -0
  25. package/python/bench/load_test.py +193 -0
  26. package/python/bench/vector_ivf_upgrade.py +128 -0
  27. package/python/docs/CHANNELS.md +195 -0
  28. package/python/docs/GOVERNANCE.md +164 -0
  29. package/python/docs/RELEASE.md +110 -0
  30. package/python/docs/RUN.md +75 -0
  31. package/python/docs/RUN_CN.md +121 -0
  32. package/python/docs//351/205/215/347/275/256/346/214/207/345/215/227.md +152 -0
  33. package/python/evals/__init__.py +0 -0
  34. package/python/evals/governance/README.md +61 -0
  35. package/python/evals/governance/__init__.py +0 -0
  36. package/python/evals/governance/cases.py +115 -0
  37. package/python/evals/governance/compare_embeddings.py +94 -0
  38. package/python/evals/governance/convergence.svg +11 -0
  39. package/python/evals/governance/report.json +371 -0
  40. package/python/evals/governance/run_evals.py +368 -0
  41. package/python/examples/governance_middleware_demo.py +72 -0
  42. package/python/examples/langgraph_governance_demo.py +104 -0
  43. package/python/examples/sample_itinerary.csv +6 -0
  44. package/python/examples/sample_knowledge.csv +9 -0
  45. package/python/examples/sample_transactions.csv +14 -0
  46. package/python/foxclaw/__init__.py +408 -0
  47. package/python/foxclaw/agents/__init__.py +12 -0
  48. package/python/foxclaw/agents/agents.py +35 -0
  49. package/python/foxclaw/agents/base.py +794 -0
  50. package/python/foxclaw/agents/impl/__init__.py +1 -0
  51. package/python/foxclaw/agents/impl/_helpers.py +70 -0
  52. package/python/foxclaw/agents/impl/finance.py +231 -0
  53. package/python/foxclaw/agents/impl/office.py +350 -0
  54. package/python/foxclaw/agents/impl/supervisor.py +592 -0
  55. package/python/foxclaw/agents/mixins/_context.py +128 -0
  56. package/python/foxclaw/agents/mixins/augment.py +143 -0
  57. package/python/foxclaw/agents/mixins/llm.py +67 -0
  58. package/python/foxclaw/agents/mixins/memory.py +41 -0
  59. package/python/foxclaw/agents/mixins/preference.py +131 -0
  60. package/python/foxclaw/agents/mixins/prompt.py +71 -0
  61. package/python/foxclaw/agents/mixins/skillbox.py +58 -0
  62. package/python/foxclaw/agents/mixins/tool_exec.py +417 -0
  63. package/python/foxclaw/api/__init__.py +224 -0
  64. package/python/foxclaw/api/_state.py +43 -0
  65. package/python/foxclaw/api/bootstrap.py +96 -0
  66. package/python/foxclaw/api/middleware.py +294 -0
  67. package/python/foxclaw/api/routes/ahs.py +404 -0
  68. package/python/foxclaw/api/routes/attachments.py +116 -0
  69. package/python/foxclaw/api/routes/browser.py +35 -0
  70. package/python/foxclaw/api/routes/domain.py +306 -0
  71. package/python/foxclaw/api/routes/knowledge.py +145 -0
  72. package/python/foxclaw/api/routes/llm_admin.py +449 -0
  73. package/python/foxclaw/api/routes/memory.py +105 -0
  74. package/python/foxclaw/api/routes/orchestration.py +39 -0
  75. package/python/foxclaw/api/routes/recovery.py +44 -0
  76. package/python/foxclaw/api/routes/review.py +266 -0
  77. package/python/foxclaw/api/routes/search.py +33 -0
  78. package/python/foxclaw/api/routes/system.py +311 -0
  79. package/python/foxclaw/api/routes/task.py +263 -0
  80. package/python/foxclaw/api/routes/ws.py +64 -0
  81. package/python/foxclaw/api/spine.py +52 -0
  82. package/python/foxclaw/browser/__init__.py +13 -0
  83. package/python/foxclaw/browser/action/__init__.py +1 -0
  84. package/python/foxclaw/browser/action/action_executor.py +50 -0
  85. package/python/foxclaw/browser/action/action_types.py +44 -0
  86. package/python/foxclaw/browser/action/action_verifier.py +68 -0
  87. package/python/foxclaw/browser/action/url_policy.py +143 -0
  88. package/python/foxclaw/browser/adapter/__init__.py +1 -0
  89. package/python/foxclaw/browser/adapter/base_adapter.py +23 -0
  90. package/python/foxclaw/browser/adapter/web_adapter.py +46 -0
  91. package/python/foxclaw/browser/driver/__init__.py +1 -0
  92. package/python/foxclaw/browser/driver/base_driver.py +61 -0
  93. package/python/foxclaw/browser/driver/playwright_driver.py +170 -0
  94. package/python/foxclaw/browser/perception/__init__.py +1 -0
  95. package/python/foxclaw/browser/perception/dom_extractor.py +42 -0
  96. package/python/foxclaw/browser/perception/element_indexer.py +56 -0
  97. package/python/foxclaw/browser/perception/semantic_reducer.py +33 -0
  98. package/python/foxclaw/browser/perception/snapshot.py +29 -0
  99. package/python/foxclaw/browser/service.py +144 -0
  100. package/python/foxclaw/browser/session/__init__.py +1 -0
  101. package/python/foxclaw/browser/session/session_manager.py +57 -0
  102. package/python/foxclaw/capability/__init__.py +12 -0
  103. package/python/foxclaw/capability/embedding_service.py +65 -0
  104. package/python/foxclaw/channels/__init__.py +138 -0
  105. package/python/foxclaw/channels/discord.py +175 -0
  106. package/python/foxclaw/channels/dispatcher.py +179 -0
  107. package/python/foxclaw/channels/feishu.py +215 -0
  108. package/python/foxclaw/channels/openclaw_bridge.py +151 -0
  109. package/python/foxclaw/channels/signing.py +187 -0
  110. package/python/foxclaw/channels/telegram.py +120 -0
  111. package/python/foxclaw/channels/weixin.py +215 -0
  112. package/python/foxclaw/cli.py +183 -0
  113. package/python/foxclaw/cognitive/__init__.py +4 -0
  114. package/python/foxclaw/cognitive/reasoner.py +81 -0
  115. package/python/foxclaw/cognitive/state.py +141 -0
  116. package/python/foxclaw/core/__init__.py +9 -0
  117. package/python/foxclaw/core/audit_chain.py +131 -0
  118. package/python/foxclaw/core/audit_sink.py +100 -0
  119. package/python/foxclaw/core/compaction.py +265 -0
  120. package/python/foxclaw/core/config.py +65 -0
  121. package/python/foxclaw/core/confirm_nonce.py +151 -0
  122. package/python/foxclaw/core/dispatch.py +27 -0
  123. package/python/foxclaw/core/envfile.py +48 -0
  124. package/python/foxclaw/core/failure_policy.py +142 -0
  125. package/python/foxclaw/core/gateway.py +81 -0
  126. package/python/foxclaw/core/governance_audit.py +171 -0
  127. package/python/foxclaw/core/idempotency.py +282 -0
  128. package/python/foxclaw/core/injection_guard.py +202 -0
  129. package/python/foxclaw/core/memory_adapter.py +489 -0
  130. package/python/foxclaw/core/metrics.py +88 -0
  131. package/python/foxclaw/core/model_router.py +985 -0
  132. package/python/foxclaw/core/paths.py +103 -0
  133. package/python/foxclaw/core/recovery.py +349 -0
  134. package/python/foxclaw/core/scheduler.py +141 -0
  135. package/python/foxclaw/core/secrets.py +131 -0
  136. package/python/foxclaw/core/sessions.py +155 -0
  137. package/python/foxclaw/core/settings.py +414 -0
  138. package/python/foxclaw/core/shared_write.py +186 -0
  139. package/python/foxclaw/core/steering_queue.py +154 -0
  140. package/python/foxclaw/core/system_bus.py +84 -0
  141. package/python/foxclaw/core/thought_chain.py +316 -0
  142. package/python/foxclaw/core/token_meter.py +231 -0
  143. package/python/foxclaw/core/tools.py +164 -0
  144. package/python/foxclaw/core/tracing.py +375 -0
  145. package/python/foxclaw/core/truth_pipeline.py +110 -0
  146. package/python/foxclaw/core/update_check.py +149 -0
  147. package/python/foxclaw/core/vec_recall_adapter.py +477 -0
  148. package/python/foxclaw/core/verify.py +173 -0
  149. package/python/foxclaw/core/web_search.py +218 -0
  150. package/python/foxclaw/finance/__init__.py +15 -0
  151. package/python/foxclaw/finance/evidence.py +149 -0
  152. package/python/foxclaw/finance/fx.py +98 -0
  153. package/python/foxclaw/finance/graph.py +179 -0
  154. package/python/foxclaw/finance/models.py +146 -0
  155. package/python/foxclaw/finance/nlparse.py +515 -0
  156. package/python/foxclaw/finance/policy.py +301 -0
  157. package/python/foxclaw/finance/reasoner.py +121 -0
  158. package/python/foxclaw/finance/reasoning.py +319 -0
  159. package/python/foxclaw/finance/reconcile.py +175 -0
  160. package/python/foxclaw/finance/runtime.py +500 -0
  161. package/python/foxclaw/governance/__init__.py +24 -0
  162. package/python/foxclaw/governance/middleware.py +176 -0
  163. package/python/foxclaw/harness/__init__.py +17 -0
  164. package/python/foxclaw/harness/_base.py +66 -0
  165. package/python/foxclaw/harness/_policy.py +340 -0
  166. package/python/foxclaw/harness/drift.py +77 -0
  167. package/python/foxclaw/harness/event_bus.py +28 -0
  168. package/python/foxclaw/harness/harness.py +358 -0
  169. package/python/foxclaw/harness/loop_detection.py +145 -0
  170. package/python/foxclaw/itinerary/__init__.py +10 -0
  171. package/python/foxclaw/itinerary/amap_client.py +114 -0
  172. package/python/foxclaw/itinerary/models.py +80 -0
  173. package/python/foxclaw/itinerary/reasoner.py +96 -0
  174. package/python/foxclaw/itinerary/reasoning.py +168 -0
  175. package/python/foxclaw/itinerary/runtime.py +144 -0
  176. package/python/foxclaw/kernel/__init__.py +13 -0
  177. package/python/foxclaw/kernel/capabilities.py +72 -0
  178. package/python/foxclaw/kernel/policy_gate.py +108 -0
  179. package/python/foxclaw/kernel/process_manager.py +186 -0
  180. package/python/foxclaw/kernel/scheduler.py +125 -0
  181. package/python/foxclaw/kernel/sentinel.py +443 -0
  182. package/python/foxclaw/kernel/sentinel_client.py +243 -0
  183. package/python/foxclaw/kernel/spine.py +97 -0
  184. package/python/foxclaw/knowledge/__init__.py +360 -0
  185. package/python/foxclaw/knowledge/truth_crystallizer.py +89 -0
  186. package/python/foxclaw/learning/__init__.py +12 -0
  187. package/python/foxclaw/learning/knowledge_graph.py +144 -0
  188. package/python/foxclaw/learning/models.py +93 -0
  189. package/python/foxclaw/learning/reasoner.py +67 -0
  190. package/python/foxclaw/learning/runtime.py +351 -0
  191. package/python/foxclaw/learning/spaced_repetition.py +91 -0
  192. package/python/foxclaw/mcp_server.py +188 -0
  193. package/python/foxclaw/orchestration/__init__.py +167 -0
  194. package/python/foxclaw/pipeline/__init__.py +23 -0
  195. package/python/foxclaw/pipeline/cognitive_pipeline.py +429 -0
  196. package/python/foxclaw/pipeline/stage_meta.py +21 -0
  197. package/python/foxclaw/pipeline/supervisor_stages.py +201 -0
  198. package/python/foxclaw/planning/__init__.py +17 -0
  199. package/python/foxclaw/planning/llm_planner.py +232 -0
  200. package/python/foxclaw/planning/planner.py +94 -0
  201. package/python/foxclaw/search/__init__.py +24 -0
  202. package/python/foxclaw/search/agent_port.py +190 -0
  203. package/python/foxclaw/search/evidence.py +109 -0
  204. package/python/foxclaw/search/external_search.py +50 -0
  205. package/python/foxclaw/search/hkc_read_port.py +60 -0
  206. package/python/foxclaw/search/internal_search.py +71 -0
  207. package/python/foxclaw/search/models.py +127 -0
  208. package/python/foxclaw/search/planner.py +44 -0
  209. package/python/foxclaw/search/retriever.py +39 -0
  210. package/python/foxclaw/search/runtime.py +127 -0
  211. package/python/foxclaw/search/strategy.py +44 -0
  212. package/python/foxclaw/skills/__init__.py +559 -0
  213. package/python/foxclaw/skills/archive.py +111 -0
  214. package/python/foxclaw/skills/fetch.py +226 -0
  215. package/python/foxclaw/skills/hooks_spec.py +69 -0
  216. package/python/foxclaw/skills/install_cmd.py +216 -0
  217. package/python/foxclaw/skills/lifecycle.py +252 -0
  218. package/python/foxclaw/skills/markdown_skill.py +175 -0
  219. package/python/foxclaw/skills/markdown_store.py +39 -0
  220. package/python/foxclaw/skills/mcp_client.py +184 -0
  221. package/python/foxclaw/skills/mcp_store.py +40 -0
  222. package/python/foxclaw/skills/permission.py +145 -0
  223. package/python/foxclaw/skills/pipeline.py +354 -0
  224. package/python/foxclaw/skills/policy.py +74 -0
  225. package/python/foxclaw/skills/review.py +72 -0
  226. package/python/foxclaw/skills/store.py +57 -0
  227. package/python/frontend/assets/core_bg.jpg +0 -0
  228. package/python/frontend/deck/auth.js +25 -0
  229. package/python/frontend/deck/chat_model_picker.js +483 -0
  230. package/python/frontend/deck/domain.js +276 -0
  231. package/python/frontend/deck/main.js +1806 -0
  232. package/python/frontend/deck/markdown.js +44 -0
  233. package/python/frontend/deck/settings.js +307 -0
  234. package/python/frontend/deck/state.js +5 -0
  235. package/python/frontend/deck/util.js +4 -0
  236. package/python/frontend/deck/visuals.js +190 -0
  237. package/python/frontend/deck.css +855 -0
  238. package/python/frontend/deck.html +686 -0
  239. package/python/frontend/deck_v2.html +341 -0
  240. package/python/frontend/planet/index.html +266 -0
  241. package/python/frontend/planet/planet.css +579 -0
  242. package/python/frontend/planet/planet.js +1436 -0
  243. package/python/frontend/planet/vendor/three.core.min.js +6 -0
  244. package/python/frontend/planet/vendor/three.module.min.js +6 -0
  245. package/python/frontend/v3/assets/index-CQSBdxk4.js +34 -0
  246. package/python/frontend/v3/assets/index-D5nIsjms.css +1 -0
  247. package/python/frontend/v3/index.html +15 -0
  248. package/python/frontend/widget_runtime.js +252 -0
  249. package/python/frontend/widgets.js +639 -0
  250. package/python/frontend_src/index.html +14 -0
  251. package/python/frontend_src/package-lock.json +1376 -0
  252. package/python/frontend_src/package.json +19 -0
  253. package/python/frontend_src/src/App.vue +58 -0
  254. package/python/frontend_src/src/api.js +82 -0
  255. package/python/frontend_src/src/components/ChatDock.vue +365 -0
  256. package/python/frontend_src/src/components/ComposerMenu.vue +75 -0
  257. package/python/frontend_src/src/components/DocViewer.vue +162 -0
  258. package/python/frontend_src/src/components/Inspector.vue +235 -0
  259. package/python/frontend_src/src/components/LeftRail.vue +415 -0
  260. package/python/frontend_src/src/components/MenuPopover.vue +128 -0
  261. package/python/frontend_src/src/components/MessageStream.vue +389 -0
  262. package/python/frontend_src/src/components/ModelPicker.vue +350 -0
  263. package/python/frontend_src/src/components/QuickIngest.vue +112 -0
  264. package/python/frontend_src/src/components/Stage.vue +272 -0
  265. package/python/frontend_src/src/components/ToolMenu.vue +141 -0
  266. package/python/frontend_src/src/components/TopBar.vue +118 -0
  267. package/python/frontend_src/src/components/panels/ActivityPanel.vue +82 -0
  268. package/python/frontend_src/src/components/panels/AgentsPanel.vue +83 -0
  269. package/python/frontend_src/src/components/panels/KnowledgePanel.vue +425 -0
  270. package/python/frontend_src/src/components/panels/MemoryPanel.vue +117 -0
  271. package/python/frontend_src/src/components/panels/PanelBox.vue +50 -0
  272. package/python/frontend_src/src/components/panels/ReviewPanel.vue +292 -0
  273. package/python/frontend_src/src/components/panels/SettingsPanel.vue +358 -0
  274. package/python/frontend_src/src/components/panels/TasksPanel.vue +73 -0
  275. package/python/frontend_src/src/components/panels/ToolsPanel.vue +746 -0
  276. package/python/frontend_src/src/components/panels/UsagePanel.vue +105 -0
  277. package/python/frontend_src/src/lib/fmt.js +44 -0
  278. package/python/frontend_src/src/lib/i18n.js +53 -0
  279. package/python/frontend_src/src/lib/locales/en.js +173 -0
  280. package/python/frontend_src/src/lib/locales/zh.js +174 -0
  281. package/python/frontend_src/src/lib/md.js +190 -0
  282. package/python/frontend_src/src/main.js +9 -0
  283. package/python/frontend_src/src/stores/app.js +91 -0
  284. package/python/frontend_src/src/stores/chat.js +450 -0
  285. package/python/frontend_src/src/stores/model.js +96 -0
  286. package/python/frontend_src/src/stores/panels.js +289 -0
  287. package/python/frontend_src/src/stores/profile.js +31 -0
  288. package/python/frontend_src/src/stores/system.js +25 -0
  289. package/python/frontend_src/src/styles/base.css +138 -0
  290. package/python/frontend_src/src/styles/panel.css +117 -0
  291. package/python/frontend_src/src/styles/tokens.css +78 -0
  292. package/python/frontend_src/vite.config.js +39 -0
  293. package/python/pyproject.toml +268 -0
  294. package/python/requirements.txt +311 -0
  295. package/python/skills/README.md +123 -0
  296. package/python/skills/execution-contract/SKILL.md +30 -0
  297. package/python/skills/general-assistant/SKILL.md +34 -0
  298. package/python/skills/planner/SKILL.md +33 -0
  299. package/python/skills/schedule-itinerary/SKILL.md +35 -0
  300. package/python/skills/skill-composition/SKILL.md +31 -0
  301. package/python/skills/skill-guard/SKILL.md +67 -0
  302. package/python/skills/skill-memory/SKILL.md +50 -0
  303. package/python/skills/skill-router/SKILL.md +35 -0
  304. package/python/tests/conftest.py +54 -0
  305. package/python/tests/run_all.py +200 -0
  306. package/python/tests/test_agent_lifecycle.py +326 -0
  307. package/python/tests/test_ahs_p2.py +393 -0
  308. package/python/tests/test_anthropic_tools.py +192 -0
  309. package/python/tests/test_api.py +97 -0
  310. package/python/tests/test_api_auth.py +79 -0
  311. package/python/tests/test_api_host_guard.py +69 -0
  312. package/python/tests/test_attachments.py +151 -0
  313. package/python/tests/test_audit_chain.py +116 -0
  314. package/python/tests/test_audit_sink.py +130 -0
  315. package/python/tests/test_browser.py +149 -0
  316. package/python/tests/test_browser_request_guard.py +180 -0
  317. package/python/tests/test_capabilities.py +152 -0
  318. package/python/tests/test_channel_signing.py +185 -0
  319. package/python/tests/test_channel_trust.py +109 -0
  320. package/python/tests/test_channels.py +174 -0
  321. package/python/tests/test_cli.py +46 -0
  322. package/python/tests/test_compaction_toolpair.py +119 -0
  323. package/python/tests/test_config_layering.py +61 -0
  324. package/python/tests/test_confirm_nonce.py +186 -0
  325. package/python/tests/test_context_compaction_wiring.py +124 -0
  326. package/python/tests/test_dispatch.py +89 -0
  327. package/python/tests/test_domain_evals.py +334 -0
  328. package/python/tests/test_domain_import.py +72 -0
  329. package/python/tests/test_domain_reasoners.py +134 -0
  330. package/python/tests/test_e2e.py +161 -0
  331. package/python/tests/test_emb_cache.py +97 -0
  332. package/python/tests/test_embedding_singleton.py +87 -0
  333. package/python/tests/test_envfile.py +83 -0
  334. package/python/tests/test_evals_smoke.py +90 -0
  335. package/python/tests/test_event_spine.py +174 -0
  336. package/python/tests/test_evidence_semantic.py +88 -0
  337. package/python/tests/test_evidence_sse.py +94 -0
  338. package/python/tests/test_file_ingest.py +135 -0
  339. package/python/tests/test_finance.py +144 -0
  340. package/python/tests/test_finance_ledger.py +245 -0
  341. package/python/tests/test_finance_persist.py +174 -0
  342. package/python/tests/test_gateway.py +125 -0
  343. package/python/tests/test_governance.py +421 -0
  344. package/python/tests/test_governance_audit.py +324 -0
  345. package/python/tests/test_governance_middleware.py +137 -0
  346. package/python/tests/test_hkc.py +268 -0
  347. package/python/tests/test_hkc_index_build_manager.py +306 -0
  348. package/python/tests/test_hkc_manifest_reuse.py +294 -0
  349. package/python/tests/test_hkc_search_event_sync.py +482 -0
  350. package/python/tests/test_import_path_guard.py +155 -0
  351. package/python/tests/test_injection_guard.py +193 -0
  352. package/python/tests/test_integration.py +117 -0
  353. package/python/tests/test_itinerary.py +100 -0
  354. package/python/tests/test_kee_semantic.py +84 -0
  355. package/python/tests/test_kernel.py +212 -0
  356. package/python/tests/test_learning.py +101 -0
  357. package/python/tests/test_llm_admin.py +145 -0
  358. package/python/tests/test_llm_planner.py +344 -0
  359. package/python/tests/test_markdown_skills.py +62 -0
  360. package/python/tests/test_markdown_skills_openclaw.py +66 -0
  361. package/python/tests/test_mcp_connectors.py +97 -0
  362. package/python/tests/test_mcp_guardian_discovery.py +87 -0
  363. package/python/tests/test_mcp_no_memory.py +43 -0
  364. package/python/tests/test_mcp_policy_gate.py +76 -0
  365. package/python/tests/test_mcp_server.py +92 -0
  366. package/python/tests/test_memory_recall.py +92 -0
  367. package/python/tests/test_metrics.py +58 -0
  368. package/python/tests/test_multi_chain.py +90 -0
  369. package/python/tests/test_multimodal.py +122 -0
  370. package/python/tests/test_negotiation.py +136 -0
  371. package/python/tests/test_orchestration.py +109 -0
  372. package/python/tests/test_orchestration_decoupled.py +103 -0
  373. package/python/tests/test_p3_p5_hardening.py +324 -0
  374. package/python/tests/test_parallel_dispatch.py +207 -0
  375. package/python/tests/test_pipeline.py +492 -0
  376. package/python/tests/test_plan_visible.py +86 -0
  377. package/python/tests/test_planner.py +88 -0
  378. package/python/tests/test_policy_gate.py +108 -0
  379. package/python/tests/test_profile.py +67 -0
  380. package/python/tests/test_readme_claims.py +163 -0
  381. package/python/tests/test_reasoner.py +170 -0
  382. package/python/tests/test_release_check.py +252 -0
  383. package/python/tests/test_resume_checkpoint.py +148 -0
  384. package/python/tests/test_routing.py +85 -0
  385. package/python/tests/test_scheduler.py +138 -0
  386. package/python/tests/test_search.py +194 -0
  387. package/python/tests/test_secrets.py +153 -0
  388. package/python/tests/test_semantic.py +69 -0
  389. package/python/tests/test_sessions.py +90 -0
  390. package/python/tests/test_settings.py +265 -0
  391. package/python/tests/test_shadow_learning.py +290 -0
  392. package/python/tests/test_shared_write.py +200 -0
  393. package/python/tests/test_skill_taint_gate.py +145 -0
  394. package/python/tests/test_skills.py +117 -0
  395. package/python/tests/test_skills_fetch.py +282 -0
  396. package/python/tests/test_stats_and_events.py +162 -0
  397. package/python/tests/test_streaming.py +55 -0
  398. package/python/tests/test_supervisor_pipeline.py +176 -0
  399. package/python/tests/test_supervisor_triage.py +102 -0
  400. package/python/tests/test_taint.py +112 -0
  401. package/python/tests/test_task_stream.py +74 -0
  402. package/python/tests/test_thinking_sse.py +66 -0
  403. package/python/tests/test_thinking_stream.py +76 -0
  404. package/python/tests/test_tool_center.py +113 -0
  405. package/python/tests/test_tool_parallel.py +113 -0
  406. package/python/tests/test_tool_params.py +99 -0
  407. package/python/tests/test_tool_use.py +229 -0
  408. package/python/tests/test_toplevel_concurrency.py +116 -0
  409. package/python/tests/test_tracing.py +256 -0
  410. package/python/tests/test_truth_crystallizer.py +125 -0
  411. package/python/tests/test_truth_flow.py +88 -0
  412. package/python/tests/test_update_check.py +95 -0
  413. package/python/tests/test_url_policy.py +53 -0
  414. package/python/tests/test_verify_evidence.py +212 -0
  415. package/python/tests/test_version_sync.py +100 -0
  416. package/python/tests/test_web_trigger.py +82 -0
  417. package/python/tools/check_faiss_type.py +30 -0
  418. package/python/tools/check_log.ps1 +38 -0
  419. package/python/tools/ivf_status.py +72 -0
  420. package/python/tools/mypy_baseline.txt +13 -0
  421. package/python/tools/mypy_ratchet.py +143 -0
  422. package/python/tools/pack.py +173 -0
  423. package/python/tools/release_check.py +349 -0
  424. package/python/tools/restart_foxclaw.ps1 +71 -0
  425. package/python/tools/shared_write_audit.py +190 -0
  426. package/python/tools/size_baseline.txt +28 -0
  427. package/python/tools/size_check.py +102 -0
  428. package/python/tools/strip_comments.py +228 -0
  429. package/python/tools/verify_env.bat +2 -0
  430. package/python/tools/verify_env.py +25 -0
  431. package/python/vendor/HMR_LICENSE +37 -0
  432. package/python/vendor/HMR_README.md +65 -0
  433. package/python/vendor/hkc/LICENSE +37 -0
  434. package/python/vendor/hkc/hkc_ace/__init__.py +0 -0
  435. package/python/vendor/hkc/hkc_ace/ace.py +457 -0
  436. package/python/vendor/hkc/hkc_ace/skill_taxonomy.json +465 -0
  437. package/python/vendor/hkc/hkc_api/__init__.py +0 -0
  438. package/python/vendor/hkc/hkc_api/container.py +416 -0
  439. package/python/vendor/hkc/hkc_api/ingest_jobs.py +103 -0
  440. package/python/vendor/hkc/hkc_api/main.py +157 -0
  441. package/python/vendor/hkc/hkc_api/routes/__init__.py +0 -0
  442. package/python/vendor/hkc/hkc_api/routes/ability.py +151 -0
  443. package/python/vendor/hkc/hkc_api/routes/config.py +51 -0
  444. package/python/vendor/hkc/hkc_api/routes/knowledge.py +630 -0
  445. package/python/vendor/hkc/hkc_api/routes/search.py +88 -0
  446. package/python/vendor/hkc/hkc_api/schemas.py +153 -0
  447. package/python/vendor/hkc/hkc_api/synthesis.py +179 -0
  448. package/python/vendor/hkc/hkc_core/__init__.py +0 -0
  449. package/python/vendor/hkc/hkc_core/graph/__init__.py +0 -0
  450. package/python/vendor/hkc/hkc_core/graph/base.py +188 -0
  451. package/python/vendor/hkc/hkc_core/graph/sqlite_store.py +789 -0
  452. package/python/vendor/hkc/hkc_core/models/__init__.py +0 -0
  453. package/python/vendor/hkc/hkc_core/models/enums.py +65 -0
  454. package/python/vendor/hkc/hkc_core/models/ku.py +307 -0
  455. package/python/vendor/hkc/hkc_core/utils/__init__.py +0 -0
  456. package/python/vendor/hkc/hkc_core/utils/id_gen.py +113 -0
  457. package/python/vendor/hkc/hkc_crystallizer/__init__.py +44 -0
  458. package/python/vendor/hkc/hkc_crystallizer/adapters.py +94 -0
  459. package/python/vendor/hkc/hkc_crystallizer/candidate.py +145 -0
  460. package/python/vendor/hkc/hkc_crystallizer/crystallizer.py +179 -0
  461. package/python/vendor/hkc/hkc_crystallizer/ingress.py +90 -0
  462. package/python/vendor/hkc/hkc_kde/__init__.py +0 -0
  463. package/python/vendor/hkc/hkc_kde/chunker.py +197 -0
  464. package/python/vendor/hkc/hkc_kde/extractor.py +623 -0
  465. package/python/vendor/hkc/hkc_kde/kde.py +298 -0
  466. package/python/vendor/hkc/hkc_kde/loaders/__init__.py +0 -0
  467. package/python/vendor/hkc/hkc_kde/loaders/ebook_loader.py +153 -0
  468. package/python/vendor/hkc/hkc_kde/loaders/office_loader.py +194 -0
  469. package/python/vendor/hkc/hkc_kde/loaders/pdf_loader.py +162 -0
  470. package/python/vendor/hkc/hkc_kde/loaders/text_loader.py +157 -0
  471. package/python/vendor/hkc/hkc_kde/loaders/web_loader.py +91 -0
  472. package/python/vendor/hkc/hkc_kde/models.py +74 -0
  473. package/python/vendor/hkc/hkc_kde/packager.py +329 -0
  474. package/python/vendor/hkc/hkc_kde/relation_disc.py +151 -0
  475. package/python/vendor/hkc/hkc_kee/__init__.py +0 -0
  476. package/python/vendor/hkc/hkc_kee/dedup.py +227 -0
  477. package/python/vendor/hkc/hkc_kee/fingerprint.py +106 -0
  478. package/python/vendor/hkc/hkc_kee/kee.py +541 -0
  479. package/python/vendor/hkc/hkc_kep/__init__.py +0 -0
  480. package/python/vendor/hkc/hkc_kep/event_bus.py +205 -0
  481. package/python/vendor/hkc/hkc_sdk/__init__.py +63 -0
  482. package/python/vendor/hkc/hkc_sdk/base.py +151 -0
  483. package/python/vendor/hkc/hkc_sdk/direct_client.py +153 -0
  484. package/python/vendor/hkc/hkc_sdk/exceptions.py +39 -0
  485. package/python/vendor/hkc/hkc_sdk/http_client.py +166 -0
  486. package/python/vendor/hkc/hkc_sdk/models.py +171 -0
  487. package/python/vendor/hkc/hkc_search/__init__.py +0 -0
  488. package/python/vendor/hkc/hkc_search/bm25.py +325 -0
  489. package/python/vendor/hkc/hkc_search/embedding_backends.py +374 -0
  490. package/python/vendor/hkc/hkc_search/graph_search.py +132 -0
  491. package/python/vendor/hkc/hkc_search/hybrid.py +331 -0
  492. package/python/vendor/hkc/hkc_search/index_build_manager.py +378 -0
  493. package/python/vendor/hkc/hkc_search/vector_search.py +484 -0
  494. package/python/vendor/hmr/__init__.py +0 -0
  495. package/python/vendor/hmr/core/__init__.py +0 -0
  496. package/python/vendor/hmr/core/hmr.py +684 -0
  497. package/python/vendor/hmr/core/models.py +310 -0
  498. package/python/vendor/hmr/engines/__init__.py +0 -0
  499. package/python/vendor/hmr/engines/evolution.py +710 -0
  500. package/python/vendor/hmr/engines/jit_compiler.py +472 -0
  501. package/python/vendor/hmr/engines/lifecycle.py +264 -0
  502. package/python/vendor/hmr/engines/policy.py +625 -0
  503. package/python/vendor/hmr/engines/recall.py +260 -0
  504. package/python/vendor/hmr/engines/runtime_state.py +158 -0
  505. package/python/vendor/hmr/engines/scheduler.py +323 -0
  506. package/python/vendor/hmr/engines/semantic.py +150 -0
  507. package/python/vendor/hmr/engines/temporal.py +261 -0
  508. package/python/vendor/hmr/engines/thought_chain.py +635 -0
  509. package/python/vendor/hmr/graph/__init__.py +0 -0
  510. package/python/vendor/hmr/graph/cwg.py +338 -0
  511. package/python/vendor/hmr/graph/memory_graph.py +530 -0
  512. package/python/vendor/hmr/storage/__init__.py +0 -0
  513. package/python/vendor/hmr/storage/memory_fs.py +300 -0
  514. package/python/vendor/hmr/storage/vector_store.py +520 -0
@@ -0,0 +1,65 @@
1
+ # HMR v1.5 — Foxclaw Memory Runtime
2
+
3
+ 持续认知运行时,为长期运行的 AI 系统而生。
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ pip install pydantic numpy
9
+
10
+ # 推荐(更好的语义理解,选其一)
11
+ pip install openai # OpenAI Embedding
12
+ pip install sentence-transformers # 本地模型,无需 API Key
13
+ ```
14
+
15
+ ## 快速开始
16
+
17
+ ```python
18
+ from hmr.core.hmr import HMR
19
+
20
+ hmr = HMR(storage_path="./my_project")
21
+
22
+ hmr.ingest("IPC 应使用异步消息队列", memory_type="concept", title="IPC 设计原则")
23
+ hmr.save_runtime_state(goal="设计调度器", plan=["研究", "设计", "实现"])
24
+
25
+ # 重启后完整恢复
26
+ hmr2 = HMR(storage_path="./my_project")
27
+ state = hmr2.restore_runtime_state()
28
+ result = hmr2.recall(query="调度器 IPC 设计")
29
+ ```
30
+
31
+ ## 目录结构
32
+
33
+ ```
34
+ hmr/
35
+ ├── core/
36
+ │ ├── models.py 数据结构
37
+ │ └── hmr.py 主引擎
38
+ ├── engines/
39
+ │ ├── semantic.py 语义检索
40
+ │ ├── runtime_state.py 运行时状态持久化
41
+ │ ├── recall.py 主动召回
42
+ │ ├── temporal.py SM-2 遗忘曲线
43
+ │ ├── jit_compiler.py 多步推理检索
44
+ │ ├── lifecycle.py 自动压缩/剪枝
45
+ │ └── scheduler.py 策略调度 + 热缓存
46
+ ├── storage/
47
+ │ ├── memory_fs.py 文件系统存储
48
+ │ └── vector_store.py 向量索引(持久化)
49
+ └── graph/
50
+ ├── cwg.py 认知工作图
51
+ └── memory_graph.py 实体/因果图
52
+ ```
53
+
54
+ ## 文档
55
+
56
+ 详见 `docs/` 目录:
57
+ - `USER_MANUAL_CN.md` — 中文操作手册
58
+ - `USER_MANUAL_EN.md` — English User Manual
59
+ - `BUGFIX_CN.md` — v1.1 修复说明
60
+ - `ARCHITECTURE_CN.md`— 系统架构
61
+ - `API_CN.md` — API 参考
62
+
63
+ ## 许可证
64
+
65
+ MIT License
@@ -0,0 +1,37 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Hestia OS Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ---
24
+
25
+ ## About This License
26
+
27
+ HKC (Hestia Knowledge Core) Core is released under the MIT License.
28
+
29
+ This means:
30
+ ✅ You can use it freely in commercial projects
31
+ ✅ You can modify it
32
+ ✅ You can distribute it
33
+ ✅ You must include the license and copyright
34
+
35
+ The only requirement: include this license text in your distribution.
36
+
37
+ For enterprise features and extended support, see Hestia Enterprise License.
File without changes
@@ -0,0 +1,457 @@
1
+ """
2
+ hkc-ace / ace.py
3
+ Ability Compiler Engine
4
+
5
+ 职责:
6
+ 1. 预定义 Skill Taxonomy(不允许 LLM 自由生成 Skill)
7
+ 2. 计算每个 Skill 的知识覆盖率
8
+ 3. 达到门槛后编译输出 .hkap 能力包
9
+ 4. Agent 直接 load_ability() 调用
10
+ """
11
+ import os
12
+
13
+ import json
14
+ from dataclasses import dataclass, field
15
+ from datetime import datetime, timezone
16
+ from pathlib import Path
17
+ from typing import Optional
18
+
19
+ from hkc_core.graph.base import GraphStore
20
+ from hkc_core.models.ku import AbilityKU, KU
21
+ from hkc_core.utils.id_gen import IDGenerator
22
+ from hkc_kep.event_bus import EventBus, KEPEvents
23
+
24
+
25
+ # ── Skill Taxonomy(从 JSON 配置加载,不再硬编码)──────────────
26
+ #
27
+ # 每个 Ability 的字段:
28
+ # display_name : 显示名(可中文)
29
+ # domain : 主领域(AbilityKU / 能力包的展示领域)
30
+ # domains : (可选) 参与覆盖匹配的领域列表;缺省则等于 [domain]。
31
+ # 中文抽取常把一个主题拆成多个细碎领域(如 公文写作 / 写作方法论 /
32
+ # 写作技巧),用 domains 把它们并起来一起算覆盖。
33
+ # required_skills : 必须覆盖的 Skill 列表
34
+ # optional_skills : 加分项
35
+ # min_coverage : required_skills 中至少多少比例的 skill 覆盖度 >= 0.5
36
+ # concept_checklist : 每个 Skill 的核心概念列表(Coverage 计算基准,中 / 英文皆可)
37
+ # workflows : 技能执行顺序
38
+ #
39
+ # 配置文件默认 = 本包目录下 skill_taxonomy.json;可用环境变量 HKC_ACE_TAXONOMY
40
+ # 指向自定义文件(开源用户可替换成自己的能力定义,无需改代码)。
41
+
42
+
43
+ def _load_taxonomy() -> dict:
44
+ path = os.environ.get("HKC_ACE_TAXONOMY") or str(
45
+ Path(__file__).parent / "skill_taxonomy.json"
46
+ )
47
+ with open(path, encoding="utf-8") as f:
48
+ return json.load(f)
49
+
50
+
51
+ SKILL_TAXONOMY: dict[str, dict] = _load_taxonomy()
52
+
53
+
54
+ def _ability_domains(taxonomy_entry: dict) -> list[str]:
55
+ """能力参与覆盖匹配的领域列表:优先 domains(多领域),否则回退单个 domain。"""
56
+ ds = taxonomy_entry.get("domains")
57
+ if ds:
58
+ return list(ds)
59
+ d = taxonomy_entry.get("domain")
60
+ return [d] if d else []
61
+
62
+
63
+ # ── Skill 数据结构 ────────────────────────────────────────────
64
+
65
+ @dataclass
66
+ class Skill:
67
+ skill_id: str
68
+ skill_key: str
69
+ display_name: str
70
+ domain: str
71
+ ku_refs: list[str] = field(default_factory=list)
72
+ coverage: float = 0.0
73
+ concept_hits: list[str] = field(default_factory=list)
74
+
75
+
76
+ @dataclass
77
+ class Workflow:
78
+ name: str
79
+ steps: list[str]
80
+
81
+
82
+ @dataclass
83
+ class AbilityPackage:
84
+ ability_key: str
85
+ display_name: str
86
+ domain: str
87
+ skills: list[Skill]
88
+ workflows: list[Workflow]
89
+ coverage: dict[str, float]
90
+ knowledge_refs: list[str]
91
+ compiled_at: str
92
+ version: str = "1.0.0"
93
+
94
+ def to_dict(self) -> dict:
95
+ return {
96
+ "hkap_version": "1.0",
97
+ "ability_key": self.ability_key,
98
+ "display_name": self.display_name,
99
+ "domain": self.domain,
100
+ "compiled_at": self.compiled_at,
101
+ "version": self.version,
102
+ "coverage": self.coverage,
103
+ "skills": [
104
+ {
105
+ "skill_key": s.skill_key,
106
+ "display_name": s.display_name,
107
+ "ku_refs": s.ku_refs,
108
+ "coverage": s.coverage,
109
+ "concept_hits": s.concept_hits,
110
+ }
111
+ for s in self.skills
112
+ ],
113
+ "workflows": [
114
+ {"name": w.name, "steps": w.steps}
115
+ for w in self.workflows
116
+ ],
117
+ "knowledge_summary": (
118
+ f"基于 {len(self.knowledge_refs)} 个 KU 编译"
119
+ ),
120
+ }
121
+
122
+ def get_skill_context(self, skill_key: str) -> dict:
123
+ """Agent 调用:获取某个 Skill 的知识上下文。"""
124
+ for s in self.skills:
125
+ if s.skill_key == skill_key:
126
+ return {
127
+ "skill_key": skill_key,
128
+ "ku_refs": s.ku_refs,
129
+ "coverage": s.coverage,
130
+ "concept_hits": s.concept_hits,
131
+ }
132
+ return {}
133
+
134
+
135
+ # ── Coverage 计算器 ───────────────────────────────────────────
136
+
137
+ class CoverageCalculator:
138
+ """
139
+ 计算每个 Skill 的知识覆盖率。
140
+ 基于 Concept Checklist:
141
+ coverage = 被 KU 覆盖的核心概念数 / 总核心概念数
142
+ """
143
+
144
+ def calculate(
145
+ self,
146
+ ability_key: str,
147
+ ku_pool: list[KU],
148
+ ) -> dict[str, float]:
149
+ taxonomy = SKILL_TAXONOMY[ability_key]
150
+ checklist = taxonomy.get("concept_checklist", {})
151
+ coverage = {}
152
+
153
+ for skill_key in taxonomy["required_skills"]:
154
+ concepts = checklist.get(skill_key, [])
155
+ if not concepts:
156
+ coverage[skill_key] = 0.0
157
+ continue
158
+ hit_count = sum(
159
+ 1 for concept in concepts
160
+ if self._concept_covered(concept, ku_pool)
161
+ )
162
+ coverage[skill_key] = round(hit_count / len(concepts), 2)
163
+
164
+ for skill_key in taxonomy.get("optional_skills", []):
165
+ concepts = checklist.get(skill_key, [])
166
+ if concepts:
167
+ hit_count = sum(
168
+ 1 for c in concepts
169
+ if self._concept_covered(c, ku_pool)
170
+ )
171
+ coverage[skill_key] = round(hit_count / len(concepts), 2)
172
+
173
+ return coverage
174
+
175
+ def _concept_covered(self, concept: str, ku_pool: list[KU]) -> bool:
176
+ """
177
+ 判断某个核心概念是否被 KU 池覆盖。
178
+ v1:关键词匹配(name + summary + tags)
179
+ v2:向量相似度匹配
180
+ """
181
+ concept_lower = concept.lower()
182
+ for ku in ku_pool:
183
+ text = f"{ku.name} {ku.summary} {' '.join(ku.tags)}".lower()
184
+ if concept_lower in text:
185
+ return True
186
+ # 支持中文关键词映射
187
+ if self._cn_match(concept_lower, text):
188
+ return True
189
+ return False
190
+
191
+ _CN_MAP = {
192
+ "momentum": ["动量", "趋势", "momentum"],
193
+ "value factor": ["价值因子", "价值", "低估"],
194
+ "drawdown": ["回撤", "最大回撤"],
195
+ "sharpe ratio": ["夏普", "sharpe"],
196
+ "diversification": ["分散", "多元", "分散化"],
197
+ "moat": ["护城河"],
198
+ "intrinsic value": ["内在价值", "内生价值"],
199
+ "loss aversion": ["损失厌恶", "亏损"],
200
+ "confirmation bias": ["确认偏差", "确认偏见"],
201
+ "attention": ["注意力", "attention"],
202
+ "transformer": ["transformer", "变换器"],
203
+ }
204
+
205
+ def _cn_match(self, concept: str, text: str) -> bool:
206
+ aliases = self._CN_MAP.get(concept, [])
207
+ return any(a in text for a in aliases)
208
+
209
+ def can_compile(
210
+ self,
211
+ ability_key: str,
212
+ coverage: dict[str, float],
213
+ ) -> bool:
214
+ """
215
+ 检查是否达到编译门槛:
216
+ required_skills 中,coverage >= 0.5 的比例 >= min_coverage
217
+ """
218
+ taxonomy = SKILL_TAXONOMY[ability_key]
219
+ required = taxonomy["required_skills"]
220
+ passed = sum(
221
+ 1 for s in required
222
+ if coverage.get(s, 0.0) >= 0.5
223
+ )
224
+ return (passed / len(required)) >= taxonomy["min_coverage"]
225
+
226
+
227
+ # ── ACE 主引擎 ───────────────────────────────────────────────
228
+
229
+ class AbilityCompilerEngine:
230
+
231
+ def __init__(
232
+ self,
233
+ graph_store: GraphStore,
234
+ event_bus: EventBus,
235
+ id_gen: IDGenerator,
236
+ output_dir: str = "abilities",
237
+ ):
238
+ self.store = graph_store
239
+ self.bus = event_bus
240
+ self.id_gen = id_gen
241
+ self.calculator = CoverageCalculator()
242
+ self.output_dir = Path(output_dir)
243
+ self.output_dir.mkdir(parents=True, exist_ok=True)
244
+
245
+ def _gather_ku_pool(self, taxonomy: dict, limit: int = 500) -> list[KU]:
246
+ """跨该能力的所有领域收集 KU 池并去重(中文细碎领域场景必需)。"""
247
+ seen: dict[str, KU] = {}
248
+ for d in _ability_domains(taxonomy):
249
+ for ku in self.store.query_by_domain(d, limit=limit):
250
+ seen[ku.ku_id] = ku
251
+ return list(seen.values())
252
+
253
+ def compile(self, ability_key: str) -> Optional[AbilityPackage]:
254
+ """
255
+ 编译一个 Ability Package。
256
+ 1. 从 GraphStore 获取相关领域 KU
257
+ 2. 计算覆盖率
258
+ 3. 检查门槛
259
+ 4. 组装 Skills + Workflows
260
+ 5. 写出 .hkap 文件
261
+ 6. 写入 GraphStore(AbilityKU)
262
+ 7. 发布事件
263
+ """
264
+ if ability_key not in SKILL_TAXONOMY:
265
+ raise ValueError(f"Unknown ability: {ability_key}")
266
+
267
+ taxonomy = SKILL_TAXONOMY[ability_key]
268
+ domain = taxonomy["domain"]
269
+
270
+ # 1. 获取 KU 池(跨该能力的多个领域并集,中文细碎领域场景必需)
271
+ ku_pool = self._gather_ku_pool(taxonomy, limit=500)
272
+ if not ku_pool:
273
+ return None
274
+
275
+ # 2. 计算覆盖率
276
+ coverage = self.calculator.calculate(ability_key, ku_pool)
277
+
278
+ # 3. 检查门槛
279
+ if not self.calculator.can_compile(ability_key, coverage):
280
+ return None
281
+
282
+ # 4. 组装 Skills
283
+ skills = self._build_skills(ability_key, ku_pool, coverage)
284
+
285
+ # 5. 组装 Workflows
286
+ workflows = [
287
+ Workflow(name=w["name"], steps=w["steps"])
288
+ for w in taxonomy["workflows"]
289
+ ]
290
+
291
+ # 6. 打包
292
+ now = datetime.now(timezone.utc).isoformat()
293
+ package = AbilityPackage(
294
+ ability_key = ability_key,
295
+ display_name = taxonomy["display_name"],
296
+ domain = domain,
297
+ skills = skills,
298
+ workflows = workflows,
299
+ coverage = coverage,
300
+ knowledge_refs = [ku.ku_id for ku in ku_pool],
301
+ compiled_at = now,
302
+ )
303
+
304
+ # 7. 确定 .hkap 路径(先定义,写 store 时引用,最后才写文件)
305
+ hkap_path = self.output_dir / f"{ability_key}.hkap"
306
+
307
+ # 8. 写入 GraphStore(先于文件,store 失败可回滚,文件失败可重新编译覆盖)
308
+ ku_id = self.id_gen.next("Ability")
309
+ ability_ku = AbilityKU(
310
+ ku_id = ku_id,
311
+ name = taxonomy["display_name"],
312
+ summary = f"ACE 编译产物,基于 {len(ku_pool)} 个 KU",
313
+ domain = domain,
314
+ ability_key = ability_key,
315
+ skills = [s.skill_id for s in skills],
316
+ coverage = coverage,
317
+ knowledge_refs = package.knowledge_refs,
318
+ package_path = str(hkap_path),
319
+ pkg_version = package.version,
320
+ )
321
+ self.store.put(ability_ku)
322
+
323
+ # 9. 写出 .hkap 文件
324
+ hkap_path = self.output_dir / f"{ability_key}.hkap"
325
+ hkap_path.write_text(
326
+ json.dumps(package.to_dict(), ensure_ascii=False, indent=2),
327
+ encoding="utf-8"
328
+ )
329
+
330
+ # 10. 发布事件
331
+ self.bus.publish({
332
+ "event": KEPEvents.ABILITY_CREATED,
333
+ "source": "ACE",
334
+ "payload": {
335
+ "ability_key": ability_key,
336
+ "ku_id": ku_id,
337
+ "coverage": coverage,
338
+ "hkap_path": str(hkap_path),
339
+ }
340
+ })
341
+
342
+ return package
343
+
344
+ def _build_skills(
345
+ self,
346
+ ability_key: str,
347
+ ku_pool: list[KU],
348
+ coverage: dict[str, float],
349
+ ) -> list[Skill]:
350
+ taxonomy = SKILL_TAXONOMY[ability_key]
351
+ checklist = taxonomy.get("concept_checklist", {})
352
+ skills = []
353
+
354
+ all_skill_keys = (
355
+ taxonomy["required_skills"] +
356
+ taxonomy.get("optional_skills", [])
357
+ )
358
+
359
+ for skill_key in all_skill_keys:
360
+ cov = coverage.get(skill_key, 0.0)
361
+ if cov == 0.0:
362
+ continue
363
+
364
+ # 找到覆盖该 Skill 的 KU
365
+ concepts = checklist.get(skill_key, [])
366
+ skill_kus = [
367
+ ku for ku in ku_pool
368
+ if self.calculator._concept_covered(
369
+ skill_key.replace("_", " "), [ku]
370
+ ) or any(
371
+ self.calculator._concept_covered(c, [ku])
372
+ for c in concepts
373
+ )
374
+ ]
375
+
376
+ # 命中的核心概念
377
+ hit_concepts = [
378
+ c for c in concepts
379
+ if self.calculator._concept_covered(c, ku_pool)
380
+ ]
381
+
382
+ skill = Skill(
383
+ skill_id = self.id_gen.next("Skill"),
384
+ skill_key = skill_key,
385
+ display_name = skill_key.replace("_", " ").title(),
386
+ domain = taxonomy["domain"],
387
+ ku_refs = [ku.ku_id for ku in skill_kus[:20]],
388
+ coverage = cov,
389
+ concept_hits = hit_concepts,
390
+ )
391
+ skills.append(skill)
392
+
393
+ return skills
394
+
395
+ def load_ability(self, ability_key: str) -> Optional[AbilityPackage]:
396
+ """从 .hkap 文件加载已编译的 Ability Package。"""
397
+ hkap_path = self.output_dir / f"{ability_key}.hkap"
398
+ if not hkap_path.exists():
399
+ return None
400
+ data = json.loads(hkap_path.read_text(encoding="utf-8"))
401
+ skills = [
402
+ Skill(
403
+ skill_id = f"SKL_{i:04d}",
404
+ skill_key = s["skill_key"],
405
+ display_name = s["display_name"],
406
+ domain = data["domain"],
407
+ ku_refs = s.get("ku_refs", []),
408
+ coverage = s.get("coverage", 0.0),
409
+ concept_hits = s.get("concept_hits", []),
410
+ )
411
+ for i, s in enumerate(data.get("skills", []))
412
+ ]
413
+ workflows = [
414
+ Workflow(name=w["name"], steps=w["steps"])
415
+ for w in data.get("workflows", [])
416
+ ]
417
+ return AbilityPackage(
418
+ ability_key = data["ability_key"],
419
+ display_name = data["display_name"],
420
+ domain = data["domain"],
421
+ skills = skills,
422
+ workflows = workflows,
423
+ coverage = data["coverage"],
424
+ knowledge_refs = data.get("knowledge_refs", []),
425
+ compiled_at = data["compiled_at"],
426
+ version = data["version"],
427
+ )
428
+
429
+ def list_available(self) -> list[str]:
430
+ """返回所有已定义的 Ability key 列表。"""
431
+ return list(SKILL_TAXONOMY.keys())
432
+
433
+ def coverage_report(self, ability_key: str) -> dict:
434
+ """
435
+ 在不编译的情况下,查看当前知识库对某 Ability 的覆盖情况。
436
+ 用于判断"还差哪些知识"。
437
+ """
438
+ if ability_key not in SKILL_TAXONOMY:
439
+ return {}
440
+ taxonomy = SKILL_TAXONOMY[ability_key]
441
+ ku_pool = self._gather_ku_pool(taxonomy, limit=500)
442
+ coverage = self.calculator.calculate(ability_key, ku_pool)
443
+ can = self.calculator.can_compile(ability_key, coverage)
444
+
445
+ missing = [
446
+ s for s in taxonomy["required_skills"]
447
+ if coverage.get(s, 0.0) < 0.5
448
+ ]
449
+ return {
450
+ "ability_key": ability_key,
451
+ "display_name": taxonomy.get("display_name", ability_key),
452
+ "domains": _ability_domains(taxonomy),
453
+ "can_compile": can,
454
+ "coverage": coverage,
455
+ "missing_skills": missing,
456
+ "ku_count": len(ku_pool),
457
+ }