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
@@ -50,6 +50,11 @@ class SearchInteractionRequest(BaseModel):
50
50
  class SearchUserProfileRequest(BaseModel):
51
51
  user_id: NonEmptyStr
52
52
  generated_from_request_id: str | None = None
53
+ # Caller correlation IDs for billing attribution on the Application line.
54
+ # Optional; when populated they flow into the usage event request_id /
55
+ # session_id columns via _meter_applied_learnings in server/api.py.
56
+ request_id: str | None = None
57
+ session_id: str | None = None
53
58
  query: str | None = None
54
59
  start_time: datetime | None = None
55
60
  end_time: datetime | None = None
@@ -59,6 +64,7 @@ class SearchUserProfileRequest(BaseModel):
59
64
  extractor_name: str | None = (
60
65
  None # Deprecated compatibility field; accepted but ignored.
61
66
  )
67
+ tags: list[str] | None = None
62
68
  threshold: float | None = Field(default=0.4, ge=0.0, le=1.0)
63
69
  enable_reformulation: bool | None = False
64
70
  search_mode: SearchMode = SearchMode.HYBRID
@@ -181,10 +187,15 @@ class GetInteractionsResponse(BaseModel):
181
187
 
182
188
  class GetUserProfilesRequest(BaseModel):
183
189
  user_id: NonEmptyStr
190
+ profile_id: str | None = None
191
+ query: str | None = None
184
192
  start_time: datetime | None = None
185
193
  end_time: datetime | None = None
186
194
  top_k: int | None = Field(default=30, gt=0)
195
+ source: str | None = None
196
+ profile_time_to_live: str | None = None
187
197
  status_filter: list[Status | None] | None = None
198
+ tags: list[str] | None = None
188
199
 
189
200
  @model_validator(mode="after")
190
201
  def check_time_range(self) -> Self:
@@ -215,10 +226,22 @@ class SetConfigResponse(BaseModel):
215
226
 
216
227
  class GetUserPlaybooksRequest(BaseModel):
217
228
  limit: int | None = Field(default=100, gt=0)
229
+ user_playbook_id: int | None = Field(default=None, gt=0)
218
230
  user_id: str | None = None
231
+ request_id: str | None = None
232
+ query: str | None = None
219
233
  playbook_name: str | None = None
220
234
  agent_version: str | None = None
235
+ start_time: datetime | None = None
236
+ end_time: datetime | None = None
221
237
  status_filter: list[Status | None] | None = None
238
+ tags: list[str] | None = None
239
+
240
+ @model_validator(mode="after")
241
+ def check_time_range(self) -> Self:
242
+ """Validate that end_time is after start_time."""
243
+ TimeRangeValidatorMixin.validate_time_range(self.start_time, self.end_time)
244
+ return self
222
245
 
223
246
 
224
247
  class GetUserPlaybooksResponse(BaseModel):
@@ -229,10 +252,25 @@ class GetUserPlaybooksResponse(BaseModel):
229
252
 
230
253
  class GetAgentPlaybooksRequest(BaseModel):
231
254
  limit: int | None = Field(default=100, gt=0)
255
+ agent_playbook_id: int | None = Field(default=None, gt=0)
256
+ query: str | None = None
232
257
  playbook_name: str | None = None
233
258
  agent_version: str | None = None
259
+ start_time: datetime | None = None
260
+ end_time: datetime | None = None
234
261
  status_filter: list[Status | None] | None = None
235
262
  playbook_status_filter: PlaybookStatus | None = None
263
+ tags: list[str] | None = None
264
+ # Caller correlation IDs for billing attribution on the Application line.
265
+ # Optional; consumed by _meter_applied_learnings in server/api.py.
266
+ request_id: str | None = None
267
+ session_id: str | None = None
268
+
269
+ @model_validator(mode="after")
270
+ def check_time_range(self) -> Self:
271
+ """Validate that end_time is after start_time."""
272
+ TimeRangeValidatorMixin.validate_time_range(self.start_time, self.end_time)
273
+ return self
236
274
 
237
275
 
238
276
  class GetAgentPlaybooksResponse(BaseModel):
@@ -241,6 +279,30 @@ class GetAgentPlaybooksResponse(BaseModel):
241
279
  msg: str | None = None
242
280
 
243
281
 
