claude-smart 0.2.44 → 0.2.46

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 (323) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/README.md +34 -5
  3. package/bin/claude-smart.js +295 -5
  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 +22 -2
  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/preferences/[id]/page.tsx +8 -8
  16. package/plugin/dashboard/app/skills/project/[id]/page.tsx +7 -3
  17. package/plugin/dashboard/app/skills/shared/[id]/page.tsx +10 -3
  18. package/plugin/dashboard/lib/claude-settings-file.ts +20 -10
  19. package/plugin/dashboard/lib/reflexio-client.ts +16 -0
  20. package/plugin/dashboard/lib/status.ts +10 -3
  21. package/plugin/dashboard/lib/types.ts +18 -6
  22. package/plugin/hooks/codex-hooks.json +0 -1
  23. package/plugin/opencode/assistant-buffer.ts +108 -0
  24. package/plugin/opencode/dist/assistant-buffer.js +96 -0
  25. package/plugin/opencode/dist/internal.js +12 -0
  26. package/plugin/opencode/dist/payload.js +85 -0
  27. package/plugin/opencode/dist/server.mjs +158 -0
  28. package/plugin/opencode/internal.ts +18 -0
  29. package/plugin/opencode/package.json +3 -0
  30. package/plugin/opencode/payload.ts +90 -0
  31. package/plugin/opencode/server.mts +174 -0
  32. package/plugin/opencode/tsconfig.json +13 -0
  33. package/plugin/pyproject.toml +20 -3
  34. package/plugin/scripts/_lib.sh +77 -29
  35. package/plugin/scripts/backend-service.sh +27 -5
  36. package/plugin/scripts/dashboard-service.sh +7 -5
  37. package/plugin/scripts/ensure-plugin-root.sh +4 -4
  38. package/plugin/scripts/hook_entry.sh +3 -3
  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 +10 -8
  43. package/plugin/src/README.md +1 -1
  44. package/plugin/src/claude_smart/cli.py +304 -6
  45. package/plugin/src/claude_smart/env_config.py +12 -4
  46. package/plugin/src/claude_smart/events/session_start.py +26 -7
  47. package/plugin/src/claude_smart/events/stop.py +1 -1
  48. package/plugin/src/claude_smart/ids.py +1 -1
  49. package/plugin/src/claude_smart/reflexio_adapter.py +5 -5
  50. package/plugin/src/claude_smart/runtime.py +7 -1
  51. package/plugin/uv.lock +1 -1
  52. package/plugin/vendor/reflexio/.env.example +54 -30
  53. package/plugin/vendor/reflexio/README.md +14 -8
  54. package/plugin/vendor/reflexio/pyproject.toml +13 -1
  55. package/plugin/vendor/reflexio/reflexio/README.md +1 -0
  56. package/plugin/vendor/reflexio/reflexio/cli/README.md +9 -7
  57. package/plugin/vendor/reflexio/reflexio/cli/__main__.py +10 -1
  58. package/plugin/vendor/reflexio/reflexio/cli/bootstrap_config.py +22 -5
  59. package/plugin/vendor/reflexio/reflexio/cli/commands/interactions.py +34 -4
  60. package/plugin/vendor/reflexio/reflexio/cli/commands/profiles.py +12 -7
  61. package/plugin/vendor/reflexio/reflexio/cli/commands/services.py +13 -6
  62. package/plugin/vendor/reflexio/reflexio/cli/commands/setup_cmd.py +210 -50
  63. package/plugin/vendor/reflexio/reflexio/cli/commands/shortcuts.py +15 -2
  64. package/plugin/vendor/reflexio/reflexio/cli/env_loader.py +292 -22
  65. package/plugin/vendor/reflexio/reflexio/cli/log_format.py +29 -4
  66. package/plugin/vendor/reflexio/reflexio/cli/run_services.py +17 -8
  67. package/plugin/vendor/reflexio/reflexio/cli/stop_services.py +13 -10
  68. package/plugin/vendor/reflexio/reflexio/client/client.py +57 -13
  69. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/README.md +135 -257
  70. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/npm/openclaw-smart/bin/openclaw-smart.js +13 -0
  71. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/npm/openclaw-smart/package.json +15 -0
  72. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/README.md +38 -0
  73. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/index.ts +151 -110
  74. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/openclaw.plugin.json +20 -10
  75. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/package.json +28 -6
  76. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/pyproject.toml +42 -0
  77. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/_lib.sh +371 -0
  78. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/backend-log-runner.sh +33 -0
  79. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/backend-service.sh +271 -0
  80. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/cli.sh +68 -0
  81. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/dashboard-open.sh +15 -0
  82. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/ensure-plugin-root.sh +84 -0
  83. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/hook_entry.sh +106 -0
  84. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/npm-cli.js +219 -0
  85. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/smart-install.sh +269 -0
  86. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/clear-all/SKILL.md +8 -0
  87. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/dashboard/SKILL.md +8 -0
  88. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/learn/SKILL.md +10 -0
  89. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/reflexio/SKILL.md +15 -44
  90. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/restart/SKILL.md +6 -0
  91. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/show/SKILL.md +8 -0
  92. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/cli.py +634 -0
  93. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/context_format.py +224 -0
  94. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/context_inject.py +79 -0
  95. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/__init__.py +0 -0
  96. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/after_tool_call.py +160 -0
  97. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/agent_end.py +187 -0
  98. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/before_prompt_build.py +69 -0
  99. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/before_tool_call.py +30 -0
  100. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/session_end.py +36 -0
  101. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/session_start.py +130 -0
  102. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/hook.py +131 -0
  103. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/ids.py +94 -0
  104. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/internal_call.py +75 -0
  105. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/oc_cite.py +196 -0
  106. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/optimizer_assistant.py +272 -0
  107. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/publish.py +96 -0
  108. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/query_compose.py +66 -0
  109. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/reflexio_adapter.py +336 -0
  110. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/runtime.py +47 -0
  111. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/stall_banner.py +61 -0
  112. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/state.py +323 -0
  113. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/__init__.py +0 -0
  114. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/__init__.py +0 -0
  115. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/test_e2e_session_loop.py +190 -0
  116. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/test_publish_to_local_reflexio_integration.py +112 -0
  117. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/test_recursion_guard_integration.py +86 -0
  118. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/test_search_inject_integration.py +144 -0
  119. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_cli.py +184 -0
  120. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_after_tool_call.py +142 -0
  121. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_agent_end.py +233 -0
  122. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_before_prompt_build.py +116 -0
  123. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_before_tool_call.py +35 -0
  124. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_session_end.py +47 -0
  125. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_session_start.py +109 -0
  126. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_hook_dispatch.py +117 -0
  127. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_ids.py +41 -0
  128. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_internal_call.py +50 -0
  129. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_oc_cite.py +88 -0
  130. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_publish.py +48 -0
  131. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_query_compose.py +48 -0
  132. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_reflexio_adapter.py +188 -0
  133. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_runtime.py +41 -0
  134. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_state.py +235 -0
  135. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests-ts/__mocks__/plugin-entry-stub.ts +6 -0
  136. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests-ts/test_npm_cli.test.ts +56 -0
  137. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests-ts/test_shim_dispatch.test.ts +171 -0
  138. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tsconfig.build.json +18 -0
  139. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/{tsconfig.json → plugin/tsconfig.json} +2 -2
  140. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/uv.lock +3835 -0
  141. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/vitest.config.ts +18 -0
  142. package/plugin/vendor/reflexio/reflexio/lib/_agent_playbook.py +238 -10
  143. package/plugin/vendor/reflexio/reflexio/lib/_config.py +11 -4
  144. package/plugin/vendor/reflexio/reflexio/lib/_generation.py +16 -5
  145. package/plugin/vendor/reflexio/reflexio/lib/_lineage_parity_readers.py +187 -0
  146. package/plugin/vendor/reflexio/reflexio/lib/_profiles.py +198 -6
  147. package/plugin/vendor/reflexio/reflexio/lib/_reflection.py +1 -1
  148. package/plugin/vendor/reflexio/reflexio/lib/_search.py +29 -20
  149. package/plugin/vendor/reflexio/reflexio/lib/_user_playbook.py +2 -1
  150. package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/entities.py +127 -38
  151. package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/enums.py +4 -0
  152. package/plugin/vendor/reflexio/reflexio/models/api_schema/eval_overview_schema.py +64 -41
  153. package/plugin/vendor/reflexio/reflexio/models/api_schema/internal_schema.py +19 -0
  154. package/plugin/vendor/reflexio/reflexio/models/api_schema/pending_tool_call_schema.py +12 -5
  155. package/plugin/vendor/reflexio/reflexio/models/api_schema/retriever_schema.py +52 -0
  156. package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/converters.py +5 -1
  157. package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/entities.py +5 -1
  158. package/plugin/vendor/reflexio/reflexio/models/config_schema.py +88 -7
  159. package/plugin/vendor/reflexio/reflexio/models/structured_output.py +148 -0
  160. package/plugin/vendor/reflexio/reflexio/server/OVERVIEW.md +3 -3
  161. package/plugin/vendor/reflexio/reflexio/server/README.md +45 -32
  162. package/plugin/vendor/reflexio/reflexio/server/__init__.py +29 -5
  163. package/plugin/vendor/reflexio/reflexio/server/__main__.py +2 -2
  164. package/plugin/vendor/reflexio/reflexio/server/_auth.py +65 -2
  165. package/plugin/vendor/reflexio/reflexio/server/api.py +734 -85
  166. package/plugin/vendor/reflexio/reflexio/server/api_endpoints/precondition_checks.py +7 -0
  167. package/plugin/vendor/reflexio/reflexio/server/api_endpoints/request_context.py +3 -1
  168. package/plugin/vendor/reflexio/reflexio/server/billing_meter.py +173 -0
  169. package/plugin/vendor/reflexio/reflexio/server/billing_signals.py +64 -0
  170. package/plugin/vendor/reflexio/reflexio/server/cache/reflexio_cache.py +46 -16
  171. package/plugin/vendor/reflexio/reflexio/server/env_utils.py +65 -0
  172. package/plugin/vendor/reflexio/reflexio/server/llm/embedding_service.py +19 -4
  173. package/plugin/vendor/reflexio/reflexio/server/llm/litellm_client.py +264 -77
  174. package/plugin/vendor/reflexio/reflexio/server/llm/llm_utils.py +69 -7
  175. package/plugin/vendor/reflexio/reflexio/server/llm/providers/embedding_service_provider.py +75 -16
  176. package/plugin/vendor/reflexio/reflexio/server/llm/providers/openclaw_provider.py +280 -0
  177. package/plugin/vendor/reflexio/reflexio/server/llm/token_accounting.py +48 -0
  178. package/plugin/vendor/reflexio/reflexio/server/llm/tools.py +107 -17
  179. package/plugin/vendor/reflexio/reflexio/server/operation_limiter.py +360 -4
  180. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.6.0.prompt.md +1 -1
  181. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.7.0.prompt.md +85 -0
  182. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.2.0.prompt.md +1 -1
  183. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.3.0.prompt.md +253 -0
  184. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.2.prompt.md +1 -1
  185. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.3.prompt.md +74 -0
  186. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.2.3.prompt.md +1 -1
  187. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.3.0.prompt.md +266 -0
  188. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.4.0.prompt.md +266 -0
  189. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.3.0.prompt.md +1 -1
  190. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.4.0.prompt.md +137 -0
  191. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.2.0.prompt.md +1 -1
  192. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.3.0.prompt.md +34 -0
  193. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.0.0.prompt.md +5 -12
  194. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.1.0.prompt.md +5 -12
  195. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.2.0.prompt.md +155 -0
  196. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/tagging/v1.0.0.prompt.md +23 -0
  197. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_manager.py +89 -32
  198. package/plugin/vendor/reflexio/reflexio/server/services/README.md +26 -11
  199. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/README.md +22 -0
  200. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/__init__.py +1 -0
  201. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_constants.py +4 -2
  202. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_utils.py +1 -0
  203. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/components/__init__.py +7 -0
  204. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/{agent_success_evaluator.py → components/evaluator.py} +3 -16
  205. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/regen_jobs.py +28 -72
  206. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/{group_evaluation_runner.py → runner.py} +12 -10
  207. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/{delayed_group_evaluator.py → scheduler.py} +10 -2
  208. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/{agent_success_evaluation_service.py → service.py} +36 -1
  209. package/plugin/vendor/reflexio/reflexio/server/services/base_generation_service.py +160 -0
  210. package/plugin/vendor/reflexio/reflexio/server/services/configurator/base_configurator.py +5 -0
  211. package/plugin/vendor/reflexio/reflexio/server/services/deduplication_utils.py +1 -1
  212. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/README.md +9 -0
  213. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/components/__init__.py +0 -0
  214. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/{rule_attribution.py → components/rule_attribution.py} +10 -9
  215. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/eval_sampler.py +15 -24
  216. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/service.py +238 -164
  217. package/plugin/vendor/reflexio/reflexio/server/services/extraction/README.md +31 -0
  218. package/plugin/vendor/reflexio/reflexio/server/services/extraction/outcome.py +13 -3
  219. package/plugin/vendor/reflexio/reflexio/server/services/extraction/pending_tool_call_dispatch.py +3 -2
  220. package/plugin/vendor/reflexio/reflexio/server/services/extraction/resumable_agent.py +32 -118
  221. package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_worker.py +39 -16
  222. package/plugin/vendor/reflexio/reflexio/server/services/generation_service.py +105 -23
  223. package/plugin/vendor/reflexio/reflexio/server/services/lineage/__init__.py +0 -0
  224. package/plugin/vendor/reflexio/reflexio/server/services/lineage/gc_scheduler.py +193 -0
  225. package/plugin/vendor/reflexio/reflexio/server/services/lineage/resolve.py +98 -0
  226. package/plugin/vendor/reflexio/reflexio/server/services/operation_state_utils.py +26 -0
  227. package/plugin/vendor/reflexio/reflexio/server/services/playbook/README.md +11 -12
  228. package/plugin/vendor/reflexio/reflexio/server/services/playbook/components/__init__.py +5 -0
  229. package/plugin/vendor/reflexio/reflexio/server/services/playbook/{playbook_aggregator.py → components/aggregator.py} +316 -178
  230. package/plugin/vendor/reflexio/reflexio/server/services/playbook/{playbook_consolidator.py → components/consolidator.py} +168 -62
  231. package/plugin/vendor/reflexio/reflexio/server/services/playbook/{playbook_extractor.py → components/extractor.py} +5 -1
  232. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_edit_apply.py +74 -0
  233. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_service_utils.py +33 -3
  234. package/plugin/vendor/reflexio/reflexio/server/services/playbook/{playbook_generation_service.py → service.py} +121 -19
  235. package/plugin/vendor/reflexio/reflexio/server/services/playbook/user_detail_stripping.py +84 -0
  236. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/README.md +10 -0
  237. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/models.py +2 -1
  238. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/optimizer.py +178 -30
  239. package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/README.md +9 -0
  240. package/plugin/vendor/reflexio/reflexio/server/services/profile/components/__init__.py +17 -0
  241. package/plugin/vendor/reflexio/reflexio/server/services/profile/{profile_deduplicator.py → components/consolidator.py} +7 -6
  242. package/plugin/vendor/reflexio/reflexio/server/services/profile/{profile_extractor.py → components/extractor.py} +30 -22
  243. package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_generation_service_utils.py +6 -13
  244. package/plugin/vendor/reflexio/reflexio/server/services/profile/{profile_generation_service.py → service.py} +32 -50
  245. package/plugin/vendor/reflexio/reflexio/server/services/reflection/__init__.py +4 -8
  246. package/plugin/vendor/reflexio/reflexio/server/services/reflection/components/__init__.py +7 -0
  247. package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_service_utils.py +12 -1
  248. package/plugin/vendor/reflexio/reflexio/server/services/reflection/{reflection_service.py → service.py} +36 -16
  249. package/plugin/vendor/reflexio/reflexio/server/services/retrieval/relevance_floor.py +83 -6
  250. package/plugin/vendor/reflexio/reflexio/server/services/service_utils.py +36 -1
  251. package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/README.md +8 -0
  252. package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/outcome.py +1 -2
  253. package/plugin/vendor/reflexio/reflexio/server/services/storage/error.py +27 -0
  254. package/plugin/vendor/reflexio/reflexio/server/services/storage/retention.py +9 -9
  255. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/__init__.py +2 -0
  256. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_agent_run.py +4 -1
  257. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_base.py +642 -197
  258. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_extras.py +61 -104
  259. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_lineage.py +628 -0
  260. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_operations.py +38 -6
  261. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_playbook.py +978 -184
  262. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_profiles.py +519 -128
  263. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_requests.py +77 -3
  264. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_shadow_verdicts.py +23 -9
  265. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_stall_state.py +5 -2
  266. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/__init__.py +131 -20
  267. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_agent_run.py +2 -8
  268. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_base.py +5 -0
  269. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_extras.py +36 -53
  270. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_lineage.py +215 -0
  271. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_operations.py +20 -0
  272. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_playbook.py +243 -7
  273. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_profiles.py +121 -1
  274. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_requests.py +60 -0
  275. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_retrieval_log.py +51 -0
  276. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_shadow_verdicts.py +17 -0
  277. package/plugin/vendor/reflexio/reflexio/server/services/tagging/README.md +8 -0
  278. package/plugin/vendor/reflexio/reflexio/server/services/tagging/__init__.py +1 -0
  279. package/plugin/vendor/reflexio/reflexio/server/services/tagging/service.py +200 -0
  280. package/plugin/vendor/reflexio/reflexio/server/services/tagging/tagging_scheduler.py +149 -0
  281. package/plugin/vendor/reflexio/reflexio/server/services/unified_search_service.py +229 -32
  282. package/plugin/vendor/reflexio/reflexio/server/site_var/README.md +2 -1
  283. package/plugin/vendor/reflexio/reflexio/server/site_var/feature_flags.py +120 -1
  284. package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/feature_flags.json +4 -0
  285. package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/search_settings.json +5 -0
  286. package/plugin/vendor/reflexio/reflexio/server/tracing.py +30 -0
  287. package/plugin/vendor/reflexio/reflexio/server/usage_metrics.py +18 -0
  288. package/plugin/vendor/reflexio/reflexio/test_support/llm_mock.py +61 -26
  289. package/plugin/vendor/reflexio/reflexio/test_support/llm_model_registry.py +41 -4
  290. package/scripts/setup-claude-smart.sh +8 -3
  291. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/TESTING.md +0 -517
  292. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/hook/handler.js +0 -473
  293. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package-lock.json +0 -2156
  294. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package.json +0 -18
  295. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/handler.ts +0 -241
  296. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/setup.ts +0 -140
  297. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/publish.ts +0 -113
  298. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/search.ts +0 -52
  299. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/server.ts +0 -103
  300. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/sqlite-buffer.ts +0 -156
  301. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/user-id.ts +0 -134
  302. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/rules/reflexio.md +0 -24
  303. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/publish_clawhub.sh +0 -278
  304. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/references/HOOK.md +0 -164
  305. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/install.sh +0 -36
  306. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/uninstall.sh +0 -35
  307. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/publish.test.ts +0 -27
  308. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/search.test.ts +0 -31
  309. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/server.test.ts +0 -42
  310. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/setup.test.ts +0 -49
  311. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/sqlite-buffer.test.ts +0 -91
  312. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/user-id.test.ts +0 -50
  313. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/vitest.config.ts +0 -13
  314. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/group_aggregation.py +0 -192
  315. package/plugin/vendor/reflexio/reflexio/server/services/extraction/invariants.py +0 -303
  316. package/plugin/vendor/reflexio/reflexio/server/services/extraction/plan.py +0 -138
  317. package/plugin/vendor/reflexio/reflexio/server/services/extraction/tools.py +0 -1125
  318. /package/plugin/vendor/reflexio/reflexio/integrations/{__init__.py → openclaw/plugin/src/openclaw_smart/__init__.py} +0 -0
  319. /package/plugin/vendor/reflexio/reflexio/integrations/openclaw/{types → plugin/types}/openclaw.d.ts +0 -0
  320. /package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/{distribution.py → components/distribution.py} +0 -0
  321. /package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/{hero_state.py → components/hero_state.py} +0 -0
  322. /package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/{shadow_aggregation.py → components/shadow_aggregation.py} +0 -0
  323. /package/plugin/vendor/reflexio/reflexio/server/services/reflection/{reflection_extractor.py → components/extractor.py} +0 -0
