claude-smart 0.2.42 → 0.2.43

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 (392) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/README.md +1 -1
  3. package/package.json +9 -3
  4. package/plugin/.claude-plugin/plugin.json +9 -3
  5. package/plugin/.codex-plugin/plugin.json +1 -1
  6. package/plugin/README.md +2 -2
  7. package/plugin/pyproject.toml +2 -2
  8. package/plugin/scripts/_lib.sh +91 -0
  9. package/plugin/scripts/backend-service.sh +1 -0
  10. package/plugin/scripts/cli.sh +1 -0
  11. package/plugin/scripts/codex-hook.js +72 -4
  12. package/plugin/scripts/dashboard-build.sh +1 -0
  13. package/plugin/scripts/dashboard-service.sh +1 -0
  14. package/plugin/scripts/hook_entry.sh +1 -0
  15. package/plugin/scripts/smart-install.sh +1 -0
  16. package/plugin/src/claude_smart/context_format.py +11 -12
  17. package/plugin/src/claude_smart/cs_cite.py +26 -12
  18. package/plugin/src/claude_smart/ids.py +13 -5
  19. package/plugin/uv.lock +1 -1
  20. package/plugin/vendor/reflexio/.env.example +53 -0
  21. package/plugin/vendor/reflexio/LICENSE +201 -0
  22. package/plugin/vendor/reflexio/README.md +338 -0
  23. package/plugin/vendor/reflexio/pyproject.toml +271 -0
  24. package/plugin/vendor/reflexio/reflexio/README.md +184 -0
  25. package/plugin/vendor/reflexio/reflexio/__init__.py +166 -0
  26. package/plugin/vendor/reflexio/reflexio/benchmarks/__init__.py +1 -0
  27. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/README.md +109 -0
  28. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/__init__.py +1 -0
  29. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/backends.py +175 -0
  30. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/bench.py +642 -0
  31. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/embed_cache.py +330 -0
  32. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/report.py +317 -0
  33. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/results/report.md +43 -0
  34. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/results/results.json +4478 -0
  35. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/scenarios.py +134 -0
  36. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/seed.py +255 -0
  37. package/plugin/vendor/reflexio/reflexio/cli/README.md +287 -0
  38. package/plugin/vendor/reflexio/reflexio/cli/__init__.py +0 -0
  39. package/plugin/vendor/reflexio/reflexio/cli/__main__.py +56 -0
  40. package/plugin/vendor/reflexio/reflexio/cli/_client.py +86 -0
  41. package/plugin/vendor/reflexio/reflexio/cli/app.py +127 -0
  42. package/plugin/vendor/reflexio/reflexio/cli/bootstrap_config.py +266 -0
  43. package/plugin/vendor/reflexio/reflexio/cli/codex_auth.py +503 -0
  44. package/plugin/vendor/reflexio/reflexio/cli/commands/__init__.py +0 -0
  45. package/plugin/vendor/reflexio/reflexio/cli/commands/admin_cmd.py +65 -0
  46. package/plugin/vendor/reflexio/reflexio/cli/commands/agent_playbooks.py +503 -0
  47. package/plugin/vendor/reflexio/reflexio/cli/commands/api.py +114 -0
  48. package/plugin/vendor/reflexio/reflexio/cli/commands/auth.py +109 -0
  49. package/plugin/vendor/reflexio/reflexio/cli/commands/config_cmd.py +511 -0
  50. package/plugin/vendor/reflexio/reflexio/cli/commands/doctor.py +127 -0
  51. package/plugin/vendor/reflexio/reflexio/cli/commands/embeddings.py +53 -0
  52. package/plugin/vendor/reflexio/reflexio/cli/commands/interactions.py +478 -0
  53. package/plugin/vendor/reflexio/reflexio/cli/commands/profiles.py +303 -0
  54. package/plugin/vendor/reflexio/reflexio/cli/commands/services.py +289 -0
  55. package/plugin/vendor/reflexio/reflexio/cli/commands/setup_cmd.py +961 -0
  56. package/plugin/vendor/reflexio/reflexio/cli/commands/shortcuts.py +285 -0
  57. package/plugin/vendor/reflexio/reflexio/cli/commands/status_cmd.py +143 -0
  58. package/plugin/vendor/reflexio/reflexio/cli/commands/user_playbooks.py +373 -0
  59. package/plugin/vendor/reflexio/reflexio/cli/env_loader.py +284 -0
  60. package/plugin/vendor/reflexio/reflexio/cli/errors.py +217 -0
  61. package/plugin/vendor/reflexio/reflexio/cli/log_format.py +247 -0
  62. package/plugin/vendor/reflexio/reflexio/cli/output.py +867 -0
  63. package/plugin/vendor/reflexio/reflexio/cli/paths.py +41 -0
  64. package/plugin/vendor/reflexio/reflexio/cli/run_services.py +391 -0
  65. package/plugin/vendor/reflexio/reflexio/cli/state.py +204 -0
  66. package/plugin/vendor/reflexio/reflexio/cli/stop_services.py +96 -0
  67. package/plugin/vendor/reflexio/reflexio/cli/utils.py +329 -0
  68. package/plugin/vendor/reflexio/reflexio/client/__init__.py +3 -0
  69. package/plugin/vendor/reflexio/reflexio/client/cache.py +150 -0
  70. package/plugin/vendor/reflexio/reflexio/client/client.py +2613 -0
  71. package/plugin/vendor/reflexio/reflexio/defaults.py +23 -0
  72. package/plugin/vendor/reflexio/reflexio/integrations/__init__.py +0 -0
  73. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/.clawhubignore +7 -0
  74. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/README.md +274 -0
  75. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/TESTING.md +517 -0
  76. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/hook/handler.js +473 -0
  77. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package-lock.json +2156 -0
  78. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package.json +18 -0
  79. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/handler.ts +241 -0
  80. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/setup.ts +140 -0
  81. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/index.ts +130 -0
  82. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/publish.ts +113 -0
  83. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/search.ts +52 -0
  84. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/server.ts +103 -0
  85. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/sqlite-buffer.ts +156 -0
  86. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/user-id.ts +134 -0
  87. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/openclaw.plugin.json +41 -0
  88. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/package.json +17 -0
  89. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/rules/reflexio.md +24 -0
  90. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/reflexio/SKILL.md +48 -0
  91. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/publish_clawhub.sh +278 -0
  92. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/references/HOOK.md +164 -0
  93. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/install.sh +36 -0
  94. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/uninstall.sh +35 -0
  95. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/publish.test.ts +27 -0
  96. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/search.test.ts +31 -0
  97. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/server.test.ts +42 -0
  98. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/setup.test.ts +49 -0
  99. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/sqlite-buffer.test.ts +91 -0
  100. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/user-id.test.ts +50 -0
  101. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tsconfig.json +16 -0
  102. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/types/openclaw.d.ts +230 -0
  103. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/vitest.config.ts +13 -0
  104. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/README.md +120 -0
  105. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/TESTING.md +168 -0
  106. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/package-lock.json +1657 -0
  107. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/package.json +16 -0
  108. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/HEARTBEAT.md +6 -0
  109. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/README.md +84 -0
  110. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/SKILL.md +194 -0
  111. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/_meta.json +6 -0
  112. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/agents/reflexio-extractor.md +45 -0
  113. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/hook/handler.ts +214 -0
  114. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/hook/setup.ts +55 -0
  115. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/index.ts +327 -0
  116. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/consolidate.ts +233 -0
  117. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/dedup.ts +80 -0
  118. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/io.ts +155 -0
  119. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/openclaw-cli.ts +67 -0
  120. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/search.ts +33 -0
  121. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/write-playbook.ts +76 -0
  122. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/write-profile.ts +79 -0
  123. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/openclaw.plugin.json +46 -0
  124. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/package.json +18 -0
  125. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/README.md +36 -0
  126. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/full_consolidation.md +56 -0
  127. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/playbook_extraction.md +217 -0
  128. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/profile_extraction.md +132 -0
  129. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/skills/reflexio-consolidate/SKILL.md +33 -0
  130. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/skills/reflexio-embedded/SKILL.md +194 -0
  131. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/HOOK.md +18 -0
  132. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/architecture.md +49 -0
  133. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/comparison.md +31 -0
  134. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/future-work.md +47 -0
  135. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/porting-notes.md +52 -0
  136. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/scripts/install.sh +52 -0
  137. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/scripts/uninstall.sh +36 -0
  138. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/consolidate.test.ts +135 -0
  139. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/dedup.test.ts +104 -0
  140. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/io.test.ts +175 -0
  141. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/search.test.ts +66 -0
  142. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/smoke-test.ts +140 -0
  143. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/write-playbook.test.ts +93 -0
  144. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/write-profile.test.ts +174 -0
  145. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tsconfig.json +16 -0
  146. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/types/openclaw.d.ts +230 -0
  147. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/vitest.config.ts +7 -0
  148. package/plugin/vendor/reflexio/reflexio/lib/__init__.py +23 -0
  149. package/plugin/vendor/reflexio/reflexio/lib/_agent_playbook.py +310 -0
  150. package/plugin/vendor/reflexio/reflexio/lib/_base.py +225 -0
  151. package/plugin/vendor/reflexio/reflexio/lib/_config.py +83 -0
  152. package/plugin/vendor/reflexio/reflexio/lib/_dashboard.py +266 -0
  153. package/plugin/vendor/reflexio/reflexio/lib/_generation.py +176 -0
  154. package/plugin/vendor/reflexio/reflexio/lib/_interactions.py +334 -0
  155. package/plugin/vendor/reflexio/reflexio/lib/_operations.py +153 -0
  156. package/plugin/vendor/reflexio/reflexio/lib/_profiles.py +545 -0
  157. package/plugin/vendor/reflexio/reflexio/lib/_reflection.py +52 -0
  158. package/plugin/vendor/reflexio/reflexio/lib/_search.py +167 -0
  159. package/plugin/vendor/reflexio/reflexio/lib/_storage_labels.py +103 -0
  160. package/plugin/vendor/reflexio/reflexio/lib/_user_playbook.py +288 -0
  161. package/plugin/vendor/reflexio/reflexio/lib/reflexio_lib.py +27 -0
  162. package/plugin/vendor/reflexio/reflexio/models/__init__.py +0 -0
  163. package/plugin/vendor/reflexio/reflexio/models/api_schema/__init__.py +0 -0
  164. package/plugin/vendor/reflexio/reflexio/models/api_schema/braintrust_schema.py +141 -0
  165. package/plugin/vendor/reflexio/reflexio/models/api_schema/common.py +41 -0
  166. package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/__init__.py +3 -0
  167. package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/entities.py +1103 -0
  168. package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/enums.py +63 -0
  169. package/plugin/vendor/reflexio/reflexio/models/api_schema/eval_overview_schema.py +487 -0
  170. package/plugin/vendor/reflexio/reflexio/models/api_schema/internal_schema.py +28 -0
  171. package/plugin/vendor/reflexio/reflexio/models/api_schema/pending_tool_call_schema.py +83 -0
  172. package/plugin/vendor/reflexio/reflexio/models/api_schema/retriever_schema.py +766 -0
  173. package/plugin/vendor/reflexio/reflexio/models/api_schema/service_schemas.py +9 -0
  174. package/plugin/vendor/reflexio/reflexio/models/api_schema/stall_state_schema.py +32 -0
  175. package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/__init__.py +3 -0
  176. package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/converters.py +177 -0
  177. package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/entities.py +129 -0
  178. package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/enums.py +25 -0
  179. package/plugin/vendor/reflexio/reflexio/models/api_schema/validators.py +280 -0
  180. package/plugin/vendor/reflexio/reflexio/models/config_schema.py +908 -0
  181. package/plugin/vendor/reflexio/reflexio/models/py.typed +0 -0
  182. package/plugin/vendor/reflexio/reflexio/server/OVERVIEW.md +90 -0
  183. package/plugin/vendor/reflexio/reflexio/server/README.md +616 -0
  184. package/plugin/vendor/reflexio/reflexio/server/__init__.py +210 -0
  185. package/plugin/vendor/reflexio/reflexio/server/__main__.py +132 -0
  186. package/plugin/vendor/reflexio/reflexio/server/_auth.py +25 -0
  187. package/plugin/vendor/reflexio/reflexio/server/api.py +2714 -0
  188. package/plugin/vendor/reflexio/reflexio/server/api_endpoints/account_api.py +143 -0
  189. package/plugin/vendor/reflexio/reflexio/server/api_endpoints/health_api.py +91 -0
  190. package/plugin/vendor/reflexio/reflexio/server/api_endpoints/pending_tool_call_api.py +572 -0
  191. package/plugin/vendor/reflexio/reflexio/server/api_endpoints/precondition_checks.py +66 -0
  192. package/plugin/vendor/reflexio/reflexio/server/api_endpoints/publisher_api.py +540 -0
  193. package/plugin/vendor/reflexio/reflexio/server/api_endpoints/request_context.py +50 -0
  194. package/plugin/vendor/reflexio/reflexio/server/api_endpoints/stall_state_api.py +100 -0
  195. package/plugin/vendor/reflexio/reflexio/server/cache/__init__.py +15 -0
  196. package/plugin/vendor/reflexio/reflexio/server/cache/reflexio_cache.py +208 -0
  197. package/plugin/vendor/reflexio/reflexio/server/correlation.py +46 -0
  198. package/plugin/vendor/reflexio/reflexio/server/llm/__init__.py +30 -0
  199. package/plugin/vendor/reflexio/reflexio/server/llm/embedding_service.py +110 -0
  200. package/plugin/vendor/reflexio/reflexio/server/llm/image_utils.py +55 -0
  201. package/plugin/vendor/reflexio/reflexio/server/llm/litellm_client.py +1595 -0
  202. package/plugin/vendor/reflexio/reflexio/server/llm/llm_utils.py +112 -0
  203. package/plugin/vendor/reflexio/reflexio/server/llm/model_defaults.py +469 -0
  204. package/plugin/vendor/reflexio/reflexio/server/llm/providers/__init__.py +1 -0
  205. package/plugin/vendor/reflexio/reflexio/server/llm/providers/claude_code_provider.py +1122 -0
  206. package/plugin/vendor/reflexio/reflexio/server/llm/providers/claude_code_stream_parser.py +197 -0
  207. package/plugin/vendor/reflexio/reflexio/server/llm/providers/embedding_service_provider.py +210 -0
  208. package/plugin/vendor/reflexio/reflexio/server/llm/providers/local_embedding_provider.py +213 -0
  209. package/plugin/vendor/reflexio/reflexio/server/llm/providers/nomic_embedding_provider.py +255 -0
  210. package/plugin/vendor/reflexio/reflexio/server/llm/rerank/__init__.py +6 -0
  211. package/plugin/vendor/reflexio/reflexio/server/llm/rerank/cross_encoder_reranker.py +177 -0
  212. package/plugin/vendor/reflexio/reflexio/server/llm/rerank/llm_reranker.py +148 -0
  213. package/plugin/vendor/reflexio/reflexio/server/llm/tools.py +699 -0
  214. package/plugin/vendor/reflexio/reflexio/server/operation_limiter.py +179 -0
  215. package/plugin/vendor/reflexio/reflexio/server/prompt/__init__.py +0 -0
  216. package/plugin/vendor/reflexio/reflexio/server/prompt/_dispatchers.py +54 -0
  217. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/README.md +121 -0
  218. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/agent_success_evaluation/v1.0.0.prompt.md +58 -0
  219. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/agent_success_evaluation_with_comparison/v1.0.0.prompt.md +76 -0
  220. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/answer_synthesis/v1.5.2.prompt.md +88 -0
  221. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/compress_session_for_query/v1.3.0.prompt.md +31 -0
  222. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/document_expansion/v1.0.0.prompt.md +20 -0
  223. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.0.0.prompt.md +53 -0
  224. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.1.0.prompt.md +57 -0
  225. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.2.0.prompt.md +68 -0
  226. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.3.0.prompt.md +70 -0
  227. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.4.0.prompt.md +77 -0
  228. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.5.0.prompt.md +82 -0
  229. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.6.0.prompt.md +83 -0
  230. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.1.0.prompt.md +193 -0
  231. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.2.0.prompt.md +206 -0
  232. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v1.0.0-deprecated.prompt.md +66 -0
  233. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v1.0.0.prompt.md +43 -0
  234. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v1.1.0.prompt.md +46 -0
  235. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.0.0-deprecated.prompt.md +64 -0
  236. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.0.0.prompt.md +39 -0
  237. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.1.0.prompt.md +39 -0
  238. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.2.0.prompt.md +47 -0
  239. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.0.prompt.md +58 -0
  240. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.0.2.prompt.md +254 -0
  241. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.1.0.prompt.md +274 -0
  242. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.2.0.prompt.md +279 -0
  243. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v1.0.0.prompt.md +73 -0
  244. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v2.0.0.prompt.md +86 -0
  245. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.0.0.prompt.md +97 -0
  246. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.1.0.prompt.md +119 -0
  247. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.2.0.prompt.md +123 -0
  248. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.3.0.prompt.md +127 -0
  249. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.0.0.prompt.md +14 -0
  250. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.1.0.prompt.md +24 -0
  251. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.2.0.prompt.md +29 -0
  252. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main_expert/v1.0.0.prompt.md +11 -0
  253. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main_expert/v1.1.0.prompt.md +21 -0
  254. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main_expert/v1.2.0.prompt.md +25 -0
  255. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_optimizer_judge/v1.0.0.prompt.md +37 -0
  256. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_optimizer_judge/v1.1.0.prompt.md +40 -0
  257. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_optimizer_judge/v1.2.0.prompt.md +36 -0
  258. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate/v1.0.0.prompt.md +45 -0
  259. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate/v2.0.0.prompt.md +81 -0
  260. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate/v3.0.0.prompt.md +80 -0
  261. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate_expert/v1.0.0.prompt.md +34 -0
  262. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_deduplication/v1.0.0.prompt.md +116 -0
  263. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_should_generate/v1.0.0.prompt.md +33 -0
  264. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_should_generate_override/v1.0.0.prompt.md +16 -0
  265. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.0.0.prompt.md +140 -0
  266. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.1.0.prompt.md +160 -0
  267. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_main/v1.0.0.prompt.md +14 -0
  268. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/query_reformulation/v1.0.0.prompt.md +19 -0
  269. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/rerank_relevance/v1.1.0.prompt.md +44 -0
  270. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/shadow_comparison/v1.0.0.prompt.md +43 -0
  271. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/shadow_content_evaluation/v1.0.0.prompt.md +33 -0
  272. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_evaluation/prompt_evaluation_dataset/feedback_extraction_main_v1.jsonl +10 -0
  273. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_evaluation/prompt_evaluation_dataset/profile_update_main_v1.jsonl +10 -0
  274. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_manager.py +280 -0
  275. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_schema.py +11 -0
  276. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/_eval_health.py +131 -0
  277. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_constants.py +60 -0
  278. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_service.py +228 -0
  279. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_utils.py +87 -0
  280. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluator.py +372 -0
  281. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/delayed_group_evaluator.py +156 -0
  282. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/group_evaluation_runner.py +340 -0
  283. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/regen_jobs.py +471 -0
  284. package/plugin/vendor/reflexio/reflexio/server/services/base_generation_service.py +1626 -0
  285. package/plugin/vendor/reflexio/reflexio/server/services/braintrust/__init__.py +0 -0
  286. package/plugin/vendor/reflexio/reflexio/server/services/braintrust/_cron.py +196 -0
  287. package/plugin/vendor/reflexio/reflexio/server/services/braintrust/_encryption.py +101 -0
  288. package/plugin/vendor/reflexio/reflexio/server/services/braintrust/client.py +167 -0
  289. package/plugin/vendor/reflexio/reflexio/server/services/braintrust/service.py +281 -0
  290. package/plugin/vendor/reflexio/reflexio/server/services/configurator/base_configurator.py +179 -0
  291. package/plugin/vendor/reflexio/reflexio/server/services/configurator/config_storage.py +62 -0
  292. package/plugin/vendor/reflexio/reflexio/server/services/configurator/configurator.py +87 -0
  293. package/plugin/vendor/reflexio/reflexio/server/services/configurator/local_file_config_storage.py +187 -0
  294. package/plugin/vendor/reflexio/reflexio/server/services/configurator/test_config_storage.py +162 -0
  295. package/plugin/vendor/reflexio/reflexio/server/services/deduplication_utils.py +112 -0
  296. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/__init__.py +0 -0
  297. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/distribution.py +33 -0
  298. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/eval_sampler.py +126 -0
  299. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/group_aggregation.py +192 -0
  300. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/hero_state.py +75 -0
  301. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/rule_attribution.py +97 -0
  302. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/service.py +515 -0
  303. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/shadow_aggregation.py +90 -0
  304. package/plugin/vendor/reflexio/reflexio/server/services/extraction/__init__.py +0 -0
  305. package/plugin/vendor/reflexio/reflexio/server/services/extraction/agent_run_records.py +91 -0
  306. package/plugin/vendor/reflexio/reflexio/server/services/extraction/invariants.py +303 -0
  307. package/plugin/vendor/reflexio/reflexio/server/services/extraction/outcome.py +25 -0
  308. package/plugin/vendor/reflexio/reflexio/server/services/extraction/pending_tool_call_dispatch.py +351 -0
  309. package/plugin/vendor/reflexio/reflexio/server/services/extraction/plan.py +138 -0
  310. package/plugin/vendor/reflexio/reflexio/server/services/extraction/prior_answer_search.py +217 -0
  311. package/plugin/vendor/reflexio/reflexio/server/services/extraction/resumable_agent.py +468 -0
  312. package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_scheduler.py +171 -0
  313. package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_worker.py +777 -0
  314. package/plugin/vendor/reflexio/reflexio/server/services/extraction/tools.py +1125 -0
  315. package/plugin/vendor/reflexio/reflexio/server/services/extractor_config_utils.py +91 -0
  316. package/plugin/vendor/reflexio/reflexio/server/services/extractor_interaction_utils.py +251 -0
  317. package/plugin/vendor/reflexio/reflexio/server/services/generation_service.py +689 -0
  318. package/plugin/vendor/reflexio/reflexio/server/services/operation_state_utils.py +835 -0
  319. package/plugin/vendor/reflexio/reflexio/server/services/playbook/README.md +89 -0
  320. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_aggregator.py +1388 -0
  321. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_consolidator.py +960 -0
  322. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_extractor.py +436 -0
  323. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_generation_service.py +808 -0
  324. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_service_constants.py +28 -0
  325. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_service_utils.py +362 -0
  326. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/__init__.py +24 -0
  327. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/assistant_webhook.py +246 -0
  328. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/gepa_adapter.py +291 -0
  329. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/judge.py +97 -0
  330. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/models.py +96 -0
  331. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/optimizer.py +645 -0
  332. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/rollout.py +35 -0
  333. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/scenario_resolver.py +93 -0
  334. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/scheduler.py +174 -0
  335. package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/__init__.py +26 -0
  336. package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/_document_expander.py +179 -0
  337. package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/_query_reformulator.py +297 -0
  338. package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_deduplicator.py +741 -0
  339. package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_extractor.py +462 -0
  340. package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_generation_service.py +734 -0
  341. package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_generation_service_utils.py +290 -0
  342. package/plugin/vendor/reflexio/reflexio/server/services/reflection/__init__.py +17 -0
  343. package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_extractor.py +247 -0
  344. package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_service.py +800 -0
  345. package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_service_utils.py +146 -0
  346. package/plugin/vendor/reflexio/reflexio/server/services/retrieval/__init__.py +0 -0
  347. package/plugin/vendor/reflexio/reflexio/server/services/retrieval/relevance_floor.py +70 -0
  348. package/plugin/vendor/reflexio/reflexio/server/services/search/__init__.py +0 -0
  349. package/plugin/vendor/reflexio/reflexio/server/services/service_utils.py +671 -0
  350. package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/__init__.py +1 -0
  351. package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/judge.py +184 -0
  352. package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/outcome.py +81 -0
  353. package/plugin/vendor/reflexio/reflexio/server/services/storage/constants.py +2 -0
  354. package/plugin/vendor/reflexio/reflexio/server/services/storage/error.py +11 -0
  355. package/plugin/vendor/reflexio/reflexio/server/services/storage/retention.py +154 -0
  356. package/plugin/vendor/reflexio/reflexio/server/services/storage/retention_mixin.py +155 -0
  357. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/__init__.py +59 -0
  358. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_agent_run.py +1253 -0
  359. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_base.py +1945 -0
  360. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_extras.py +600 -0
  361. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_operations.py +346 -0
  362. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_playbook.py +1378 -0
  363. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_profiles.py +747 -0
  364. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_requests.py +263 -0
  365. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_shadow_verdicts.py +193 -0
  366. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_share_links.py +166 -0
  367. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_stall_state.py +217 -0
  368. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/__init__.py +153 -0
  369. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_agent_run.py +372 -0
  370. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_base.py +71 -0
  371. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_extras.py +235 -0
  372. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_operations.py +170 -0
  373. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_playbook.py +677 -0
  374. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_profiles.py +250 -0
  375. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_requests.py +154 -0
  376. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_shadow_verdicts.py +130 -0
  377. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_share_links.py +93 -0
  378. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_stall_state.py +76 -0
  379. package/plugin/vendor/reflexio/reflexio/server/services/unified_search_service.py +568 -0
  380. package/plugin/vendor/reflexio/reflexio/server/site_var/README.md +77 -0
  381. package/plugin/vendor/reflexio/reflexio/server/site_var/feature_flags.py +116 -0
  382. package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_manager.py +263 -0
  383. package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/feature_flags.json +13 -0
  384. package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/llm_model_setting.json +7 -0
  385. package/plugin/vendor/reflexio/reflexio/server/tracing.py +158 -0
  386. package/plugin/vendor/reflexio/reflexio/server/usage_metrics.py +113 -0
  387. package/plugin/vendor/reflexio/reflexio/server/uvicorn_logging.py +76 -0
  388. package/plugin/vendor/reflexio/reflexio/test_support/__init__.py +1 -0
  389. package/plugin/vendor/reflexio/reflexio/test_support/llm_fixtures.py +62 -0
  390. package/plugin/vendor/reflexio/reflexio/test_support/llm_mock.py +242 -0
  391. package/plugin/vendor/reflexio/reflexio/test_support/llm_model_registry.py +129 -0
  392. package/plugin/vendor/reflexio/reflexio/test_support/skip_decorators.py +43 -0
