claude-smart 0.2.42 → 0.2.44

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 (402) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/README.md +1 -1
  3. package/bin/claude-smart.js +2 -2
  4. package/package.json +9 -3
  5. package/plugin/.claude-plugin/plugin.json +9 -3
  6. package/plugin/.codex-plugin/plugin.json +1 -1
  7. package/plugin/README.md +23 -3
  8. package/plugin/pyproject.toml +3 -3
  9. package/plugin/scripts/_lib.sh +91 -0
  10. package/plugin/scripts/backend-service.sh +51 -4
  11. package/plugin/scripts/cli.sh +3 -1
  12. package/plugin/scripts/codex-hook.js +72 -4
  13. package/plugin/scripts/dashboard-build.sh +1 -0
  14. package/plugin/scripts/dashboard-service.sh +1 -0
  15. package/plugin/scripts/ensure-plugin-root.sh +1 -0
  16. package/plugin/scripts/hook_entry.sh +6 -3
  17. package/plugin/scripts/smart-install.sh +3 -2
  18. package/plugin/src/README.md +57 -0
  19. package/plugin/src/claude_smart/context_format.py +11 -12
  20. package/plugin/src/claude_smart/cs_cite.py +26 -12
  21. package/plugin/src/claude_smart/ids.py +13 -5
  22. package/plugin/uv.lock +126 -5
  23. package/plugin/vendor/reflexio/.env.example +62 -0
  24. package/plugin/vendor/reflexio/LICENSE +201 -0
  25. package/plugin/vendor/reflexio/README.md +338 -0
  26. package/plugin/vendor/reflexio/pyproject.toml +274 -0
  27. package/plugin/vendor/reflexio/reflexio/README.md +184 -0
  28. package/plugin/vendor/reflexio/reflexio/__init__.py +166 -0
  29. package/plugin/vendor/reflexio/reflexio/benchmarks/__init__.py +1 -0
  30. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/README.md +109 -0
  31. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/__init__.py +1 -0
  32. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/backends.py +175 -0
  33. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/bench.py +642 -0
  34. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/embed_cache.py +330 -0
  35. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/report.py +317 -0
  36. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/results/report.md +43 -0
  37. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/results/results.json +4478 -0
  38. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/scenarios.py +134 -0
  39. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/seed.py +255 -0
  40. package/plugin/vendor/reflexio/reflexio/cli/README.md +287 -0
  41. package/plugin/vendor/reflexio/reflexio/cli/__init__.py +0 -0
  42. package/plugin/vendor/reflexio/reflexio/cli/__main__.py +56 -0
  43. package/plugin/vendor/reflexio/reflexio/cli/_client.py +86 -0
  44. package/plugin/vendor/reflexio/reflexio/cli/app.py +127 -0
  45. package/plugin/vendor/reflexio/reflexio/cli/bootstrap_config.py +265 -0
  46. package/plugin/vendor/reflexio/reflexio/cli/codex_auth.py +503 -0
  47. package/plugin/vendor/reflexio/reflexio/cli/commands/__init__.py +0 -0
  48. package/plugin/vendor/reflexio/reflexio/cli/commands/admin_cmd.py +65 -0
  49. package/plugin/vendor/reflexio/reflexio/cli/commands/agent_playbooks.py +503 -0
  50. package/plugin/vendor/reflexio/reflexio/cli/commands/api.py +114 -0
  51. package/plugin/vendor/reflexio/reflexio/cli/commands/auth.py +109 -0
  52. package/plugin/vendor/reflexio/reflexio/cli/commands/config_cmd.py +511 -0
  53. package/plugin/vendor/reflexio/reflexio/cli/commands/doctor.py +127 -0
  54. package/plugin/vendor/reflexio/reflexio/cli/commands/embeddings.py +53 -0
  55. package/plugin/vendor/reflexio/reflexio/cli/commands/interactions.py +478 -0
  56. package/plugin/vendor/reflexio/reflexio/cli/commands/profiles.py +303 -0
  57. package/plugin/vendor/reflexio/reflexio/cli/commands/services.py +289 -0
  58. package/plugin/vendor/reflexio/reflexio/cli/commands/setup_cmd.py +964 -0
  59. package/plugin/vendor/reflexio/reflexio/cli/commands/shortcuts.py +285 -0
  60. package/plugin/vendor/reflexio/reflexio/cli/commands/status_cmd.py +143 -0
  61. package/plugin/vendor/reflexio/reflexio/cli/commands/user_playbooks.py +373 -0
  62. package/plugin/vendor/reflexio/reflexio/cli/env_loader.py +284 -0
  63. package/plugin/vendor/reflexio/reflexio/cli/errors.py +217 -0
  64. package/plugin/vendor/reflexio/reflexio/cli/log_format.py +247 -0
  65. package/plugin/vendor/reflexio/reflexio/cli/output.py +867 -0
  66. package/plugin/vendor/reflexio/reflexio/cli/paths.py +41 -0
  67. package/plugin/vendor/reflexio/reflexio/cli/run_services.py +391 -0
  68. package/plugin/vendor/reflexio/reflexio/cli/state.py +204 -0
  69. package/plugin/vendor/reflexio/reflexio/cli/stop_services.py +96 -0
  70. package/plugin/vendor/reflexio/reflexio/cli/utils.py +329 -0
  71. package/plugin/vendor/reflexio/reflexio/client/__init__.py +3 -0
  72. package/plugin/vendor/reflexio/reflexio/client/cache.py +150 -0
  73. package/plugin/vendor/reflexio/reflexio/client/client.py +2613 -0
  74. package/plugin/vendor/reflexio/reflexio/defaults.py +23 -0
  75. package/plugin/vendor/reflexio/reflexio/integrations/__init__.py +0 -0
  76. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/.clawhubignore +7 -0
  77. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/README.md +274 -0
  78. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/TESTING.md +517 -0
  79. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/hook/handler.js +473 -0
  80. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package-lock.json +2156 -0
  81. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package.json +18 -0
  82. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/handler.ts +241 -0
  83. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/setup.ts +140 -0
  84. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/index.ts +130 -0
  85. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/publish.ts +113 -0
  86. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/search.ts +52 -0
  87. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/server.ts +103 -0
  88. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/sqlite-buffer.ts +156 -0
  89. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/user-id.ts +134 -0
  90. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/openclaw.plugin.json +41 -0
  91. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/package.json +17 -0
  92. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/rules/reflexio.md +24 -0
  93. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/reflexio/SKILL.md +48 -0
  94. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/publish_clawhub.sh +278 -0
  95. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/references/HOOK.md +164 -0
  96. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/install.sh +36 -0
  97. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/uninstall.sh +35 -0
  98. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/publish.test.ts +27 -0
  99. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/search.test.ts +31 -0
  100. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/server.test.ts +42 -0
  101. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/setup.test.ts +49 -0
  102. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/sqlite-buffer.test.ts +91 -0
  103. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/user-id.test.ts +50 -0
  104. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tsconfig.json +16 -0
  105. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/types/openclaw.d.ts +230 -0
  106. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/vitest.config.ts +13 -0
  107. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/README.md +120 -0
  108. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/TESTING.md +168 -0
  109. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/package-lock.json +1657 -0
  110. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/package.json +16 -0
  111. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/HEARTBEAT.md +6 -0
  112. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/README.md +84 -0
  113. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/SKILL.md +194 -0
  114. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/_meta.json +6 -0
  115. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/agents/reflexio-extractor.md +45 -0
  116. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/hook/handler.ts +214 -0
  117. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/hook/setup.ts +55 -0
  118. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/index.ts +327 -0
  119. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/consolidate.ts +233 -0
  120. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/dedup.ts +80 -0
  121. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/io.ts +155 -0
  122. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/openclaw-cli.ts +67 -0
  123. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/search.ts +33 -0
  124. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/write-playbook.ts +76 -0
  125. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/write-profile.ts +79 -0
  126. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/openclaw.plugin.json +46 -0
  127. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/package.json +18 -0
  128. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/README.md +36 -0
  129. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/full_consolidation.md +56 -0
  130. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/playbook_extraction.md +217 -0
  131. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/profile_extraction.md +132 -0
  132. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/skills/reflexio-consolidate/SKILL.md +33 -0
  133. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/skills/reflexio-embedded/SKILL.md +194 -0
  134. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/HOOK.md +18 -0
  135. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/architecture.md +49 -0
  136. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/comparison.md +31 -0
  137. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/future-work.md +47 -0
  138. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/porting-notes.md +52 -0
  139. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/scripts/install.sh +52 -0
  140. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/scripts/uninstall.sh +36 -0
  141. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/consolidate.test.ts +135 -0
  142. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/dedup.test.ts +104 -0
  143. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/io.test.ts +175 -0
  144. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/search.test.ts +66 -0
  145. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/smoke-test.ts +140 -0
  146. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/write-playbook.test.ts +93 -0
  147. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/write-profile.test.ts +174 -0
  148. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tsconfig.json +16 -0
  149. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/types/openclaw.d.ts +230 -0
  150. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/vitest.config.ts +7 -0
  151. package/plugin/vendor/reflexio/reflexio/lib/__init__.py +23 -0
  152. package/plugin/vendor/reflexio/reflexio/lib/_agent_playbook.py +310 -0
  153. package/plugin/vendor/reflexio/reflexio/lib/_base.py +225 -0
  154. package/plugin/vendor/reflexio/reflexio/lib/_config.py +83 -0
  155. package/plugin/vendor/reflexio/reflexio/lib/_dashboard.py +266 -0
  156. package/plugin/vendor/reflexio/reflexio/lib/_generation.py +176 -0
  157. package/plugin/vendor/reflexio/reflexio/lib/_interactions.py +334 -0
  158. package/plugin/vendor/reflexio/reflexio/lib/_operations.py +153 -0
  159. package/plugin/vendor/reflexio/reflexio/lib/_profiles.py +545 -0
  160. package/plugin/vendor/reflexio/reflexio/lib/_reflection.py +52 -0
  161. package/plugin/vendor/reflexio/reflexio/lib/_search.py +167 -0
  162. package/plugin/vendor/reflexio/reflexio/lib/_storage_labels.py +103 -0
  163. package/plugin/vendor/reflexio/reflexio/lib/_user_playbook.py +288 -0
  164. package/plugin/vendor/reflexio/reflexio/lib/reflexio_lib.py +27 -0
  165. package/plugin/vendor/reflexio/reflexio/models/__init__.py +0 -0
  166. package/plugin/vendor/reflexio/reflexio/models/api_schema/__init__.py +0 -0
  167. package/plugin/vendor/reflexio/reflexio/models/api_schema/braintrust_schema.py +141 -0
  168. package/plugin/vendor/reflexio/reflexio/models/api_schema/common.py +41 -0
  169. package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/__init__.py +3 -0
  170. package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/entities.py +1112 -0
  171. package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/enums.py +63 -0
  172. package/plugin/vendor/reflexio/reflexio/models/api_schema/eval_overview_schema.py +487 -0
  173. package/plugin/vendor/reflexio/reflexio/models/api_schema/internal_schema.py +28 -0
  174. package/plugin/vendor/reflexio/reflexio/models/api_schema/pending_tool_call_schema.py +83 -0
  175. package/plugin/vendor/reflexio/reflexio/models/api_schema/retriever_schema.py +768 -0
  176. package/plugin/vendor/reflexio/reflexio/models/api_schema/service_schemas.py +9 -0
  177. package/plugin/vendor/reflexio/reflexio/models/api_schema/stall_state_schema.py +32 -0
  178. package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/__init__.py +3 -0
  179. package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/converters.py +177 -0
  180. package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/entities.py +129 -0
  181. package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/enums.py +25 -0
  182. package/plugin/vendor/reflexio/reflexio/models/api_schema/validators.py +333 -0
  183. package/plugin/vendor/reflexio/reflexio/models/config_schema.py +908 -0
  184. package/plugin/vendor/reflexio/reflexio/models/py.typed +0 -0
  185. package/plugin/vendor/reflexio/reflexio/server/OVERVIEW.md +90 -0
  186. package/plugin/vendor/reflexio/reflexio/server/README.md +622 -0
  187. package/plugin/vendor/reflexio/reflexio/server/__init__.py +210 -0
  188. package/plugin/vendor/reflexio/reflexio/server/__main__.py +132 -0
  189. package/plugin/vendor/reflexio/reflexio/server/_auth.py +25 -0
  190. package/plugin/vendor/reflexio/reflexio/server/api.py +2868 -0
  191. package/plugin/vendor/reflexio/reflexio/server/api_endpoints/README.md +34 -0
  192. package/plugin/vendor/reflexio/reflexio/server/api_endpoints/account_api.py +143 -0
  193. package/plugin/vendor/reflexio/reflexio/server/api_endpoints/health_api.py +91 -0
  194. package/plugin/vendor/reflexio/reflexio/server/api_endpoints/pending_tool_call_api.py +572 -0
  195. package/plugin/vendor/reflexio/reflexio/server/api_endpoints/precondition_checks.py +66 -0
  196. package/plugin/vendor/reflexio/reflexio/server/api_endpoints/publisher_api.py +562 -0
  197. package/plugin/vendor/reflexio/reflexio/server/api_endpoints/request_context.py +50 -0
  198. package/plugin/vendor/reflexio/reflexio/server/api_endpoints/stall_state_api.py +100 -0
  199. package/plugin/vendor/reflexio/reflexio/server/cache/__init__.py +15 -0
  200. package/plugin/vendor/reflexio/reflexio/server/cache/reflexio_cache.py +208 -0
  201. package/plugin/vendor/reflexio/reflexio/server/correlation.py +46 -0
  202. package/plugin/vendor/reflexio/reflexio/server/llm/__init__.py +30 -0
  203. package/plugin/vendor/reflexio/reflexio/server/llm/embedding_service.py +359 -0
  204. package/plugin/vendor/reflexio/reflexio/server/llm/image_utils.py +55 -0
  205. package/plugin/vendor/reflexio/reflexio/server/llm/litellm_client.py +1871 -0
  206. package/plugin/vendor/reflexio/reflexio/server/llm/llm_utils.py +140 -0
  207. package/plugin/vendor/reflexio/reflexio/server/llm/model_defaults.py +479 -0
  208. package/plugin/vendor/reflexio/reflexio/server/llm/providers/__init__.py +1 -0
  209. package/plugin/vendor/reflexio/reflexio/server/llm/providers/claude_code_provider.py +1122 -0
  210. package/plugin/vendor/reflexio/reflexio/server/llm/providers/claude_code_stream_parser.py +197 -0
  211. package/plugin/vendor/reflexio/reflexio/server/llm/providers/embedding_service_provider.py +338 -0
  212. package/plugin/vendor/reflexio/reflexio/server/llm/providers/local_embedding_provider.py +213 -0
  213. package/plugin/vendor/reflexio/reflexio/server/llm/providers/nomic_embedding_provider.py +288 -0
  214. package/plugin/vendor/reflexio/reflexio/server/llm/rerank/__init__.py +6 -0
  215. package/plugin/vendor/reflexio/reflexio/server/llm/rerank/cross_encoder_reranker.py +187 -0
  216. package/plugin/vendor/reflexio/reflexio/server/llm/rerank/llm_reranker.py +148 -0
  217. package/plugin/vendor/reflexio/reflexio/server/llm/tools.py +716 -0
  218. package/plugin/vendor/reflexio/reflexio/server/operation_limiter.py +179 -0
  219. package/plugin/vendor/reflexio/reflexio/server/prompt/__init__.py +0 -0
  220. package/plugin/vendor/reflexio/reflexio/server/prompt/_dispatchers.py +54 -0
  221. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/README.md +121 -0
  222. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/agent_success_evaluation/v1.0.0.prompt.md +58 -0
  223. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/agent_success_evaluation_with_comparison/v1.0.0.prompt.md +76 -0
  224. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/answer_synthesis/v1.5.2.prompt.md +88 -0
  225. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/compress_session_for_query/v1.3.0.prompt.md +31 -0
  226. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/document_expansion/v1.0.0.prompt.md +20 -0
  227. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.0.0.prompt.md +53 -0
  228. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.1.0.prompt.md +57 -0
  229. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.2.0.prompt.md +68 -0
  230. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.3.0.prompt.md +70 -0
  231. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.4.0.prompt.md +77 -0
  232. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.5.0.prompt.md +82 -0
  233. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.6.0.prompt.md +83 -0
  234. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.1.0.prompt.md +193 -0
  235. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.2.0.prompt.md +206 -0
  236. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v1.0.0-deprecated.prompt.md +66 -0
  237. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v1.0.0.prompt.md +43 -0
  238. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v1.1.0.prompt.md +46 -0
  239. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.0.0-deprecated.prompt.md +64 -0
  240. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.0.0.prompt.md +39 -0
  241. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.1.0.prompt.md +39 -0
  242. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.2.0.prompt.md +47 -0
  243. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.0.prompt.md +58 -0
  244. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.1.prompt.md +69 -0
  245. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.2.prompt.md +71 -0
  246. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.0.2.prompt.md +254 -0
  247. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.1.0.prompt.md +274 -0
  248. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.2.0.prompt.md +283 -0
  249. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.2.2.prompt.md +234 -0
  250. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.2.3.prompt.md +244 -0
  251. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v1.0.0.prompt.md +73 -0
  252. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v2.0.0.prompt.md +86 -0
  253. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.0.0.prompt.md +97 -0
  254. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.1.0.prompt.md +119 -0
  255. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.2.0.prompt.md +123 -0
  256. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.3.0.prompt.md +137 -0
  257. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.0.0.prompt.md +14 -0
  258. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.1.0.prompt.md +24 -0
  259. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.2.0.prompt.md +29 -0
  260. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main_expert/v1.0.0.prompt.md +11 -0
  261. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main_expert/v1.1.0.prompt.md +21 -0
  262. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main_expert/v1.2.0.prompt.md +25 -0
  263. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_optimizer_judge/v1.0.0.prompt.md +37 -0
  264. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_optimizer_judge/v1.1.0.prompt.md +40 -0
  265. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_optimizer_judge/v1.2.0.prompt.md +36 -0
  266. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate/v1.0.0.prompt.md +45 -0
  267. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate/v2.0.0.prompt.md +81 -0
  268. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate/v3.0.0.prompt.md +80 -0
  269. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate_expert/v1.0.0.prompt.md +34 -0
  270. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_deduplication/v1.0.0.prompt.md +116 -0
  271. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_should_generate/v1.0.0.prompt.md +33 -0
  272. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_should_generate_override/v1.0.0.prompt.md +16 -0
  273. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.0.0.prompt.md +140 -0
  274. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.1.0.prompt.md +160 -0
  275. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_main/v1.0.0.prompt.md +14 -0
  276. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/query_reformulation/v1.0.0.prompt.md +19 -0
  277. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/rerank_relevance/v1.1.0.prompt.md +44 -0
  278. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/shadow_comparison/v1.0.0.prompt.md +43 -0
  279. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/shadow_content_evaluation/v1.0.0.prompt.md +33 -0
  280. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_evaluation/prompt_evaluation_dataset/feedback_extraction_main_v1.jsonl +10 -0
  281. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_evaluation/prompt_evaluation_dataset/profile_update_main_v1.jsonl +10 -0
  282. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_manager.py +280 -0
  283. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_schema.py +11 -0
  284. package/plugin/vendor/reflexio/reflexio/server/services/README.md +58 -0
  285. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/_eval_health.py +131 -0
  286. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_constants.py +60 -0
  287. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_service.py +228 -0
  288. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_utils.py +87 -0
  289. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluator.py +372 -0
  290. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/delayed_group_evaluator.py +156 -0
  291. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/group_evaluation_runner.py +336 -0
  292. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/regen_jobs.py +471 -0
  293. package/plugin/vendor/reflexio/reflexio/server/services/base_generation_service.py +1668 -0
  294. package/plugin/vendor/reflexio/reflexio/server/services/braintrust/__init__.py +0 -0
  295. package/plugin/vendor/reflexio/reflexio/server/services/braintrust/_cron.py +196 -0
  296. package/plugin/vendor/reflexio/reflexio/server/services/braintrust/_encryption.py +101 -0
  297. package/plugin/vendor/reflexio/reflexio/server/services/braintrust/client.py +167 -0
  298. package/plugin/vendor/reflexio/reflexio/server/services/braintrust/service.py +281 -0
  299. package/plugin/vendor/reflexio/reflexio/server/services/configurator/base_configurator.py +179 -0
  300. package/plugin/vendor/reflexio/reflexio/server/services/configurator/config_storage.py +62 -0
  301. package/plugin/vendor/reflexio/reflexio/server/services/configurator/configurator.py +87 -0
  302. package/plugin/vendor/reflexio/reflexio/server/services/configurator/local_file_config_storage.py +187 -0
  303. package/plugin/vendor/reflexio/reflexio/server/services/configurator/test_config_storage.py +162 -0
  304. package/plugin/vendor/reflexio/reflexio/server/services/deduplication_utils.py +112 -0
  305. package/plugin/vendor/reflexio/reflexio/server/services/embedding_text.py +62 -0
  306. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/__init__.py +0 -0
  307. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/distribution.py +33 -0
  308. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/eval_sampler.py +126 -0
  309. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/group_aggregation.py +192 -0
  310. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/hero_state.py +75 -0
  311. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/rule_attribution.py +97 -0
  312. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/service.py +515 -0
  313. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/shadow_aggregation.py +90 -0
  314. package/plugin/vendor/reflexio/reflexio/server/services/extraction/__init__.py +0 -0
  315. package/plugin/vendor/reflexio/reflexio/server/services/extraction/agent_run_records.py +91 -0
  316. package/plugin/vendor/reflexio/reflexio/server/services/extraction/invariants.py +303 -0
  317. package/plugin/vendor/reflexio/reflexio/server/services/extraction/outcome.py +25 -0
  318. package/plugin/vendor/reflexio/reflexio/server/services/extraction/pending_tool_call_dispatch.py +358 -0
  319. package/plugin/vendor/reflexio/reflexio/server/services/extraction/plan.py +138 -0
  320. package/plugin/vendor/reflexio/reflexio/server/services/extraction/prior_answer_search.py +217 -0
  321. package/plugin/vendor/reflexio/reflexio/server/services/extraction/resumable_agent.py +535 -0
  322. package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_scheduler.py +171 -0
  323. package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_worker.py +779 -0
  324. package/plugin/vendor/reflexio/reflexio/server/services/extraction/tools.py +1125 -0
  325. package/plugin/vendor/reflexio/reflexio/server/services/extractor_config_utils.py +94 -0
  326. package/plugin/vendor/reflexio/reflexio/server/services/extractor_interaction_utils.py +251 -0
  327. package/plugin/vendor/reflexio/reflexio/server/services/generation_service.py +702 -0
  328. package/plugin/vendor/reflexio/reflexio/server/services/operation_state_utils.py +835 -0
  329. package/plugin/vendor/reflexio/reflexio/server/services/playbook/README.md +89 -0
  330. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_aggregator.py +1388 -0
  331. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_consolidator.py +1045 -0
  332. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_extractor.py +436 -0
  333. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_generation_service.py +808 -0
  334. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_service_constants.py +28 -0
  335. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_service_utils.py +362 -0
  336. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/__init__.py +24 -0
  337. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/assistant_webhook.py +246 -0
  338. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/gepa_adapter.py +291 -0
  339. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/judge.py +97 -0
  340. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/models.py +96 -0
  341. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/optimizer.py +645 -0
  342. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/rollout.py +35 -0
  343. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/scenario_resolver.py +93 -0
  344. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/scheduler.py +174 -0
  345. package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/__init__.py +26 -0
  346. package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/_document_expander.py +179 -0
  347. package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/_query_reformulator.py +297 -0
  348. package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_deduplicator.py +772 -0
  349. package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_extractor.py +462 -0
  350. package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_generation_service.py +737 -0
  351. package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_generation_service_utils.py +290 -0
  352. package/plugin/vendor/reflexio/reflexio/server/services/reflection/__init__.py +17 -0
  353. package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_extractor.py +247 -0
  354. package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_service.py +803 -0
  355. package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_service_utils.py +146 -0
  356. package/plugin/vendor/reflexio/reflexio/server/services/retrieval/__init__.py +0 -0
  357. package/plugin/vendor/reflexio/reflexio/server/services/retrieval/relevance_floor.py +80 -0
  358. package/plugin/vendor/reflexio/reflexio/server/services/search/__init__.py +0 -0
  359. package/plugin/vendor/reflexio/reflexio/server/services/service_utils.py +756 -0
  360. package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/__init__.py +1 -0
  361. package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/judge.py +184 -0
  362. package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/outcome.py +81 -0
  363. package/plugin/vendor/reflexio/reflexio/server/services/storage/constants.py +2 -0
  364. package/plugin/vendor/reflexio/reflexio/server/services/storage/error.py +11 -0
  365. package/plugin/vendor/reflexio/reflexio/server/services/storage/retention.py +154 -0
  366. package/plugin/vendor/reflexio/reflexio/server/services/storage/retention_mixin.py +155 -0
  367. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/__init__.py +59 -0
  368. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_agent_run.py +1298 -0
  369. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_base.py +1945 -0
  370. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_extras.py +600 -0
  371. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_operations.py +346 -0
  372. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_playbook.py +1378 -0
  373. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_profiles.py +747 -0
  374. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_requests.py +263 -0
  375. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_shadow_verdicts.py +193 -0
  376. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_share_links.py +166 -0
  377. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_stall_state.py +217 -0
  378. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/__init__.py +153 -0
  379. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_agent_run.py +384 -0
  380. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_base.py +71 -0
  381. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_extras.py +235 -0
  382. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_operations.py +170 -0
  383. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_playbook.py +677 -0
  384. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_profiles.py +250 -0
  385. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_requests.py +154 -0
  386. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_shadow_verdicts.py +130 -0
  387. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_share_links.py +93 -0
  388. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_stall_state.py +76 -0
  389. package/plugin/vendor/reflexio/reflexio/server/services/unified_search_service.py +572 -0
  390. package/plugin/vendor/reflexio/reflexio/server/site_var/README.md +77 -0
  391. package/plugin/vendor/reflexio/reflexio/server/site_var/feature_flags.py +116 -0
  392. package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_manager.py +263 -0
  393. package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/feature_flags.json +13 -0
  394. package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/llm_model_setting.json +7 -0
  395. package/plugin/vendor/reflexio/reflexio/server/tracing.py +158 -0
  396. package/plugin/vendor/reflexio/reflexio/server/usage_metrics.py +113 -0
  397. package/plugin/vendor/reflexio/reflexio/server/uvicorn_logging.py +76 -0
  398. package/plugin/vendor/reflexio/reflexio/test_support/__init__.py +1 -0
  399. package/plugin/vendor/reflexio/reflexio/test_support/llm_fixtures.py +62 -0
  400. package/plugin/vendor/reflexio/reflexio/test_support/llm_mock.py +242 -0
  401. package/plugin/vendor/reflexio/reflexio/test_support/llm_model_registry.py +129 -0
  402. package/plugin/vendor/reflexio/reflexio/test_support/skip_decorators.py +43 -0