282
+ class GetLearningProvenanceRequest(BaseModel):
283
+ kind: Literal["profile", "user_playbook", "agent_playbook"]
284
+ id: str
285
+
286
+
287
+ class SourceUserPlaybookProvenanceView(BaseModel):
288
+ user_playbook: UserPlaybookView
289
+ interactions: list[InteractionView] = Field(default_factory=list)
290
+ source_interaction_ids: list[int] = Field(default_factory=list)
291
+
292
+
293
+ class LearningProvenanceViewResponse(BaseModel):
294
+ success: bool
295
+ target_kind: Literal["profile", "user_playbook", "agent_playbook"]
296
+ target_id: str
297
+ provenance_status: Literal["exact", "best_effort", "unavailable"] = "unavailable"
298
+ trigger_request_id: str | None = None
299
+ interactions: list[InteractionView] = Field(default_factory=list)
300
+ source_user_playbooks: list[SourceUserPlaybookProvenanceView] = Field(
301
+ default_factory=list
302
+ )
303
+ msg: str | None = None
304
+
305
+
244
306
  class SearchUserPlaybookRequest(BaseModel):
245
307
  """Request for searching user playbooks with semantic/text search and filtering.
246
308
 
@@ -263,10 +325,15 @@ class SearchUserPlaybookRequest(BaseModel):
263
325
  start_time: datetime | None = None
264
326
  end_time: datetime | None = None
265
327
  status_filter: list[Status | None] | None = None
328
+ tags: list[str] | None = None
266
329
  top_k: int | None = Field(default=10, gt=0)
267
330
  threshold: float | None = Field(default=0.4, ge=0.0, le=1.0)
268
331
  enable_reformulation: bool | None = False
269
332
  search_mode: SearchMode = SearchMode.HYBRID
333
+ # Caller correlation IDs for billing attribution on the Application line.
334
+ # Optional; consumed by _meter_applied_learnings in server/api.py.
335
+ request_id: str | None = None
336
+ session_id: str | None = None
270
337
 
271
338
  @model_validator(mode="after")
272
339
  def check_time_range(self) -> Self:
@@ -316,10 +383,15 @@ class SearchAgentPlaybookRequest(BaseModel):
316
383
  end_time: datetime | None = None
317
384
  status_filter: list[Status | None] | None = None
318
385
  playbook_status_filter: PlaybookStatus | list[PlaybookStatus] | None = None
386
+ tags: list[str] | None = None
319
387
  top_k: int | None = Field(default=10, gt=0)
320
388
  threshold: float | None = Field(default=0.4, ge=0.0, le=1.0)
321
389
  enable_reformulation: bool | None = False
322
390
  search_mode: SearchMode = SearchMode.HYBRID
391
+ # Caller correlation IDs for billing attribution on the Application line.
392
+ # Optional; consumed by _meter_applied_learnings in server/api.py.
393
+ request_id: str | None = None
394
+ session_id: str | None = None
323
395
 
324
396
  @model_validator(mode="after")
325
397
  def check_time_range(self) -> Self:
@@ -345,6 +417,14 @@ class SearchAgentPlaybookResponse(BaseModel):
345
417
  class GetAgentSuccessEvaluationResultsRequest(BaseModel):
346
418
  limit: int | None = Field(default=100, gt=0)
347
419
  agent_version: str | None = None
420
+ start_time: datetime | None = None
421
+ end_time: datetime | None = None
422
+
423
+ @model_validator(mode="after")
424
+ def check_time_range(self) -> Self:
425
+ """Validate that end_time is after start_time."""
426
+ TimeRangeValidatorMixin.validate_time_range(self.start_time, self.end_time)
427
+ return self
348
428
 
349
429
 
350
430
  class GetAgentSuccessEvaluationResultsResponse(BaseModel):
@@ -357,10 +437,18 @@ class GetRequestsRequest(BaseModel):
357
437
  user_id: str | None = None
358
438
  request_id: str | None = None
359
439
  session_id: str | None = None
440
+ source: str | None = None
360
441
  start_time: datetime | None = None
361
442
  end_time: datetime | None = None
362
- top_k: int | None = Field(default=30, gt=0)
363
- offset: int | None = Field(default=0, ge=0)
443
+ top_k: int | None = Field(
444
+ default=30,
445
+ gt=0,
446
+ description="Maximum number of sessions to return. Pagination is "
447
+ "per-session: every returned session includes all of its requests.",
448
+ )
449
+ offset: int | None = Field(
450
+ default=0, ge=0, description="Number of sessions to skip for pagination."
451
+ )
364
452
 
365
453
  @model_validator(mode="after")
366
454
  def check_time_range(self) -> Self:
@@ -450,7 +538,8 @@ class TimeSeriesDataPoint(BaseModel):
450
538
  """A single data point in a time series."""
451
539
 
452
540
  timestamp: int = Field(gt=0) # Unix timestamp
453
- value: int = Field(ge=0) # Count or metric value
541
+ value: float = Field(ge=0) # Count or metric value
542
+ count: int | None = Field(default=None, ge=0) # Optional weight for rate metrics
454
543
 
455
544
 
456
545
  class PeriodStats(BaseModel):
@@ -621,6 +710,11 @@ class UnifiedSearchRequest(BaseModel):
621
710
  enable_reformulation: bool | None = False
622
711
  enable_agent_answer: bool | None = False
623
712
  search_mode: SearchMode = SearchMode.HYBRID
713
+ # Caller correlation IDs for billing attribution on the Application line.
714
+ # Optional; consumed by _meter_applied_learnings in server/api.py.
715
+ request_id: str | None = None
716
+ session_id: str | None = None
717
+ interaction_id: int | None = Field(default=None, gt=0)
624
718
 
625
719
 
626
720
  class UnifiedSearchResponse(BaseModel):
@@ -78,6 +78,8 @@ def to_profile_view(profile: UserProfile) -> ProfileView:
78
78
  status=profile.status,
79
79
  extractor_names=profile.extractor_names,
80
80
  source_span=profile.source_span,
81
+ source_interaction_ids=profile.source_interaction_ids,
82
+ tags=profile.tags or [],
81
83
  )
82
84
 
83
85
 
@@ -104,6 +106,7 @@ def to_user_playbook_view(rf: UserPlaybook) -> UserPlaybookView:
104
106
  source=rf.source,
105
107
  source_interaction_ids=rf.source_interaction_ids,
106
108
  source_span=rf.source_span,
109
+ tags=rf.tags or [],
107
110
  )
108
111
 
109
112
 
@@ -127,6 +130,7 @@ def to_agent_playbook_view(fb: AgentPlaybook) -> AgentPlaybookView:
127
130
  playbook_status=fb.playbook_status,
128
131
  playbook_metadata=fb.playbook_metadata,
129
132
  status=fb.status,
133
+ tags=fb.tags or [],
130
134
  )
131
135
 
132
136
 
@@ -143,6 +147,7 @@ def to_evaluation_result_view(
143
147
  """
