foxclaw 0.1.0 → 0.1.2

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 (495) hide show
  1. package/README.md +54 -29
  2. package/bin/foxclaw.cjs +51 -0
  3. package/index.js +11 -10
  4. package/package.json +46 -38
  5. package/python/.dockerignore +35 -0
  6. package/python/.env.example +165 -0
  7. package/python/.gitattributes +46 -0
  8. package/python/.github/workflows/ci.yml +122 -0
  9. package/python/.github/workflows/release.yml +183 -0
  10. package/python/Dockerfile +64 -0
  11. package/python/LICENSE +21 -0
  12. package/python/MANIFEST.in +14 -0
  13. package/python/README.md +192 -0
  14. package/python/README_CN.md +324 -0
  15. package/python/bench/bm25_audit.py +199 -0
  16. package/python/bench/bm25_regression.py +178 -0
  17. package/python/bench/bm25_stress.py +159 -0
  18. package/python/bench/cd_audit.py +238 -0
  19. package/python/bench/chaos.py +142 -0
  20. package/python/bench/concurrency.py +103 -0
  21. package/python/bench/e2e_real_models.py +95 -0
  22. package/python/bench/llm_retry_test.py +248 -0
  23. package/python/bench/load_test.py +196 -0
  24. package/python/bench/vector_ivf_upgrade.py +134 -0
  25. package/python/docs/CHANNELS.md +195 -0
  26. package/python/docs/GOVERNANCE.md +164 -0
  27. package/python/docs/RELEASE.md +109 -0
  28. package/python/docs/RUN.md +75 -0
  29. package/python/docs/RUN_CN.md +121 -0
  30. package/python/docs//351/205/215/347/275/256/346/214/207/345/215/227.md +152 -0
  31. package/python/evals/__init__.py +0 -0
  32. package/python/evals/governance/README.md +61 -0
  33. package/python/evals/governance/__init__.py +0 -0
  34. package/python/evals/governance/cases.py +152 -0
  35. package/python/evals/governance/compare_embeddings.py +94 -0
  36. package/python/evals/governance/convergence.svg +11 -0
  37. package/python/evals/governance/report.json +371 -0
  38. package/python/evals/governance/run_evals.py +400 -0
  39. package/python/examples/governance_middleware_demo.py +77 -0
  40. package/python/examples/langgraph_governance_demo.py +108 -0
  41. package/python/examples/sample_itinerary.csv +6 -0
  42. package/python/examples/sample_knowledge.csv +9 -0
  43. package/python/examples/sample_transactions.csv +14 -0
  44. package/python/foxclaw/__init__.py +526 -0
  45. package/python/foxclaw/agents/__init__.py +12 -0
  46. package/python/foxclaw/agents/agents.py +35 -0
  47. package/python/foxclaw/agents/base.py +865 -0
  48. package/python/foxclaw/agents/impl/__init__.py +1 -0
  49. package/python/foxclaw/agents/impl/_helpers.py +78 -0
  50. package/python/foxclaw/agents/impl/finance.py +248 -0
  51. package/python/foxclaw/agents/impl/office.py +367 -0
  52. package/python/foxclaw/agents/impl/supervisor.py +659 -0
  53. package/python/foxclaw/agents/mixins/_context.py +151 -0
  54. package/python/foxclaw/agents/mixins/augment.py +149 -0
  55. package/python/foxclaw/agents/mixins/llm.py +66 -0
  56. package/python/foxclaw/agents/mixins/memory.py +35 -0
  57. package/python/foxclaw/agents/mixins/preference.py +81 -0
  58. package/python/foxclaw/agents/mixins/prompt.py +77 -0
  59. package/python/foxclaw/agents/mixins/skillbox.py +58 -0
  60. package/python/foxclaw/agents/mixins/tool_exec.py +443 -0
  61. package/python/foxclaw/api/__init__.py +283 -0
  62. package/python/foxclaw/api/app.py +123 -0
  63. package/python/foxclaw/api/middleware.py +317 -0
  64. package/python/foxclaw/api/routes/ahs.py +417 -0
  65. package/python/foxclaw/api/routes/attachments.py +117 -0
  66. package/python/foxclaw/api/routes/browser.py +39 -0
  67. package/python/foxclaw/api/routes/domain.py +314 -0
  68. package/python/foxclaw/api/routes/knowledge.py +163 -0
  69. package/python/foxclaw/api/routes/llm_admin.py +461 -0
  70. package/python/foxclaw/api/routes/memory.py +89 -0
  71. package/python/foxclaw/api/routes/orchestration.py +41 -0
  72. package/python/foxclaw/api/routes/recovery.py +43 -0
  73. package/python/foxclaw/api/routes/review.py +275 -0
  74. package/python/foxclaw/api/routes/search.py +37 -0
  75. package/python/foxclaw/api/routes/system.py +327 -0
  76. package/python/foxclaw/api/routes/task.py +281 -0
  77. package/python/foxclaw/api/routes/ws.py +68 -0
  78. package/python/foxclaw/api/spine.py +55 -0
  79. package/python/foxclaw/browser/__init__.py +13 -0
  80. package/python/foxclaw/browser/action/__init__.py +1 -0
  81. package/python/foxclaw/browser/action/action_executor.py +54 -0
  82. package/python/foxclaw/browser/action/action_types.py +45 -0
  83. package/python/foxclaw/browser/action/action_verifier.py +68 -0
  84. package/python/foxclaw/browser/action/url_policy.py +147 -0
  85. package/python/foxclaw/browser/adapter/__init__.py +1 -0
  86. package/python/foxclaw/browser/adapter/base_adapter.py +23 -0
  87. package/python/foxclaw/browser/adapter/web_adapter.py +46 -0
  88. package/python/foxclaw/browser/driver/__init__.py +1 -0
  89. package/python/foxclaw/browser/driver/base_driver.py +61 -0
  90. package/python/foxclaw/browser/driver/playwright_driver.py +166 -0
  91. package/python/foxclaw/browser/perception/__init__.py +1 -0
  92. package/python/foxclaw/browser/perception/dom_extractor.py +43 -0
  93. package/python/foxclaw/browser/perception/element_indexer.py +57 -0
  94. package/python/foxclaw/browser/perception/semantic_reducer.py +33 -0
  95. package/python/foxclaw/browser/perception/snapshot.py +29 -0
  96. package/python/foxclaw/browser/service.py +148 -0
  97. package/python/foxclaw/browser/session/__init__.py +1 -0
  98. package/python/foxclaw/browser/session/session_manager.py +57 -0
  99. package/python/foxclaw/capability/__init__.py +12 -0
  100. package/python/foxclaw/capability/embedding_service.py +67 -0
  101. package/python/foxclaw/channels/__init__.py +140 -0
  102. package/python/foxclaw/channels/discord.py +184 -0
  103. package/python/foxclaw/channels/dispatcher.py +204 -0
  104. package/python/foxclaw/channels/feishu.py +225 -0
  105. package/python/foxclaw/channels/openclaw_bridge.py +156 -0
  106. package/python/foxclaw/channels/signing.py +187 -0
  107. package/python/foxclaw/channels/telegram.py +121 -0
  108. package/python/foxclaw/channels/weixin.py +225 -0
  109. package/python/foxclaw/cli.py +154 -0
  110. package/python/foxclaw/cognitive/__init__.py +4 -0
  111. package/python/foxclaw/cognitive/reasoner.py +82 -0
  112. package/python/foxclaw/cognitive/state.py +147 -0
  113. package/python/foxclaw/core/__init__.py +9 -0
  114. package/python/foxclaw/core/audit_chain.py +133 -0
  115. package/python/foxclaw/core/audit_sink.py +100 -0
  116. package/python/foxclaw/core/compaction.py +283 -0
  117. package/python/foxclaw/core/config.py +65 -0
  118. package/python/foxclaw/core/confirm_nonce.py +157 -0
  119. package/python/foxclaw/core/dispatch.py +27 -0
  120. package/python/foxclaw/core/envfile.py +48 -0
  121. package/python/foxclaw/core/failure_policy.py +151 -0
  122. package/python/foxclaw/core/gateway.py +85 -0
  123. package/python/foxclaw/core/governance_audit.py +175 -0
  124. package/python/foxclaw/core/idempotency.py +289 -0
  125. package/python/foxclaw/core/injection_guard.py +221 -0
  126. package/python/foxclaw/core/memory_adapter.py +516 -0
  127. package/python/foxclaw/core/metrics.py +89 -0
  128. package/python/foxclaw/core/model_router.py +1097 -0
  129. package/python/foxclaw/core/paths.py +103 -0
  130. package/python/foxclaw/core/recovery.py +362 -0
  131. package/python/foxclaw/core/scheduler.py +144 -0
  132. package/python/foxclaw/core/secrets.py +134 -0
  133. package/python/foxclaw/core/sessions.py +157 -0
  134. package/python/foxclaw/core/settings.py +430 -0
  135. package/python/foxclaw/core/shared_write.py +198 -0
  136. package/python/foxclaw/core/steering_queue.py +153 -0
  137. package/python/foxclaw/core/system_bus.py +84 -0
  138. package/python/foxclaw/core/thought_chain.py +318 -0
  139. package/python/foxclaw/core/token_meter.py +235 -0
  140. package/python/foxclaw/core/tools.py +172 -0
  141. package/python/foxclaw/core/tracing.py +390 -0
  142. package/python/foxclaw/core/truth_pipeline.py +114 -0
  143. package/python/foxclaw/core/vec_recall_adapter.py +503 -0
  144. package/python/foxclaw/core/verify.py +181 -0
  145. package/python/foxclaw/core/web_search.py +242 -0
  146. package/python/foxclaw/finance/__init__.py +15 -0
  147. package/python/foxclaw/finance/evidence.py +153 -0
  148. package/python/foxclaw/finance/fx.py +100 -0
  149. package/python/foxclaw/finance/graph.py +188 -0
  150. package/python/foxclaw/finance/models.py +150 -0
  151. package/python/foxclaw/finance/nlparse.py +575 -0
  152. package/python/foxclaw/finance/policy.py +329 -0
  153. package/python/foxclaw/finance/reasoner.py +129 -0
  154. package/python/foxclaw/finance/reasoning.py +340 -0
  155. package/python/foxclaw/finance/reconcile.py +180 -0
  156. package/python/foxclaw/finance/runtime.py +527 -0
  157. package/python/foxclaw/governance/__init__.py +24 -0
  158. package/python/foxclaw/governance/middleware.py +184 -0
  159. package/python/foxclaw/harness/__init__.py +17 -0
  160. package/python/foxclaw/harness/_base.py +72 -0
  161. package/python/foxclaw/harness/_policy.py +359 -0
  162. package/python/foxclaw/harness/drift.py +89 -0
  163. package/python/foxclaw/harness/event_bus.py +31 -0
  164. package/python/foxclaw/harness/harness.py +446 -0
  165. package/python/foxclaw/harness/loop_detection.py +152 -0
  166. package/python/foxclaw/itinerary/__init__.py +10 -0
  167. package/python/foxclaw/itinerary/amap_client.py +117 -0
  168. package/python/foxclaw/itinerary/models.py +80 -0
  169. package/python/foxclaw/itinerary/reasoner.py +101 -0
  170. package/python/foxclaw/itinerary/reasoning.py +174 -0
  171. package/python/foxclaw/itinerary/runtime.py +148 -0
  172. package/python/foxclaw/kernel/__init__.py +13 -0
  173. package/python/foxclaw/kernel/capabilities.py +73 -0
  174. package/python/foxclaw/kernel/policy_gate.py +114 -0
  175. package/python/foxclaw/kernel/process_manager.py +205 -0
  176. package/python/foxclaw/kernel/scheduler.py +131 -0
  177. package/python/foxclaw/kernel/sentinel.py +453 -0
  178. package/python/foxclaw/kernel/sentinel_client.py +246 -0
  179. package/python/foxclaw/kernel/spine.py +97 -0
  180. package/python/foxclaw/knowledge/__init__.py +376 -0
  181. package/python/foxclaw/knowledge/truth_crystallizer.py +92 -0
  182. package/python/foxclaw/learning/__init__.py +12 -0
  183. package/python/foxclaw/learning/knowledge_graph.py +149 -0
  184. package/python/foxclaw/learning/models.py +93 -0
  185. package/python/foxclaw/learning/reasoner.py +70 -0
  186. package/python/foxclaw/learning/runtime.py +363 -0
  187. package/python/foxclaw/learning/spaced_repetition.py +96 -0
  188. package/python/foxclaw/mcp_server.py +189 -0
  189. package/python/foxclaw/orchestration/__init__.py +184 -0
  190. package/python/foxclaw/pipeline/__init__.py +23 -0
  191. package/python/foxclaw/pipeline/cognitive_pipeline.py +481 -0
  192. package/python/foxclaw/pipeline/supervisor_stages.py +230 -0
  193. package/python/foxclaw/planning/__init__.py +17 -0
  194. package/python/foxclaw/planning/llm_planner.py +232 -0
  195. package/python/foxclaw/planning/planner.py +99 -0
  196. package/python/foxclaw/search/__init__.py +24 -0
  197. package/python/foxclaw/search/agent_port.py +194 -0
  198. package/python/foxclaw/search/evidence.py +113 -0
  199. package/python/foxclaw/search/external_search.py +50 -0
  200. package/python/foxclaw/search/hkc_read_port.py +60 -0
  201. package/python/foxclaw/search/internal_search.py +73 -0
  202. package/python/foxclaw/search/models.py +129 -0
  203. package/python/foxclaw/search/planner.py +44 -0
  204. package/python/foxclaw/search/retriever.py +39 -0
  205. package/python/foxclaw/search/runtime.py +134 -0
  206. package/python/foxclaw/search/strategy.py +44 -0
  207. package/python/foxclaw/skills/__init__.py +613 -0
  208. package/python/foxclaw/skills/hooks_spec.py +73 -0
  209. package/python/foxclaw/skills/lifecycle.py +278 -0
  210. package/python/foxclaw/skills/markdown_skill.py +174 -0
  211. package/python/foxclaw/skills/markdown_store.py +39 -0
  212. package/python/foxclaw/skills/mcp_client.py +190 -0
  213. package/python/foxclaw/skills/mcp_store.py +43 -0
  214. package/python/foxclaw/skills/permission.py +180 -0
  215. package/python/foxclaw/skills/pipeline.py +386 -0
  216. package/python/foxclaw/skills/policy.py +80 -0
  217. package/python/foxclaw/skills/review.py +72 -0
  218. package/python/foxclaw/skills/store.py +57 -0
  219. package/python/frontend/assets/core_bg.jpg +0 -0
  220. package/python/frontend/deck/auth.js +32 -0
  221. package/python/frontend/deck/chat_model_picker.js +537 -0
  222. package/python/frontend/deck/domain.js +296 -0
  223. package/python/frontend/deck/main.js +1950 -0
  224. package/python/frontend/deck/markdown.js +48 -0
  225. package/python/frontend/deck/settings.js +324 -0
  226. package/python/frontend/deck/state.js +6 -0
  227. package/python/frontend/deck/util.js +6 -0
  228. package/python/frontend/deck/visuals.js +212 -0
  229. package/python/frontend/deck.css +855 -0
  230. package/python/frontend/deck.html +686 -0
  231. package/python/frontend/deck_v2.html +341 -0
  232. package/python/frontend/planet/index.html +266 -0
  233. package/python/frontend/planet/planet.css +579 -0
  234. package/python/frontend/planet/planet.js +1637 -0
  235. package/python/frontend/planet/vendor/three.core.min.js +6 -0
  236. package/python/frontend/planet/vendor/three.module.min.js +6 -0
  237. package/python/frontend/v3/assets/index-BD7VPbMV.js +33 -0
  238. package/python/frontend/v3/assets/index-CAvnYWGH.css +1 -0
  239. package/python/frontend/v3/index.html +15 -0
  240. package/python/frontend/widget_runtime.js +295 -0
  241. package/python/frontend/widgets.js +696 -0
  242. package/python/frontend_src/index.html +14 -0
  243. package/python/frontend_src/package-lock.json +1376 -0
  244. package/python/frontend_src/package.json +19 -0
  245. package/python/frontend_src/src/App.vue +62 -0
  246. package/python/frontend_src/src/api.js +89 -0
  247. package/python/frontend_src/src/components/ChatDock.vue +377 -0
  248. package/python/frontend_src/src/components/ComposerMenu.vue +75 -0
  249. package/python/frontend_src/src/components/DocViewer.vue +171 -0
  250. package/python/frontend_src/src/components/Inspector.vue +241 -0
  251. package/python/frontend_src/src/components/LeftRail.vue +394 -0
  252. package/python/frontend_src/src/components/MenuPopover.vue +130 -0
  253. package/python/frontend_src/src/components/MessageStream.vue +401 -0
  254. package/python/frontend_src/src/components/ModelPicker.vue +355 -0
  255. package/python/frontend_src/src/components/QuickIngest.vue +118 -0
  256. package/python/frontend_src/src/components/Stage.vue +226 -0
  257. package/python/frontend_src/src/components/ToolMenu.vue +144 -0
  258. package/python/frontend_src/src/components/TopBar.vue +90 -0
  259. package/python/frontend_src/src/components/panels/ActivityPanel.vue +84 -0
  260. package/python/frontend_src/src/components/panels/AgentsPanel.vue +86 -0
  261. package/python/frontend_src/src/components/panels/KnowledgePanel.vue +441 -0
  262. package/python/frontend_src/src/components/panels/MemoryPanel.vue +118 -0
  263. package/python/frontend_src/src/components/panels/PanelBox.vue +51 -0
  264. package/python/frontend_src/src/components/panels/ReviewPanel.vue +308 -0
  265. package/python/frontend_src/src/components/panels/SettingsPanel.vue +254 -0
  266. package/python/frontend_src/src/components/panels/TasksPanel.vue +74 -0
  267. package/python/frontend_src/src/components/panels/ToolsPanel.vue +640 -0
  268. package/python/frontend_src/src/components/panels/UsagePanel.vue +105 -0
  269. package/python/frontend_src/src/lib/fmt.js +48 -0
  270. package/python/frontend_src/src/lib/md.js +204 -0
  271. package/python/frontend_src/src/main.js +7 -0
  272. package/python/frontend_src/src/stores/app.js +106 -0
  273. package/python/frontend_src/src/stores/chat.js +484 -0
  274. package/python/frontend_src/src/stores/model.js +104 -0
  275. package/python/frontend_src/src/stores/panels.js +330 -0
  276. package/python/frontend_src/src/styles/base.css +138 -0
  277. package/python/frontend_src/src/styles/panel.css +117 -0
  278. package/python/frontend_src/src/styles/tokens.css +78 -0
  279. package/python/frontend_src/vite.config.js +46 -0
  280. package/python/pyproject.toml +265 -0
  281. package/python/skills/README.md +123 -0
  282. package/python/skills/execution-contract/SKILL.md +30 -0
  283. package/python/skills/general-assistant/SKILL.md +34 -0
  284. package/python/skills/planner/SKILL.md +33 -0
  285. package/python/skills/schedule-itinerary/SKILL.md +35 -0
  286. package/python/skills/skill-composition/SKILL.md +31 -0
  287. package/python/skills/skill-guard/SKILL.md +67 -0
  288. package/python/skills/skill-memory/SKILL.md +50 -0
  289. package/python/skills/skill-router/SKILL.md +35 -0
  290. package/python/tests/conftest.py +76 -0
  291. package/python/tests/run_all.py +263 -0
  292. package/python/tests/test_agent_lifecycle.py +360 -0
  293. package/python/tests/test_ahs_p2.py +414 -0
  294. package/python/tests/test_anthropic_tools.py +206 -0
  295. package/python/tests/test_api.py +87 -0
  296. package/python/tests/test_api_auth.py +83 -0
  297. package/python/tests/test_api_host_guard.py +69 -0
  298. package/python/tests/test_attachments.py +167 -0
  299. package/python/tests/test_audit_chain.py +121 -0
  300. package/python/tests/test_audit_sink.py +136 -0
  301. package/python/tests/test_browser.py +153 -0
  302. package/python/tests/test_browser_request_guard.py +184 -0
  303. package/python/tests/test_capabilities.py +158 -0
  304. package/python/tests/test_channel_signing.py +192 -0
  305. package/python/tests/test_channel_trust.py +109 -0
  306. package/python/tests/test_channels.py +184 -0
  307. package/python/tests/test_cli.py +46 -0
  308. package/python/tests/test_compaction_toolpair.py +119 -0
  309. package/python/tests/test_config_layering.py +65 -0
  310. package/python/tests/test_confirm_nonce.py +197 -0
  311. package/python/tests/test_context_compaction_wiring.py +130 -0
  312. package/python/tests/test_dispatch.py +95 -0
  313. package/python/tests/test_domain_evals.py +403 -0
  314. package/python/tests/test_domain_import.py +78 -0
  315. package/python/tests/test_domain_reasoners.py +148 -0
  316. package/python/tests/test_e2e.py +178 -0
  317. package/python/tests/test_emb_cache.py +107 -0
  318. package/python/tests/test_embedding_singleton.py +89 -0
  319. package/python/tests/test_envfile.py +83 -0
  320. package/python/tests/test_evals_smoke.py +114 -0
  321. package/python/tests/test_event_spine.py +182 -0
  322. package/python/tests/test_evidence_semantic.py +101 -0
  323. package/python/tests/test_evidence_sse.py +97 -0
  324. package/python/tests/test_file_ingest.py +146 -0
  325. package/python/tests/test_finance.py +153 -0
  326. package/python/tests/test_finance_ledger.py +252 -0
  327. package/python/tests/test_finance_persist.py +178 -0
  328. package/python/tests/test_gateway.py +144 -0
  329. package/python/tests/test_governance.py +468 -0
  330. package/python/tests/test_governance_audit.py +359 -0
  331. package/python/tests/test_governance_middleware.py +143 -0
  332. package/python/tests/test_hkc.py +286 -0
  333. package/python/tests/test_hkc_index_build_manager.py +339 -0
  334. package/python/tests/test_hkc_manifest_reuse.py +317 -0
  335. package/python/tests/test_hkc_search_event_sync.py +533 -0
  336. package/python/tests/test_import_path_guard.py +161 -0
  337. package/python/tests/test_injection_guard.py +211 -0
  338. package/python/tests/test_integration.py +141 -0
  339. package/python/tests/test_itinerary.py +103 -0
  340. package/python/tests/test_kee_semantic.py +89 -0
  341. package/python/tests/test_kernel.py +222 -0
  342. package/python/tests/test_learning.py +110 -0
  343. package/python/tests/test_llm_admin.py +160 -0
  344. package/python/tests/test_llm_planner.py +366 -0
  345. package/python/tests/test_markdown_skills.py +73 -0
  346. package/python/tests/test_markdown_skills_openclaw.py +71 -0
  347. package/python/tests/test_mcp_connectors.py +109 -0
  348. package/python/tests/test_mcp_guardian_discovery.py +91 -0
  349. package/python/tests/test_mcp_no_memory.py +43 -0
  350. package/python/tests/test_mcp_policy_gate.py +77 -0
  351. package/python/tests/test_mcp_server.py +95 -0
  352. package/python/tests/test_memory_recall.py +95 -0
  353. package/python/tests/test_metrics.py +66 -0
  354. package/python/tests/test_multi_chain.py +102 -0
  355. package/python/tests/test_multimodal.py +135 -0
  356. package/python/tests/test_negotiation.py +146 -0
  357. package/python/tests/test_orchestration.py +119 -0
  358. package/python/tests/test_orchestration_decoupled.py +109 -0
  359. package/python/tests/test_p3_p5_hardening.py +338 -0
  360. package/python/tests/test_parallel_dispatch.py +215 -0
  361. package/python/tests/test_pipeline.py +533 -0
  362. package/python/tests/test_plan_visible.py +86 -0
  363. package/python/tests/test_planner.py +95 -0
  364. package/python/tests/test_policy_gate.py +109 -0
  365. package/python/tests/test_reasoner.py +185 -0
  366. package/python/tests/test_release_check.py +263 -0
  367. package/python/tests/test_resume_checkpoint.py +156 -0
  368. package/python/tests/test_routing.py +95 -0
  369. package/python/tests/test_scheduler.py +141 -0
  370. package/python/tests/test_search.py +204 -0
  371. package/python/tests/test_secrets.py +159 -0
  372. package/python/tests/test_semantic.py +78 -0
  373. package/python/tests/test_sessions.py +91 -0
  374. package/python/tests/test_settings.py +281 -0
  375. package/python/tests/test_shadow_learning.py +330 -0
  376. package/python/tests/test_shared_write.py +207 -0
  377. package/python/tests/test_skill_taint_gate.py +154 -0
  378. package/python/tests/test_skills.py +133 -0
  379. package/python/tests/test_stats_and_events.py +165 -0
  380. package/python/tests/test_streaming.py +60 -0
  381. package/python/tests/test_supervisor_pipeline.py +177 -0
  382. package/python/tests/test_supervisor_triage.py +108 -0
  383. package/python/tests/test_taint.py +117 -0
  384. package/python/tests/test_task_stream.py +85 -0
  385. package/python/tests/test_thinking_sse.py +67 -0
  386. package/python/tests/test_thinking_stream.py +76 -0
  387. package/python/tests/test_tool_center.py +129 -0
  388. package/python/tests/test_tool_parallel.py +113 -0
  389. package/python/tests/test_tool_params.py +103 -0
  390. package/python/tests/test_tool_use.py +242 -0
  391. package/python/tests/test_toplevel_concurrency.py +117 -0
  392. package/python/tests/test_tracing.py +290 -0
  393. package/python/tests/test_truth_crystallizer.py +127 -0
  394. package/python/tests/test_truth_flow.py +93 -0
  395. package/python/tests/test_url_policy.py +53 -0
  396. package/python/tests/test_verify_evidence.py +225 -0
  397. package/python/tests/test_version_sync.py +71 -0
  398. package/python/tests/test_web_trigger.py +99 -0
  399. package/python/tools/check_faiss_type.py +31 -0
  400. package/python/tools/check_log.ps1 +46 -0
  401. package/python/tools/ivf_status.py +72 -0
  402. package/python/tools/mypy_baseline.txt +5 -0
  403. package/python/tools/mypy_ratchet.py +97 -0
  404. package/python/tools/pack.py +178 -0
  405. package/python/tools/release_check.py +349 -0
  406. package/python/tools/restart_foxclaw.ps1 +74 -0
  407. package/python/tools/shared_write_audit.py +204 -0
  408. package/python/tools/size_baseline.txt +28 -0
  409. package/python/tools/size_check.py +102 -0
  410. package/python/tools/verify_env.bat +2 -0
  411. package/python/tools/verify_env.py +25 -0
  412. package/python/vendor/HMR_LICENSE +37 -0
  413. package/python/vendor/HMR_README.md +65 -0
  414. package/python/vendor/hkc/LICENSE +37 -0
  415. package/python/vendor/hkc/hkc_ace/__init__.py +0 -0
  416. package/python/vendor/hkc/hkc_ace/ace.py +457 -0
  417. package/python/vendor/hkc/hkc_ace/skill_taxonomy.json +465 -0
  418. package/python/vendor/hkc/hkc_api/__init__.py +0 -0
  419. package/python/vendor/hkc/hkc_api/container.py +416 -0
  420. package/python/vendor/hkc/hkc_api/ingest_jobs.py +103 -0
  421. package/python/vendor/hkc/hkc_api/main.py +157 -0
  422. package/python/vendor/hkc/hkc_api/routes/__init__.py +0 -0
  423. package/python/vendor/hkc/hkc_api/routes/ability.py +151 -0
  424. package/python/vendor/hkc/hkc_api/routes/config.py +51 -0
  425. package/python/vendor/hkc/hkc_api/routes/knowledge.py +630 -0
  426. package/python/vendor/hkc/hkc_api/routes/search.py +88 -0
  427. package/python/vendor/hkc/hkc_api/schemas.py +153 -0
  428. package/python/vendor/hkc/hkc_api/synthesis.py +179 -0
  429. package/python/vendor/hkc/hkc_core/__init__.py +0 -0
  430. package/python/vendor/hkc/hkc_core/graph/__init__.py +0 -0
  431. package/python/vendor/hkc/hkc_core/graph/base.py +188 -0
  432. package/python/vendor/hkc/hkc_core/graph/sqlite_store.py +789 -0
  433. package/python/vendor/hkc/hkc_core/models/__init__.py +0 -0
  434. package/python/vendor/hkc/hkc_core/models/enums.py +65 -0
  435. package/python/vendor/hkc/hkc_core/models/ku.py +307 -0
  436. package/python/vendor/hkc/hkc_core/utils/__init__.py +0 -0
  437. package/python/vendor/hkc/hkc_core/utils/id_gen.py +113 -0
  438. package/python/vendor/hkc/hkc_crystallizer/__init__.py +44 -0
  439. package/python/vendor/hkc/hkc_crystallizer/adapters.py +94 -0
  440. package/python/vendor/hkc/hkc_crystallizer/candidate.py +145 -0
  441. package/python/vendor/hkc/hkc_crystallizer/crystallizer.py +179 -0
  442. package/python/vendor/hkc/hkc_crystallizer/ingress.py +90 -0
  443. package/python/vendor/hkc/hkc_kde/__init__.py +0 -0
  444. package/python/vendor/hkc/hkc_kde/chunker.py +197 -0
  445. package/python/vendor/hkc/hkc_kde/extractor.py +623 -0
  446. package/python/vendor/hkc/hkc_kde/kde.py +298 -0
  447. package/python/vendor/hkc/hkc_kde/loaders/__init__.py +0 -0
  448. package/python/vendor/hkc/hkc_kde/loaders/ebook_loader.py +153 -0
  449. package/python/vendor/hkc/hkc_kde/loaders/office_loader.py +194 -0
  450. package/python/vendor/hkc/hkc_kde/loaders/pdf_loader.py +162 -0
  451. package/python/vendor/hkc/hkc_kde/loaders/text_loader.py +157 -0
  452. package/python/vendor/hkc/hkc_kde/loaders/web_loader.py +91 -0
  453. package/python/vendor/hkc/hkc_kde/models.py +74 -0
  454. package/python/vendor/hkc/hkc_kde/packager.py +329 -0
  455. package/python/vendor/hkc/hkc_kde/relation_disc.py +151 -0
  456. package/python/vendor/hkc/hkc_kee/__init__.py +0 -0
  457. package/python/vendor/hkc/hkc_kee/dedup.py +227 -0
  458. package/python/vendor/hkc/hkc_kee/fingerprint.py +106 -0
  459. package/python/vendor/hkc/hkc_kee/kee.py +541 -0
  460. package/python/vendor/hkc/hkc_kep/__init__.py +0 -0
  461. package/python/vendor/hkc/hkc_kep/event_bus.py +205 -0
  462. package/python/vendor/hkc/hkc_sdk/__init__.py +63 -0
  463. package/python/vendor/hkc/hkc_sdk/base.py +151 -0
  464. package/python/vendor/hkc/hkc_sdk/direct_client.py +153 -0
  465. package/python/vendor/hkc/hkc_sdk/exceptions.py +39 -0
  466. package/python/vendor/hkc/hkc_sdk/http_client.py +166 -0
  467. package/python/vendor/hkc/hkc_sdk/models.py +171 -0
  468. package/python/vendor/hkc/hkc_search/__init__.py +0 -0
  469. package/python/vendor/hkc/hkc_search/bm25.py +325 -0
  470. package/python/vendor/hkc/hkc_search/embedding_backends.py +374 -0
  471. package/python/vendor/hkc/hkc_search/graph_search.py +132 -0
  472. package/python/vendor/hkc/hkc_search/hybrid.py +331 -0
  473. package/python/vendor/hkc/hkc_search/index_build_manager.py +378 -0
  474. package/python/vendor/hkc/hkc_search/vector_search.py +484 -0
  475. package/python/vendor/hmr/__init__.py +0 -0
  476. package/python/vendor/hmr/core/__init__.py +0 -0
  477. package/python/vendor/hmr/core/hmr.py +684 -0
  478. package/python/vendor/hmr/core/models.py +310 -0
  479. package/python/vendor/hmr/engines/__init__.py +0 -0
  480. package/python/vendor/hmr/engines/evolution.py +710 -0
  481. package/python/vendor/hmr/engines/jit_compiler.py +472 -0
  482. package/python/vendor/hmr/engines/lifecycle.py +264 -0
  483. package/python/vendor/hmr/engines/policy.py +625 -0
  484. package/python/vendor/hmr/engines/recall.py +260 -0
  485. package/python/vendor/hmr/engines/runtime_state.py +158 -0
  486. package/python/vendor/hmr/engines/scheduler.py +323 -0
  487. package/python/vendor/hmr/engines/semantic.py +150 -0
  488. package/python/vendor/hmr/engines/temporal.py +261 -0
  489. package/python/vendor/hmr/engines/thought_chain.py +635 -0
  490. package/python/vendor/hmr/graph/__init__.py +0 -0
  491. package/python/vendor/hmr/graph/cwg.py +338 -0
  492. package/python/vendor/hmr/graph/memory_graph.py +530 -0
  493. package/python/vendor/hmr/storage/__init__.py +0 -0
  494. package/python/vendor/hmr/storage/memory_fs.py +300 -0
  495. package/python/vendor/hmr/storage/vector_store.py +520 -0