@@ -0,0 +1 @@
1
+ """F1 per-turn shadow comparison service."""
@@ -0,0 +1,184 @@
1
+ """F1 per-turn shadow comparison judge service.
2
+
3
+ Stateless beyond construction. Routes every LLM call through
4
+ ``LiteLLMClient`` and every prompt through ``PromptManager`` per project
5
+ guardrails — never imports OpenAIClient or ClaudeClient directly.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import logging
11
+ import random
12
+ from datetime import UTC, datetime
13
+ from typing import TYPE_CHECKING
14
+
15
+ from reflexio.models.api_schema.eval_overview_schema import (
16
+ ShadowComparisonOutput,
17
+ ShadowComparisonVerdict,
18
+ )
19
+ from reflexio.server.services.shadow_comparison.outcome import assign_positions
20
+
21
+ if TYPE_CHECKING:
22
+ from reflexio.models.api_schema.domain.entities import Interaction
23
+ from reflexio.server.llm.litellm_client import LiteLLMClient
24
+ from reflexio.server.prompt.prompt_manager import PromptManager
25
+
26
+
27
+ logger = logging.getLogger(__name__)
28
+
29
+ _PROMPT_ID = "shadow_comparison"
30
+
31
+
32
+ class ShadowComparisonJudge:
33
+ """Per-turn LLM-as-judge for Reflexio vs Shadow responses (F1).
34
+
35
+ The judge sees Request 1 + Request 2 (position-randomized) and decides
36
+ which is better, or whether they tie. The position assignment is
37
+ recorded on the verdict so the dashboard can derive Reflexio-relative
38
+ win / tie / loss via
39
+ :func:`reflexio.server.services.shadow_comparison.outcome.derive_reflexio_outcome`.
40
+ """
41
+
42
+ def __init__(
43
+ self,
44
+ llm_client: LiteLLMClient,
45
+ prompt_manager: PromptManager,
46
+ prompt_version: str,
47
+ ):
48
+ """
49
+ Initialize the judge.
50
+
51
+ Args:
52
+ llm_client (LiteLLMClient): Unified LLM client. Used to render
53
+ the verdict via ``generate_chat_response`` with a Pydantic
54
+ ``response_format``.
55
+ prompt_manager (PromptManager): Prompt manager for the
56
+ ``shadow_comparison`` prompt. Prompt-version selection is
57
+ governed by the manager's ``version_override`` dict;
58
+ ``prompt_version`` below is recorded on the verdict for
59
+ later filtering but does not affect rendering.
60
+ prompt_version (str): Semver of the active shadow_comparison
61
+ prompt. Stamped onto every verdict so the dashboard can
62
+ exclude verdicts from a stale rubric.
63
+ """
64
+ self._llm_client = llm_client
65
+ self._prompt_manager = prompt_manager
66
+ self._prompt_version = prompt_version
67
+
68
+ # ===============================
69
+ # public methods
70
+ # ===============================
71
+
72
+ def judge_turn(
73
+ self,
74
+ *,
75
+ interaction: Interaction,
76
+ session_id: str,
77
+ agent_version: str,
78
+ rng: random.Random,
79
+ user_message: str = "",
80
+ ) -> ShadowComparisonVerdict | None:
81
+ """
82
+ Grade one interaction; return ``None`` when the LLM fails or the
83
+ interaction has no shadow response to compare against.
84
+
85
+ Returning ``None`` (rather than raising) lets the regen worker
86
+ skip this turn and continue with the rest of the session — one
87
+ rate-limit blip should not abort an entire batch.
88
+
89
+ Args:
90
+ interaction (Interaction): The agent-side interaction. Its
91
+ ``content`` is the Reflexio response and ``shadow_content``
92
+ is the no-Reflexio response. When ``shadow_content`` is
93
+ empty the judge short-circuits with ``None``.
94
+ session_id (str): Denormalized onto the verdict for cheap
95
+ session-scoped queries.
96
+ agent_version (str): Pinned onto the verdict for trend slicing.
97
+ rng (random.Random): Position-randomization source.
98
+ Production callers pass a fresh ``random.Random()`` per
99
+ judge call; tests inject a seeded ``Random`` for
100
+ reproducibility.
101
+ user_message (str): The user turn this interaction responds
102
+ to. Optional — empty string is rendered into the prompt
103
+ if the caller does not provide a value.
104
+
105
+ Returns:
106
+ ShadowComparisonVerdict | None: The constructed verdict, or
107
+ ``None`` when shadow content is missing or the LLM call fails.
108
+ """
109
+ if not interaction.shadow_content:
110
+ return None
111
+
112
+ request_1, request_2, reflexio_is_request_1 = assign_positions(
113
+ reflexio_response=interaction.content,
114
+ shadow_response=interaction.shadow_content,
115
+ rng=rng,
116
+ )
117
+
118
+ prompt = self._prompt_manager.render_prompt(
119
+ prompt_id=_PROMPT_ID,
120
+ variables={
121
+ "user_message": user_message,
122
+ "request_1_response": request_1,
123
+ "request_2_response": request_2,
124
+ },
125
+ )
126
+
127
+ output = self._call_judge_llm(prompt, interaction.interaction_id)
128
+ if output is None:
129
+ return None
130
+
131
+ return ShadowComparisonVerdict(
132
+ verdict_id=0, # storage assigns the autoincrement id
133
+ interaction_id=str(interaction.interaction_id),
134
+ session_id=session_id,
135
+ agent_version=agent_version,
136
+ reflexio_is_request_1=reflexio_is_request_1,
137
+ output=output,
138
+ judge_prompt_version=self._prompt_version,
139
+ created_at=datetime.now(UTC),
140
+ )
141
+
142
+ # ===============================
143
+ # private helpers
144
+ # ===============================
145
+
146
+ def _call_judge_llm(
147
+ self,
148
+ prompt: str,
149
+ interaction_id: int,
150
+ ) -> ShadowComparisonOutput | None:
151
+ """
152
+ Invoke the LLM with structured-output and unwrap the response.
153
+
154
+ Args:
155
+ prompt (str): The rendered judge prompt.
156
+ interaction_id (int): Interaction id for failure-logging context.
157
+
158
+ Returns:
159
+ ShadowComparisonOutput | None: The parsed structured output,
160
+ or ``None`` if the call failed or returned an unexpected type.
161
+ """
162
+ try:
163
+ response = self._llm_client.generate_chat_response(
164
+ messages=[{"role": "user", "content": prompt}],
165
+ response_format=ShadowComparisonOutput,
166
+ )
167
+ except Exception as exc: # noqa: BLE001 — judge failure must not abort batch
168
+ logger.warning(
169
+ "shadow_comparison judge failed for interaction %s: %s",
170
+ interaction_id,
171
+ exc,
172
+ )
173
+ return None
174
+
175
+ if not isinstance(response, ShadowComparisonOutput):
176
+ logger.warning(
177
+ "Unexpected response type from shadow_comparison judge for "
178
+ "interaction %s: %s",
179
+ interaction_id,
180
+ type(response).__name__,
181
+ )
182
+ return None
183
+
184
+ return response
@@ -0,0 +1,81 @@
1
+ """Pure F1 outcome helpers — position randomization + win/loss/tie derivation.
2
+
3
+ These functions are deliberately DB-free and LLM-free so they can be unit
4
+ tested in milliseconds and exercised by mutmut.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import random
10
+ from enum import StrEnum
11
+
12
+ from reflexio.models.api_schema.eval_overview_schema import ShadowComparisonVerdict
13
+
14
+
15
+ class Outcome(StrEnum):
16
+ """Reflexio-relative outcome derived from a judge's position-randomized verdict.
17
+
18
+ Mirrors the GroupAssignment pattern from F2's group_aggregation module —
19
+ StrEnum so values serialize transparently to JSON / SQL.
20
+ """
21
+
22
+ WIN = "win"
23
+ LOSS = "loss"
24
+ TIE = "tie"
25
+
26
+
27
+ def assign_positions(
28
+ reflexio_response: str,
29
+ shadow_response: str,
30
+ rng: random.Random,
31
+ ) -> tuple[str, str, bool]:
32
+ """
33
+ Randomize which response is shown as "Request 1" to the judge.
34
+
35
+ The judge prompt is blind to the assignment — it sees the two strings
36
+ labeled "REQUEST 1" and "REQUEST 2". We record the assignment so the
37
+ dashboard can derive the Reflexio-relative outcome via
38
+ `derive_reflexio_outcome`.
39
+
40
+ Args:
41
+ reflexio_response (str): The response generated with Reflexio rules in context.
42
+ shadow_response (str): The response generated without Reflexio rules.
43
+ rng (random.Random): Seeded random for reproducibility (tests inject a
44
+ seed; production uses `random.Random()` per judge call).
45
+
46
+ Returns:
47
+ tuple[str, str, bool]: (request_1_response, request_2_response,
48
+ reflexio_is_request_1). Storage records the third element on the
49
+ verdict row.
50
+ """
51
+ reflexio_is_request_1 = rng.random() < 0.5
52
+ if reflexio_is_request_1:
53
+ return reflexio_response, shadow_response, True
54
+ return shadow_response, reflexio_response, False
55
+
56
+
57
+ def derive_reflexio_outcome(verdict: ShadowComparisonVerdict) -> Outcome:
58
+ """
59
+ Map a position-randomized verdict to a Reflexio-relative outcome.
60
+
61
+ Truth table:
62
+ better=='tie' -> TIE
63
+ better=='1' AND reflexio_is_request_1==True -> WIN
64
+ better=='1' AND reflexio_is_request_1==False -> LOSS
65
+ better=='2' AND reflexio_is_request_1==True -> LOSS
66
+ better=='2' AND reflexio_is_request_1==False -> WIN
67
+
68
+ Args:
69
+ verdict (ShadowComparisonVerdict): The stored verdict, including the
70
+ judge's `better_request` choice and the `reflexio_is_request_1`
71
+ position-randomization record.
72
+
73
+ Returns:
74
+ Outcome: WIN / LOSS / TIE relative to the Reflexio response.
75
+ """
76
+ if verdict.output.better_request == "tie":
77
+ return Outcome.TIE
78
+ is_reflexio_better = (
79
+ verdict.output.better_request == "1"
80
+ ) == verdict.reflexio_is_request_1
81
+ return Outcome.WIN if is_reflexio_better else Outcome.LOSS
@@ -0,0 +1,2 @@
1
+ class StorageConstants:
2
+ STORAGE_TYPE_CONFIG_NAME = "storage_type"
@@ -0,0 +1,11 @@
1
+ class StorageError(Exception):
2
+ """
3
+ Exception raised for storage errors
4
+ """
5
+
6
+ def __init__(self, message: str):
7
+ self.message = message
8
+ super().__init__(self.message)
9
+
10
+ def __str__(self):
11
+ return f"StorageError: {self.message}"
@@ -0,0 +1,154 @@
1
+ """Shared row-retention policy for storage backends."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import math
6
+ import os
7
+ from dataclasses import dataclass
8
+
9
+ DEFAULT_ROW_RETENTION_LIMIT = 250_000
10
+ ROW_RETENTION_DELETE_FRACTION = 0.20
11
+
12
+
13
+ @dataclass(frozen=True, slots=True)
14
+ class RetentionTarget:
15
+ """A physical storage target eligible for row-count retention."""
16
+
17
+ name: str
18
+ table_name: str
19
+ order_column: str
20
+ id_columns: tuple[str, ...]
21
+
22
+
23
+ RETENTION_TARGETS: tuple[RetentionTarget, ...] = (
24
+ RetentionTarget("profiles", "profiles", "created_at", ("profile_id",)),
25
+ RetentionTarget("interactions", "interactions", "created_at", ("interaction_id",)),
26
+ RetentionTarget("requests", "requests", "created_at", ("request_id",)),
27
+ RetentionTarget(
28
+ "user_playbooks", "user_playbooks", "created_at", ("user_playbook_id",)
29
+ ),
30
+ RetentionTarget(
31
+ "agent_playbooks", "agent_playbooks", "created_at", ("agent_playbook_id",)
32
+ ),
33
+ RetentionTarget(
34
+ "agent_success_evaluation_result",
35
+ "agent_success_evaluation_result",
36
+ "created_at",
37
+ ("result_id",),
38
+ ),
39
+ RetentionTarget(
40
+ "profile_change_logs", "profile_change_logs", "created_at", ("id",)
41
+ ),
42
+ RetentionTarget(
43
+ "playbook_aggregation_change_logs",
44
+ "playbook_aggregation_change_logs",
45
+ "created_at",
46
+ ("id",),
47
+ ),
48
+ RetentionTarget("share_links", "share_links", "created_at", ("id",)),
49
+ RetentionTarget(
50
+ "agent_playbook_source_user_playbooks",
51
+ "agent_playbook_source_user_playbooks",
52
+ "created_at",
53
+ ("agent_playbook_id", "user_playbook_id"),
54
+ ),
55
+ RetentionTarget(
56
+ "playbook_optimization_jobs",
57
+ "playbook_optimization_jobs",
58
+ "created_at",
59
+ ("job_id",),
60
+ ),
61
+ RetentionTarget(
62
+ "playbook_optimization_candidates",
63
+ "playbook_optimization_candidates",
64
+ "created_at",
65
+ ("candidate_id",),
66
+ ),
67
+ RetentionTarget(
68
+ "playbook_optimization_evaluations",
69
+ "playbook_optimization_evaluations",
70
+ "created_at",
71
+ ("evaluation_id",),
72
+ ),
73
+ RetentionTarget(
74
+ "playbook_optimization_events",
75
+ "playbook_optimization_events",
76
+ "created_at",
77
+ ("event_id",),
78
+ ),
79
+ RetentionTarget("skills", "skills", "created_at", ("skill_id",)),
80
+ )
81
+
82
+ RETENTION_TARGETS_BY_NAME = {target.name: target for target in RETENTION_TARGETS}
83
+
84
+
85
+ @dataclass(frozen=True, slots=True)
86
+ class CascadeRef:
87
+ """A dependent table that must be cleaned when a retention target's rows
88
+ are deleted.
89
+
90
+ Attributes:
91
+ table_name (str): Table whose rows depend on the retention target.
92
+ fk_column (str): Column in ``table_name`` holding the parent target's
93
+ primary key. Always references the first column of the parent
94
+ target's ``id_columns`` (single-key parents only).
95
+ """
96
+
97
+ table_name: str
98
+ fk_column: str
99
+
100
+
101
+ # Maps a retention target → its dependent tables that must be deleted first
102
+ # when retention removes rows. Keep in sync with the storage backends that
103
+ # rely on it (Postgres, Supabase, and the SQLite bespoke implementations).
104
+ RETENTION_CASCADES: dict[str, tuple[CascadeRef, ...]] = {
105
+ "requests": (CascadeRef("interactions", "request_id"),),
106
+ "user_playbooks": (
107
+ CascadeRef("agent_playbook_source_user_playbooks", "user_playbook_id"),
108
+ ),
109
+ "agent_playbooks": (
110
+ CascadeRef("agent_playbook_source_user_playbooks", "agent_playbook_id"),
111
+ ),
112
+ "playbook_optimization_jobs": (
113
+ CascadeRef("playbook_optimization_evaluations", "job_id"),
114
+ CascadeRef("playbook_optimization_events", "job_id"),
115
+ CascadeRef("playbook_optimization_candidates", "job_id"),
116
+ ),
117
+ "playbook_optimization_candidates": (
118
+ CascadeRef("playbook_optimization_evaluations", "candidate_id"),
119
+ ),
120
+ }
121
+
122
+
123
+ def get_row_retention_limits() -> dict[str, int]:
124
+ """Return per-target row limits from env with code defaults.
125
+
126
+ ``REFLEXIO_ROW_LIMIT_<TARGET>`` takes precedence for every target.
127
+ ``INTERACTION_CLEANUP_THRESHOLD`` remains the legacy override for
128
+ interactions when the new variable is not present.
129
+ """
130
+ limits: dict[str, int] = {}
131
+ for target in RETENTION_TARGETS:
132
+ env_name = f"REFLEXIO_ROW_LIMIT_{target.name.upper()}"
133
+ default = DEFAULT_ROW_RETENTION_LIMIT
134
+ if target.name == "interactions":
135
+ default = _get_int_env("INTERACTION_CLEANUP_THRESHOLD", default)
136
+ limits[target.name] = _get_int_env(env_name, default)
137
+ return limits
138
+
139
+
140
+ def delete_count_for_retention(current_count: int) -> int:
141
+ """Return how many rows to delete when a target exceeds its limit."""
142
+ if current_count <= 0:
143
+ return 0
144
+ return max(1, math.ceil(current_count * ROW_RETENTION_DELETE_FRACTION))
145
+
146
+
147
+ def _get_int_env(name: str, default: int) -> int:
148
+ value = os.environ.get(name)
149
+ if value is None or not value.strip():
150
+ return default
151
+ try:
152
+ return int(value)
153
+ except ValueError:
154
+ return default
@@ -0,0 +1,155 @@
1
+ """Shared scaffolding for SQL-backed row-retention cleanup.
2
+
3
+ Concrete SQL backends (SQLite, Postgres, Supabase) mix in
4
+ ``RetentionMixin`` and implement a small set of hooks. The public surface
5
+ ``count_retention_target_rows`` / ``delete_oldest_retention_target_rows``
6
+ lives here so the dispatch — limit lookup, key selection, cascade,
7
+ delete — cannot drift across the three backends.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from abc import ABC, abstractmethod
13
+ from collections.abc import Iterator, Sequence
14
+ from typing import Any
15
+
16
+ from reflexio.server.services.storage.retention import (
17
+ RETENTION_TARGETS_BY_NAME,
18
+ RetentionTarget,
19
+ )
20
+
21
+ # Conservative chunk size for IN-list deletes. Picked to stay well under:
22
+ # - SQLite's SQLITE_MAX_VARIABLE_NUMBER (999 on builds before 3.32; 32766 after).
23
+ # - PostgREST URL length limits (gateway caps are commonly 8-16 KB).
24
+ RETENTION_DELETE_CHUNK = 500
25
+
26
+
27
+ def chunked(
28
+ values: Sequence[Any], chunk_size: int = RETENTION_DELETE_CHUNK
29
+ ) -> Iterator[list[Any]]:
30
+ """Yield consecutive ``chunk_size`` slices of ``values`` as lists.
31
+
32
+ Args:
33
+ values (Sequence[Any]): Items to split.
34
+ chunk_size (int): Maximum number of items per chunk.
35
+
36
+ Yields:
37
+ list[Any]: Successive non-empty chunks.
38
+ """
39
+ for start in range(0, len(values), chunk_size):
40
+ yield list(values[start : start + chunk_size])
41
+
42
+
43
+ def get_retention_target(target_name: str) -> RetentionTarget:
44
+ """Resolve a retention target by name.
45
+
46
+ Args:
47
+ target_name (str): Registered name (e.g. ``"interactions"``).
48
+
49
+ Returns:
50
+ RetentionTarget: The matching target.
51
+
52
+ Raises:
53
+ ValueError: If ``target_name`` is not registered.
54
+ """
55
+ try:
56
+ return RETENTION_TARGETS_BY_NAME[target_name]
57
+ except KeyError as exc:
58
+ raise ValueError(f"Unknown retention target: {target_name}") from exc
59
+
60
+
61
+ class RetentionMixin(ABC):
62
+ """Backend-agnostic orchestration of row-retention cleanup.
63
+
64
+ SQL backends mix this in and implement the abstract hooks. The public
65
+ methods are intentionally defined once here so that the count/select/
66
+ cascade/delete ordering is identical across all three backends.
67
+ """
68
+
69
+ def count_retention_target_rows(self, target_name: str) -> int:
70
+ """Return the current row count for a retention target.
71
+
72
+ Args:
73
+ target_name (str): Registered retention target name.
74
+
75
+ Returns:
76
+ int: Row count, or 0 if the underlying table is missing.
77
+ """
78
+ target = get_retention_target(target_name)
79
+ if not self._retention_table_exists(target.table_name):
80
+ return 0
81
+ return self._retention_count_rows(target)
82
+
83
+ def delete_oldest_retention_target_rows(self, target_name: str, count: int) -> int:
84
+ """Delete up to ``count`` oldest rows for a retention target.
85
+
86
+ Calls the dependency-cascade hook before the target-row delete so
87
+ backends with foreign-key constraints stay consistent.
88
+
89
+ Args:
90
+ target_name (str): Registered retention target name.
91
+ count (int): Maximum number of rows to delete.
92
+
93
+ Returns:
94
+ int: Number of rows actually selected for deletion.
95
+ """
96
+ if count <= 0:
97
+ return 0
98
+ target = get_retention_target(target_name)
99
+ if not self._retention_table_exists(target.table_name):
100
+ return 0
101
+ keys = self._retention_select_oldest_keys(target, count)
102
+ if not keys:
103
+ return 0
104
+ self._retention_perform_delete(target, keys)
105
+ return len(keys)
106
+
107
+ def _retention_perform_delete(
108
+ self, target: RetentionTarget, keys: list[tuple[Any, ...]]
109
+ ) -> None:
110
+ """Run dependency cleanup then target-row delete.
111
+
112
+ Default implementation runs the hooks in sequence. Backends that
113
+ need both steps inside one transaction (notably SQLite) should
114
+ override this method.
115
+ """
116
+ self._retention_delete_dependencies(target, keys)
117
+ self._retention_delete_target_rows(target, keys)
118
+
119
+ # -- Backend hooks --
120
+
121
+ @abstractmethod
122
+ def _retention_table_exists(self, table_name: str) -> bool:
123
+ """Return whether ``table_name`` exists in the backing store."""
124
+ raise NotImplementedError
125
+
126
+ @abstractmethod
127
+ def _retention_count_rows(self, target: RetentionTarget) -> int:
128
+ """Return the live row count for ``target``'s table."""
129
+ raise NotImplementedError
130
+
131
+ @abstractmethod
132
+ def _retention_select_oldest_keys(
133
+ self, target: RetentionTarget, count: int
134
+ ) -> list[tuple[Any, ...]]:
135
+ """Return up to ``count`` oldest key tuples for ``target``.
136
+
137
+ Each key tuple contains values aligned with ``target.id_columns``.
138
+ Ordering is by ``target.order_column`` ascending with the id
139
+ columns as a stable tiebreaker.
140
+ """
141
+ raise NotImplementedError
142
+
143
+ @abstractmethod
144
+ def _retention_delete_dependencies(
145
+ self, target: RetentionTarget, keys: list[tuple[Any, ...]]
146
+ ) -> None:
147
+ """Remove rows in tables that depend on ``target`` for ``keys``."""
148
+ raise NotImplementedError
149
+
150
+ @abstractmethod
151
+ def _retention_delete_target_rows(
152
+ self, target: RetentionTarget, keys: list[tuple[Any, ...]]
153
+ ) -> None:
154
+ """Remove the rows for ``keys`` from ``target``'s table."""
155
+ raise NotImplementedError
@@ -0,0 +1,59 @@
1
+ from ._agent_run import SQLiteAgentRunMixin
2
+ from ._base import (
3
+ SQLiteStorageBase,
4
+ _cosine_similarity,
5
+ _effective_search_mode,
6
+ _sanitize_fts_query,
7
+ _true_rrf_merge,
8
+ _vector_rank_rows,
9
+ )
10
+ from ._extras import ExtrasMixin
11
+ from ._operations import OperationMixin
12
+ from ._playbook import PlaybookMixin
13
+ from ._profiles import ProfileMixin
14
+ from ._requests import RequestMixin
15
+ from ._shadow_verdicts import ShadowVerdictsMixin as SQLiteShadowVerdictsMixin
16
+ from ._share_links import SQLiteShareLinkMixin
17
+ from ._stall_state import (
18
+ SQLiteStallStateMixin,
19
+ StallReason,
20
+ StallState,
21
+ clear_stall_state,
22
+ get_stall_state,
23
+ init_stall_state_table,
24
+ mark_stall_notified,
25
+ upsert_stall_state,
26
+ )
27
+
28
+
29
+ class SQLiteStorage(
30
+ SQLiteAgentRunMixin,
31
+ ProfileMixin,
32
+ RequestMixin,
33
+ PlaybookMixin,
34
+ OperationMixin,
35
+ ExtrasMixin,
36
+ SQLiteShareLinkMixin,
37
+ SQLiteStallStateMixin,
38
+ SQLiteShadowVerdictsMixin,
39
+ SQLiteStorageBase,
40
+ ):
41
+ """SQLite-based storage with FTS5 and hybrid search."""
42
+
43
+ pass
44
+
45
+
46
+ __all__ = [
47
+ "SQLiteStorage",
48
+ "_cosine_similarity",
49
+ "_effective_search_mode",
50
+ "_sanitize_fts_query",
51
+ "_true_rrf_merge",
52
+ "_vector_rank_rows",
53
+ "StallReason",
54
+ "StallState",
55
+ "clear_stall_state",
56
+ "get_stall_state",
57
+ "mark_stall_notified",
58
+ "upsert_stall_state",
59
+ ]