@@ -1,4 +1,5 @@
1
1
  ---
2
+ name: show
2
3
  description: Show current project-specific skills and session preferences
3
4
  allowed-tools: Bash(bash:*)
4
5
  ---
@@ -6,10 +6,21 @@ import { PageHeader } from "@/components/common/page-header";
6
6
  import { Button } from "@/components/ui/button";
7
7
  import { Input } from "@/components/ui/input";
8
8
  import { Label } from "@/components/ui/label";
9
+ import {
10
+ Select,
11
+ SelectContent,
12
+ SelectItem,
13
+ SelectTrigger,
14
+ SelectValue,
15
+ } from "@/components/ui/select";
9
16
  import { Switch } from "@/components/ui/switch";
10
17
  import { Separator } from "@/components/ui/separator";
11
18
  import { SETTINGS_CHANGED_EVENT } from "@/hooks/use-settings";
12
- import type { ClaudeCodeHookConfig, ClaudeSmartConfig } from "@/lib/types";
19
+ import type {
20
+ ClaudeCodeHookConfig,
21
+ ClaudeSmartConfig,
22
+ OptimizerMode,
23
+ } from "@/lib/types";
13
24
 
14
25
  export default function ConfigureEnvPage() {
15
26
  const [config, setConfig] = useState<ClaudeSmartConfig | null>(null);
@@ -44,14 +55,14 @@ export default function ConfigureEnvPage() {
44
55
  setSaved(false);
45
56
  };
46
57
 
47
- const updateOptimizer = (enabled: boolean) => {
58
+ const updateOptimizer = (mode: OptimizerMode) => {
48
59
  setHookConfig((prev) =>
49
60
  prev
50
61
  ? {
51
62
  ...prev,
52
- CLAUDE_SMART_ENABLE_OPTIMIZER: enabled,
53
- effectiveValue: enabled,
54
- localValue: enabled,
63
+ CLAUDE_SMART_ENABLE_OPTIMIZER: mode,
64
+ effectiveValue: mode,
65
+ localValue: mode === "auto" ? null : mode,
55
66
  }
56
67
  : prev,
57
68
  );
@@ -280,15 +291,29 @@ export default function ConfigureEnvPage() {
280
291
  CLAUDE_SMART_ENABLE_OPTIMIZER
281
292
  </Label>
282
293
  <p className="text-xs text-muted-foreground mt-0.5">
283
- Enable shared skill optimization and rollups during
284
- SessionStart.
294
+ Control shared skill optimization and rollups during
295
+ SessionStart. Auto applies only to local Reflexio.
285
296
  </p>
286
297
  </div>
287
- <Switch
288
- id="enable-optimizer"
289
- checked={!!hookConfig.CLAUDE_SMART_ENABLE_OPTIMIZER}
290
- onCheckedChange={updateOptimizer}
291
- />
298
+ <Select
299
+ value={hookConfig.CLAUDE_SMART_ENABLE_OPTIMIZER}
300
+ onValueChange={(value) =>
301
+ updateOptimizer((value as OptimizerMode) ?? "auto")
302
+ }
303
+ >
304
+ <SelectTrigger
305
+ id="enable-optimizer"
306
+ size="sm"
307
+ className="w-40 text-xs bg-background/80"
308
+ >
309
+ <SelectValue placeholder="Mode" />
310
+ </SelectTrigger>
311
+ <SelectContent align="end">
312
+ <SelectItem value="auto">Auto</SelectItem>
313
+ <SelectItem value="enabled">Enabled</SelectItem>
314
+ <SelectItem value="disabled">Disabled</SelectItem>
315
+ </SelectContent>
316
+ </Select>
292
317
  </div>
293
318
  <div className="rounded-md border border-border bg-background/60 p-3 text-xs text-muted-foreground space-y-2">
294
319
  <div className="flex items-center justify-between gap-4">
@@ -332,7 +357,8 @@ export default function ConfigureEnvPage() {
332
357
  );
333
358
  }
334
359
 
335
- function formatSettingValue(value: boolean | null): string {
360
+ function formatSettingValue(value: OptimizerMode | null): string {
336
361
  if (value === null) return "Not set";
337
- return value ? "Enabled" : "Disabled";
362
+ if (value === "auto") return "Auto (local only)";
363
+ return value === "enabled" ? "Enabled" : "Disabled";
338
364
  }
@@ -6,12 +6,30 @@ import { PageHeader } from "@/components/common/page-header";
6
6
  import { Button } from "@/components/ui/button";
7
7
  import { Input } from "@/components/ui/input";
8
8
  import { Label } from "@/components/ui/label";
9
- import type { ReflexioConfig } from "@/lib/types";
9
+ import { Switch } from "@/components/ui/switch";
10
+ import type { ReflexioConfig, ReflexioRetrievalFloorConfig } from "@/lib/types";
10
11
 
11
12
  type ExtractorField =
12
13
  | "profile_extractor_configs"
13
14
  | "user_playbook_extractor_configs";
14
15
 
16
+ const DEFAULT_RETRIEVAL_FLOOR: Required<
17
+ Pick<
18
+ ReflexioRetrievalFloorConfig,
19
+ | "enabled"
20
+ | "pool_size"
21
+ | "profile_floor"
22
+ | "user_playbook_floor"
23
+ | "agent_playbook_floor"
24
+ >
25
+ > = {
26
+ enabled: false,
27
+ pool_size: 30,
28
+ profile_floor: -3,
29
+ user_playbook_floor: -3,
30
+ agent_playbook_floor: -3,
31
+ };
32
+
15
33
  export default function ConfigureServerPage() {
16
34
  const [srvConfig, setSrvConfig] = useState<ReflexioConfig | null>(null);
17
35
  const [srvError, setSrvError] = useState<string | null>(null);
@@ -73,6 +91,22 @@ export default function ConfigureServerPage() {
73
91
  setSrvSaved(false);
74
92
  };
75
93
 
94
+ const updateReranker = (enabled: boolean) => {
95
+ setSrvConfig((prev) =>
96
+ prev
97
+ ? {
98
+ ...prev,
99
+ retrieval_floor: {
100
+ ...DEFAULT_RETRIEVAL_FLOOR,
101
+ ...(prev.retrieval_floor ?? {}),
102
+ enabled,
103
+ },
104
+ }
105
+ : prev,
106
+ );
107
+ setSrvSaved(false);
108
+ };
109
+
76
110
  const saveSrv = async () => {
77
111
  if (!srvConfig) return;
78
112
  setSrvSaving(true);
@@ -191,6 +225,22 @@ export default function ConfigureServerPage() {
191
225
  />
192
226
  </div>
193
227
 
228
+ <div className="flex items-start justify-between gap-4 rounded-md border border-border bg-background/60 p-3">
229
+ <div className="min-w-0">
230
+ <Label htmlFor="search-reranker">Search reranker</Label>
231
+ <p className="text-xs text-muted-foreground mt-0.5">
232
+ Use the local cross-encoder relevance floor for injected
233
+ memory search. The first enabled search loads the model into
234
+ the backend process.
235
+ </p>
236
+ </div>
237
+ <Switch
238
+ id="search-reranker"
239
+ checked={!!srvConfig.retrieval_floor?.enabled}
240
+ onCheckedChange={updateReranker}
241
+ />
242
+ </div>
243
+
194
244
  <div className="space-y-2">
195
245
  <Label>Preference focus area</Label>
196
246
  <p className="text-xs text-muted-foreground">
@@ -53,12 +53,9 @@ export default function PreferenceDetailPage({
53
53
  useEffect(() => {
54
54
  let cancelled = false;
55
55
  reflexio
56
- .getAllProfiles({ limit: 500 })
57
- .then((res) => {
56
+ .getProfileById(id, { includeTombstones: true })
57
+ .then((found) => {
58
58
  if (cancelled) return;
59
- const found = (res.user_profiles ?? []).find(
60
- (p) => p.profile_id === id,
61
- );
62
59
  if (!found) {
63
60
  setNotFound(true);
64
61
  return;
@@ -397,12 +394,12 @@ function Prose({ text }: { text: string }) {
397
394
  function StatusBadge({
398
395
  status,
399
396
  }: {
400
- status: "CURRENT" | "ARCHIVED" | "PENDING";
397
+ status: "CURRENT" | "ARCHIVED" | "PENDING" | "MERGED" | "SUPERSEDED";
401
398
  }) {
402
399
  const variant =
403
400
  status === "CURRENT"
404
401
  ? "secondary"
405
- : status === "ARCHIVED"
402
+ : status === "ARCHIVED" || status === "MERGED" || status === "SUPERSEDED"
406
403
  ? "outline"
407
404
  : "default";
408
405
  return (
@@ -412,7 +409,10 @@ function StatusBadge({
412
409
  "h-1.5 w-1.5 rounded-full",
413
410
  status === "CURRENT" && "bg-emerald-500",
414
411
  status === "PENDING" && "bg-amber-500",
415
- status === "ARCHIVED" && "bg-muted-foreground",
412
+ (status === "ARCHIVED" ||
413
+ status === "MERGED" ||
414
+ status === "SUPERSEDED") &&
415
+ "bg-muted-foreground",
416
416
  )}
417
417
  />
418
418
  {status}
@@ -28,6 +28,7 @@ import { reflexio } from "@/lib/reflexio-client";
28
28
  import { formatTimestamp, truncateId } from "@/lib/format";
29
29
  import { cn } from "@/lib/utils";
30
30
  import { statusLabel } from "@/lib/status";
31
+ import type { StatusLabel } from "@/lib/status";
31
32
  import type { UserPlaybook } from "@/lib/types";
32
33
 
33
34
  type FormState = { content: string; trigger: string; rationale: string };
@@ -464,12 +465,12 @@ function AutoTextarea({
464
465
  function StatusBadge({
465
466
  status,
466
467
  }: {
467
- status: "CURRENT" | "ARCHIVED" | "PENDING";
468
+ status: StatusLabel;
468
469
  }) {
469
470
  const variant =
470
471
  status === "CURRENT"
471
472
  ? "secondary"
472
- : status === "ARCHIVED"
473
+ : status === "ARCHIVED" || status === "MERGED" || status === "SUPERSEDED"
473
474
  ? "outline"
474
475
  : "default";
475
476
  return (
@@ -479,7 +480,10 @@ function StatusBadge({
479
480
  "h-1.5 w-1.5 rounded-full",
480
481
  status === "CURRENT" && "bg-emerald-500",
481
482
  status === "PENDING" && "bg-amber-500",
482
- status === "ARCHIVED" && "bg-muted-foreground",
483
+ (status === "ARCHIVED" ||
484
+ status === "MERGED" ||
485
+ status === "SUPERSEDED") &&
486
+ "bg-muted-foreground",
483
487
  )}
484
488
  />
485
489
  {status}
@@ -35,6 +35,7 @@ import { reflexio } from "@/lib/reflexio-client";
35
35
  import { formatTimestamp, truncateId } from "@/lib/format";
36
36
  import { cn } from "@/lib/utils";
37
37
  import { agentPlaybookStatusLabel, statusLabel } from "@/lib/status";
38
+ import type { StatusLabel } from "@/lib/status";
38
39
  import type { AgentPlaybook, AgentPlaybookStatus } from "@/lib/types";
39
40
 
40
41
  type FormState = {
@@ -571,12 +572,15 @@ function AutoTextarea({
571
572
  function StatusBadge({
572
573
  status,
573
574
  }: {
574
- status: "CURRENT" | "ARCHIVED" | "PENDING" | "APPROVED" | "REJECTED";
575
+ status: StatusLabel | "APPROVED" | "REJECTED";
575
576
  }) {
576
577
  const variant =
577
578
  status === "CURRENT" || status === "APPROVED"
578
579
  ? "secondary"
579
- : status === "ARCHIVED" || status === "REJECTED"
580
+ : status === "ARCHIVED" ||
581
+ status === "MERGED" ||
582
+ status === "SUPERSEDED" ||
583
+ status === "REJECTED"
580
584
  ? "outline"
581
585
  : "default";
582
586
  return (
@@ -588,7 +592,10 @@ function StatusBadge({
588
592
  status === "APPROVED" && "bg-emerald-500",
589
593
  status === "PENDING" && "bg-amber-500",
590
594
  status === "REJECTED" && "bg-destructive",
591
- status === "ARCHIVED" && "bg-muted-foreground",
595
+ (status === "ARCHIVED" ||
596
+ status === "MERGED" ||
597
+ status === "SUPERSEDED") &&
598
+ "bg-muted-foreground",
592
599
  )}
593
600
  />
594
601
  {status}
@@ -10,7 +10,7 @@ import fs from "node:fs/promises";
10
10
  import { existsSync } from "node:fs";
11
11
  import os from "node:os";
12
12
  import path from "node:path";
13
- import type { ClaudeCodeHookConfig } from "./types";
13
+ import type { ClaudeCodeHookConfig, OptimizerMode } from "./types";
14
14
 
15
15
  const ENV_KEY = "CLAUDE_SMART_ENABLE_OPTIMIZER";
16
16
 
@@ -52,17 +52,22 @@ function asRecord(value: unknown): Record<string, unknown> {
52
52
  return value as Record<string, unknown>;
53
53
  }
54
54
 
55
- function parseEnabled(value: unknown): boolean {
56
- if (value === undefined || value === null || value === "") return true;
57
- if (value === false || value === 0) return false;
58
- if (typeof value === "string" && value.trim() === "0") return false;
59
- return true;
55
+ function parseOptimizerMode(value: unknown): OptimizerMode {
56
+ if (
57
+ value === false ||
58
+ value === 0 ||
59
+ (typeof value === "string" &&
60
+ ["0", "false", "no", "off"].includes(value.trim().toLowerCase()))
61
+ ) {
62
+ return "disabled";
63
+ }
64
+ return "enabled";
60
65
  }
61
66
 
62
- function optimizerValue(settings: Record<string, unknown>): boolean | null {
67
+ function optimizerValue(settings: Record<string, unknown>): OptimizerMode | null {
63
68
  const env = asRecord(settings.env);
64
69
  if (!(ENV_KEY in env)) return null;
65
- return parseEnabled(env[ENV_KEY]);
70
+ return parseOptimizerMode(env[ENV_KEY]);
66
71
  }
67
72
 
68
73
  async function readSettingsFile(file: string): Promise<Record<string, unknown>> {
@@ -84,7 +89,7 @@ export async function readClaudeCodeHookConfig(): Promise<ClaudeCodeHookConfig>
84
89
  ]);
85
90
  const localValue = optimizerValue(localSettings);
86
91
  const userValue = optimizerValue(userSettings);
87
- const effectiveValue = localValue ?? userValue ?? true;
92
+ const effectiveValue = localValue ?? userValue ?? "auto";
88
93
  return {
89
94
  CLAUDE_SMART_ENABLE_OPTIMIZER: effectiveValue,
90
95
  effectiveValue,
@@ -103,7 +108,12 @@ export async function writeClaudeCodeHookConfig(
103
108
  const env = asRecord(settings.env);
104
109
 
105
110
  if (!("CLAUDE_SMART_ENABLE_OPTIMIZER" in update)) return;
106
- env[ENV_KEY] = update.CLAUDE_SMART_ENABLE_OPTIMIZER ? "1" : "0";
111
+ if (update.CLAUDE_SMART_ENABLE_OPTIMIZER === "auto") {
112
+ delete env[ENV_KEY];
113
+ } else {
114
+ env[ENV_KEY] =
115
+ update.CLAUDE_SMART_ENABLE_OPTIMIZER === "enabled" ? "1" : "0";
116
+ }
107
117
 
108
118
  settings.env = env;
109
119
  await fs.mkdir(path.dirname(file), { recursive: true });
@@ -93,6 +93,22 @@ export const reflexio = {
93
93
  return get(`get_all_profiles?${qs.toString()}`);
94
94
  },
95
95
 
96
+ async getProfileById(
97
+ profileId: string,
98
+ opts: { includeTombstones?: boolean } = {},
99
+ ): Promise<UserProfile | null> {
100
+ const qs = new URLSearchParams();
101
+ qs.set("profile_id", profileId);
102
+ if (opts.includeTombstones) qs.set("include_tombstones", "true");
103
+ const res = await get<{ user_profiles: UserProfile[] }>(
104
+ `get_all_profiles?${qs.toString()}`,
105
+ );
106
+ return (
107
+ res.user_profiles?.find((profile) => profile.profile_id === profileId) ??
108
+ null
109
+ );
110
+ },
111
+
96
112
  /** GET /api/get_all_interactions — global, unfiltered. */
97
113
  async getAllInteractions(
98
114
  opts: { limit?: number } = {},
@@ -1,9 +1,14 @@
1
- // Wire status comes from Python's Status StrEnum: lowercase strings
2
- // ("archived", "pending"). CURRENT rows are omitted from JSON entirely
1
+ // Wire status comes from Python's Status enum: lowercase strings
2
+ // ("archived", "pending", "merged", "superseded"). CURRENT rows are omitted from JSON entirely
3
3
  // (response_model_exclude_none) and arrive as `null`/undefined.
4
4
  // Normalize to the uppercase label the dashboard renders.
5
5
 
6
- export type StatusLabel = "CURRENT" | "ARCHIVED" | "PENDING";
6
+ export type StatusLabel =
7
+ | "CURRENT"
8
+ | "ARCHIVED"
9
+ | "PENDING"
10
+ | "MERGED"
11
+ | "SUPERSEDED";
7
12
  export type AgentPlaybookStatusLabel = "PENDING" | "APPROVED" | "REJECTED";
8
13
 
9
14
  export function statusLabel(p: { status?: string | null }): StatusLabel {
@@ -11,6 +16,8 @@ export function statusLabel(p: { status?: string | null }): StatusLabel {
11
16
  const s = String(p.status).toLowerCase();
12
17
  if (s === "archived") return "ARCHIVED";
13
18
  if (s === "pending") return "PENDING";
19
+ if (s === "merged") return "MERGED";
20
+ if (s === "superseded") return "SUPERSEDED";
14
21
  return "CURRENT";
15
22
  }
16
23
 
@@ -9,11 +9,11 @@ export type UserActionType =
9
9
  // (response_model_exclude_none strips it from the JSON entirely), so the type
10
10
  // only enumerates the non-null values. The values are lowercase because they
11
11
  // come from Python's Status StrEnum.
12
- export type LifecycleStatus = "pending" | "archived";
12
+ export type LifecycleStatus = "pending" | "archived" | "merged" | "superseded";
13
13
 
14
14
  export type AgentPlaybookStatus = "pending" | "approved" | "rejected";
15
15
 
16
- export type ProfileStatus = "pending" | "archived";
16
+ export type ProfileStatus = "pending" | "archived" | "merged" | "superseded";
17
17
 
18
18
  export interface ToolUsed {
19
19
  tool_name: string;
@@ -124,11 +124,13 @@ export interface ClaudeSmartConfig {
124
124
  [extra: string]: string | boolean | undefined;
125
125
  }
126
126
 
127
+ export type OptimizerMode = "auto" | "enabled" | "disabled";
128
+
127
129
  export interface ClaudeCodeHookConfig {
128
- CLAUDE_SMART_ENABLE_OPTIMIZER: boolean;
129
- effectiveValue: boolean;
130
- localValue: boolean | null;
131
- userValue: boolean | null;
130
+ CLAUDE_SMART_ENABLE_OPTIMIZER: OptimizerMode;
131
+ effectiveValue: OptimizerMode;
132
+ localValue: OptimizerMode | null;
133
+ userValue: OptimizerMode | null;
132
134
  settingsPath: string;
133
135
  userSettingsPath: string;
134
136
  }
@@ -138,10 +140,20 @@ export interface ReflexioExtractorConfig {
138
140
  [k: string]: unknown;
139
141
  }
140
142
 
143
+ export interface ReflexioRetrievalFloorConfig {
144
+ enabled?: boolean;
145
+ pool_size?: number;
146
+ profile_floor?: number;
147
+ user_playbook_floor?: number;
148
+ agent_playbook_floor?: number;
149
+ [k: string]: unknown;
150
+ }
151
+
141
152
  export interface ReflexioConfig {
142
153
  agent_context_prompt?: string | null;
143
154
  window_size?: number;
144
155
  stride_size?: number;
156
+ retrieval_floor?: ReflexioRetrievalFloorConfig | null;
145
157
  profile_extractor_configs?: ReflexioExtractorConfig[] | null;
146
158
  user_playbook_extractor_configs?: ReflexioExtractorConfig[] | null;
147
159
  [k: string]: unknown;
@@ -1,5 +1,4 @@
1
1
  {
2
- "description": "claude-smart hooks for Codex — learn from sessions via reflexio",
3
2
  "hooks": {
4
3
  "SessionStart": [
5
4
  {
@@ -0,0 +1,108 @@
1
+ import { eventProperties, type EventLike, sessionIDFrom } from "./internal.js"
2
+
3
+ type PartLike = {
4
+ id?: string
5
+ type?: string
6
+ text?: string
7
+ messageID?: string
8
+ }
9
+
10
+ type SessionText = {
11
+ messageID?: string
12
+ parts: Map<string, string>
13
+ textPartIDs: Set<string>
14
+ ignoredPartIDs: Set<string>
15
+ }
16
+
17
+ function textFromPart(part: unknown): { id: string; text: string; messageID?: string } | undefined {
18
+ if (!part || typeof part !== "object") return undefined
19
+ const item = part as PartLike
20
+ if (item.type !== "text") return undefined
21
+ if (typeof item.text !== "string") return undefined
22
+ return {
23
+ id: item.id || `${item.messageID || "message"}:${item.type}`,
24
+ text: item.text,
25
+ messageID: item.messageID,
26
+ }
27
+ }
28
+
29
+ function partIDFrom(part: unknown): string | undefined {
30
+ if (!part || typeof part !== "object") return undefined
31
+ const item = part as PartLike
32
+ return item.id || (item.messageID && item.type ? `${item.messageID}:${item.type}` : undefined)
33
+ }
34
+
35
+ function emptySession(messageID?: string): SessionText {
36
+ return { messageID, parts: new Map(), textPartIDs: new Set(), ignoredPartIDs: new Set() }
37
+ }
38
+
39
+ export class AssistantBuffer {
40
+ private readonly sessions = new Map<string, SessionText>()
41
+
42
+ update(event: EventLike): void {
43
+ const type = event.type
44
+ const properties = eventProperties(event)
45
+ const sessionID = sessionIDFrom(properties)
46
+ if (!sessionID || !type) return
47
+
48
+ if (type === "message.updated") {
49
+ const info = properties.info
50
+ if (!info || typeof info !== "object") return
51
+ const message = info as { id?: string; role?: string }
52
+ if (message.role !== "assistant") return
53
+ const current = this.sessions.get(sessionID)
54
+ if (!current || current.messageID !== message.id) {
55
+ this.sessions.set(sessionID, emptySession(message.id))
56
+ }
57
+ return
58
+ }
59
+
60
+ if (type === "message.part.updated") {
61
+ const hit = textFromPart(properties.part)
62
+ if (!hit) {
63
+ const ignoredID = partIDFrom(properties.part)
64
+ if (!ignoredID) return
65
+ const current: SessionText = this.sessions.get(sessionID) ?? emptySession()
66
+ current.ignoredPartIDs.add(ignoredID)
67
+ current.textPartIDs.delete(ignoredID)
68
+ current.parts.delete(ignoredID)
69
+ this.sessions.set(sessionID, current)
70
+ return
71
+ }
72
+ const current: SessionText = this.sessions.get(sessionID) ?? emptySession()
73
+ if (hit.messageID && current.messageID && hit.messageID !== current.messageID) {
74
+ current.messageID = hit.messageID
75
+ current.parts.clear()
76
+ current.textPartIDs.clear()
77
+ current.ignoredPartIDs.clear()
78
+ } else if (hit.messageID) {
79
+ current.messageID = hit.messageID
80
+ }
81
+ current.ignoredPartIDs.delete(hit.id)
82
+ current.textPartIDs.add(hit.id)
83
+ current.parts.set(hit.id, hit.text)
84
+ this.sessions.set(sessionID, current)
85
+ return
86
+ }
87
+
88
+ if (type === "message.part.delta") {
89
+ const partID = typeof properties.partID === "string" ? properties.partID : undefined
90
+ const delta = typeof properties.delta === "string" ? properties.delta : undefined
91
+ if (!partID || !delta) return
92
+ const current: SessionText = this.sessions.get(sessionID) ?? emptySession()
93
+ if (current.ignoredPartIDs.has(partID) || !current.textPartIDs.has(partID)) return
94
+ current.parts.set(partID, `${current.parts.get(partID) || ""}${delta}`)
95
+ this.sessions.set(sessionID, current)
96
+ }
97
+ }
98
+
99
+ text(sessionID: string): string {
100
+ const current = this.sessions.get(sessionID)
101
+ if (!current) return ""
102
+ return Array.from(current.parts.values()).filter(Boolean).join("\n\n")
103
+ }
104
+
105
+ clear(sessionID: string): void {
106
+ this.sessions.delete(sessionID)
107
+ }
108
+ }
@@ -0,0 +1,96 @@
1
+ import { eventProperties, sessionIDFrom } from "./internal.js";
2
+ function textFromPart(part) {
3
+ if (!part || typeof part !== "object")
4
+ return undefined;
5
+ const item = part;
6
+ if (item.type !== "text")
7
+ return undefined;
8
+ if (typeof item.text !== "string")
9
+ return undefined;
10
+ return {
11
+ id: item.id || `${item.messageID || "message"}:${item.type}`,
12
+ text: item.text,
13
+ messageID: item.messageID,
14
+ };
15
+ }
16
+ function partIDFrom(part) {
17
+ if (!part || typeof part !== "object")
18
+ return undefined;
19
+ const item = part;
20
+ return item.id || (item.messageID && item.type ? `${item.messageID}:${item.type}` : undefined);
21
+ }
22
+ function emptySession(messageID) {
23
+ return { messageID, parts: new Map(), textPartIDs: new Set(), ignoredPartIDs: new Set() };
24
+ }
25
+ export class AssistantBuffer {
26
+ sessions = new Map();
27
+ update(event) {
28
+ const type = event.type;
29
+ const properties = eventProperties(event);
30
+ const sessionID = sessionIDFrom(properties);
31
+ if (!sessionID || !type)
32
+ return;
33
+ if (type === "message.updated") {
34
+ const info = properties.info;
35
+ if (!info || typeof info !== "object")
36
+ return;
37
+ const message = info;
38
+ if (message.role !== "assistant")
39
+ return;
40
+ const current = this.sessions.get(sessionID);
41
+ if (!current || current.messageID !== message.id) {
42
+ this.sessions.set(sessionID, emptySession(message.id));
43
+ }
44
+ return;
45
+ }
46
+ if (type === "message.part.updated") {
47
+ const hit = textFromPart(properties.part);
48
+ if (!hit) {
49
+ const ignoredID = partIDFrom(properties.part);
50
+ if (!ignoredID)
51
+ return;
52
+ const current = this.sessions.get(sessionID) ?? emptySession();
53
+ current.ignoredPartIDs.add(ignoredID);
54
+ current.textPartIDs.delete(ignoredID);
55
+ current.parts.delete(ignoredID);
56
+ this.sessions.set(sessionID, current);
57
+ return;
58
+ }
59
+ const current = this.sessions.get(sessionID) ?? emptySession();
60
+ if (hit.messageID && current.messageID && hit.messageID !== current.messageID) {
61
+ current.messageID = hit.messageID;
62
+ current.parts.clear();
63
+ current.textPartIDs.clear();
64
+ current.ignoredPartIDs.clear();
65
+ }
66
+ else if (hit.messageID) {
67
+ current.messageID = hit.messageID;
68
+ }
69
+ current.ignoredPartIDs.delete(hit.id);
70
+ current.textPartIDs.add(hit.id);
71
+ current.parts.set(hit.id, hit.text);
72
+ this.sessions.set(sessionID, current);
73
+ return;
74
+ }
75
+ if (type === "message.part.delta") {
76
+ const partID = typeof properties.partID === "string" ? properties.partID : undefined;
77
+ const delta = typeof properties.delta === "string" ? properties.delta : undefined;
78
+ if (!partID || !delta)
79
+ return;
80
+ const current = this.sessions.get(sessionID) ?? emptySession();
81
+ if (current.ignoredPartIDs.has(partID) || !current.textPartIDs.has(partID))
82
+ return;
83
+ current.parts.set(partID, `${current.parts.get(partID) || ""}${delta}`);
84
+ this.sessions.set(sessionID, current);
85
+ }
86
+ }
87
+ text(sessionID) {
88
+ const current = this.sessions.get(sessionID);
89
+ if (!current)
90
+ return "";
91
+ return Array.from(current.parts.values()).filter(Boolean).join("\n\n");
92
+ }
93
+ clear(sessionID) {
94
+ this.sessions.delete(sessionID);
95
+ }
96
+ }