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,14 +1,21 @@
1
1
  import logging
2
+ from collections import defaultdict
2
3
 
3
4
  logger = logging.getLogger(__name__)
4
5
 
5
6
  from datetime import UTC, datetime
7
+ from typing import Protocol
6
8
 
7
9
  from reflexio.lib._base import (
8
10
  STORAGE_NOT_CONFIGURED_MSG,
9
11
  ReflexioBase,
10
12
  _require_storage,
11
13
  )
14
+ from reflexio.models.api_schema.domain.entities import (
15
+ LineageEvent,
16
+ ProfileChangeLog,
17
+ UserProfile,
18
+ )
12
19
  from reflexio.models.api_schema.retriever_schema import (
13
20
  GetProfileStatisticsResponse,
14
21
  GetUserProfilesRequest,
@@ -36,7 +43,7 @@ from reflexio.models.api_schema.service_schemas import (
36
43
  UpgradeProfilesRequest,
37
44
  UpgradeProfilesResponse,
38
45
  )
39
- from reflexio.server.services.profile.profile_generation_service import (
46
+ from reflexio.server.services.profile.service import (
40
47
  ProfileGenerationService,
41
48
  )
42
49
  from reflexio.server.tracing import profile_step
@@ -199,15 +206,21 @@ class ProfilesMixin(ReflexioBase):
199
206
  )
200
207
 
201
208
  def get_profile_change_logs(self) -> ProfileChangeLogResponse:
202
- """Get profile change logs.
209
+ """Get profile change logs, served from the lineage reconstruction.
210
+
211
+ The change-log view is rebuilt on demand from ``lineage_event`` linkage
212
+ joined to survivor/tombstone content via
213
+ :func:`reconstruct_profile_change_log`. The legacy ``profile_change_logs``
214
+ table is no longer written (B3 Task 6) or read (B3 Task 7); it is retained
215
+ frozen until its removal in Task 8.
203
216
 
204
217
  Returns:
205
- ProfileChangeLogResponse: Response containing profile change logs
218
+ ProfileChangeLogResponse: Response containing the reconstructed
219
+ profile change logs.
206
220
  """
207
221
  if not self._is_storage_configured():
208
222
  return ProfileChangeLogResponse(success=True, profile_change_logs=[])
209
- changelogs = self._get_storage().get_profile_change_logs()
210
- return ProfileChangeLogResponse(success=True, profile_change_logs=changelogs)
223
+ return reconstruct_profile_change_log(self._get_storage())
211
224
 
212
225
  @_require_storage(DeleteUserProfileResponse)
213
226
  def delete_profile(
@@ -401,26 +414,22 @@ class ProfilesMixin(ReflexioBase):
401
414
  status_filter = [None] # Default to current profiles
402
415
 
403
416
  profiles = self._get_storage().get_user_profile(
404
- request.user_id, status_filter=status_filter
417
+ request.user_id,
418
+ status_filter=status_filter,
419
+ tags=request.tags,
420
+ profile_id=request.profile_id,
421
+ query=request.query,
422
+ source=request.source,
423
+ profile_time_to_live=request.profile_time_to_live,
424
+ start_time=(
425
+ int(request.start_time.timestamp()) if request.start_time else None
426
+ ),
427
+ end_time=int(request.end_time.timestamp()) if request.end_time else None,
405
428
  )
406
429
  profiles = sorted(
407
430
  profiles, key=lambda x: x.last_modified_timestamp, reverse=True
408
431
  )
409
432
 
410
- # Apply time filters
411
- if request.start_time:
412
- profiles = [
413
- p
414
- for p in profiles
415
- if p.last_modified_timestamp >= int(request.start_time.timestamp())
416
- ]
417
- if request.end_time:
418
- profiles = [
419
- p
420
- for p in profiles
421
- if p.last_modified_timestamp <= int(request.end_time.timestamp())
422
- ]
423
-
424
433
  # Apply top_k limit
425
434
  if request.top_k:
426
435
  profiles = sorted(
@@ -437,6 +446,13 @@ class ProfilesMixin(ReflexioBase):
437
446
  self,
438
447
  limit: int = 100,
439
448
  status_filter: list[Status | None] | None = None,
449
+ user_id: str | None = None,
450
+ profile_id: str | None = None,
451
+ query: str | None = None,
452
+ source: str | None = None,
453
+ profile_time_to_live: str | None = None,
454
+ start_time: int | None = None,
455
+ end_time: int | None = None,
440
456
  ) -> GetUserProfilesResponse:
441
457
  """Get all user profiles across all users.
442
458
 
@@ -454,7 +470,15 @@ class ProfilesMixin(ReflexioBase):
454
470
  if status_filter is None:
455
471
  status_filter = [None] # Default to current profiles
456
472
  profiles = self._get_storage().get_all_profiles(
457
- limit=limit, status_filter=status_filter
473
+ limit=limit,
474
+ status_filter=status_filter,
475
+ user_id=user_id,
476
+ profile_id=profile_id,
477
+ query=query,
478
+ source=source,
479
+ profile_time_to_live=profile_time_to_live,
480
+ start_time=start_time,
481
+ end_time=end_time,
458
482
  )
459
483
  profiles = sorted(
460
484
  profiles, key=lambda x: x.last_modified_timestamp, reverse=True
@@ -543,3 +567,182 @@ class ProfilesMixin(ReflexioBase):
543
567
  return GetProfileStatisticsResponse(
544
568
  success=False, msg=f"Failed to get profile statistics: {str(e)}"
545
569
  )
570
+
571
+
572
+ # ---------------------------------------------------------------------------
573
+ # Standalone read-side reconstruction (Phase B3 Task 2)
574
+ # ---------------------------------------------------------------------------
575
+
576
+
577
+ class ChangeLogReadStorage(Protocol):
578
+ """The storage read surface ``reconstruct_profile_change_log`` requires.
579
+
580
+ Both the real ``BaseStorage`` backends and the read-only
581
+ ``RestStorageReader`` satisfy this structurally — no inheritance required —
582
+ so reconstruction can run against either without an unsound ``cast`` to
583
+ ``BaseStorage``.
584
+ """
585
+
586
+ org_id: str
587
+
588
+ def get_lineage_events(
589
+ self,
590
+ *,
591
+ entity_type: str | None = ...,
592
+ entity_id: str | None = ...,
593
+ org_id: str | None = ...,
594
+ request_id: str | None = ...,
595
+ ) -> list[LineageEvent]: ...
596
+
597
+ def get_distinct_generated_from_request_ids(self) -> list[str]: ...
598
+
599
+ def get_profiles_by_generated_from_request_id(
600
+ self, request_id: str
601
+ ) -> list[UserProfile]: ...
602
+
603
+ def get_all_generated_profiles(self) -> list[UserProfile]: ...
604
+
605
+ def get_profile_by_id(
606
+ self, profile_id: str, *, include_tombstones: bool = ...
607
+ ) -> UserProfile | None: ...
608
+
609
+
610
+ def reconstruct_profile_change_log(
611
+ storage: ChangeLogReadStorage,
612
+ *,
613
+ limit: int = 100,
614
+ ) -> ProfileChangeLogResponse:
615
+ """Rebuild the ProfileChangeLog view using time-travel-stable signals.
616
+
617
+ Uses two immutable / stable signals to classify every dedup run:
618
+
619
+ * **added(R)** — profiles whose ``generated_from_request_id == R``. This
620
+ column is set at creation and never changes, so it correctly classifies
621
+ a profile as "added in run R" even if it is later tombstoned in run R2.
622
+ Tombstones are included so the content is available.
623
+
624
+ * **removed(R)** — entity_ids of ``status_change`` lineage events with
625
+ ``to_status == "superseded"`` and ``request_id == R``. This is the
626
+ exact signature emitted by ``supersede_profiles_by_ids`` (the dedup
627
+ soft-delete path). It is distinct from reflection which emits
628
+ ``op="revise"``, so reflection events are never mis-counted as removals.
629
+
630
+ Groups are formed over the union of request_ids from both signals.
631
+ Request_id ``""`` is skipped — it would merge unrelated runs.
632
+ A row is emitted only when ``added or removed`` is non-empty (matching
633
+ legacy semantics: the legacy table was written only when
634
+ ``all_new_profiles or superseded_profiles``).
635
+
636
+ When a removed profile's tombstone has been physically purged (GDPR GC),
637
+ it is silently omitted from ``removed_profiles`` rather than crashing.
638
+
639
+ Args:
640
+ storage (ChangeLogReadStorage): Storage read surface to query (any
641
+ BaseStorage backend or the read-only ``RestStorageReader``).
642
+ limit (int): Maximum number of reconstructed entries to return.
643
+ Defaults to 100.
644
+
645
+ Returns:
646
+ ProfileChangeLogResponse: ``success=True`` with reconstructed rows
647
+ ordered most-recent first (by max event ``created_at`` in each
648
+ request_id group), capped at ``limit``.
649
+ """
650
+ if limit <= 0:
651
+ return ProfileChangeLogResponse(success=True, profile_change_logs=[])
652
+
653
+ all_events = storage.get_lineage_events(
654
+ entity_type="profile", org_id=storage.org_id
655
+ )
656
+
657
+ # Dedup soft-delete signature: status_change to_status=="superseded".
658
+ # Each such event records one profile removed in the dedup run ``request_id``.
659
+ # Distinct from reflection which emits op="revise" — so revise events are
660
+ # never counted as removals here.
661
+ removal_by_req: dict[str, list[str]] = defaultdict(list)
662
+ sort_key: dict[str, tuple[int, int]] = {} # request_id -> (created_at, event_id)
663
+ for evt in all_events:
664
+ key = evt.request_id
665
+ if not key:
666
+ continue # skip empty-string request_ids — never merge unrelated runs
667
+ cur = sort_key.get(key, (0, 0))
668
+ if (evt.created_at, evt.event_id) > cur:
669
+ sort_key[key] = (evt.created_at, evt.event_id)
670
+ if evt.op == "status_change" and evt.to_status == "superseded":
671
+ removal_by_req[key].append(evt.entity_id)
672
+
673
+ # Resolve the "added" side for every run in ONE bulk read, grouped by each
674
+ # profile's immutable generated_from_request_id. This replaces a read per
675
+ # candidate request_id, which fanned out over the org's whole dedup history
676
+ # before the limit slice below — a hot-path N+1 on network-backed storage now
677
+ # that the live endpoint serves this reconstruction.
678
+ added_by_req: dict[str, list] = defaultdict(list)
679
+ for profile in storage.get_all_generated_profiles():
680
+ added_by_req[profile.generated_from_request_id].append(profile)
681
+
682
+ # Candidate request_ids are the UNION of:
683
+ # (a) lineage EVENT request_ids — runs that produced a dedup removal
684
+ # (status_change/superseded event); and
685
+ # (b) request_ids stamped on profile rows (the keys of added_by_req) —
686
+ # discovers ADD-ONLY dedup runs (new profiles, nothing superseded) that
687
+ # emit no lineage event. ``get_all_generated_profiles`` already excludes
688
+ # the empty-string sentinel, so unrelated runs are never merged.
689
+ #
690
+ # This closes the reconstruction-completeness gap for add-only runs: the
691
+ # legacy `add_profile_change_log` fired whenever `all_new_profiles or
692
+ # superseded_profiles` was non-empty, so a run with only adds was still
693
+ # recorded. The (b) path mirrors that.
694
+ #
695
+ # For add-only runs (in set (b) but not (a)), no event timestamp exists.
696
+ # We derive their sort key from the max `last_modified_timestamp` of the
697
+ # profiles in that group — set at creation, giving a sensible most-recent-first
698
+ # ordering relative to event-timestamped runs. The secondary key is 0.
699
+ candidate_req_ids: set[str] = set(sort_key.keys()) | set(added_by_req.keys())
700
+
701
+ def _effective_sort_key(req_id: str) -> tuple[int, int]:
702
+ """Return (timestamp, event_id) for sorting; for add-only runs fall back to
703
+ the max last_modified_timestamp of the profiles in that group."""
704
+ if req_id in sort_key:
705
+ return sort_key[req_id]
706
+ profiles = added_by_req.get(req_id, [])
707
+ max_ts = max((p.last_modified_timestamp for p in profiles), default=0)
708
+ return (max_ts, 0)
709
+
710
+ sorted_keys = sorted(
711
+ candidate_req_ids,
712
+ key=_effective_sort_key,
713
+ reverse=True,
714
+ )[:limit]
715
+
716
+ logs: list[ProfileChangeLog] = []
717
+ for req_id in sorted_keys:
718
+ # added: profiles whose generated_from_request_id == req_id (any status,
719
+ # include tombstones — a profile added in R1 and tombstoned in R2 is still
720
+ # "added in R1").
721
+ added = added_by_req[req_id]
722
+
723
+ # removed: dedup-superseded profiles from this run's lineage events.
724
+ removed: list = []
725
+ for entity_id in removal_by_req.get(req_id, []):
726
+ profile = storage.get_profile_by_id(entity_id, include_tombstones=True)
727
+ if profile is not None:
728
+ removed.append(profile)
729
+ # Tombstone physically purged (GDPR GC) → silently omit; no crash.
730
+
731
+ if not added and not removed:
732
+ # No dedup activity for this request_id — skip to match legacy semantics.
733
+ continue
734
+
735
+ ts, _ = _effective_sort_key(req_id)
736
+ user_id = added[0].user_id if added else removed[0].user_id
737
+ logs.append(
738
+ ProfileChangeLog(
739
+ id=0,
740
+ user_id=user_id,
741
+ request_id=req_id,
742
+ created_at=ts,
743
+ added_profiles=added,
744
+ removed_profiles=removed,
745
+ )
746
+ )
747
+
748
+ return ProfileChangeLogResponse(success=True, profile_change_logs=logs)
@@ -41,7 +41,7 @@ class ReflectionMixin(ReflexioBase):
41
41
 
42
42
  # Local import keeps the heavy service module out of facade
43
43
  # cold-start when reflection is disabled.
44
- from reflexio.server.services.reflection.reflection_service import (
44
+ from reflexio.server.services.reflection.service import (
45
45
  ReflectionService,
46
46
  )
47
47
 
@@ -13,6 +13,7 @@ from reflexio.models.api_schema.retriever_schema import (
13
13
  )
14
14
  from reflexio.server.llm.model_defaults import ModelRole, resolve_model_name
15
15
  from reflexio.server.site_var.site_var_manager import SiteVarManager
16
+ from reflexio.server.tracing import profile_step
16
17
 
17
18
  _LOGGER = logging.getLogger(__name__)
18
19
 
@@ -40,9 +41,23 @@ class SearchMixin(ReflexioBase):
40
41
  request = GetAgentSuccessEvaluationResultsRequest(**request)
41
42
 
42
43
  try:
43
- results = self._get_storage().get_agent_success_evaluation_results(
44
- limit=request.limit or 100, agent_version=request.agent_version
45
- )
44
+ if request.start_time or request.end_time:
45
+ results = self._get_storage().get_agent_success_evaluation_results_in_window(
46
+ from_ts=(
47
+ int(request.start_time.timestamp()) if request.start_time else 0
48
+ ),
49
+ to_ts=(
50
+ int(request.end_time.timestamp())
51
+ if request.end_time
52
+ else 2**31 - 1
53
+ ),
54
+ limit=request.limit or 100,
55
+ agent_version=request.agent_version,
56
+ )
57
+ else:
58
+ results = self._get_storage().get_agent_success_evaluation_results(
59
+ limit=request.limit or 100, agent_version=request.agent_version
60
+ )
46
61
  return GetAgentSuccessEvaluationResultsResponse(
47
62
  success=True,
48
63
  agent_success_evaluation_results=results,
@@ -78,6 +93,7 @@ class SearchMixin(ReflexioBase):
78
93
  user_id=request.user_id,
79
94
  request_id=request.request_id,
80
95
  session_id=request.session_id,
96
+ source=request.source,
81
97
  start_time=(
82
98
  int(request.start_time.timestamp()) if request.start_time else None
83
99
  ),
@@ -103,10 +119,11 @@ class SearchMixin(ReflexioBase):
103
119
  Session(session_id=group_name, requests=request_data_list)
104
120
  )
105
121
 
106
- # Determine has_more: count total requests returned across all groups
122
+ # Pagination is session-based (top_k counts sessions): there may be
123
+ # more pages when this page filled the session limit.
107
124
  total_returned = sum(len(s.requests) for s in sessions)
108
125
  effective_limit = request.top_k or 100
109
- has_more = total_returned >= effective_limit
126
+ has_more = len(sessions) >= effective_limit
110
127
 
111
128
  return GetRequestsResponse(
112
129
  success=True,
@@ -136,32 +153,42 @@ class SearchMixin(ReflexioBase):
136
153
  if isinstance(request, dict):
137
154
  request = UnifiedSearchRequest(**request)
138
155
 
139
- config = self.request_context.configurator.get_config()
156
+ with profile_step(
157
+ "search.prepare",
158
+ enabled=bool(request.enable_reformulation),
159
+ has_conversation_history=bool(request.conversation_history),
160
+ search_mode=request.search_mode,
161
+ ):
162
+ config = self.request_context.configurator.get_config()
163
+ config_llm_config = config.llm_config if config else None
164
+
165
+ # Resolve pre_retrieval_model_name: config override -> site var -> auto-detect.
166
+ model_setting = SiteVarManager().get_site_var("llm_model_setting")
167
+ site_var = model_setting if isinstance(model_setting, dict) else {}
168
+ api_key_config = config.api_key_config if config else None
169
+
170
+ pre_retrieval_model_name = resolve_model_name(
171
+ ModelRole.PRE_RETRIEVAL,
172
+ site_var_value=site_var.get("pre_retrieval_model_name"),
173
+ config_override=config_llm_config.pre_retrieval_model_name
174
+ if config_llm_config
175
+ else None,
176
+ api_key_config=api_key_config,
177
+ )
178
+ storage = self._get_storage()
179
+ prompt_manager = self.request_context.prompt_manager
180
+ retrieval_floor = config.retrieval_floor if config else None
181
+ recency = getattr(storage, "recency", None)
140
182
 
141
183
  from reflexio.server.services.unified_search_service import run_unified_search
142
184
 
143
- config_llm_config = config.llm_config if config else None
144
-
145
- # Resolve pre_retrieval_model_name: config override → site var → auto-detect
146
- model_setting = SiteVarManager().get_site_var("llm_model_setting")
147
- site_var = model_setting if isinstance(model_setting, dict) else {}
148
- api_key_config = config.api_key_config if config else None
149
-
150
- pre_retrieval_model_name = resolve_model_name(
151
- ModelRole.PRE_RETRIEVAL,
152
- site_var_value=site_var.get("pre_retrieval_model_name"),
153
- config_override=config_llm_config.pre_retrieval_model_name
154
- if config_llm_config
155
- else None,
156
- api_key_config=api_key_config,
157
- )
158
-
159
185
  return run_unified_search(
160
186
  request=request,
161
187
  org_id=org_id,
162
- storage=self._get_storage(),
188
+ storage=storage,
163
189
  llm_client=self.llm_client,
164
- prompt_manager=self.request_context.prompt_manager,
190
+ prompt_manager=prompt_manager,
165
191
  pre_retrieval_model_name=pre_retrieval_model_name,
166
- retrieval_floor=config.retrieval_floor if config else None,
192
+ retrieval_floor=retrieval_floor,
193
+ recency=recency,
167
194
  )
@@ -24,7 +24,7 @@ from reflexio.models.api_schema.service_schemas import (
24
24
  UpgradeUserPlaybooksResponse,
25
25
  )
26
26
  from reflexio.models.config_schema import SearchOptions
27
- from reflexio.server.services.playbook.playbook_generation_service import (
27
+ from reflexio.server.services.playbook.service import (
28
28
  PlaybookGenerationService,
29
29
  )
30
30
  from reflexio.server.tracing import profile_step
@@ -53,10 +53,20 @@ class UserPlaybookMixin(ReflexioBase):
53
53
  try:
54
54
  user_playbooks = self._get_storage().get_user_playbooks(
55
55
  limit=request.limit or 100,
56
+ user_playbook_id=request.user_playbook_id,
56
57
  user_id=request.user_id,
58
+ request_id=request.request_id,
59
+ query=request.query,
57
60
  playbook_name=request.playbook_name,
58
61
  agent_version=request.agent_version,
59
62
  status_filter=request.status_filter,
63
+ start_time=(
64
+ int(request.start_time.timestamp()) if request.start_time else None
65
+ ),
66
+ end_time=(
67
+ int(request.end_time.timestamp()) if request.end_time else None
68
+ ),
69
+ tags=request.tags,
60
70
  )
61
71
  return GetUserPlaybooksResponse(
62
72
  success=True,
@@ -1,3 +1,4 @@
1
1
  from ..common import * # noqa: F401, F403
2
2
  from .entities import * # noqa: F401, F403
3
3
  from .enums import * # noqa: F401, F403
4
+ from .governance import * # noqa: F401, F403