claude-smart 0.2.45 → 0.2.47

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 (353) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/README.md +47 -10
  3. package/bin/claude-smart.js +535 -23
  4. package/package.json +22 -3
  5. package/plugin/.claude-plugin/plugin.json +4 -2
  6. package/plugin/.codex-plugin/plugin.json +1 -1
  7. package/plugin/README.md +27 -6
  8. package/plugin/commands/clear-all.md +1 -0
  9. package/plugin/commands/dashboard.md +1 -0
  10. package/plugin/commands/learn.md +1 -0
  11. package/plugin/commands/restart.md +1 -0
  12. package/plugin/commands/show.md +1 -0
  13. package/plugin/dashboard/app/configure/env/page.tsx +40 -14
  14. package/plugin/dashboard/app/configure/server/page.tsx +51 -1
  15. package/plugin/dashboard/app/layout.tsx +20 -0
  16. package/plugin/dashboard/app/preferences/[id]/page.tsx +8 -8
  17. package/plugin/dashboard/app/skills/project/[id]/page.tsx +7 -3
  18. package/plugin/dashboard/app/skills/shared/[id]/page.tsx +10 -3
  19. package/plugin/dashboard/lib/claude-settings-file.ts +20 -10
  20. package/plugin/dashboard/lib/reflexio-client.ts +16 -0
  21. package/plugin/dashboard/lib/status.ts +10 -3
  22. package/plugin/dashboard/lib/types.ts +18 -6
  23. package/plugin/hooks/codex-hooks.json +0 -1
  24. package/plugin/opencode/assistant-buffer.ts +108 -0
  25. package/plugin/opencode/dist/assistant-buffer.js +96 -0
  26. package/plugin/opencode/dist/internal.js +12 -0
  27. package/plugin/opencode/dist/payload.js +85 -0
  28. package/plugin/opencode/dist/server.mjs +232 -0
  29. package/plugin/opencode/internal.ts +18 -0
  30. package/plugin/opencode/package.json +3 -0
  31. package/plugin/opencode/payload.ts +90 -0
  32. package/plugin/opencode/server.mts +251 -0
  33. package/plugin/opencode/tsconfig.json +13 -0
  34. package/plugin/pyproject.toml +25 -4
  35. package/plugin/scripts/_lib.sh +5 -1
  36. package/plugin/scripts/backend-service.sh +22 -2
  37. package/plugin/scripts/ensure-plugin-root.sh +4 -4
  38. package/plugin/scripts/hook_entry.sh +1 -1
  39. package/plugin/scripts/opencode-claude-compat +4 -0
  40. package/plugin/scripts/opencode-claude-compat.cmd +3 -0
  41. package/plugin/scripts/opencode-claude-compat.js +225 -0
  42. package/plugin/scripts/smart-install.sh +17 -9
  43. package/plugin/src/README.md +1 -1
  44. package/plugin/src/claude_smart/cli.py +498 -12
  45. package/plugin/src/claude_smart/context_format.py +9 -9
  46. package/plugin/src/claude_smart/cs_cite.py +66 -19
  47. package/plugin/src/claude_smart/env_config.py +12 -4
  48. package/plugin/src/claude_smart/events/session_start.py +26 -7
  49. package/plugin/src/claude_smart/events/stop.py +1 -1
  50. package/plugin/src/claude_smart/ids.py +1 -1
  51. package/plugin/src/claude_smart/reflexio_adapter.py +5 -5
  52. package/plugin/src/claude_smart/runtime.py +7 -1
  53. package/plugin/uv.lock +5 -5
  54. package/plugin/vendor/reflexio/.env.example +54 -30
  55. package/plugin/vendor/reflexio/README.md +17 -11
  56. package/plugin/vendor/reflexio/pyproject.toml +13 -1
  57. package/plugin/vendor/reflexio/reflexio/README.md +4 -1
  58. package/plugin/vendor/reflexio/reflexio/cli/README.md +9 -7
  59. package/plugin/vendor/reflexio/reflexio/cli/__main__.py +10 -1
  60. package/plugin/vendor/reflexio/reflexio/cli/bootstrap_config.py +22 -5
  61. package/plugin/vendor/reflexio/reflexio/cli/commands/interactions.py +34 -4
  62. package/plugin/vendor/reflexio/reflexio/cli/commands/profiles.py +12 -7
  63. package/plugin/vendor/reflexio/reflexio/cli/commands/services.py +13 -6
  64. package/plugin/vendor/reflexio/reflexio/cli/commands/setup_cmd.py +212 -52
  65. package/plugin/vendor/reflexio/reflexio/cli/commands/shortcuts.py +15 -2
  66. package/plugin/vendor/reflexio/reflexio/cli/env_loader.py +292 -22
  67. package/plugin/vendor/reflexio/reflexio/cli/log_format.py +29 -4
  68. package/plugin/vendor/reflexio/reflexio/cli/run_services.py +17 -8
  69. package/plugin/vendor/reflexio/reflexio/cli/stop_services.py +13 -10
  70. package/plugin/vendor/reflexio/reflexio/cli/utils.py +44 -1
  71. package/plugin/vendor/reflexio/reflexio/client/client.py +154 -13
  72. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/README.md +135 -257
  73. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/npm/openclaw-smart/bin/openclaw-smart.js +13 -0
  74. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/npm/openclaw-smart/package.json +15 -0
  75. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/README.md +38 -0
  76. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/index.ts +151 -110
  77. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/openclaw.plugin.json +20 -10
  78. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/package.json +28 -6
  79. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/pyproject.toml +42 -0
  80. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/_lib.sh +371 -0
  81. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/backend-log-runner.sh +33 -0
  82. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/backend-service.sh +271 -0
  83. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/cli.sh +68 -0
  84. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/dashboard-open.sh +15 -0
  85. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/ensure-plugin-root.sh +84 -0
  86. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/hook_entry.sh +106 -0
  87. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/npm-cli.js +219 -0
  88. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/smart-install.sh +269 -0
  89. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/clear-all/SKILL.md +8 -0
  90. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/dashboard/SKILL.md +8 -0
  91. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/learn/SKILL.md +10 -0
  92. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/reflexio/SKILL.md +15 -44
  93. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/restart/SKILL.md +6 -0
  94. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/show/SKILL.md +8 -0
  95. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/cli.py +634 -0
  96. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/context_format.py +224 -0
  97. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/context_inject.py +79 -0
  98. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/__init__.py +0 -0
  99. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/after_tool_call.py +160 -0
  100. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/agent_end.py +187 -0
  101. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/before_prompt_build.py +69 -0
  102. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/before_tool_call.py +30 -0
  103. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/session_end.py +36 -0
  104. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/session_start.py +130 -0
  105. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/hook.py +131 -0
  106. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/ids.py +94 -0
  107. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/internal_call.py +75 -0
  108. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/oc_cite.py +196 -0
  109. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/optimizer_assistant.py +272 -0
  110. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/publish.py +96 -0
  111. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/query_compose.py +66 -0
  112. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/reflexio_adapter.py +336 -0
  113. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/runtime.py +47 -0
  114. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/stall_banner.py +61 -0
  115. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/state.py +323 -0
  116. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/__init__.py +0 -0
  117. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/__init__.py +0 -0
  118. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/test_e2e_session_loop.py +190 -0
  119. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/test_publish_to_local_reflexio_integration.py +112 -0
  120. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/test_recursion_guard_integration.py +86 -0
  121. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/test_search_inject_integration.py +144 -0
  122. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_cli.py +184 -0
  123. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_after_tool_call.py +142 -0
  124. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_agent_end.py +233 -0
  125. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_before_prompt_build.py +116 -0
  126. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_before_tool_call.py +35 -0
  127. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_session_end.py +47 -0
  128. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_session_start.py +109 -0
  129. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_hook_dispatch.py +117 -0
  130. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_ids.py +41 -0
  131. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_internal_call.py +50 -0
  132. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_oc_cite.py +88 -0
  133. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_publish.py +48 -0
  134. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_query_compose.py +48 -0
  135. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_reflexio_adapter.py +188 -0
  136. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_runtime.py +41 -0
  137. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_state.py +235 -0
  138. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests-ts/__mocks__/plugin-entry-stub.ts +6 -0
  139. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests-ts/test_npm_cli.test.ts +56 -0
  140. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests-ts/test_shim_dispatch.test.ts +171 -0
  141. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tsconfig.build.json +18 -0
  142. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/{tsconfig.json → plugin/tsconfig.json} +2 -2
  143. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/uv.lock +3835 -0
  144. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/vitest.config.ts +18 -0
  145. package/plugin/vendor/reflexio/reflexio/lib/_agent_playbook.py +246 -10
  146. package/plugin/vendor/reflexio/reflexio/lib/_base.py +15 -0
  147. package/plugin/vendor/reflexio/reflexio/lib/_config.py +11 -4
  148. package/plugin/vendor/reflexio/reflexio/lib/_generation.py +17 -5
  149. package/plugin/vendor/reflexio/reflexio/lib/_lineage_parity_readers.py +187 -0
  150. package/plugin/vendor/reflexio/reflexio/lib/_profiles.py +224 -21
  151. package/plugin/vendor/reflexio/reflexio/lib/_reflection.py +1 -1
  152. package/plugin/vendor/reflexio/reflexio/lib/_search.py +52 -25
  153. package/plugin/vendor/reflexio/reflexio/lib/_user_playbook.py +11 -1
  154. package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/__init__.py +1 -0
  155. package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/entities.py +127 -38
  156. package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/enums.py +4 -0
  157. package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/governance.py +117 -0
  158. package/plugin/vendor/reflexio/reflexio/models/api_schema/eval_overview_schema.py +64 -41
  159. package/plugin/vendor/reflexio/reflexio/models/api_schema/internal_schema.py +19 -0
  160. package/plugin/vendor/reflexio/reflexio/models/api_schema/pending_tool_call_schema.py +12 -5
  161. package/plugin/vendor/reflexio/reflexio/models/api_schema/retriever_schema.py +97 -3
  162. package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/converters.py +5 -1
  163. package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/entities.py +5 -1
  164. package/plugin/vendor/reflexio/reflexio/models/config_schema.py +104 -7
  165. package/plugin/vendor/reflexio/reflexio/models/structured_output.py +148 -0
  166. package/plugin/vendor/reflexio/reflexio/server/OVERVIEW.md +3 -3
  167. package/plugin/vendor/reflexio/reflexio/server/README.md +58 -33
  168. package/plugin/vendor/reflexio/reflexio/server/__init__.py +29 -5
  169. package/plugin/vendor/reflexio/reflexio/server/__main__.py +2 -2
  170. package/plugin/vendor/reflexio/reflexio/server/api.py +899 -103
  171. package/plugin/vendor/reflexio/reflexio/server/api_endpoints/precondition_checks.py +7 -0
  172. package/plugin/vendor/reflexio/reflexio/server/api_endpoints/request_context.py +4 -2
  173. package/plugin/vendor/reflexio/reflexio/server/auth.py +90 -0
  174. package/plugin/vendor/reflexio/reflexio/server/billing_meter.py +173 -0
  175. package/plugin/vendor/reflexio/reflexio/server/billing_signals.py +64 -0
  176. package/plugin/vendor/reflexio/reflexio/server/cache/reflexio_cache.py +46 -16
  177. package/plugin/vendor/reflexio/reflexio/server/env_utils.py +65 -0
  178. package/plugin/vendor/reflexio/reflexio/server/extensions.py +213 -0
  179. package/plugin/vendor/reflexio/reflexio/server/llm/embedding_service.py +19 -4
  180. package/plugin/vendor/reflexio/reflexio/server/llm/litellm_client.py +264 -77
  181. package/plugin/vendor/reflexio/reflexio/server/llm/llm_utils.py +69 -7
  182. package/plugin/vendor/reflexio/reflexio/server/llm/model_defaults.py +4 -4
  183. package/plugin/vendor/reflexio/reflexio/server/llm/providers/claude_code_provider.py +1 -1
  184. package/plugin/vendor/reflexio/reflexio/server/llm/providers/embedding_service_provider.py +75 -16
  185. package/plugin/vendor/reflexio/reflexio/server/llm/providers/openclaw_provider.py +280 -0
  186. package/plugin/vendor/reflexio/reflexio/server/llm/rerank/cross_encoder_reranker.py +12 -1
  187. package/plugin/vendor/reflexio/reflexio/server/llm/token_accounting.py +48 -0
  188. package/plugin/vendor/reflexio/reflexio/server/llm/tools.py +107 -17
  189. package/plugin/vendor/reflexio/reflexio/server/operation_limiter.py +360 -4
  190. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.6.0.prompt.md +1 -1
  191. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.7.0.prompt.md +85 -0
  192. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.2.0.prompt.md +1 -1
  193. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.3.0.prompt.md +253 -0
  194. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.2.prompt.md +1 -1
  195. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.3.prompt.md +74 -0
  196. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.2.3.prompt.md +1 -1
  197. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.3.0.prompt.md +266 -0
  198. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.4.0.prompt.md +278 -0
  199. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.3.0.prompt.md +1 -1
  200. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.4.0.prompt.md +137 -0
  201. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.2.0.prompt.md +1 -1
  202. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.3.0.prompt.md +34 -0
  203. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.0.0.prompt.md +5 -12
  204. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.1.0.prompt.md +5 -12
  205. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.2.0.prompt.md +155 -0
  206. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/tagging/v1.0.0.prompt.md +23 -0
  207. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_manager.py +89 -32
  208. package/plugin/vendor/reflexio/reflexio/server/services/README.md +28 -11
  209. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/README.md +22 -0
  210. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/__init__.py +1 -0
  211. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_constants.py +4 -2
  212. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_utils.py +1 -0
  213. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/components/__init__.py +7 -0
  214. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/{agent_success_evaluator.py → components/evaluator.py} +3 -16
  215. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/regen_jobs.py +28 -72
  216. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/{group_evaluation_runner.py → runner.py} +12 -10
  217. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/{delayed_group_evaluator.py → scheduler.py} +10 -2
  218. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/{agent_success_evaluation_service.py → service.py} +36 -1
  219. package/plugin/vendor/reflexio/reflexio/server/services/base_generation_service.py +160 -0
  220. package/plugin/vendor/reflexio/reflexio/server/services/configurator/base_configurator.py +5 -0
  221. package/plugin/vendor/reflexio/reflexio/server/services/deduplication_utils.py +1 -1
  222. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/README.md +9 -0
  223. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/components/__init__.py +0 -0
  224. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/{rule_attribution.py → components/rule_attribution.py} +10 -9
  225. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/eval_sampler.py +15 -24
  226. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/service.py +238 -164
  227. package/plugin/vendor/reflexio/reflexio/server/services/extraction/README.md +31 -0
  228. package/plugin/vendor/reflexio/reflexio/server/services/extraction/outcome.py +13 -3
  229. package/plugin/vendor/reflexio/reflexio/server/services/extraction/pending_tool_call_dispatch.py +3 -2
  230. package/plugin/vendor/reflexio/reflexio/server/services/extraction/resumable_agent.py +32 -118
  231. package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_worker.py +47 -16
  232. package/plugin/vendor/reflexio/reflexio/server/services/generation_service.py +105 -23
  233. package/plugin/vendor/reflexio/reflexio/server/services/governance/config.py +52 -0
  234. package/plugin/vendor/reflexio/reflexio/server/services/governance/service.py +378 -0
  235. package/plugin/vendor/reflexio/reflexio/server/services/governance/subject_refs.py +34 -0
  236. package/plugin/vendor/reflexio/reflexio/server/services/lineage/__init__.py +0 -0
  237. package/plugin/vendor/reflexio/reflexio/server/services/lineage/gc_scheduler.py +219 -0
  238. package/plugin/vendor/reflexio/reflexio/server/services/lineage/resolve.py +98 -0
  239. package/plugin/vendor/reflexio/reflexio/server/services/operation_state_utils.py +26 -0
  240. package/plugin/vendor/reflexio/reflexio/server/services/playbook/README.md +18 -11
  241. package/plugin/vendor/reflexio/reflexio/server/services/playbook/aggregation_prompt_processing.py +100 -0
  242. package/plugin/vendor/reflexio/reflexio/server/services/playbook/components/__init__.py +5 -0
  243. package/plugin/vendor/reflexio/reflexio/server/services/playbook/{playbook_aggregator.py → components/aggregator.py} +334 -178
  244. package/plugin/vendor/reflexio/reflexio/server/services/playbook/{playbook_consolidator.py → components/consolidator.py} +168 -62
  245. package/plugin/vendor/reflexio/reflexio/server/services/playbook/{playbook_extractor.py → components/extractor.py} +5 -1
  246. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_edit_apply.py +74 -0
  247. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_service_utils.py +33 -3
  248. package/plugin/vendor/reflexio/reflexio/server/services/playbook/{playbook_generation_service.py → service.py} +121 -19
  249. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/README.md +10 -0
  250. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/models.py +2 -1
  251. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/optimizer.py +178 -30
  252. package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/README.md +9 -0
  253. package/plugin/vendor/reflexio/reflexio/server/services/profile/components/__init__.py +17 -0
  254. package/plugin/vendor/reflexio/reflexio/server/services/profile/{profile_deduplicator.py → components/consolidator.py} +7 -6
  255. package/plugin/vendor/reflexio/reflexio/server/services/profile/{profile_extractor.py → components/extractor.py} +31 -22
  256. package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_generation_service_utils.py +6 -13
  257. package/plugin/vendor/reflexio/reflexio/server/services/profile/{profile_generation_service.py → service.py} +32 -50
  258. package/plugin/vendor/reflexio/reflexio/server/services/reflection/__init__.py +4 -8
  259. package/plugin/vendor/reflexio/reflexio/server/services/reflection/components/__init__.py +7 -0
  260. package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_service_utils.py +12 -1
  261. package/plugin/vendor/reflexio/reflexio/server/services/reflection/{reflection_service.py → service.py} +36 -16
  262. package/plugin/vendor/reflexio/reflexio/server/services/retrieval/recency.py +211 -0
  263. package/plugin/vendor/reflexio/reflexio/server/services/retrieval/relevance_floor.py +99 -6
  264. package/plugin/vendor/reflexio/reflexio/server/services/service_utils.py +36 -1
  265. package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/README.md +8 -0
  266. package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/outcome.py +1 -2
  267. package/plugin/vendor/reflexio/reflexio/server/services/storage/error.py +31 -0
  268. package/plugin/vendor/reflexio/reflexio/server/services/storage/governance_validation.py +681 -0
  269. package/plugin/vendor/reflexio/reflexio/server/services/storage/retention.py +9 -9
  270. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/__init__.py +16 -2
  271. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_agent_run.py +4 -1
  272. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_base.py +644 -197
  273. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_extras.py +106 -119
  274. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_governance.py +1965 -0
  275. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_lineage.py +630 -0
  276. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_operations.py +38 -6
  277. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_playbook.py +31 -1369
  278. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_profiles.py +756 -210
  279. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_requests.py +148 -34
  280. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_shadow_verdicts.py +23 -9
  281. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_stall_state.py +5 -2
  282. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/__init__.py +13 -0
  283. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_agent.py +952 -0
  284. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_eval_results.py +189 -0
  285. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_optimization.py +247 -0
  286. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_source_linkage.py +145 -0
  287. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_user.py +838 -0
  288. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/__init__.py +150 -23
  289. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_agent_run.py +2 -8
  290. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_base.py +5 -0
  291. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_extras.py +40 -57
  292. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_governance.py +148 -0
  293. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_lineage.py +215 -0
  294. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_operations.py +20 -0
  295. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_playbook.py +4 -677
  296. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_profiles.py +134 -1
  297. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_requests.py +62 -0
  298. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_retrieval_log.py +51 -0
  299. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_shadow_verdicts.py +17 -0
  300. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/__init__.py +13 -0
  301. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/_agent.py +365 -0
  302. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/_eval_results.py +124 -0
  303. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/_optimization.py +85 -0
  304. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/_source_linkage.py +47 -0
  305. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/_user.py +333 -0
  306. package/plugin/vendor/reflexio/reflexio/server/services/tagging/README.md +8 -0
  307. package/plugin/vendor/reflexio/reflexio/server/services/tagging/__init__.py +1 -0
  308. package/plugin/vendor/reflexio/reflexio/server/services/tagging/service.py +200 -0
  309. package/plugin/vendor/reflexio/reflexio/server/services/tagging/tagging_scheduler.py +149 -0
  310. package/plugin/vendor/reflexio/reflexio/server/services/unified_search_service.py +372 -34
  311. package/plugin/vendor/reflexio/reflexio/server/site_var/README.md +2 -1
  312. package/plugin/vendor/reflexio/reflexio/server/site_var/feature_flags.py +120 -1
  313. package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/feature_flags.json +4 -0
  314. package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/search_settings.json +5 -0
  315. package/plugin/vendor/reflexio/reflexio/server/tracing.py +30 -0
  316. package/plugin/vendor/reflexio/reflexio/server/usage_metrics.py +18 -0
  317. package/plugin/vendor/reflexio/reflexio/test_support/llm_mock.py +61 -26
  318. package/plugin/vendor/reflexio/reflexio/test_support/llm_model_registry.py +41 -4
  319. package/scripts/setup-claude-smart.sh +8 -3
  320. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/TESTING.md +0 -517
  321. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/hook/handler.js +0 -473
  322. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package-lock.json +0 -2156
  323. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package.json +0 -18
  324. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/handler.ts +0 -241
  325. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/setup.ts +0 -140
  326. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/publish.ts +0 -113
  327. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/search.ts +0 -52
  328. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/server.ts +0 -103
  329. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/sqlite-buffer.ts +0 -156
  330. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/user-id.ts +0 -134
  331. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/rules/reflexio.md +0 -24
  332. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/publish_clawhub.sh +0 -278
  333. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/references/HOOK.md +0 -164
  334. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/install.sh +0 -36
  335. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/uninstall.sh +0 -35
  336. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/publish.test.ts +0 -27
  337. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/search.test.ts +0 -31
  338. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/server.test.ts +0 -42
  339. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/setup.test.ts +0 -49
  340. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/sqlite-buffer.test.ts +0 -91
  341. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/user-id.test.ts +0 -50
  342. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/vitest.config.ts +0 -13
  343. package/plugin/vendor/reflexio/reflexio/server/_auth.py +0 -25
  344. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/group_aggregation.py +0 -192
  345. package/plugin/vendor/reflexio/reflexio/server/services/extraction/invariants.py +0 -303
  346. package/plugin/vendor/reflexio/reflexio/server/services/extraction/plan.py +0 -138
  347. package/plugin/vendor/reflexio/reflexio/server/services/extraction/tools.py +0 -1125
  348. /package/plugin/vendor/reflexio/reflexio/integrations/{__init__.py → openclaw/plugin/src/openclaw_smart/__init__.py} +0 -0
  349. /package/plugin/vendor/reflexio/reflexio/integrations/openclaw/{types → plugin/types}/openclaw.d.ts +0 -0
  350. /package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/{distribution.py → components/distribution.py} +0 -0
  351. /package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/{hero_state.py → components/hero_state.py} +0 -0
  352. /package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/{shadow_aggregation.py → components/shadow_aggregation.py} +0 -0
  353. /package/plugin/vendor/reflexio/reflexio/server/services/reflection/{reflection_extractor.py → components/extractor.py} +0 -0