@@ -0,0 +1,734 @@
1
+ """Service to generate user profiles from interactions"""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+ import uuid
7
+ from dataclasses import dataclass
8
+ from datetime import UTC, datetime
9
+ from typing import TYPE_CHECKING, Any
10
+
11
+ if TYPE_CHECKING:
12
+ from reflexio.server.api_endpoints.request_context import RequestContext
13
+ from reflexio.server.llm.litellm_client import LiteLLMClient
14
+
15
+ from reflexio.models.api_schema.internal_schema import RequestInteractionDataModel
16
+ from reflexio.models.api_schema.service_schemas import (
17
+ DeleteUserProfileRequest,
18
+ DowngradeProfilesResponse,
19
+ ManualProfileGenerationRequest,
20
+ ManualProfileGenerationResponse,
21
+ ProfileChangeLog,
22
+ RerunProfileGenerationRequest,
23
+ RerunProfileGenerationResponse,
24
+ Status,
25
+ UpgradeProfilesResponse,
26
+ UserProfile,
27
+ )
28
+ from reflexio.models.config_schema import ProfileExtractorConfig
29
+ from reflexio.server.services.base_generation_service import (
30
+ BaseGenerationService,
31
+ StatusChangeOperation,
32
+ )
33
+ from reflexio.server.services.profile.profile_extractor import ProfileExtractor
34
+ from reflexio.server.services.profile.profile_generation_service_utils import (
35
+ ProfileGenerationRequest,
36
+ ProfileGenerationServiceConstants,
37
+ )
38
+ from reflexio.server.services.service_utils import (
39
+ format_sessions_to_history_string,
40
+ )
41
+ from reflexio.server.tracing import sentry_tags
42
+
43
+ logger = logging.getLogger(__name__)
44
+
45
+
46
+ @dataclass
47
+ class ProfileGenerationServiceConfig:
48
+ """Runtime configuration for profile generation service shared across all extractors.
49
+
50
+ Attributes:
51
+ user_id: The user ID
52
+ request_id: The request ID
53
+ source: Source of the interactions (triggering source)
54
+ existing_data: Existing profiles for the user
55
+ allow_manual_trigger: Whether to allow extractors with manual_trigger=True
56
+ output_pending_status: Whether to output profiles with PENDING status
57
+ rerun_start_time: Optional start time filter for rerun flows (Unix timestamp)
58
+ rerun_end_time: Optional end time filter for rerun flows (Unix timestamp)
59
+ auto_run: True for regular flow (checks stride_size), False for rerun/manual (skips stride_size)
60
+ """
61
+
62
+ user_id: str
63
+ request_id: str
64
+ source: str | None = None
65
+ existing_data: Any = None
66
+ allow_manual_trigger: bool = False
67
+ output_pending_status: bool = False
68
+ rerun_start_time: int | None = None
69
+ rerun_end_time: int | None = None
70
+ auto_run: bool = True
71
+ force_extraction: bool = False
72
+
73
+
74
+ class ProfileGenerationService(
75
+ BaseGenerationService[
76
+ ProfileExtractorConfig,
77
+ ProfileExtractor,
78
+ ProfileGenerationServiceConfig,
79
+ ProfileGenerationRequest,
80
+ ]
81
+ ):
82
+ """Service to generate user profiles from interactions"""
83
+
84
+ def __init__(
85
+ self,
86
+ llm_client: LiteLLMClient,
87
+ request_context: RequestContext,
88
+ allow_manual_trigger: bool = False,
89
+ output_pending_status: bool = False,
90
+ ) -> None:
91
+ """
92
+ Initialize the profile generation service.
93
+
94
+ Args:
95
+ llm_client: Unified LLM client supporting both OpenAI and Claude
96
+ request_context: Request context with storage, configurator, and org_id
97
+ allow_manual_trigger: Whether to allow extractors with manual_trigger=True
98
+ output_pending_status: Whether to output profiles with PENDING status (for rerun)
99
+ """
100
+ super().__init__(llm_client=llm_client, request_context=request_context)
101
+ self.allow_manual_trigger = allow_manual_trigger
102
+ self.output_pending_status = output_pending_status
103
+
104
+ def _load_generation_service_config(
105
+ self, request: ProfileGenerationRequest
106
+ ) -> ProfileGenerationServiceConfig:
107
+ """
108
+ Extract parameters from ProfileGenerationRequest.
109
+
110
+ Args:
111
+ request: ProfileGenerationRequest containing request interaction groups and metadata
112
+
113
+ Returns:
114
+ ProfileGenerationServiceConfig object
115
+ """
116
+ # Get existing profiles for the user
117
+ # When output_pending_status is True (rerun mode), only include pending profiles as existing data
118
+ # This allows the LLM to generate fresh profiles instead of just mentioning current ones
119
+ if self.output_pending_status:
120
+ existing_profiles = self.storage.get_user_profile( # type: ignore[reportOptionalMemberAccess]
121
+ request.user_id, status_filter=[Status.PENDING]
122
+ )
123
+ else:
124
+ existing_profiles = self.storage.get_user_profile(request.user_id) # type: ignore[reportOptionalMemberAccess]
125
+
126
+ return ProfileGenerationServiceConfig(
127
+ user_id=request.user_id,
128
+ request_id=request.request_id,
129
+ source=request.source,
130
+ existing_data=existing_profiles,
131
+ allow_manual_trigger=self.allow_manual_trigger,
132
+ output_pending_status=self.output_pending_status,
133
+ rerun_start_time=request.rerun_start_time,
134
+ rerun_end_time=request.rerun_end_time,
135
+ auto_run=request.auto_run,
136
+ force_extraction=request.force_extraction,
137
+ )
138
+
139
+ def _process_results(self, results: list[list[UserProfile]]) -> None:
140
+ """
141
+ Process, deduplicate, and apply all extracted profiles. Called once after all extractors complete.
142
+
143
+ Args:
144
+ results: List of profile lists from extractors (one list per successful extractor)
145
+ """
146
+ self._finalize_extracted_items(
147
+ [p for result in results if result for p in result]
148
+ )
149
+
150
+ def _finalize_extracted_items(self, all_new_profiles: list[UserProfile]) -> None:
151
+ """Deduplicate, persist, and changelog extracted profile items."""
152
+ user_id = self.service_config.user_id # type: ignore[reportOptionalMemberAccess]
153
+ source = self.service_config.source # type: ignore[reportOptionalMemberAccess]
154
+ request_id = self.service_config.request_id # type: ignore[reportOptionalMemberAccess]
155
+
156
+ existing_ids_to_delete: list[str] = []
157
+ superseded_profiles: list[UserProfile] = []
158
+
159
+ # Always run deduplicator when enabled and there are new profiles
160
+ if all_new_profiles:
161
+ from reflexio.server.site_var.feature_flags import is_deduplicator_enabled
162
+
163
+ if is_deduplicator_enabled(self.org_id):
164
+ from reflexio.server.services.profile.profile_deduplicator import (
165
+ ProfileDeduplicator,
166
+ )
167
+
168
+ deduplicator = ProfileDeduplicator(
169
+ request_context=self.request_context,
170
+ llm_client=self.client,
171
+ output_pending_status=self.output_pending_status,
172
+ )
173
+ all_new_profiles, existing_ids_to_delete, superseded_profiles = (
174
+ deduplicator.deduplicate(all_new_profiles, user_id, request_id)
175
+ )
176
+ logger.info(
177
+ "Profile updates after deduplication: %d profiles, %d existing to delete",
178
+ len(all_new_profiles),
179
+ len(existing_ids_to_delete),
180
+ )
181
+
182
+ # Set source and status for all profiles
183
+ for profile in all_new_profiles:
184
+ profile.source = source
185
+ profile.status = Status.PENDING if self.output_pending_status else None
186
+
187
+ # Save new profiles
188
+ if all_new_profiles:
189
+ try:
190
+ self.storage.add_user_profile(user_id, all_new_profiles) # type: ignore[reportOptionalMemberAccess]
191
+ except Exception as e:
192
+ with sentry_tags(
193
+ subsystem="profile_generation",
194
+ op="save_profiles",
195
+ org_id=self.org_id,
196
+ user_id=user_id,
197
+ request_id=request_id,
198
+ error_type=type(e).__name__,
199
+ ):
200
+ logger.exception(
201
+ "Failed to save profiles for user id: %s", user_id,
202
+ )
203
+ return
204
+
205
+ # Delete superseded existing profiles
206
+ if existing_ids_to_delete:
207
+ for profile_id in existing_ids_to_delete:
208
+ try:
209
+ self.storage.delete_user_profile( # type: ignore[reportOptionalMemberAccess]
210
+ DeleteUserProfileRequest(
211
+ user_id=user_id,
212
+ profile_id=profile_id,
213
+ )
214
+ )
215
+ except Exception as e: # noqa: PERF203
216
+ with sentry_tags(
217
+ subsystem="profile_generation",
218
+ op="delete_superseded_profile",
219
+ org_id=self.org_id,
220
+ user_id=user_id,
221
+ request_id=request_id,
222
+ profile_id=profile_id,
223
+ error_type=type(e).__name__,
224
+ ):
225
+ logger.exception(
226
+ "Failed to delete superseded profile %s for user %s",
227
+ profile_id, user_id,
228
+ )
229
+
230
+ # Create profile changelog post-deduplication
231
+ if all_new_profiles or superseded_profiles:
232
+ try:
233
+ profile_change_log = ProfileChangeLog(
234
+ id=0, # Auto-generated by storage
235
+ user_id=user_id,
236
+ request_id=request_id,
237
+ created_at=int(datetime.now(UTC).timestamp()),
238
+ added_profiles=all_new_profiles,
239
+ removed_profiles=superseded_profiles,
240
+ mentioned_profiles=[],
241
+ )
242
+ self.storage.add_profile_change_log(profile_change_log) # type: ignore[reportOptionalMemberAccess]
243
+ except Exception as e:
244
+ with sentry_tags(
245
+ subsystem="profile_generation",
246
+ op="add_profile_change_log",
247
+ org_id=self.org_id,
248
+ user_id=user_id,
249
+ request_id=request_id,
250
+ error_type=type(e).__name__,
251
+ ):
252
+ logger.exception(
253
+ "Failed to add profile change log for user %s", user_id,
254
+ )
255
+
256
+ def check_and_update_profiles(self, profiles: list[UserProfile]) -> None:
257
+ """check if the profiles are expired and update them if they are"""
258
+ raise NotImplementedError
259
+
260
+ def _load_extractor_config(self) -> ProfileExtractorConfig | None:
261
+ """
262
+ Load the configured profile extractor from configurator.
263
+
264
+ Returns:
265
+ ProfileExtractorConfig | None: The configured profile extractor, if enabled.
266
+ """
267
+ root_config = self.configurator.get_config()
268
+ return getattr(root_config, "profile_extractor_config", None)
269
+
270
+ def _create_extractor(
271
+ self,
272
+ extractor_config: ProfileExtractorConfig,
273
+ service_config: ProfileGenerationServiceConfig,
274
+ ) -> ProfileExtractor:
275
+ """
276
+ Create a ProfileExtractor instance from configuration.
277
+
278
+ Args:
279
+ extractor_config: ProfileExtractorConfig configuration object from YAML
280
+ service_config: ProfileGenerationServiceConfig containing runtime parameters
281
+
282
+ Returns:
283
+ ProfileExtractor instance
284
+ """
285
+ return ProfileExtractor(
286
+ request_context=self.request_context,
287
+ llm_client=self.client,
288
+ extractor_config=extractor_config,
289
+ service_config=service_config,
290
+ agent_context=self.configurator.get_agent_context(),
291
+ )
292
+
293
+ def _build_should_run_prompt(
294
+ self,
295
+ scoped_config: ProfileExtractorConfig,
296
+ session_data_models: list[RequestInteractionDataModel],
297
+ ) -> str | None:
298
+ """
299
+ Build prompt for consolidated should_extract_profile check.
300
+
301
+ Renders the configured extractor's profile definition and override
302
+ condition for one LLM call.
303
+
304
+ Args:
305
+ scoped_config: Profile extractor config that had scoped interactions
306
+ session_data_models: Deduplicated request interaction data models
307
+
308
+ Returns:
309
+ str | None: The rendered prompt, or None if no criteria to check
310
+ """
311
+ new_interactions = format_sessions_to_history_string(session_data_models)
312
+ agent_context = self.configurator.get_agent_context()
313
+ prompt_manager = self.request_context.prompt_manager
314
+
315
+ criteria_parts = []
316
+ if scoped_config.extraction_definition_prompt:
317
+ criteria_parts.append(
318
+ f"definition: {scoped_config.extraction_definition_prompt.strip()}"
319
+ )
320
+ if scoped_config.should_extract_profile_prompt_override:
321
+ criteria_parts.append(
322
+ "condition: "
323
+ f"{scoped_config.should_extract_profile_prompt_override.strip()}"
324
+ )
325
+
326
+ combined_criteria = "; ".join(criteria_parts)
327
+ if not combined_criteria:
328
+ return None
329
+
330
+ return prompt_manager.render_prompt(
331
+ ProfileGenerationServiceConstants.PROFILE_SHOULD_GENERATE_PROMPT_ID,
332
+ {
333
+ "agent_context_prompt": agent_context,
334
+ "should_extract_profile_prompt": combined_criteria,
335
+ "new_interactions": new_interactions,
336
+ },
337
+ )
338
+
339
+ def _get_extractor_state_service_name(self) -> str:
340
+ """
341
+ Get the service name for stride_size bookmark lookups.
342
+
343
+ Returns:
344
+ str: "profile_extractor" for OperationStateManager stride_size checks
345
+ """
346
+ return "profile_extractor"
347
+
348
+ def _get_service_name(self) -> str:
349
+ """
350
+ Get the name of the service for logging and operation state tracking.
351
+
352
+ Returns:
353
+ Service name string - "rerun_profile_generation" for rerun operations,
354
+ "profile_generation" for regular operations
355
+ """
356
+ if self.output_pending_status:
357
+ return "rerun_profile_generation"
358
+ return "profile_generation"
359
+
360
+ def _get_base_service_name(self) -> str:
361
+ """
362
+ Get the base service name for OperationStateManager keys.
363
+
364
+ Returns:
365
+ str: "profile_generation"
366
+ """
367
+ return "profile_generation"
368
+
369
+ def _should_track_in_progress(self) -> bool:
370
+ """
371
+ Profile generation should track in-progress state to prevent duplicates.
372
+
373
+ Returns:
374
+ bool: True - profile generation tracks in-progress state
375
+ """
376
+ return True
377
+
378
+ def _get_lock_scope_id(self, request: ProfileGenerationRequest) -> str | None:
379
+ """
380
+ Get the scope ID for lock key construction.
381
+
382
+ Profile generation is user-scoped, so returns user_id.
383
+
384
+ Args:
385
+ request: The ProfileGenerationRequest
386
+
387
+ Returns:
388
+ str: The user_id from the request
389
+ """
390
+ return request.user_id
391
+
392
+ # ===============================
393
+ # Rerun hook implementations (override base class methods)
394
+ # ===============================
395
+
396
+ def _get_rerun_user_ids(self, request: RerunProfileGenerationRequest) -> list[str]:
397
+ """Get user IDs to process. Extractors collect their own data.
398
+
399
+ Identifies unique user_ids with matching requests via storage-level filtering.
400
+
401
+ Args:
402
+ request: RerunProfileGenerationRequest with optional filters
403
+
404
+ Returns:
405
+ List of user IDs to process
406
+ """
407
+ return self.storage.get_rerun_user_ids( # type: ignore[reportOptionalMemberAccess]
408
+ user_id=request.user_id,
409
+ start_time=(
410
+ int(request.start_time.timestamp()) if request.start_time else None
411
+ ),
412
+ end_time=(int(request.end_time.timestamp()) if request.end_time else None),
413
+ source=request.source,
414
+ )
415
+
416
+ def _build_rerun_request_params(
417
+ self, request: RerunProfileGenerationRequest
418
+ ) -> dict:
419
+ """Build request params dict for operation state tracking.
420
+
421
+ Args:
422
+ request: Original rerun request
423
+
424
+ Returns:
425
+ Dictionary of request parameters
426
+ """
427
+ return {
428
+ "user_id": request.user_id,
429
+ "start_time": (
430
+ request.start_time.isoformat() if request.start_time else None
431
+ ),
432
+ "end_time": request.end_time.isoformat() if request.end_time else None,
433
+ "source": request.source,
434
+ }
435
+
436
+ def _create_run_request_for_item(
437
+ self,
438
+ user_id: str,
439
+ request: RerunProfileGenerationRequest | ManualProfileGenerationRequest,
440
+ ) -> ProfileGenerationRequest:
441
+ """Create ProfileGenerationRequest for a single user.
442
+
443
+ Handles both rerun and manual request types.
444
+
445
+ Args:
446
+ user_id: The user ID to process
447
+ request: The original rerun or manual request
448
+
449
+ Returns:
450
+ ProfileGenerationRequest for this user with filter constraints
451
+ """
452
+ # Handle rerun requests (have start_time/end_time datetime objects)
453
+ if isinstance(request, RerunProfileGenerationRequest):
454
+ return ProfileGenerationRequest(
455
+ user_id=user_id,
456
+ request_id=f"rerun_{uuid.uuid4().hex[:8]}",
457
+ source=request.source,
458
+ rerun_start_time=(
459
+ int(request.start_time.timestamp()) if request.start_time else None
460
+ ),
461
+ rerun_end_time=(
462
+ int(request.end_time.timestamp()) if request.end_time else None
463
+ ),
464
+ auto_run=False,
465
+ )
466
+ # Handle manual requests (ManualProfileGenerationRequest)
467
+ return ProfileGenerationRequest(
468
+ user_id=user_id,
469
+ request_id=f"manual_{uuid.uuid4().hex[:8]}",
470
+ source=request.source,
471
+ auto_run=False,
472
+ )
473
+
474
+ def _create_rerun_response(
475
+ self, success: bool, msg: str, count: int
476
+ ) -> RerunProfileGenerationResponse:
477
+ """Create RerunProfileGenerationResponse.
478
+
479
+ Args:
480
+ success: Whether the operation succeeded
481
+ msg: Status message
482
+ count: Number of profiles generated
483
+
484
+ Returns:
485
+ RerunProfileGenerationResponse
486
+ """
487
+ return RerunProfileGenerationResponse(
488
+ success=success,
489
+ msg=msg,
490
+ profiles_generated=count,
491
+ )
492
+
493
+ def _get_generated_count(
494
+ self,
495
+ request: RerunProfileGenerationRequest,
496
+ processed_user_ids: list[str] | None = None,
497
+ ) -> int:
498
+ """Get the count of profiles generated during rerun.
499
+
500
+ Counts profiles with PENDING status for each processed user.
501
+
502
+ Args:
503
+ request: The rerun request object
504
+ processed_user_ids: List of user IDs processed in the batch
505
+
506
+ Returns:
507
+ Number of profiles generated
508
+ """
509
+ user_ids = processed_user_ids or ([request.user_id] if request.user_id else [])
510
+ total = 0
511
+ for user_id in user_ids:
512
+ profiles = self.storage.get_user_profile( # type: ignore[reportOptionalMemberAccess]
513
+ user_id=user_id,
514
+ status_filter=[Status.PENDING],
515
+ )
516
+ total += len(profiles)
517
+ return total
518
+
519
+ # ===============================
520
+ # Upgrade/Downgrade hook implementations (override base class methods)
521
+ # ===============================
522
+
523
+ def _has_items_with_status(
524
+ self,
525
+ status: Status | None,
526
+ request: ProfileGenerationRequest, # noqa: ARG002
527
+ ) -> bool:
528
+ """Check if profiles exist with given status.
529
+
530
+ Args:
531
+ status: The status to check for (None for CURRENT)
532
+ request: The upgrade/downgrade request object
533
+
534
+ Returns:
535
+ bool: True if any matching profiles exist
536
+ """
537
+ user_ids = self.storage.get_user_ids_with_status(status=status) # type: ignore[reportOptionalMemberAccess]
538
+ return bool(user_ids)
539
+
540
+ def _delete_items_by_status(
541
+ self,
542
+ status: Status,
543
+ request: ProfileGenerationRequest, # noqa: ARG002
544
+ ) -> int:
545
+ """Delete profiles with given status.
546
+
547
+ Args:
548
+ status: The status of profiles to delete
549
+ request: The upgrade/downgrade request object
550
+
551
+ Returns:
552
+ int: Number of profiles deleted
553
+ """
554
+ return self.storage.delete_all_profiles_by_status(status=status) # type: ignore[reportOptionalMemberAccess]
555
+
556
+ def _update_items_status(
557
+ self,
558
+ old_status: Status | None,
559
+ new_status: Status | None,
560
+ request: ProfileGenerationRequest, # noqa: ARG002
561
+ user_ids: list[str] | None = None, # noqa: ARG002
562
+ ) -> int:
563
+ """Update profiles from old_status to new_status.
564
+
565
+ Args:
566
+ old_status: The current status to match (None for CURRENT)
567
+ new_status: The new status to set (None for CURRENT)
568
+ request: The upgrade/downgrade request object
569
+ user_ids: Optional pre-computed list of user IDs to filter by
570
+
571
+ Returns:
572
+ int: Number of profiles updated
573
+ """
574
+ return self.storage.update_all_profiles_status( # type: ignore[reportOptionalMemberAccess]
575
+ old_status, new_status, user_ids=user_ids
576
+ )
577
+
578
+ def _get_affected_user_ids_for_upgrade(
579
+ self, request: ProfileGenerationRequest
580
+ ) -> list[str] | None:
581
+ """Get user IDs to filter by for upgrade operations.
582
+
583
+ Args:
584
+ request: The upgrade request object
585
+
586
+ Returns:
587
+ Optional[list[str]]: List of user IDs with PENDING profiles, or None for no filtering
588
+ """
589
+ if hasattr(request, "only_affected_users") and request.only_affected_users: # type: ignore[reportAttributeAccessIssue]
590
+ return self.storage.get_user_ids_with_status(Status.PENDING) # type: ignore[reportOptionalMemberAccess]
591
+ return None
592
+
593
+ def _get_affected_user_ids_for_downgrade(
594
+ self, request: ProfileGenerationRequest
595
+ ) -> list[str] | None:
596
+ """Get user IDs to filter by for downgrade operations.
597
+
598
+ Args:
599
+ request: The downgrade request object
600
+
601
+ Returns:
602
+ Optional[list[str]]: List of user IDs with ARCHIVED profiles, or None for no filtering
603
+ """
604
+ if hasattr(request, "only_affected_users") and request.only_affected_users: # type: ignore[reportAttributeAccessIssue]
605
+ return self.storage.get_user_ids_with_status(Status.ARCHIVED) # type: ignore[reportOptionalMemberAccess]
606
+ return None
607
+
608
+ def _create_status_change_response(
609
+ self,
610
+ operation: StatusChangeOperation,
611
+ success: bool,
612
+ counts: dict,
613
+ msg: str,
614
+ ) -> UpgradeProfilesResponse | DowngradeProfilesResponse:
615
+ """Create upgrade or downgrade response object for profiles.
616
+
617
+ Args:
618
+ operation: The operation type (UPGRADE or DOWNGRADE)
619
+ success: Whether the operation succeeded
620
+ counts: Dictionary of counts
621
+ msg: Status message
622
+
623
+ Returns:
624
+ UpgradeProfilesResponse or DowngradeProfilesResponse
625
+ """
626
+ if operation == StatusChangeOperation.UPGRADE:
627
+ return UpgradeProfilesResponse(
628
+ success=success,
629
+ profiles_deleted=counts.get("deleted", 0),
630
+ profiles_archived=counts.get("archived", 0),
631
+ profiles_promoted=counts.get("promoted", 0),
632
+ message=msg,
633
+ )
634
+ # DOWNGRADE
635
+ return DowngradeProfilesResponse(
636
+ success=success,
637
+ profiles_demoted=counts.get("demoted", 0),
638
+ profiles_restored=counts.get("restored", 0),
639
+ message=msg,
640
+ )
641
+
642
+ # ===============================
643
+ # Manual Regular Generation (window-sized, CURRENT output)
644
+ # ===============================
645
+
646
+ def run_manual_regular(
647
+ self, request: ManualProfileGenerationRequest
648
+ ) -> ManualProfileGenerationResponse:
649
+ """
650
+ Run profile generation with window-sized interactions and CURRENT output.
651
+
652
+ This is a manual trigger that behaves like regular generation
653
+ (uses window_size, outputs CURRENT profiles) but only runs
654
+ profile extraction (not feedback or agent success).
655
+
656
+ Each extractor collects its own data using its configured window_size.
657
+ Uses progress tracking via OperationStateManager.
658
+
659
+ Args:
660
+ request: ManualProfileGenerationRequest with optional user_id, source, and extractor_names
661
+
662
+ Returns:
663
+ ManualProfileGenerationResponse with success status and count
664
+ """
665
+ state_manager = self._create_state_manager()
666
+
667
+ try:
668
+ # Check for existing in-progress operation
669
+ error = state_manager.check_in_progress()
670
+ if error:
671
+ return ManualProfileGenerationResponse(
672
+ success=False, msg=error, profiles_generated=0
673
+ )
674
+
675
+ # 1. Get users to process
676
+ if request.user_id:
677
+ user_ids = [request.user_id]
678
+ else:
679
+ user_ids = self.storage.get_all_user_ids() # type: ignore[reportAttributeAccessIssue, reportOptionalMemberAccess]
680
+
681
+ if not user_ids:
682
+ return ManualProfileGenerationResponse(
683
+ success=True,
684
+ msg="No users found to process",
685
+ profiles_generated=0,
686
+ )
687
+
688
+ # 2. Run batch with progress tracking
689
+ request_params = {
690
+ "user_id": request.user_id,
691
+ "source": request.source,
692
+ "mode": "manual_regular",
693
+ }
694
+ users_processed, _ = self._run_batch_with_progress(
695
+ user_ids=user_ids,
696
+ request=request, # type: ignore[reportArgumentType]
697
+ request_params=request_params,
698
+ state_manager=state_manager,
699
+ )
700
+
701
+ # 3. Count generated profiles (CURRENT status = None)
702
+ total_profiles = self._count_manual_generated(request)
703
+
704
+ return ManualProfileGenerationResponse(
705
+ success=True,
706
+ msg=f"Generated {total_profiles} profiles for {users_processed} user(s)",
707
+ profiles_generated=total_profiles,
708
+ )
709
+
710
+ except Exception as e:
711
+ state_manager.mark_progress_failed(str(e))
712
+ return ManualProfileGenerationResponse(
713
+ success=False,
714
+ msg=f"Failed to run manual profile generation: {str(e)}",
715
+ profiles_generated=0,
716
+ )
717
+
718
+ def _count_manual_generated(self, request: ManualProfileGenerationRequest) -> int:
719
+ """
720
+ Count profiles generated during manual regular generation.
721
+
722
+ Counts profiles with CURRENT status (None), optionally filtered by user_id.
723
+
724
+ Args:
725
+ request: The manual generation request object
726
+
727
+ Returns:
728
+ Number of profiles with CURRENT status
729
+ """
730
+ profiles = self.storage.get_user_profile( # type: ignore[reportOptionalMemberAccess]
731
+ user_id=request.user_id, # type: ignore[reportArgumentType]
732
+ status_filter=[None], # CURRENT profiles
733
+ )
734
+ return len(profiles)