144
148
  return EvaluationResultView(
145
149
  result_id=result.result_id,
150
+ user_id=result.user_id,
146
151
  agent_version=result.agent_version,
147
152
  session_id=result.session_id,
148
153
  is_success=result.is_success,
@@ -173,5 +178,4 @@ def to_profile_change_log_view(log: ProfileChangeLog) -> ProfileChangeLogView:
173
178
  created_at=log.created_at,
174
179
  added_profiles=[to_profile_view(p) for p in log.added_profiles],
175
180
  removed_profiles=[to_profile_view(p) for p in log.removed_profiles],
176
- mentioned_profiles=[to_profile_view(p) for p in log.mentioned_profiles],
177
181
  )
@@ -65,6 +65,8 @@ class ProfileView(BaseModel):
65
65
  status: Status | None = None
66
66
  extractor_names: list[str] | None = None
67
67
  source_span: str | None = None
68
+ source_interaction_ids: list[int] = Field(default_factory=list)
69
+ tags: list[str] = Field(default_factory=list)
68
70
 
69
71
 
70
72
  class UserPlaybookView(BaseModel):
@@ -83,6 +85,7 @@ class UserPlaybookView(BaseModel):
83
85
  source: str | None = None
84
86
  source_interaction_ids: list[int] = Field(default_factory=list)
85
87
  source_span: str | None = None
88
+ tags: list[str] = Field(default_factory=list)
86
89
 
87
90
 
88
91
  class AgentPlaybookView(BaseModel):
@@ -98,12 +101,14 @@ class AgentPlaybookView(BaseModel):
98
101
  playbook_status: PlaybookStatus = PlaybookStatus.PENDING
