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,702 @@
1
+ from __future__ import annotations
2
+
3
+ import contextvars
4
+ import logging
5
+ import os
6
+ import threading
7
+ import time
8
+ import uuid
9
+ from collections.abc import Callable
10
+ from concurrent.futures import ThreadPoolExecutor
11
+ from concurrent.futures import TimeoutError as FuturesTimeoutError
12
+ from dataclasses import dataclass, field
13
+ from typing import TYPE_CHECKING
14
+
15
+ from reflexio.defaults import resolve_agent_version
16
+ from reflexio.models.api_schema.service_schemas import (
17
+ Interaction,
18
+ PublishUserInteractionRequest,
19
+ Request,
20
+ )
21
+ from reflexio.models.config_schema import Config
22
+ from reflexio.server.api_endpoints.request_context import RequestContext
23
+ from reflexio.server.llm.litellm_client import LiteLLMClient
24
+ from reflexio.server.services.agent_success_evaluation.delayed_group_evaluator import (
25
+ GroupEvaluationScheduler,
26
+ )
27
+ from reflexio.server.services.agent_success_evaluation.group_evaluation_runner import (
28
+ run_group_evaluation,
29
+ )
30
+ from reflexio.server.services.operation_state_utils import OperationStateManager
31
+ from reflexio.server.services.playbook.playbook_generation_service import (
32
+ PlaybookGenerationService,
33
+ )
34
+ from reflexio.server.services.playbook.playbook_service_utils import (
35
+ PlaybookGenerationRequest,
36
+ )
37
+ from reflexio.server.services.profile.profile_generation_service import (
38
+ ProfileGenerationService,
39
+ )
40
+ from reflexio.server.services.profile.profile_generation_service_utils import (
41
+ ProfileGenerationRequest,
42
+ )
43
+ from reflexio.server.services.reflection.reflection_service import ReflectionService
44
+ from reflexio.server.services.reflection.reflection_service_utils import (
45
+ ReflectionServiceRequest,
46
+ )
47
+ from reflexio.server.services.storage.retention import (
48
+ delete_count_for_retention,
49
+ get_row_retention_limits,
50
+ )
51
+ from reflexio.server.tracing import sentry_tags
52
+ from reflexio.server.usage_metrics import record_usage_event
53
+
54
+ if TYPE_CHECKING:
55
+ from reflexio.server.services.unified_search_service import UnifiedSearchService
56
+
57
+ logger = logging.getLogger(__name__)
58
+ # Stale lock timeout - if cleanup started > 10 min ago and still "in_progress", assume it crashed
59
+ CLEANUP_STALE_LOCK_SECONDS = 600
60
+ # Timeout for the outer generation service parallel execution
61
+ GENERATION_SERVICE_TIMEOUT_SECONDS = 600
62
+ _STALL_WARNING_PREFIX = "Reflexio learning is paused"
63
+
64
+
65
+ def _retention_cleanup_interval_seconds() -> float:
66
+ raw = os.getenv("REFLEXIO_RETENTION_CLEANUP_INTERVAL_SECONDS", "300") or "300"
67
+ try:
68
+ return max(0.0, float(raw))
69
+ except ValueError:
70
+ logger.warning(
71
+ "Invalid REFLEXIO_RETENTION_CLEANUP_INTERVAL_SECONDS=%r; using 300",
72
+ raw,
73
+ )
74
+ return 300.0
75
+
76
+
77
+ _RETENTION_CLEANUP_INTERVAL_SECONDS = _retention_cleanup_interval_seconds()
78
+ _retention_cleanup_last_run: dict[tuple[str, str], float] = {}
79
+ _retention_cleanup_lock = threading.Lock()
80
+
81
+
82
+ @dataclass
83
+ class GenerationServiceResult:
84
+ """Result of a GenerationService.run call.
85
+
86
+ Exposes the internally generated request_id plus any warnings so callers
87
+ (CLI, API) can report back to users where their publish landed.
88
+
89
+ Attributes:
90
+ request_id (str | None): The UUID assigned to this publish call, or
91
+ None when ``run()`` returned early before generating one (e.g.
92
+ empty request, missing ``user_id``, or no interactions).
93
+ warnings (list[str]): Non-fatal warnings raised by individual
94
+ generation services during the run.
95
+ """
96
+
97
+ request_id: str | None = None
98
+ warnings: list[str] = field(default_factory=list)
99
+
100
+
101
+ class GenerationService:
102
+ """
103
+ Main service for orchestrating profile, playbook, and agent success evaluation generation.
104
+
105
+ This service coordinates multiple generation services (profile, playbook, agent success)
106
+ and manages the overall interaction processing workflow.
107
+ """
108
+
109
+ def __init__(
110
+ self,
111
+ llm_client: LiteLLMClient,
112
+ request_context: RequestContext,
113
+ ) -> None:
114
+ """
115
+ Initialize the generation service.
116
+
117
+ Args:
118
+ llm_client: Pre-configured LLM client for making API calls.
119
+ request_context: Request context with storage and configurator.
120
+ """
121
+ self.client = llm_client
122
+ self.storage = request_context.storage
123
+ self.org_id = request_context.org_id
124
+ self.configurator = request_context.configurator
125
+ self.request_context = request_context
126
+
127
+ # ===============================
128
+ # public methods
129
+ # ===============================
130
+
131
+ def run(
132
+ self, publish_user_interaction_request: PublishUserInteractionRequest
133
+ ) -> GenerationServiceResult:
134
+ """
135
+ Process a user interaction request by storing interactions and triggering generation services.
136
+
137
+ Profile and playbook generation services run inline in parallel. Agent success
138
+ evaluation is deferred via GroupEvaluationScheduler when a session_id is present,
139
+ so the full session can be evaluated after a period of inactivity.
140
+
141
+ Each generation service (profile, playbook) handles its own:
142
+ - Data collection based on extractor-specific configs
143
+ - Stride checking based on extractor-specific settings
144
+ - Operation state tracking per extractor
145
+
146
+ Args:
147
+ publish_user_interaction_request: The incoming user interaction request
148
+
149
+ Returns:
150
+ GenerationServiceResult: The request_id assigned to this publish call
151
+ and any non-fatal warnings raised by individual generation services.
152
+ """
153
+ result = GenerationServiceResult()
154
+
155
+ if not publish_user_interaction_request:
156
+ logger.error("Received None publish_user_interaction_request")
157
+ return result
158
+
159
+ user_id = publish_user_interaction_request.user_id
160
+ if not user_id:
161
+ logger.error("Received None user_id in publish_user_interaction_request")
162
+ return result
163
+
164
+ # Check if cleanup is needed before adding new interactions.
165
+ self._cleanup_storage_tables_if_needed()
166
+
167
+ publish_start = time.perf_counter()
168
+ # Resolve agent_version: explicit > env var > default. Resolved here
169
+ # (before the try) so success and failure telemetry share the same value.
170
+ agent_version = resolve_agent_version(
171
+ publish_user_interaction_request.agent_version
172
+ )
173
+
174
+ try:
175
+ caller_request_id = publish_user_interaction_request.request_id
176
+ request_id = (
177
+ caller_request_id
178
+ if caller_request_id is not None
179
+ else str(uuid.uuid4())
180
+ )
181
+ result.request_id = request_id
182
+
183
+ if (
184
+ caller_request_id is not None
185
+ and self.storage.get_request(request_id) is not None # type: ignore[reportOptionalMemberAccess]
186
+ ):
187
+ raise ValueError(f"request_id {request_id!r} already exists")
188
+
189
+ new_interactions: list[Interaction] = (
190
+ GenerationService.get_interaction_from_publish_user_interaction_request(
191
+ publish_user_interaction_request, request_id
192
+ )
193
+ )
194
+
195
+ if not new_interactions:
196
+ logger.info(
197
+ "No interactions from the publish user interaction request: %s, get all interactions for the user: %s",
198
+ request_id,
199
+ user_id,
200
+ )
201
+ return result
202
+
203
+ record_usage_event(
204
+ org_id=self.org_id,
205
+ user_id=user_id,
206
+ request_id=request_id,
207
+ session_id=publish_user_interaction_request.session_id or None,
208
+ source=publish_user_interaction_request.source,
209
+ agent_version=agent_version,
210
+ event_name="publish_request_received",
211
+ event_category="publish",
212
+ outcome="received",
213
+ count_value=len(new_interactions),
214
+ )
215
+
216
+ # Store Request — propagate customer-stamped metadata so the
217
+ # eval pipeline (e.g. F2 sticky-group aggregator) can read it
218
+ # back from the first request of each session.
219
+ new_request = Request(
220
+ request_id=request_id,
221
+ user_id=user_id,
222
+ source=publish_user_interaction_request.source,
223
+ agent_version=agent_version,
224
+ session_id=publish_user_interaction_request.session_id or None,
225
+ metadata=publish_user_interaction_request.metadata,
226
+ )
227
+ self.storage.add_request(new_request) # type: ignore[reportOptionalMemberAccess]
228
+
229
+ # Add interactions to storage (bulk insert with batched embedding generation)
230
+ self.storage.add_user_interactions_bulk( # type: ignore[reportOptionalMemberAccess]
231
+ user_id=user_id, interactions=new_interactions
232
+ )
233
+
234
+ # Extract source (empty string treated as None)
235
+ source = publish_user_interaction_request.source or None
236
+
237
+ if (
238
+ not publish_user_interaction_request.override_learning_stall
239
+ and (stall_warning := self._active_learning_stall_warning()) is not None
240
+ ):
241
+ result.warnings.append(stall_warning)
242
+ logger.warning("%s; skipping automatic extraction", stall_warning)
243
+ record_usage_event(
244
+ org_id=self.org_id,
245
+ user_id=user_id,
246
+ request_id=request_id,
247
+ session_id=new_request.session_id,
248
+ source=source,
249
+ agent_version=agent_version,
250
+ event_name="publish_request_succeeded",
251
+ event_category="publish",
252
+ outcome="success",
253
+ count_value=len(new_interactions),
254
+ duration_ms=int((time.perf_counter() - publish_start) * 1000),
255
+ metadata={"warning_count": len(result.warnings)},
256
+ )
257
+ return result
258
+
259
+ # Reflection runs as its own sliding-window step BEFORE the
260
+ # extractor pool spins up, so any replacements it makes are
261
+ # visible to the extractors when they retrieve existing
262
+ # profile/playbook context. Wrapped in a broad except so a
263
+ # reflection bug never breaks the publish.
264
+ self._maybe_run_reflection(
265
+ user_id=user_id, agent_version=agent_version, source=source
266
+ )
267
+
268
+ # Create generation services and requests
269
+ # Each service writes to separate storage tables and has no dependencies on others
270
+ profile_generation_service = ProfileGenerationService(
271
+ llm_client=self.client, request_context=self.request_context
272
+ )
273
+ profile_generation_request = ProfileGenerationRequest(
274
+ user_id=user_id,
275
+ request_id=request_id,
276
+ source=source,
277
+ force_extraction=publish_user_interaction_request.force_extraction,
278
+ )
279
+
280
+ playbook_generation_service = PlaybookGenerationService(
281
+ llm_client=self.client,
282
+ request_context=self.request_context,
283
+ skip_aggregation=publish_user_interaction_request.skip_aggregation,
284
+ )
285
+ playbook_generation_request = PlaybookGenerationRequest(
286
+ request_id=request_id,
287
+ agent_version=agent_version,
288
+ user_id=user_id,
289
+ source=source,
290
+ force_extraction=publish_user_interaction_request.force_extraction,
291
+ )
292
+
293
+ # Run profile and playbook generation services in parallel
294
+ # Each service creates its own internal ThreadPoolExecutor for extractors
295
+ # This is safe because we create separate, independent pool instances
296
+ # Uses manual executor management to avoid blocking on shutdown(wait=True)
297
+ # when threads are hung on LLM calls
298
+ executor = ThreadPoolExecutor(max_workers=2)
299
+ try:
300
+ # Each thread needs its own context copy — Context.run() is non-reentrant
301
+ futures = [
302
+ executor.submit(
303
+ contextvars.copy_context().run,
304
+ profile_generation_service.run,
305
+ profile_generation_request,
306
+ ),
307
+ executor.submit(
308
+ contextvars.copy_context().run,
309
+ playbook_generation_service.run,
310
+ playbook_generation_request,
311
+ ),
312
+ ]
313
+
314
+ # Collect results and handle any exceptions
315
+ # Each service failure is logged but doesn't block others
316
+ service_names = ["profile_generation", "playbook_generation"]
317
+ for future, service_name in zip(futures, service_names, strict=True):
318
+ try:
319
+ future.result(timeout=GENERATION_SERVICE_TIMEOUT_SECONDS)
320
+ except FuturesTimeoutError: # noqa: PERF203
321
+ msg = f"{service_name} timed out after {GENERATION_SERVICE_TIMEOUT_SECONDS}s"
322
+ with sentry_tags(
323
+ subsystem="generation",
324
+ service=service_name,
325
+ request_id=request_id,
326
+ error_type="timeout",
327
+ ):
328
+ logger.error("%s for request %s", msg, request_id)
329
+ result.warnings.append(msg)
330
+ except Exception as e:
331
+ msg = f"{service_name} failed: {e}"
332
+ with sentry_tags(
333
+ subsystem="generation",
334
+ service=service_name,
335
+ request_id=request_id,
336
+ error_type=type(e).__name__,
337
+ ):
338
+ logger.exception(
339
+ "Generation service failed for request %s",
340
+ request_id,
341
+ )
342
+ result.warnings.append(msg)
343
+ finally:
344
+ executor.shutdown(wait=False, cancel_futures=True)
345
+
346
+ # Schedule delayed group evaluation if session_id is present
347
+ self._schedule_group_evaluation_if_needed(
348
+ new_request=new_request,
349
+ user_id=user_id,
350
+ agent_version=agent_version,
351
+ source=source,
352
+ )
353
+
354
+ record_usage_event(
355
+ org_id=self.org_id,
356
+ user_id=user_id,
357
+ request_id=request_id,
358
+ session_id=new_request.session_id,
359
+ source=source,
360
+ agent_version=agent_version,
361
+ backend="classic",
362
+ event_name="publish_request_succeeded",
363
+ event_category="publish",
364
+ outcome="success",
365
+ count_value=len(new_interactions),
366
+ duration_ms=int((time.perf_counter() - publish_start) * 1000),
367
+ metadata={"warning_count": len(result.warnings)},
368
+ )
369
+ return result
370
+
371
+ except Exception as e:
372
+ record_usage_event(
373
+ org_id=self.org_id,
374
+ user_id=user_id,
375
+ request_id=result.request_id,
376
+ session_id=publish_user_interaction_request.session_id or None,
377
+ source=publish_user_interaction_request.source,
378
+ agent_version=agent_version,
379
+ event_name="publish_request_failed",
380
+ event_category="publish",
381
+ outcome="failed",
382
+ duration_ms=int((time.perf_counter() - publish_start) * 1000),
383
+ error_kind=type(e).__name__,
384
+ )
385
+ with sentry_tags(
386
+ subsystem="generation",
387
+ op="refresh_profile",
388
+ org_id=self.org_id,
389
+ user_id=user_id,
390
+ request_id=result.request_id,
391
+ error_type=type(e).__name__,
392
+ ):
393
+ logger.exception(
394
+ "Failed to refresh user profile for user id: %s",
395
+ user_id,
396
+ )
397
+ raise
398
+
399
+ # ===============================
400
+ # private methods
401
+ # ===============================
402
+
403
+ def _schedule_group_evaluation_if_needed(
404
+ self,
405
+ *,
406
+ new_request: Request,
407
+ user_id: str,
408
+ agent_version: str,
409
+ source: str | None,
410
+ ) -> None:
411
+ """Enqueue agent-success evaluation for this session, if session_id is set.
412
+
413
+ Must be called once per publish — from BOTH the classic and the agentic
414
+ extraction code paths — so that ``AgentSuccessEvaluationResult`` records
415
+ get produced regardless of which backend is in use. Skipping this for
416
+ the agentic path was the silent root cause of empty /evaluations tiles.
417
+
418
+ Args:
419
+ new_request (Request): The just-stored request whose session is being
420
+ published into. ``new_request.session_id`` gates scheduling.
421
+ user_id (str): The user owning the session.
422
+ agent_version (str): Agent version string carried into the evaluator.
423
+ source (str | None): Optional source label.
424
+ """
425
+ session_id = new_request.session_id
426
+ if not session_id:
427
+ return
428
+
429
+ scheduler = GroupEvaluationScheduler.get_instance()
430
+ key = (self.org_id, user_id, session_id)
431
+
432
+ def make_callback(
433
+ _org_id: str,
434
+ _user_id: str,
435
+ _sid: str,
436
+ _av: str,
437
+ _src: str | None,
438
+ _rc: RequestContext,
439
+ _llm: LiteLLMClient,
440
+ ) -> Callable[[], None]:
441
+ def callback() -> None:
442
+ run_group_evaluation(
443
+ org_id=_org_id,
444
+ user_id=_user_id,
445
+ session_id=_sid,
446
+ agent_version=_av,
447
+ source=_src,
448
+ request_context=_rc,
449
+ llm_client=_llm,
450
+ )
451
+
452
+ return callback
453
+
454
+ scheduler.schedule(
455
+ key,
456
+ make_callback(
457
+ self.org_id,
458
+ user_id,
459
+ session_id,
460
+ agent_version,
461
+ source,
462
+ self.request_context,
463
+ self.client,
464
+ ),
465
+ )
466
+
467
+ def _maybe_run_reflection(
468
+ self, *, user_id: str, agent_version: str, source: str | None
469
+ ) -> None:
470
+ """Best-effort reflection pass before extraction.
471
+
472
+ Any failure is caught and logged so the surrounding publish
473
+ flow (extraction + delayed evaluation) is unaffected.
474
+ """
475
+ try:
476
+ service = ReflectionService(
477
+ request_context=self.request_context,
478
+ llm_client=self.client,
479
+ )
480
+ service.run(
481
+ ReflectionServiceRequest(
482
+ user_id=user_id,
483
+ agent_version=agent_version,
484
+ source=source,
485
+ )
486
+ )
487
+ except Exception as exc: # noqa: BLE001 — must not break publish
488
+ # Promoted to logger.exception so Sentry's LoggingIntegration
489
+ # captures the event. The except still doesn't re-raise — the
490
+ # publish loop continues — but on-call now sees the failure
491
+ # instead of it being buried at WARNING level.
492
+ with sentry_tags(
493
+ subsystem="generation",
494
+ op="reflection",
495
+ org_id=self.org_id,
496
+ user_id=user_id,
497
+ error_type=type(exc).__name__,
498
+ ):
499
+ logger.exception("reflection step failed for user %s", user_id)
500
+
501
+ def _cleanup_storage_tables_if_needed(self) -> None:
502
+ """Best-effort publish-boundary cleanup for capped storage tables."""
503
+ now = time.monotonic()
504
+ limits = {
505
+ target_name: limit
506
+ for target_name, limit in get_row_retention_limits().items()
507
+ if limit > 0 and self._should_check_retention_target(target_name, now)
508
+ }
509
+ if not limits:
510
+ return
511
+
512
+ try:
513
+ mgr = OperationStateManager(
514
+ self.storage, # type: ignore[reportArgumentType]
515
+ self.org_id,
516
+ "storage_table_cleanup", # type: ignore[reportArgumentType]
517
+ )
518
+ if not mgr.acquire_simple_lock(stale_seconds=CLEANUP_STALE_LOCK_SECONDS):
519
+ return
520
+
521
+ try:
522
+ for target_name, limit in limits.items():
523
+ # Isolate per-target failures so one bad table does not
524
+ # short-circuit cleanup for every subsequent target.
525
+ try:
526
+ self._cleanup_retention_target(target_name, limit)
527
+ except Exception as e: # noqa: BLE001
528
+ with sentry_tags(
529
+ subsystem="generation",
530
+ op="cleanup_retention_target",
531
+ org_id=self.org_id,
532
+ target_name=target_name,
533
+ error_type=type(e).__name__,
534
+ ):
535
+ logger.exception(
536
+ "Failed to cleanup retention target %s",
537
+ target_name,
538
+ )
539
+ finally:
540
+ mgr.release_simple_lock()
541
+
542
+ except Exception as e:
543
+ with sentry_tags(
544
+ subsystem="generation",
545
+ op="cleanup_storage_tables",
546
+ org_id=self.org_id,
547
+ error_type=type(e).__name__,
548
+ ):
549
+ logger.exception("Failed to cleanup storage tables")
550
+ # Don't raise - cleanup failure shouldn't block normal operation
551
+
552
+ def _should_check_retention_target(self, target_name: str, now: float) -> bool:
553
+ if _RETENTION_CLEANUP_INTERVAL_SECONDS <= 0:
554
+ return True
555
+ key = (self.org_id, target_name)
556
+ with _retention_cleanup_lock:
557
+ last_run = _retention_cleanup_last_run.get(key)
558
+ if (
559
+ last_run is not None
560
+ and now - last_run < _RETENTION_CLEANUP_INTERVAL_SECONDS
561
+ ):
562
+ return False
563
+ _retention_cleanup_last_run[key] = now
564
+ return True
565
+
566
+ def _active_learning_stall_warning(self) -> str | None:
567
+ """Return a warning when extraction should not auto-retry.
568
+
569
+ Plugin publishes should still store raw interactions while the local
570
+ LLM provider is blocked by auth or billing, but they
571
+ must not keep invoking extraction on every publish. Only callers that
572
+ pass ``override_learning_stall=True`` bypass this check so an explicit
573
+ retry after reauth can clear the stall state on a successful provider
574
+ call.
575
+ """
576
+ try:
577
+ stall_state = self.storage.get_stall_state() # type: ignore[reportOptionalMemberAccess]
578
+ except (AttributeError, NotImplementedError):
579
+ return None
580
+ except Exception as exc: # noqa: BLE001 - stall telemetry must not block publish.
581
+ logger.debug("Failed to read stall_state before extraction: %s", exc)
582
+ return None
583
+
584
+ if not getattr(stall_state, "stalled", False):
585
+ return None
586
+ reason = getattr(stall_state, "reason", None) or "unknown"
587
+ suffix = (
588
+ "reauthenticate the active coding-agent provider, then run an explicit "
589
+ "override retry to resume."
590
+ if reason == "auth_error"
591
+ else "wait for the limit/reset condition to clear, then run an explicit "
592
+ "override retry to resume."
593
+ )
594
+ return f"{_STALL_WARNING_PREFIX} ({reason}); {suffix}"
595
+
596
+ def _cleanup_retention_target(self, target_name: str, limit: int) -> None:
597
+ total_count = self.storage.count_retention_target_rows(target_name) # type: ignore[reportOptionalMemberAccess]
598
+ if total_count < limit:
599
+ return
600
+ delete_count = delete_count_for_retention(total_count)
601
+ deleted = self.storage.delete_oldest_retention_target_rows( # type: ignore[reportOptionalMemberAccess]
602
+ target_name,
603
+ delete_count,
604
+ )
605
+ logger.info(
606
+ "Cleaned up %d oldest %s row(s) (total was %d, limit %d)",
607
+ deleted,
608
+ target_name,
609
+ total_count,
610
+ limit,
611
+ )
612
+
613
+ # ===============================
614
+ # static methods
615
+ # ===============================
616
+
617
+ @staticmethod
618
+ def get_interaction_from_publish_user_interaction_request(
619
+ publish_user_interaction_request: PublishUserInteractionRequest,
620
+ request_id: str,
621
+ ) -> list[Interaction]:
622
+ """get interaction from publish user interaction request
623
+
624
+ Args:
625
+ publish_user_interaction_request (PublishUserInteractionRequest): The publish user interaction request
626
+ request_id (str): The request ID generated by the service
627
+
628
+ Returns:
629
+ list[Interaction]: List of interactions created from the request
630
+ """
631
+ interaction_data_list = publish_user_interaction_request.interaction_data_list
632
+
633
+ user_id = publish_user_interaction_request.user_id
634
+ # Honor the client-provided ``created_at`` — InteractionData defaults
635
+ # it to client-side ``now()`` on construction, so it's always populated.
636
+ # Apps that publish backdated conversations (e.g., a benchmark replay
637
+ # of 2023 chats run in 2026) need the wall-clock time preserved so the
638
+ # extraction agent has a real temporal anchor for relative-time
639
+ # references like "X weeks ago" / "yesterday". Stamping server-now here
640
+ # would erase that anchor and force every event onto today's date.
641
+ return [
642
+ Interaction(
643
+ # interaction_id is auto-generated by DB
644
+ user_id=user_id,
645
+ request_id=request_id,
646
+ created_at=interaction_data.created_at,
647
+ content=interaction_data.content,
648
+ role=interaction_data.role,
649
+ user_action=interaction_data.user_action,
650
+ user_action_description=interaction_data.user_action_description,
651
+ interacted_image_url=interaction_data.interacted_image_url,
652
+ image_encoding=interaction_data.image_encoding,
653
+ shadow_content=interaction_data.shadow_content,
654
+ expert_content=interaction_data.expert_content,
655
+ tools_used=interaction_data.tools_used,
656
+ citations=interaction_data.citations,
657
+ )
658
+ for interaction_data in interaction_data_list
659
+ ]
660
+
661
+
662
+ def build_extraction_service(
663
+ config: Config,
664
+ *,
665
+ llm_client: LiteLLMClient,
666
+ request_context: RequestContext,
667
+ ) -> ProfileGenerationService:
668
+ """Return the profile extraction service.
669
+
670
+ Args:
671
+ config (Config): Top-level ``Config`` (unused; kept for API consistency).
672
+ llm_client (LiteLLMClient): Configured ``LiteLLMClient``.
673
+ request_context (RequestContext): Current request context.
674
+
675
+ Returns:
676
+ ProfileGenerationService: Classic profile extraction service.
677
+ """
678
+ del config # unused — agentic path bypasses this factory
679
+ return ProfileGenerationService(
680
+ llm_client=llm_client, request_context=request_context
681
+ )
682
+
683
+
684
+ def build_search_service(
685
+ config: Config, # noqa: ARG001
686
+ *,
687
+ llm_client: LiteLLMClient,
688
+ request_context: RequestContext,
689
+ ) -> UnifiedSearchService:
690
+ """Build the unified search service.
691
+
692
+ Args:
693
+ config (Config): Top-level ``Config`` (unused; kept for API consistency).
694
+ llm_client (LiteLLMClient): Configured ``LiteLLMClient``.
695
+ request_context (RequestContext): Current request context.
696
+
697
+ Returns:
698
+ A ``UnifiedSearchService`` holding ``llm_client`` and ``request_context``.
699
+ """
700
+ from reflexio.server.services.unified_search_service import UnifiedSearchService
701
+
702
+ return UnifiedSearchService(llm_client=llm_client, request_context=request_context)