@@ -0,0 +1,183 @@
1
+ name: Release
2
+
3
+ # 两段式发布。为什么不能"打 tag 就自动上传":
4
+ # PyPI / npm 的版本号**不可撤回** —— 传上去只能 yank(仍占号、仍能被 pin 装到),
5
+ # 不能覆盖重发。所以 CI 的默认行为是「校验 + 构建 + 挂 GitHub Release」,
6
+ # 真正的外发必须人工触发一次 workflow_dispatch,并在 environment 里审批。
7
+ #
8
+ # 阶段一(push tag v*):版本/tag 一致性 → 构建 wheel+sdist+npm tgz → 产物结构校验
9
+ # → GitHub Release 附件(可反复重跑,错了删 tag 重来)
10
+ # 阶段二(workflow_dispatch):勾 publish=pypi/npm/both + 填 ref=tag,审批后才上传
11
+ #
12
+ # 需要预先准备(仓库 Settings):
13
+ # Environments: pypi、npm(各配 Required reviewers → 这就是"审批门")
14
+ # Secrets: PYPI_API_TOKEN(npt_... 项目级 token)、NPM_TOKEN(granular,仅 publish)
15
+ # 换 OIDC 时:PyPI 用 pending publisher、npm 用 trusted publishing,
16
+ # 把 publish-* 里的 password/NODE_AUTH_TOKEN 去掉并加 `permissions: id-token: write`。
17
+ on:
18
+ push:
19
+ tags: ["v*"]
20
+ workflow_dispatch:
21
+ inputs:
22
+ publish:
23
+ description: "上传目标(需对应 environment 审批)"
24
+ type: choice
25
+ options: ["none", "pypi", "npm", "both"]
26
+ default: "none"
27
+ ref:
28
+ description: "要构建/发布的 tag(如 v0.1.0;发布时必填)"
29
+ type: string
30
+ default: ""
31
+
32
+ permissions:
33
+ contents: read
34
+
35
+ # 同一 tag 并发跑两次发布 = 两个进程抢同一个版本号
36
+ concurrency:
37
+ group: release-${{ github.ref }}
38
+ cancel-in-progress: false
39
+
40
+ jobs:
41
+ build:
42
+ runs-on: ubuntu-latest
43
+ timeout-minutes: 15
44
+ steps:
45
+ - uses: actions/checkout@v4
46
+ with:
47
+ ref: ${{ inputs.ref || github.ref }}
48
+
49
+ - uses: actions/setup-python@v5
50
+ with:
51
+ python-version: "3.12"
52
+
53
+ - uses: actions/setup-node@v4
54
+ with:
55
+ node-version: "20"
56
+
57
+ - name: Install release toolchain
58
+ # 只装构建器,不 `pip install -e .`:构建 wheel 不需要 torch/faiss 那套运行时
59
+ # 依赖(唯一 import 的 release_check.py 是纯标准库),装了只会把 job 拖成 5 分钟。
60
+ run: |
61
+ python -m pip install --upgrade pip
62
+ pip install "build>=1.2"
63
+
64
+ # 发布必须锚定 tag:否则发出去的是分支 HEAD,版本号对不上任何 tag,
65
+ # 事后连"这版对应哪次提交"都答不上来。
66
+ - name: Require tag when publishing
67
+ if: github.event_name == 'workflow_dispatch' && inputs.publish != 'none'
68
+ env:
69
+ REF: ${{ inputs.ref }}
70
+ run: |
71
+ if [ -z "$REF" ]; then
72
+ echo "::error::publish=${{ inputs.publish }} 时必须填 ref(如 v0.1.0),不能发分支 HEAD"
73
+ exit 1
74
+ fi
75
+
76
+ - name: Version / tag gate
77
+ env:
78
+ TAG: ${{ github.event_name == 'push' && github.ref_name || inputs.ref }}
79
+ run: |
80
+ if [ -n "$TAG" ]; then
81
+ python tools/release_check.py --tag "$TAG"
82
+ else
83
+ python tools/release_check.py
84
+ fi
85
+
86
+ - name: Build wheel + sdist
87
+ run: python -m build --outdir dist
88
+
89
+ - name: Pack npm tarball
90
+ # 必须先跑 build.cjs:它把项目源码复制进 npm/python/,npm 包才算完整。
91
+ # `npm pack` 不触发 prepublishOnly(只有 publish 才触发),漏了这步打出来的
92
+ # 是 2KB 空壳——里面没有 python/,npx foxclaw 直接跑不起来。
93
+ # 同时 build.cjs 自带红线自检:含内部文档就 exit 1,构建随之失败。
94
+ working-directory: npm
95
+ run: |
96
+ node build.cjs
97
+ npm pack --pack-destination ../dist
98
+
99
+ - name: Artifact gate
100
+ # 包里出现 .env / docs/internal / 运行期数据 = 停下,不许发(宁可不出包)
101
+ run: python tools/release_check.py --dist dist --npm-tgz dist/*.tgz
102
+
103
+ - uses: actions/upload-artifact@v4
104
+ with:
105
+ name: python-dist
106
+ path: |
107
+ dist/*.whl
108
+ dist/*.tar.gz
109
+ if-no-files-found: error
110
+
111
+ - uses: actions/upload-artifact@v4
112
+ with:
113
+ name: npm-tgz
114
+ path: dist/*.tgz
115
+ if-no-files-found: error
116
+
117
+ github-release:
118
+ # 只有 tag 才挂 Release;手工触发构建不建 Release
119
+ if: startsWith(github.ref, 'refs/tags/v')
120
+ needs: build
121
+ runs-on: ubuntu-latest
122
+ permissions:
123
+ contents: write
124
+ steps:
125
+ - uses: actions/download-artifact@v4
126
+ with:
127
+ path: dist
128
+ merge-multiple: true
129
+
130
+ - name: Publish GitHub Release
131
+ env:
132
+ GH_TOKEN: ${{ github.token }}
133
+ GH_REPO: ${{ github.repository }}
134
+ TAG: ${{ github.ref_name }}
135
+ run: |
136
+ if gh release view "$TAG" >/dev/null 2>&1; then
137
+ gh release upload "$TAG" dist/* --clobber # 重跑时覆盖附件,不重建 Release
138
+ else
139
+ gh release create "$TAG" dist/* --title "$TAG" --generate-notes
140
+ fi
141
+
142
+ publish-pypi:
143
+ if: >-
144
+ github.event_name == 'workflow_dispatch' &&
145
+ (inputs.publish == 'pypi' || inputs.publish == 'both')
146
+ needs: build
147
+ runs-on: ubuntu-latest
148
+ # environment 上配 Required reviewers:这一步停在"等待审批",人点了才动
149
+ environment: pypi
150
+ steps:
151
+ - uses: actions/download-artifact@v4
152
+ with:
153
+ name: python-dist
154
+ path: dist
155
+
156
+ - name: Upload to PyPI
157
+ uses: pypa/gh-action-pypi-publish@release/v1
158
+ with:
159
+ password: ${{ secrets.PYPI_API_TOKEN }}
160
+ packages-dir: dist/
161
+
162
+ publish-npm:
163
+ if: >-
164
+ github.event_name == 'workflow_dispatch' &&
165
+ (inputs.publish == 'npm' || inputs.publish == 'both')
166
+ needs: build
167
+ runs-on: ubuntu-latest
168
+ environment: npm
169
+ steps:
170
+ - uses: actions/setup-node@v4
171
+ with:
172
+ node-version: "20"
173
+ registry-url: "https://registry.npmjs.org"
174
+
175
+ - uses: actions/download-artifact@v4
176
+ with:
177
+ name: npm-tgz
178
+ path: dist
179
+
180
+ - name: Publish to npm
181
+ env:
182
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
183
+ run: npm publish ./dist/*.tgz --access public
@@ -0,0 +1,64 @@
1
+ # syntax=docker/dockerfile:1
2
+
3
+ # Foxclaw — 认知智能体操作系统
4
+ #
5
+ # 一个镜像两种用法:
6
+ # 1) 跑服务:docker run -p 8000:8000 foxclaw
7
+ # 2) 跑全量回归(构建/CI 自检):docker run --rm foxclaw python tests/run_all.py
8
+ #
9
+ # 镜像较大(>2GB)是 sentence-transformers/torch 的代价——语义检索与治理漂移检测
10
+ # 都依赖真实 embedding,这是能力而非可裁剪项。测试锁 HF_HUB_OFFLINE 离线读预热缓存。
11
+
12
+ FROM python:3.12-slim
13
+
14
+ ENV PYTHONUNBUFFERED=1 \
15
+ PIP_NO_CACHE_DIR=1 \
16
+ PYTHONDONTWRITEBYTECODE=1 \
17
+ HF_HOME=/root/.cache/huggingface
18
+
19
+ WORKDIR /app
20
+
21
+ # 系统依赖:torch 需要 libgomp1(OpenMP 运行时)。slim 镜像默认缺失,
22
+ # 缺了会在 import torch 时报 libgomp.so.1 找不到。
23
+ RUN apt-get update \
24
+ && apt-get install -y --no-install-recommends libgomp1 \
25
+ && rm -rf /var/lib/apt/lists/*
26
+
27
+ # ── 依赖层(利用 Docker layer 缓存:改源码不重装 torch)──────────────
28
+ # 必须拷 foxclaw/ 与 vendor/ 才能 editable install(HMR/HKC 是 vendor 内嵌、
29
+ # 走 sys.path 加载,非 PyPI 依赖,见 pyproject.toml 注记)。
30
+ COPY pyproject.toml ./
31
+ COPY foxclaw/ foxclaw/
32
+ COPY vendor/ vendor/
33
+
34
+ # 依赖以 pyproject.toml 为唯一来源;dev extra 补 pytest/ruff/mypy/coverage +
35
+ # openpyxl/python-docx(默认回归 test_file_ingest/test_domain_import 硬依赖),
36
+ # 使镜像既能跑服务又能跑全量回归(与 CI 对齐)。
37
+ # 【关键】先装 CPU 版 torch:PyPI 默认 torch 在 Linux 上会拖入整套 CUDA toolkit
38
+ # (nvidia-* 十几个包 + cuda-toolkit,镜像 +4GB、下载极慢),而 Foxclaw 语义检索
39
+ # 只需 CPU。先从 PyTorch 官方 CPU index 装好 torch,sentence-transformers 见
40
+ # 约束已满足即不再重装 CUDA 版。
41
+ # --mount=type=cache 复用 pip 下载缓存:改依赖后重建无需重下 torch 等大 wheel
42
+ # --retries/--timeout:国内网络抖动时 pip 默认重试(5次/15s)偏短,会把 filelock 等
43
+ # 依赖的 index 元数据请求超时误判为"无匹配发行版"(ResolutionImpossible),放宽后更稳。
44
+ RUN --mount=type=cache,target=/root/.cache/pip pip install --upgrade pip \
45
+ && pip install --retries 8 --timeout 60 torch --index-url https://download.pytorch.org/whl/cpu \
46
+ && pip install --retries 8 --timeout 60 -e ".[dev]"
47
+
48
+ # ── 预热默认 embedding(all-MiniLM-L6-v2)────────────────────────────
49
+ # run_all.py 内部注入 HF_HUB_OFFLINE=1 离线读取。若镜像内没有缓存,
50
+ # sentence-transformers 会降级为 n-gram 哈希嵌入——对中文几乎无区分度,
51
+ # 语义漂移分恒为 1.0 → 治理测试全红(见 .github/workflows/ci.yml 的教训)。
52
+ # 故在 build 期一次性下载好,运行期离线可用、不依赖外网。
53
+ # 【HF_ENDPOINT】默认走 hf-mirror.com(国内直连 huggingface.co 常被墙、DNS 解析失败);
54
+ # 海外/CI 可 `docker build --build-arg HF_ENDPOINT= ...` 覆盖,或留空走官方 HuggingFace。
55
+ ARG HF_ENDPOINT=https://hf-mirror.com
56
+ RUN HF_ENDPOINT="${HF_ENDPOINT}" python -c "from sentence_transformers import SentenceTransformer; SentenceTransformer('all-MiniLM-L6-v2')"
57
+
58
+ # ── 其余仓库内容(frontend 前端静态 / skills / docs 等)──────────────
59
+ COPY . .
60
+
61
+ EXPOSE 8000
62
+
63
+ # 默认启动 API 服务;跑回归用:docker run --rm foxclaw python tests/run_all.py
64
+ CMD ["python", "-m", "uvicorn", "foxclaw.api:app", "--host", "0.0.0.0", "--port", "8000"]
package/python/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 snowfoxHQ
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.
@@ -0,0 +1,14 @@
1
+ # sdist 必须自带 vendor/ 下的 HMR 与 HKC —— 它们是内嵌运行时,不是 PyPI 依赖。
2
+ # 缺了它们,pip install 装出来的包记忆/知识子系统会整体降级为 None。
3
+ graft vendor
4
+ graft foxclaw
5
+
6
+ # sdist 必须带正文文件:pyproject 的 readme 指向 README_CN.md,PyPI 项目页正文取自它。
7
+ include README.md
8
+ include README_CN.md
9
+ include LICENSE
10
+
11
+ prune vendor/__pycache__
12
+ prune foxclaw/__pycache__
13
+ global-exclude *.pyc
14
+ global-exclude *.pyo
@@ -0,0 +1,192 @@
1
+ # Foxclaw · A Personal Agent with Memory
2
+
3
+ A **personal agent with memory** — to a user, an agent that remembers; to a developer, an agent runtime built on the HMR memory runtime: three collaborating agents, cross-layer Harness governance, with the memory/cognition layer fully decoupled from any LLM.
4
+
5
+ ```
6
+ Traditional frameworks: memory = storage, agents = stateless execution
7
+ Foxclaw: memory = living cognitive runtime, agents = reason · learn · evolve
8
+ ```
9
+
10
+ ## What it is
11
+
12
+ Foxclaw is not "yet another agent framework" but a personal agent that actually remembers; under the hood, an agent runtime. Its moats are independent of any LLM:
13
+
14
+ - **ThoughtChain** — each agent's reasoning is an auditable, comparable directed graph, not a log
15
+ - **Harness** — three-dimensional drift detection (semantic / tool / scope) + shadow-mode self-calibration + policy self-learning
16
+ - **Evolution** — every harness truncation teaches the policy; the system gets sharper with use
17
+ - **Runtime governance** — idempotency, crash recovery, loop detection, etc., keeping the system reliable under real-world operation
18
+
19
+ Three agents: Supervisor (coordination), Finance, Office (learning + itinerary). Each has isolated memory and policy evolution, mounts external ecosystems via the Skill layer, and connects to mainstream messaging platforms via the channel layer. The former Assistant and Admin responsibilities are now **instruction skills** (`skills/general-assistant`, `skills/schedule-itinerary`) mounted on demand, not separate agents.
20
+
21
+ ## Domain kernels
22
+
23
+ Finance / Office each mount an isomorphic kernel (pure-algorithm layer + external tool interface + gatekeeper):
24
+
25
+ - **Finance** — budget reasoning, MAD anomaly detection, cash-flow forecast; gatekeeper with four permissions, emits approval requests rather than moving money. **Advanced trio**: structured evidence chains (explainable risk), financial data graph (trace who caused an overspend), reconciliation (3-tier matching + suspicious-charge detection).
26
+ - **Office** — SM-2 spaced repetition (mastery + forgetting risk) + knowledge graph (cluster discovery).
27
+ - **Office · itinerary** — TSP routing, reachability ("won't make it") detection, time conflicts, geo-clustering; integrates Amap.
28
+
29
+ ## Messaging platforms
30
+
31
+ Four mainstream platforms via a unified channel abstraction, **each adapter implemented to its own official spec** (not one mold):
32
+
33
+ | Channel | Model | Credential |
34
+ |---------|-------|-----------|
35
+ | WeChat | iLink Bot API, long-poll + context_token | scan-login token |
36
+ | Feishu | event-subscription webhook + signature + token refresh | App ID/Secret |
37
+ | Telegram | Bot API getUpdates polling | bot token |
38
+ | Discord | Gateway WebSocket + REST | bot token |
39
+
40
+ Closed loop (`ChannelDispatcher`): receive → Supervisor → reply to origin, with per-channel session isolation and idempotent dedup. See [docs/CHANNELS.md](docs/CHANNELS.md).
41
+
42
+ ## Runtime governance
43
+
44
+ Keeps the system reliable under message redelivery, crashes, long tasks, and loops. See [docs/GOVERNANCE.md](docs/GOVERNANCE.md): idempotency guard, crash/restart recovery (boot_id avoids pid reuse), tool-loop detection, context compaction, hook standardization, steering queue.
45
+
46
+ ## Quick start
47
+
48
+ ```bash
49
+ pip install fastapi uvicorn "httpx<0.28" openai cryptography websockets pyyaml numpy scikit-learn rich pydantic
50
+ python tests/run_all.py # full regression (all green)
51
+ export DEEPSEEK_API_KEY=sk-... # or ANTHROPIC_API_KEY; unset → stub
52
+ python -m uvicorn foxclaw.api:app --port 8000
53
+ ```
54
+
55
+ See [docs/RUN.md](docs/RUN.md). Chinese docs: [README_CN.md](README_CN.md).
56
+
57
+ > **Windows**: don't place the project under OneDrive-managed folders (Documents/Desktop/Pictures); Python can't create dirs inside redirect placeholders. Use a path like `C:\foxclaw`.
58
+
59
+ ## Knowledge base (HKC) model config
60
+
61
+ HKC's knowledge base uses **two different types of models**, each for one job, both configured in `.env` — no code changes:
62
+
63
+ | Stage | Model type | What it does | Config keys |
64
+ |-------|-----------|-------------|-------------|
65
+ | Write (ingesting books/files) | **Generative LLM** (reads & emits JSON) | Extracts entities / concepts / facts / claims from each chunk | `HKC_LLM_*` |
66
+ | Retrieve (querying) | **embedding** (text → vector) | Vectorizes knowledge & queries, ranks by semantic similarity | `HKC_EMBEDDING_*` |
67
+
68
+ They are not interchangeable: an embedding model cannot generate text (can't produce JSON), and an LLM is not suited to vector search.
69
+
70
+ ### First, pick your case
71
+
72
+ | Your environment | Extraction model setup | `HKC_LLM_API_KEY` value |
73
+ |---|---|---|
74
+ | Have local Ollama | `openai-compatible` + `base_url` pointing at Ollama | **any non-empty value** (Ollama ignores it; `ollama` is just a placeholder) |
75
+ | No local model | Use a **public cloud model** (DeepSeek / OpenAI / Qwen …), see table | the platform's **real API key** |
76
+
77
+ ### Case A · local Ollama
78
+
79
+ ```bash
80
+ HKC_LLM_PROVIDER=openai-compatible
81
+ HKC_LLM_API_KEY=ollama # placeholder only for local Ollama; never use this for cloud
82
+ HKC_LLM_MODEL=my-qwen-32k:latest # a model name from your `ollama list`
83
+ HKC_LLM_BASE_URL=http://localhost:11434/v1 # Ollama's OpenAI-compatible endpoint
84
+ HKC_LLM_TIMEOUT=180 # local models are slow; relax the default 60s
85
+ HKC_EXTRACT_CONCURRENCY=2 # 1–2 for local, up to 5 for cloud APIs
86
+ HKC_EXTRACT_BATCH=8 # optional: extract N chunks per call, saves tokens & time; default 1 = per-chunk
87
+ HKC_MAX_CHUNKS_PER_DOC=800 # optional: per-doc chunk cap; default 800 (~1.25M chars); 0 = no cap, see below
88
+ ```
89
+
90
+ ### Case B · public cloud model (no local model)
91
+
92
+ `HKC_LLM_MODEL` is the platform's **public model id** (passed through verbatim); `HKC_LLM_API_KEY` is the platform's **real key**:
93
+
94
+ | Platform | `HKC_LLM_PROVIDER` | `HKC_LLM_API_KEY` | `HKC_LLM_MODEL` example | `HKC_LLM_BASE_URL` |
95
+ |---|---|---|---|---|
96
+ | DeepSeek | `deepseek` | `sk-...` (DeepSeek key) | `deepseek-chat` / `deepseek-reasoner` | leave blank (official default) |
97
+ | OpenAI | `openai` | `sk-...` (OpenAI key) | `gpt-4o-mini` / `gpt-4o` | leave blank |
98
+ | Qwen (Alibaba) | `openai-compatible` | DashScope key | `qwen-max` / `qwen-plus` | `https://dashscope.aliyuncs.com/compatible-mode/v1` |
99
+ | Zhipu / Moonshot / MiniMax … | `openai-compatible` | that platform's key | that platform's model id | that platform's OpenAI-compatible URL |
100
+
101
+ DeepSeek example:
102
+
103
+ ```bash
104
+ HKC_LLM_PROVIDER=deepseek
105
+ HKC_LLM_API_KEY=sk-your-deepseek-key
106
+ HKC_LLM_MODEL=deepseek-chat
107
+ ```
108
+
109
+ ### Retrieval model (embedding)
110
+
111
+ The retrieval model does **not** use Ollama; it uses sentence-transformers, and auto-downloads weights from HuggingFace when missing locally:
112
+
113
+ ```bash
114
+ HKC_EMBEDDING=local
115
+ HKC_EMBEDDING_MODEL=BAAI/bge-m3 # auto-downloads on first use (~2.2 GB); or a local path like C:\...\bge-m3
116
+ ```
117
+
118
+ Leave it unset if you don't need semantic precision (defaults to `stub` pseudo-semantics, works out of the box).
119
+
120
+ ### Where to put the key, and precedence
121
+
122
+ - **`.env` is the source of truth** — read at startup; restart after editing.
123
+ - The "extraction model" section in the planet page's connection settings is an **optional runtime override** (stored in browser localStorage, may override `.env` on refresh); leave it blank to always follow `.env`.
124
+ - The page's first "API Key" field is the backend auth token (`.env`'s `FOXCLAW_API_KEY`), unrelated to the model keys.
125
+
126
+ > Note: switching the embedding model changes the vector dimension (e.g. 384 → 1024), so you must rebuild the knowledge index (clear and re-ingest).
127
+
128
+ ### How much can I ingest at once?
129
+
130
+ **The limits are hard — exceeding them returns an error, never a silent truncation:**
131
+
132
+ | Entry point | Limit | On overflow |
133
+ |---|---|---|
134
+ | File upload (`/knowledge/ingest/file`, `/ingest/file/async`) | **20 MB per file** | `413 file too large` |
135
+ | Pasted text (`/knowledge/ingest/text`) | **2,000,000 characters** | `413 text too large` |
136
+ | Chunks per document | **800 by default** (~1.25M chars); `HKC_MAX_CHUNKS_PER_DOC=0` disables the cap | Only the first N chunks are processed, with a "document too large" warning |
137
+
138
+ Supported formats: `.pdf` `.md` `.markdown` `.txt` `.epub` `.mobi` `.azw3` `.azw` `.docx` `.xlsx`. `.doc` is not supported, and **scanned PDFs get no OCR** — image-only pages yield no text at all.
139
+
140
+ **A chunk is the billing and timing unit**, and it is fixed:
141
+
142
+ ```
143
+ max 1792 chars per chunk, 224 chars of overlap
144
+ → roughly 1 chunk per 1568 characters
145
+ ```
146
+
147
+ **Time and cost reference** (batch=4, concurrency=8, cloud DeepSeek, CJK content):
148
+
149
+ | Content | File size | Chunks | Expected time |
150
+ |---|---|---|---|
151
+ | 100k chars | ~100 KB | ~64 | ~6 min |
152
+ | 500k chars | ~500 KB | ~320 | ~32 min |
153
+ | 1M chars | ~1 MB | ~640 | ~1 hour |
154
+ | 7M chars (ceiling) | ~20 MB | ~4400 | ~7 hours |
155
+
156
+ Token ratio: **~4k input + 2k output tokens per 10k characters** (batch extraction already amortizes the system prompt) — multiply by your provider's rates. English content is 2–3× the characters of CJK for the same bytes, so it costs proportionally more.
157
+
158
+ **Practical guidance:**
159
+
160
+ - **Keep single files at 2–5 MB.** That covers an ordinary ebook, finishes within tens of minutes, and lets you watch progress.
161
+ - **Leave `HKC_MAX_CHUNKS_PER_DOC` at its default of 800.** Read the section below before lifting it — the reason is not just "it's slow".
162
+ - **Use file upload, not paste, for anything long.** `/ingest/text` is synchronous and holds the request; `/ingest/file/async` runs in a background thread and exposes `processed/total` progress.
163
+ - **Re-uploading the same file is free.** Content SHA-256 is checked first and duplicates return `409 already ingested`.
164
+ - **When extraction fails, check the log keyword first.** "JSON parse failed" means the model's output was cut off mid-JSON (common with dense CJK documents) — lower `HKC_EXTRACT_BATCH` or raise `HKC_EXTRACT_MAX_TOKENS` (default 8192, the output ceiling). Only when that keyword is absent should you check the API key or network.
165
+
166
+ ### Per-document chunk cap: why the default is 800
167
+
168
+ `HKC_MAX_CHUNKS_PER_DOC` defaults to **800 chunks**, chosen as the intersection of "covers real documents completely" and "finishes in a time you can sit through, at a cost you can predict":
169
+
170
+ | Cap | Characters covered | Chunks | Expected time | Cost (cloud) |
171
+ |---|---|---|---|---|
172
+ | **800 (default)** | ~1.25M | 800 | ~1.3 hours | ~$0.4 |
173
+ | 2000 | ~3.1M | 2000 | ~3.3 hours | ~$1 |
174
+ | 0 (uncapped, i.e. a full 20 MB file) | ~7M | ~4400 | **7+ hours** | ~$2.3 |
175
+
176
+ > Costs are rough order-of-magnitude estimates at DeepSeek list prices; scale for your provider.
177
+
178
+ **Why not raise it (and especially not to 0):** uploads accept up to 20 MB. With no chunk cap, one accidental upload — a 20 MB scanned PDF, a rotated log dump — runs in the background for the better part of a day while billing the whole time. Ingestion runs on a background thread with no checkpoint and no rollback button: you either watch it finish or kill the whole service. The default exists to stop obviously unreasonable volumes up front, not to be as restrictive as possible.
179
+
180
+ **Why not shrink it either:** past the cap only the first N chunks are processed, and the **whole file's SHA-256 is already recorded** as ingested. Re-uploading the same file is rejected with `409`. So a truncated ingest cannot be completed by "raising the cap and sending it again" — you must split the file by chapter and upload the parts separately. 800 chunks leaves enough headroom that ordinary documents and normal ebooks never hit the cap.
181
+
182
+ **If you genuinely need a whole book,** raise the cap (or set 0) for that one ingest and set it back to 800 afterwards. A "document too large: split into N chunks" warning in the log means truncation happened, and it reports how much was dropped.
183
+
184
+ ## Philosophy
185
+
186
+ Memory and cognition are fully decoupled from the LLM. The model is a replaceable text generator; the real moat (ThoughtChain audit + Harness drift + policy self-learning + domain kernels) exists independently of any model.
187
+
188
+ ## License
189
+
190
+ MIT — see [LICENSE](LICENSE). Use it, modify it, ship it, sell it; just keep the copyright notice.
191
+
192
+ The runtimes vendored under `vendor/` keep their own licenses (see `vendor/hkc/LICENSE`).