99
102
  playbook_metadata: str = ""
100
103
  status: Status | None = None
104
+ tags: list[str] = Field(default_factory=list)
101
105
 
102
106
 
103
107
  class EvaluationResultView(BaseModel):
104
108
  """User-facing AgentSuccessEvaluationResult — excludes embedding."""
105
109
 
106
110
  result_id: int = 0
111
+ user_id: str = ""
107
112
  agent_version: str
108
113
  session_id: str
109
114
  is_success: bool
@@ -126,4 +131,3 @@ class ProfileChangeLogView(BaseModel):
126
131
  created_at: int = Field(default_factory=lambda: int(datetime.now(UTC).timestamp()))
127
132
  added_profiles: list[ProfileView]
128
133
  removed_profiles: list[ProfileView]
129
- mentioned_profiles: list[ProfileView]
@@ -95,7 +95,13 @@ def _migrate_dict(data: Any, mapping: dict[str, str]) -> Any:
95
95
  if isinstance(data, dict):
96
96
  data = dict(data)
97
97
  for old, new in mapping.items():
98
- if old in data and new not in data:
98
+ if old not in data:
99
+ continue
100
+ # New name wins when both are present; always drop the old key so it
101
+ # doesn't survive into validation and trip ``extra="forbid"``.
102
+ if new in data:
103
+ data.pop(old)
104
+ else:
99
105
  data[new] = data.pop(old)
100
106
  return data
101
107
 
@@ -397,6 +403,16 @@ class DeduplicationConfig(BaseModel):
397
403
  SINGLETON_PROFILE_EXTRACTOR_NAME = "profile"
398
404
  SINGLETON_USER_PLAYBOOK_NAME = "playbook"
399
405
  SINGLETON_AGENT_SUCCESS_EVALUATION_NAME = "agent_success"
406
+ DEFAULT_AGENT_SUCCESS_SAMPLING_RATE = 0.05
407
+ DEFAULT_AGENT_SUCCESS_DEFINITION_PROMPT = (
408
+ "Evaluate whether the AI agent successfully handled the user's session.\n\n"
409
+ "Mark the session successful when, by the end of the conversation, the agent:\n"
410
+ "1. Identified and addressed the user's main goal or question.\n"
411
+ "2. Provided a correct, useful, and actionable response or completed the requested action.\n"
412
+ "Mark the session unsuccessful when the agent failed to understand the request,\n"
413
+ "gave incorrect or unhelpful guidance, did not complete an available action,\n"
414
+ "ignored important constraints, or left the user unsatisfied."
415
+ )
400
416
 
401
417
 
402
418
  class ProfileExtractorConfig(_ExtractorWindowOverrideCompatMixin, BaseModel):
@@ -405,7 +421,7 @@ class ProfileExtractorConfig(_ExtractorWindowOverrideCompatMixin, BaseModel):
405
421
  extractor_name: NonEmptyStr | None = None
406
422
  extraction_definition_prompt: SanitizedNonEmptyStr
407
423
  context_prompt: str | None = None
408
- metadata_definition_prompt: str | None = None
424
+ tagging_definition_prompt: str | None = None
409
425
  should_extract_profile_prompt_override: str | None = None