@@ -1,473 +0,0 @@
1
- // ---------------------------------------------------------------------------
2
- // Security contract — localhost only, HTTP only.
3
- //
4
- // This hook is a localhost-only integration. It buffers OpenClaw conversations
5
- // to a local SQLite database and talks to the Reflexio backend HTTP server on
6
- // the same machine via native fetch(). It does not spawn subprocesses, does
7
- // not read configuration from the filesystem, and does not consult any
8
- // environment variables. The destination is a hardcoded loopback URL.
9
- //
10
- // Traffic: only HTTP requests to http://127.0.0.1:8081/api/* and
11
- // http://127.0.0.1:8081/health. No other hosts are contacted.
12
- //
13
- // Bootstrap: the Reflexio server must be running on port 8081 before the
14
- // hook is useful. If it is not, every fetch() attempt fails gracefully with
15
- // a logged error and the hook returns — the agent continues without
16
- // cross-session memory that session. Starting the server is the user's
17
- // responsibility; the skill's First-Use Setup runs `reflexio services start`
18
- // once at install time.
19
- //
20
- // Writes are confined to ~/.reflexio/sessions.db (SQLite buffer).
21
- // ---------------------------------------------------------------------------
22
-
23
- const { randomUUID } = require("node:crypto");
24
- const { mkdirSync } = require("node:fs");
25
- const { homedir } = require("node:os");
26
- const { dirname, join } = require("node:path");
27
-
28
- const Database = require("better-sqlite3");
29
-
30
- // Hardcoded loopback destination — all traffic goes here, nowhere else.
31
- const LOCAL_SERVER_URL = "http://127.0.0.1:8081";
32
- // Hardcoded agent label; stored alongside extracted playbooks so they are
33
- // scoped to this integration build.
34
- const AGENT_VERSION = "openclaw-agent";
35
-
36
- // ---------------------------------------------------------------------------
37
- // HTTP helper — single fetch() path for every API call
38
- // ---------------------------------------------------------------------------
39
-
40
- async function apiPost(path, body, timeoutMs = 10_000) {
41
- const ctrl = new AbortController();
42
- const timer = setTimeout(() => ctrl.abort(), timeoutMs);
43
- try {
44
- const res = await fetch(`${LOCAL_SERVER_URL}${path}`, {
45
- method: "POST",
46
- headers: { "Content-Type": "application/json" },
47
- body: JSON.stringify(body),
48
- signal: ctrl.signal,
49
- });
50
- if (!res.ok) {
51
- throw new Error(`HTTP ${res.status} ${res.statusText}`);
52
- }
53
- return await res.json();
54
- } finally {
55
- clearTimeout(timer);
56
- }
57
- }
58
-
59
- // Format unified search results (profiles + playbooks) as a markdown block
60
- // the agent can read directly. Kept in sync with the CLI's text output
61
- // shape so the injected bootstrap file looks familiar.
62
- function formatSearchResults(data) {
63
- const lines = [];
64
- const profiles = data?.profiles ?? [];
65
- const userPlaybooks = data?.user_playbooks ?? [];
66
- const agentPlaybooks = data?.agent_playbooks ?? [];
67
-
68
- if (profiles.length > 0) {
69
- lines.push("## User Profiles");
70
- for (const p of profiles) {
71
- const content = p.profile_content ?? p.content ?? "";
72
- if (content.trim()) lines.push(`- ${content.trim()}`);
73
- }
74
- lines.push("");
75
- }
76
- if (userPlaybooks.length > 0) {
77
- lines.push("## User Playbooks (from this agent's history)");
78
- for (const pb of userPlaybooks) {
79
- const summary =
80
- pb.content ?? pb.instruction ?? pb.trigger ?? JSON.stringify(pb);
81
- lines.push(`- ${summary}`);
82
- }
83
- lines.push("");
84
- }
85
- if (agentPlaybooks.length > 0) {
86
- lines.push("## Agent Playbooks (shared across instances)");
87
- for (const pb of agentPlaybooks) {
88
- const summary =
89
- pb.content ?? pb.instruction ?? pb.trigger ?? JSON.stringify(pb);
90
- lines.push(`- ${summary}`);
91
- }
92
- lines.push("");
93
- }
94
- return lines.join("\n").trim();
95
- }
96
-
97
- // ---------------------------------------------------------------------------
98
- // SQLite session store — persistent, crash-safe conversation buffer.
99
- // DB lives in ~/.reflexio/sessions.db.
100
- // ---------------------------------------------------------------------------
101
-
102
- const DB_PATH = join(homedir(), ".reflexio", "sessions.db");
103
- const MAX_CONTENT_LENGTH = 10_000;
104
- const MAX_INTERACTIONS = 200;
105
- const BATCH_SIZE = 10; // Publish every N complete exchanges mid-session
106
- const MAX_RETRIES = 3; // Give up retrying after this many failures
107
-
108
- let _db = null;
109
-
110
- function getDb() {
111
- if (_db) return _db;
112
- mkdirSync(dirname(DB_PATH), { recursive: true, mode: 0o700 });
113
- _db = new Database(DB_PATH);
114
- _db.pragma("journal_mode = WAL");
115
- // Use prepare().run() for DDL; better-sqlite3 accepts DDL statements
116
- // through prepared statements the same as DML.
117
- _db.prepare(
118
- "CREATE TABLE IF NOT EXISTS turns (" +
119
- "id INTEGER PRIMARY KEY AUTOINCREMENT, " +
120
- "session_id TEXT NOT NULL, " +
121
- "role TEXT NOT NULL, " +
122
- "content TEXT NOT NULL, " +
123
- "timestamp TEXT NOT NULL, " +
124
- "published INTEGER DEFAULT 0, " +
125
- "retry_count INTEGER DEFAULT 0" +
126
- ")",
127
- ).run();
128
- _db.prepare(
129
- "CREATE INDEX IF NOT EXISTS idx_session_published ON turns(session_id, published)",
130
- ).run();
131
- // Add retry_count column if missing (migration for existing DBs)
132
- try {
133
- _db.prepare("ALTER TABLE turns ADD COLUMN retry_count INTEGER DEFAULT 0").run();
134
- } catch {
135
- // Column already exists -- ignore
136
- }
137
- // Clean up old published turns (keep 7 days)
138
- _db.prepare(
139
- "DELETE FROM turns WHERE published = 1 AND timestamp < datetime('now', '-7 days')",
140
- ).run();
141
- // Graceful close on process exit is intentionally omitted:
142
- // better-sqlite3 flushes WAL on its own and we avoid referencing the
143
- // runtime's process object here.
144
- return _db;
145
- }
146
-
147
- // ---------------------------------------------------------------------------
148
- // Smart truncation — preserves head + tail with a marker in between
149
- // ---------------------------------------------------------------------------
150
-
151
- function smartTruncate(content, maxLength = MAX_CONTENT_LENGTH) {
152
- if (!content || content.length <= maxLength) return content || "";
153
- const headLen = Math.floor(maxLength * 0.8);
154
- const tailLen = Math.max(0, maxLength - headLen - 80);
155
- const truncated = content.length - headLen - tailLen;
156
- const marker = `\n\n[...truncated ${truncated} chars...]\n\n`;
157
- if (tailLen === 0) return content.slice(0, headLen) + marker;
158
- return content.slice(0, headLen) + marker + content.slice(-tailLen);
159
- }
160
-
161
- // ---------------------------------------------------------------------------
162
- // Session ID resolution
163
- // ---------------------------------------------------------------------------
164
-
165
- let _fallbackSessionId = null;
166
-
167
- function getSessionId(event) {
168
- const key = event.context?.sessionKey;
169
- if (key) return key;
170
- if (!_fallbackSessionId) {
171
- _fallbackSessionId = `anon-${randomUUID()}`;
172
- console.error(
173
- `[reflexio] No sessionKey; using fallback: ${_fallbackSessionId}`,
174
- );
175
- }
176
- return _fallbackSessionId;
177
- }
178
-
179
- // ---------------------------------------------------------------------------
180
- // User ID resolution — multi-agent instance support
181
- //
182
- // Derived entirely from the OpenClaw session key, which encodes the
183
- // per-agent identifier as a prefix of the form "agent:<id>:<rest>".
184
- // When the session key doesn't match that shape, everything falls back to
185
- // the single label "openclaw".
186
- // ---------------------------------------------------------------------------
187
-
188
- function resolveUserId(event) {
189
- const sessionKey = event.context?.sessionKey ?? "";
190
- const sessionMatch = sessionKey.match(/^agent:([^:]+):/);
191
- if (sessionMatch) return sessionMatch[1];
192
- return "openclaw";
193
- }
194
-
195
- // ---------------------------------------------------------------------------
196
- // Shared publish logic — POSTs buffered turns to /api/publish_interaction
197
- // ---------------------------------------------------------------------------
198
-
199
- async function publishSession(db, sessionId, userId, agentVersion) {
200
- const turns = db
201
- .prepare(
202
- "SELECT id, role, content FROM turns WHERE session_id = ? AND published = 0 AND retry_count < ? ORDER BY id LIMIT ?",
203
- )
204
- .all(sessionId, MAX_RETRIES, MAX_INTERACTIONS);
205
-
206
- if (turns.length === 0) return;
207
-
208
- // Mark selected turns as in-flight (published = 2) synchronously to prevent
209
- // concurrent publishSession calls from picking up the same rows.
210
- const maxId = turns[turns.length - 1].id;
211
- db.prepare(
212
- "UPDATE turns SET published = 2 WHERE session_id = ? AND published = 0 AND retry_count < ? AND id <= ?",
213
- ).run(sessionId, MAX_RETRIES, maxId);
214
-
215
- const body = {
216
- user_id: userId,
217
- source: "openclaw",
218
- agent_version: agentVersion,
219
- session_id: sessionId,
220
- interaction_data_list: turns.map((t) => ({
221
- role: t.role,
222
- content: t.content,
223
- })),
224
- skip_aggregation: false,
225
- force_extraction: false,
226
- };
227
-
228
- try {
229
- await apiPost("/api/publish_interaction", body, 15_000);
230
- db.prepare(
231
- "UPDATE turns SET published = 1 WHERE session_id = ? AND published = 2",
232
- ).run(sessionId);
233
- console.error(
234
- `[reflexio] Published ${turns.length} interactions (session ${sessionId})`,
235
- );
236
- } catch (err) {
237
- console.error(
238
- `[reflexio] Publish failed: ${err?.message ?? err}, incrementing retry count`,
239
- );
240
- try {
241
- db.prepare(
242
- "UPDATE turns SET published = 0, retry_count = retry_count + 1 WHERE session_id = ? AND published = 2",
243
- ).run(sessionId);
244
- } catch (e) {
245
- console.error(
246
- `[reflexio] Failed to update retry count: ${e.message}`,
247
- );
248
- }
249
- }
250
- }
251
-
252
- /**
253
- * Main hook dispatcher for Reflexio-OpenClaw integration.
254
- *
255
- * Events handled:
256
- * agent:bootstrap - Inject user profile + retry unpublished sessions
257
- * message:received - Search Reflexio before agent responds
258
- * message:sent - Buffer turn to SQLite + incremental publish
259
- * command:stop - Flush remaining unpublished turns to Reflexio
260
- */
261
- async function reflexioHook(event) {
262
- // Skip sub-agent sessions to avoid recursion (guards all event types)
263
- const sessionKey = event.context?.sessionKey ?? "";
264
- if (sessionKey.includes(":subagent:")) return;
265
-
266
- const eventKey = `${event.type}:${event.action}`;
267
-
268
- switch (eventKey) {
269
- case "agent:bootstrap":
270
- return handleBootstrap(event);
271
- case "message:received":
272
- return handleSearchBeforeResponse(event);
273
- case "message:sent":
274
- return handleMessageSent(event);
275
- case "command:stop":
276
- return handleSessionEnd(event);
277
- }
278
- }
279
-
280
- // ---------------------------------------------------------------------------
281
- // Bootstrap: inject user profile + retry unpublished sessions
282
- //
283
- // Precondition: the Reflexio backend is already running on LOCAL_SERVER_URL.
284
- // The hook does not start it — that's the user's responsibility, handled
285
- // once at install time by the skill's First-Use Setup. If the server is
286
- // unreachable, every API call fails quickly and the handler returns.
287
- // ---------------------------------------------------------------------------
288
-
289
- async function handleBootstrap(event) {
290
- const workspaceDir = event.context?.workspaceDir;
291
- if (!workspaceDir) return;
292
-
293
- console.error(`[reflexio] bootstrap hook fired, workspace=${workspaceDir}`);
294
-
295
- const userId = resolveUserId(event);
296
- const currentSessionId = getSessionId(event);
297
-
298
- // --- Inject user profile via unified search ---
299
- try {
300
- const data = await apiPost(
301
- "/api/search",
302
- {
303
- query: "communication style, expertise, and preferences",
304
- user_id: userId,
305
- top_k: 3,
306
- },
307
- 10_000,
308
- );
309
-
310
- const profiles = Array.isArray(data?.profiles) ? data.profiles : [];
311
- if (profiles.length > 0) {
312
- const profileLines = profiles
313
- .map((p) => `- ${(p.profile_content ?? p.content ?? "").trim()}`)
314
- .filter((line) => line.length > 2);
315
-
316
- if (profileLines.length > 0 && Array.isArray(event.context.bootstrapFiles)) {
317
- const bootstrapContent = [
318
- "## About This User (from Reflexio)",
319
- "",
320
- ...profileLines,
321
- "",
322
- 'Use `reflexio search "<your current task>"` before starting work to get task-specific behavioral corrections.',
323
- ].join("\n");
324
-
325
- event.context.bootstrapFiles.push({
326
- name: "REFLEXIO_USER_PROFILE.md",
327
- path: "REFLEXIO_USER_PROFILE.md",
328
- content: bootstrapContent,
329
- source: "hook:reflexio-context",
330
- });
331
- console.error(
332
- `[reflexio] Injected user profile (${bootstrapContent.length} chars)`,
333
- );
334
- }
335
- }
336
- } catch (err) {
337
- console.error(
338
- `[reflexio] Bootstrap profile fetch failed: ${err?.message ?? err}`,
339
- );
340
- }
341
-
342
- // --- Retry unpublished turns from previous sessions ---
343
- try {
344
- const db = getDb();
345
- const oldSessions = db
346
- .prepare(
347
- "SELECT DISTINCT session_id FROM turns WHERE published = 0 AND retry_count < ? AND session_id != ? LIMIT 5",
348
- )
349
- .all(MAX_RETRIES, currentSessionId);
350
-
351
- if (oldSessions.length > 0) {
352
- console.error(
353
- `[reflexio] Retrying ${oldSessions.length} unpublished session(s)`,
354
- );
355
- for (const { session_id } of oldSessions) {
356
- // Await sequentially so we don't hammer the server with
357
- // concurrent publishes for stale sessions.
358
- // eslint-disable-next-line no-await-in-loop
359
- await publishSession(db, session_id, userId, AGENT_VERSION);
360
- }
361
- }
362
- } catch (err) {
363
- console.error(`[reflexio] Retry failed: ${err?.message ?? err}`);
364
- }
365
- }
366
-
367
- // ---------------------------------------------------------------------------
368
- // Message received: search Reflexio before the agent responds
369
- // ---------------------------------------------------------------------------
370
-
371
- const TRIVIAL_RESPONSE_RE = /^(yes|no|ok|sure|thanks|y|n)$/i;
372
-
373
- async function handleSearchBeforeResponse(event) {
374
- let prompt = event.context?.userMessage;
375
- if (!prompt || prompt.length < 5) return;
376
- if (TRIVIAL_RESPONSE_RE.test(prompt.trim())) return;
377
- prompt = prompt.slice(0, 4096);
378
-
379
- try {
380
- const userId = resolveUserId(event);
381
- const data = await apiPost(
382
- "/api/search",
383
- {
384
- query: prompt,
385
- user_id: userId,
386
- top_k: 5,
387
- agent_version: AGENT_VERSION,
388
- },
389
- 5_000,
390
- );
391
-
392
- const formatted = formatSearchResults(data);
393
- if (formatted && Array.isArray(event.context?.bootstrapFiles)) {
394
- event.context.bootstrapFiles.push({
395
- name: "REFLEXIO_CONTEXT.md",
396
- path: "REFLEXIO_CONTEXT.md",
397
- content: formatted,
398
- source: "hook:reflexio-context",
399
- });
400
- console.error(
401
- `[reflexio] Injected search context for message (${formatted.length} chars)`,
402
- );
403
- }
404
- } catch (err) {
405
- console.error(
406
- `[reflexio] Per-message search failed: ${err?.message ?? err}`,
407
- );
408
- // Server may be down. The skill's First-Use Setup is responsible for
409
- // starting it; the hook does not launch processes.
410
- }
411
- }
412
-
413
- // ---------------------------------------------------------------------------
414
- // Message sent: buffer turn + incremental publish every BATCH_SIZE exchanges
415
- // ---------------------------------------------------------------------------
416
-
417
- function handleMessageSent(event) {
418
- const userMessage = event.context?.userMessage;
419
- const agentResponse = event.context?.agentResponse;
420
- const sessionId = getSessionId(event);
421
-
422
- if (!userMessage && !agentResponse) return;
423
-
424
- try {
425
- const db = getDb();
426
- const now = new Date().toISOString();
427
-
428
- const insertTurn = db.transaction((sid, user, agent, ts) => {
429
- const stmt = db.prepare(
430
- "INSERT INTO turns (session_id, role, content, timestamp) VALUES (?, ?, ?, ?)",
431
- );
432
- if (user) stmt.run(sid, "user", smartTruncate(user), ts);
433
- if (agent) stmt.run(sid, "assistant", smartTruncate(agent), ts);
434
- });
435
- insertTurn(sessionId, userMessage, agentResponse, now);
436
-
437
- // Incremental publish: every BATCH_SIZE complete exchanges
438
- const { count } = db
439
- .prepare(
440
- "SELECT COUNT(*) as count FROM turns WHERE session_id = ? AND published = 0",
441
- )
442
- .get(sessionId);
443
-
444
- if (count >= BATCH_SIZE * 2) {
445
- const userId = resolveUserId(event);
446
- void publishSession(db, sessionId, userId, AGENT_VERSION).catch((e) =>
447
- console.error(`[reflexio] Incremental publish failed: ${e?.message ?? e}`),
448
- );
449
- }
450
- } catch (err) {
451
- console.error(`[reflexio] Failed to buffer turn: ${err.message}`);
452
- }
453
- }
454
-
455
- // ---------------------------------------------------------------------------
456
- // Session end: flush remaining unpublished turns
457
- // ---------------------------------------------------------------------------
458
-
459
- async function handleSessionEnd(event) {
460
- const sessionId = getSessionId(event);
461
- const userId = resolveUserId(event);
462
-
463
- try {
464
- const db = getDb();
465
- await publishSession(db, sessionId, userId, AGENT_VERSION);
466
- } catch (err) {
467
- console.error(`[reflexio] Session flush failed: ${err?.message ?? err}`);
468
- }
469
- }
470
-
471
- // OpenClaw expects a CommonJS default export.
472
- module.exports = reflexioHook;
473
- module.exports.default = reflexioHook;