410
426
  request_sources_enabled: list[str] | None = (
411
427
  None # default enabled for all sources, if set, only extract profiles from the enabled request sources
@@ -456,7 +472,7 @@ class UserPlaybookExtractorConfig(_ExtractorWindowOverrideCompatMixin, BaseModel
456
472
  extractor_name: NonEmptyStr | None = None
457
473
  extraction_definition_prompt: SanitizedNonEmptyStr
458
474
  context_prompt: str | None = None
459
- metadata_definition_prompt: str | None = None
475
+ tagging_definition_prompt: str | None = None
460
476
  aggregation_config: PlaybookAggregatorConfig | None = None
461
477
  deduplication_config: DeduplicationConfig | None = None
462
478
  request_sources_enabled: list[str] | None = (
@@ -488,9 +504,15 @@ class AgentSuccessConfig(_ExtractorWindowOverrideCompatMixin, BaseModel):
488
504
  evaluation_name: NonEmptyStr | None = None
489
505
  success_definition_prompt: SanitizedNonEmptyStr
490
506
  metadata_definition_prompt: str | None = None
507
+ request_sources_enabled: list[str] | None = (
508
+ None # default enabled for all sources, if set, only evaluate requests from the enabled request sources
509
+ )
491
510
  sampling_rate: float = Field(
492
- default=1.0, ge=0.0, le=1.0
493
- ) # fraction of window of interactions to be sampled for success evaluation
511
+ default=DEFAULT_AGENT_SUCCESS_SAMPLING_RATE,
512
+ ge=0.0,
513
+ le=1.0,
514
+ description="Fraction of sessions to evaluate automatically.",
515
+ )
494
516
  window_size_override: int | None = Field(default=None, gt=0)
495
517
  stride_size_override: int | None = Field(default=None, gt=0)
496
518
 
@@ -500,6 +522,14 @@ class AgentSuccessConfig(_ExtractorWindowOverrideCompatMixin, BaseModel):
500
522
  return _migrate_dict(data, _EXTRACTOR_OVERRIDE_MIGRATION)
501
523
 
502
524
 
525
+ def _default_agent_success_config() -> AgentSuccessConfig:
526
+ return AgentSuccessConfig(
527
+ evaluation_name=SINGLETON_AGENT_SUCCESS_EVALUATION_NAME,
528
+ success_definition_prompt=DEFAULT_AGENT_SUCCESS_DEFINITION_PROMPT,
529
+ sampling_rate=DEFAULT_AGENT_SUCCESS_SAMPLING_RATE,
530
+ )
531
+
532
+
503
533
  class ReflectionConfig(BaseModel):
504
534
  """Configuration for the sliding-window reflection step.
505
535
 
@@ -559,7 +589,7 @@ class RetrievalFloorConfig(BaseModel):
559
589
  weak tail that drives false-positive citations. Calibrate per arm on real data.
560
590
  """
561
591
 
562
- enabled: bool = True
592
+ enabled: bool = False
563
593
  pool_size: int = Field(
564
594
  default=30,
565
595
  gt=0,
@@ -634,6 +664,62 @@ class PlaybookOptimizerConfig(BaseModel):
634
664
  return self
635
665
 
636
666
 
667
+ class LineageGCConfig(BaseModel):
668
+ """Configuration for the tombstone garbage-collection job (enabled by default).
669
+
670
+ Purpose
671
+ -------
672
+ Retains tombstone content for ``tombstone_grace_window_days`` days after the
673
+ row's *retirement instant* (``retired_at``) to support audit, replay of dedup
674
+ and aggregation runs, and rollback. After the window expires the row is
675
+ hard-deleted and a ``hard_delete`` lineage event is recorded.
676
+
677
+ Age basis
678
+ ---------
679
+ The GC ages on ``retired_at`` — the INTEGER epoch set when a row is tombstoned
680
+ (merged, superseded, or archived). Rows with ``retired_at = NULL`` (created
681
+ before the column was added) are never eligible; they have no retirement clock.
682
+
683
+ Grace window
684
+ ------------
685
+ 90 days is the default grace window. This matches common 90-day soft-delete
686
+ retention policies and satisfies GDPR Art. 5(1)(e) storage-limitation for
687
+ personal data in profiles. The value is a per-deployment policy knob; ratify
688
+ with your DPO before shortening it in production. The 90-day floor also
689
+ preserves tombstones long enough for B3 changelog replay and rollback
690
+ consumers — raise ``tombstone_grace_window_days`` further if your replay
691
+ horizon exceeds 90 days.
692
+
693
+ Enabled by default
694
+ ------------------
695
+ GC is ON by default so tombstones created by the soft-delete flags (also ON by
696
+ default) are reclaimed automatically. Disabling GC while soft-delete is enabled
697
+ allows tombstone counts to grow without bound — only do this deliberately (e.g.
698
+ extended audit hold) and with a plan to re-enable.
699
+
700
+ Disabling
701
+ ---------
702
+ Set ``enabled = False`` in your deployment config to hold all tombstones
703
+ indefinitely (e.g. for an extended audit window or rollback standby period).
704
+ """
705
+
706
+ enabled: bool = True
707
+ tombstone_grace_window_days: int = Field(default=90, gt=0)
708
+ poll_interval_seconds: int = Field(default=86400, gt=0)
709
+
710
+
711
+ class GovernanceRetentionConfig(BaseModel):
712
+ """Audit-event retention policy. **Enterprise-only:** reclamation is performed
713
+ by the reflexio_ext GovernanceRetentionCapability. In an OSS-only deployment
714
+ these knobs are accepted but inert (the OSS lineage scheduler does not reclaim
715
+ audit events) and the server logs a startup warning when retention is enabled.
716
+ """
717
+
718
+ audit_events_retention_enabled: bool = False
719
+ audit_events_retention_days: int = Field(default=365, gt=0)
720
+ audit_events_delete_batch_limit: int = Field(default=500, gt=0)
721
+
722
+
637
723
  @dataclass(frozen=True)
638
724
  class EffectivePendingToolCallConfig:
639
725
  """Resolved pending-tool-call settings after applying tool overrides."""
@@ -733,6 +819,8 @@ def _default_user_playbook_extractor_config() -> UserPlaybookExtractorConfig:
733
819
 
734
820
 
735
821
  class Config(BaseModel):
822
+ model_config = ConfigDict(extra="forbid")
823
+
736
824
  # define where user configuration is stored at
737
825
  storage_config: StorageConfig
738
826
  storage_config_test: StorageConfigTest | None = StorageConfigTest.UNKNOWN
@@ -749,7 +837,9 @@ class Config(BaseModel):
749
837
  default_factory=_default_user_playbook_extractor_config
750
838
  )
751
839
  # agent level success
752
- agent_success_config: AgentSuccessConfig | None = None
840
+ agent_success_config: AgentSuccessConfig | None = Field(
841
+ default_factory=_default_agent_success_config
842
+ )
753
843
  # extraction preset — selects bundled window_size/stride_size values
754
844
  extraction_preset: ExtractionPreset | None = None
755
845
  # extraction parameters
@@ -767,6 +857,11 @@ class Config(BaseModel):
767
857
  playbook_optimizer_config: PlaybookOptimizerConfig = Field(
768
858
  default_factory=PlaybookOptimizerConfig
769
859
  )
860
+ # Tombstone GC job gate (opt-in, off by default — see LineageGCConfig)
861
+ lineage_gc: LineageGCConfig = Field(default_factory=LineageGCConfig)
862
+ governance_retention: GovernanceRetentionConfig = Field(
863
+ default_factory=GovernanceRetentionConfig
864
+ )
770
865
  # Optional non-blocking async information tools for classic extraction.
771
866
  pending_tool_call_config: PendingToolCallConfig = Field(
772
867
  default_factory=PendingToolCallConfig
@@ -824,6 +919,8 @@ class Config(BaseModel):
824
919
  "stride_size",
825
920
  "reflection_config",
826
921
  "playbook_optimizer_config",
922
+ "lineage_gc",
923
+ "governance_retention",
827
924
  "pending_tool_call_config",
828
925
  "retrieval_floor",
829
926
  ):
@@ -0,0 +1,148 @@
1
+ """Provider-safe base class for LLM structured-output Pydantic models.
2
+
3
+ Every Pydantic model sent to an LLM as a structured-output schema (a
4
+ ``response_format`` or a tool's parameter schema) should inherit
5
+ ``StrictStructuredOutput``. It carries a ``__get_pydantic_json_schema__`` hook
6
+ (via ``ProviderSafeUnionMixin``) that folds a discriminated union's ``oneOf`` into
7
+ ``anyOf`` and drops ``discriminator`` in the *emitted* JSON schema, so strict
8
+ structured-output endpoints (OpenAI, minimax) accept it **by construction** — with
9
+ no provider-detection gate and no post-processing. Only the wire schema is
10
+ rewritten; the core (validation) schema keeps the discriminator, so keyed dispatch
11
+ and precise per-variant errors are preserved.
12
+
13
+ This module lives under ``models/`` (depending only on pydantic) so both
14
+ ``models/api_schema/`` schemas and ``server/services/*`` models can inherit the
15
+ base without a layering inversion (a ``models/`` file importing from
16
+ ``server/llm/`` would invert the dependency direction).
17
+ """
18
+
19
+ from typing import TYPE_CHECKING, Any
20
+
21
+ from pydantic import BaseModel, GetJsonSchemaHandler
22
+ from pydantic.json_schema import JsonSchemaValue
23
+ from pydantic_core import CoreSchema
24
+
25
+ # Keys whose *values* are name→subschema maps: their entries are user-chosen names
26
+ # (field names, $def names), not JSON-Schema keywords. Traversals must recurse into
27
+ # the subschemas but never treat the names themselves as keywords — otherwise a
28
+ # model with a field literally named ``oneOf`` would be mishandled.
29
+ _SCHEMA_NAME_MAP_KEYS = ("properties", "$defs", "definitions", "patternProperties")
30
+
31
+
32
+ def _fold_oneof_to_anyof(node: Any) -> None:
33
+ """Rewrite ``oneOf`` to ``anyOf`` and drop ``discriminator`` in place (recursive).
34
+
35
+ Pydantic emits ``oneOf`` + ``discriminator`` for a discriminated union, which
36
+ strict structured-output endpoints (OpenAI, minimax) reject. Folding into
37
+ ``anyOf`` keeps the identical variant set so generation stays constrained;
38
+ Pydantic still enforces the discriminator after parse, so semantics are
39
+ preserved.
40
+
41
+ Structure-aware: under a name→subschema map (``properties``/``$defs``/…) it
42
+ recurses into the subschemas but does NOT treat a property/``$def`` *name* as a
43
+ keyword — so a model field literally named ``oneOf``/``discriminator`` is
44
+ preserved (only keyword-position occurrences are folded). Precondition:
45
+ ``node`` is a finite acyclic tree, as produced by ``model_json_schema()``
46
+ (which expresses recursion via ``$ref``/``$defs`` strings, never in-memory
47
+ cycles) — there is no cycle guard.
48
+
49
+ Args:
50
+ node (Any): A JSON-schema fragment (dict, list, or scalar); mutated in place.
51
+ """
52
+ if isinstance(node, dict):
53
+ one_of = node.pop("oneOf", None)
54
+ node.pop("discriminator", None)
55
+ if isinstance(one_of, list):
56
+ node["anyOf"] = node.get("anyOf", []) + one_of
57
+ for key, value in node.items():
58
+ if key in _SCHEMA_NAME_MAP_KEYS and isinstance(value, dict):
59
+ for sub in value.values():
60
+ _fold_oneof_to_anyof(sub)
61
+ else:
62
+ _fold_oneof_to_anyof(value)
63
+ elif isinstance(node, list):
64
+ for item in node:
65
+ _fold_oneof_to_anyof(item)
66
+
67
+
68
+ # Statically the mixin must appear to derive from ``BaseModel`` so the ``super()``
69
+ # call below type-checks; at runtime it is a bare mixin (``object`` base), and
70
+ # ``super()`` resolves to ``BaseModel.__get_pydantic_json_schema__`` via the MRO
71
+ # of the concrete model (e.g. ``class X(ProviderSafeUnionMixin, BaseModel)``).
72
+ _ProviderSafeUnionBase = BaseModel if TYPE_CHECKING else object
73
+
74
+
75
+ class ProviderSafeUnionMixin(_ProviderSafeUnionBase):
76
+ """Make a model emit a provider-safe JSON schema by construction.
77
+
78
+ A model containing a Pydantic discriminated union serializes to JSON Schema
79
+ with ``oneOf`` + ``discriminator``, which strict structured-output endpoints
80
+ reject (the Sentry ``PYTHON-FASTAPI-9J`` incident). Mixing this in folds
81
+ ``oneOf`` into ``anyOf`` (and drops ``discriminator``) at the model boundary,
82
+ so every caller of ``model_json_schema()`` — litellm, instructor, our own
83
+ path — gets a provider-safe schema **unconditionally**, without depending on
84
+ a provider-detection gate (e.g. ``litellm.supports_response_schema``, which
85
+ under-reports some providers). Only the JSON (wire) schema is rewritten; the
86
+ core validation schema keeps the discriminator, so keyed dispatch and precise
87
+ per-variant errors are preserved.
88
+
89
+ Prefer inheriting ``StrictStructuredOutput`` (below) on output models rather
90
+ than mixing this in directly.
91
+ """
92
+
93
+ @classmethod
94
+ def __get_pydantic_json_schema__(
95
+ cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler
96
+ ) -> JsonSchemaValue:
97
+ # Chain via super() (not handler() directly) so a cooperative base that
98
+ # also customizes __get_pydantic_json_schema__ is not silently shadowed;
99
+ # BaseModel's default impl just invokes handler(core_schema).
100
+ schema = super().__get_pydantic_json_schema__(core_schema, handler)
101
+ _fold_oneof_to_anyof(schema)
102
+ return schema
103
+
104
+
105
+ class StrictStructuredOutput(ProviderSafeUnionMixin, BaseModel):
106
+ """Base for every Pydantic model sent to an LLM as a structured-output schema.
107
+
108
+ Inherits the provider-safe schema hook from ``ProviderSafeUnionMixin`` so the
109
+ emitted JSON schema folds any discriminated union (``oneOf``→``anyOf``, drop
110
+ ``discriminator``) by construction — accepted by strict structured-output
111
+ providers with no provider gate, including any *future* discriminated union.
112
+
113
+ Deliberately adds NO ``model_config``: each model keeps its own ``extra=`` and
114
+ ``json_schema_extra`` exactly as before. This base unifies the *provider-safety
115
+ guarantee*, not the per-model config (centralizing config is a separate change —
116
+ ``extra=`` is not uniform across models, so a blanket dedup would silently shift
117
+ validation/serialization behavior).
118
+ """
119
+
120
+
121
+ def find_schema_keyword(node: Any, keyword: str) -> bool:
122
+ """Report whether ``keyword`` appears as a JSON-Schema *keyword* anywhere in ``node``.
123
+
124
+ Structure-aware: an occurrence of ``keyword`` as a property/``$defs`` *name*
125
+ (e.g. a model field literally named ``oneOf``) is NOT a match — only an
126
+ occurrence in JSON-Schema keyword position counts. Use this (not a blind
127
+ ``in``-walk) to check a schema for provider-unsafe keywords.
128
+
129
+ Args:
130
+ node (Any): A JSON-schema fragment (dict, list, or scalar).
131
+ keyword (str): The JSON-Schema keyword to search for (e.g. ``"oneOf"``).
132
+
133
+ Returns:
134
+ bool: True if ``keyword`` appears in keyword position, else False.
135
+ """
136
+ if isinstance(node, dict):
137
+ if keyword in node:
138
+ return True
139
+ for key, value in node.items():
140
+ if key in _SCHEMA_NAME_MAP_KEYS and isinstance(value, dict):
141
+ if any(find_schema_keyword(sub, keyword) for sub in value.values()):
142
+ return True
143
+ elif find_schema_keyword(value, keyword):
144
+ return True
145
+ return False
146
+ if isinstance(node, list):
147
+ return any(find_schema_keyword(item, keyword) for item in node)
148
+ return False
@@ -23,7 +23,7 @@ Client (SDK/Web)
23
23
  -> GenerationService (server/services/)
24
24
  ├─> ProfileGenerationService -> ProfileExtractor(s) -> Storage
25
25
  ├─> PlaybookGenerationService -> PlaybookExtractor(s) -> Storage
26
- └─> GroupEvaluationScheduler (deferred 10 min) -> Evaluator(s) -> Storage
26
+ └─> agent_success_evaluation/scheduler.py:GroupEvaluationScheduler (deferred 10 min) -> agent_success_evaluation/runner.py:run_group_evaluation -> agent_success_evaluation/service.py -> agent_success_evaluation/components/evaluator.py -> Storage
27
27
  ```
28
28
 
29
29
  ## Prerequisites
@@ -41,7 +41,7 @@ cp .env.example .env # Configure environment (set at lea
41
41
  uv sync # Install Python dependencies (includes workspace packages)
42
42
  npm --prefix src/website install # Install frontend dependencies
43
43
  npm --prefix src/public_docs install # Install docs dependencies
44
- ./run_services.sh # Starts API (8081), Website (8080), Docs (8082)
44
+ ./run_services.sh # Starts API (8061), Website (8080), Docs (8062)
45
45
  ./stop_services.sh # Stop all services
46
46
  ```
47
47
 
@@ -56,7 +56,7 @@ npm --prefix src/public_docs install # Install docs dependencies
56
56
  **Testing:**
57
57
  ```python
58
58
  import reflexio
59
- client = reflexio.ReflexioClient(api_key="your-api-key", url_endpoint="http://127.0.0.1:8081/")
59
+ client = reflexio.ReflexioClient(api_key="your-api-key", url_endpoint="http://127.0.0.1:8061/")
60
60
  ```
61
61
  See `notebooks/reflexio_cookbook.ipynb` and `src/tests/readme.md`
62
62