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,737 @@
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",
202
+ user_id,
203
+ )
204
+ return
205
+
206
+ # Delete superseded existing profiles
207
+ if existing_ids_to_delete:
208
+ for profile_id in existing_ids_to_delete:
209
+ try:
210
+ self.storage.delete_user_profile( # type: ignore[reportOptionalMemberAccess]
211
+ DeleteUserProfileRequest(
212
+ user_id=user_id,
213
+ profile_id=profile_id,
214
+ )
215
+ )
216
+ except Exception as e: # noqa: PERF203
217
+ with sentry_tags(
218
+ subsystem="profile_generation",
219
+ op="delete_superseded_profile",
220
+ org_id=self.org_id,
221
+ user_id=user_id,
222
+ request_id=request_id,
223
+ profile_id=profile_id,
224
+ error_type=type(e).__name__,
225
+ ):
226
+ logger.exception(
227
+ "Failed to delete superseded profile %s for user %s",
228
+ profile_id,
229
+ user_id,
230
+ )
231
+
232
+ # Create profile changelog post-deduplication
233
+ if all_new_profiles or superseded_profiles:
234
+ try:
235
+ profile_change_log = ProfileChangeLog(
236
+ id=0, # Auto-generated by storage
237
+ user_id=user_id,
238
+ request_id=request_id,
239
+ created_at=int(datetime.now(UTC).timestamp()),
240
+ added_profiles=all_new_profiles,
241
+ removed_profiles=superseded_profiles,
242
+ mentioned_profiles=[],
243
+ )
244
+ self.storage.add_profile_change_log(profile_change_log) # type: ignore[reportOptionalMemberAccess]
245
+ except Exception as e:
246
+ with sentry_tags(
247
+ subsystem="profile_generation",
248
+ op="add_profile_change_log",
249
+ org_id=self.org_id,
250
+ user_id=user_id,
251
+ request_id=request_id,
252
+ error_type=type(e).__name__,
253
+ ):
254
+ logger.exception(
255
+ "Failed to add profile change log for user %s",
256
+ user_id,
257
+ )
258
+
259
+ def check_and_update_profiles(self, profiles: list[UserProfile]) -> None:
260
+ """check if the profiles are expired and update them if they are"""
261
+ raise NotImplementedError
262
+
263
+ def _load_extractor_config(self) -> ProfileExtractorConfig | None:
264
+ """
265
+ Load the configured profile extractor from configurator.
266
+
267
+ Returns:
268
+ ProfileExtractorConfig | None: The configured profile extractor, if enabled.
269
+ """
270
+ root_config = self.configurator.get_config()
271
+ return getattr(root_config, "profile_extractor_config", None)
272
+
273
+ def _create_extractor(
274
+ self,
275
+ extractor_config: ProfileExtractorConfig,
276
+ service_config: ProfileGenerationServiceConfig,
277
+ ) -> ProfileExtractor:
278
+ """
279
+ Create a ProfileExtractor instance from configuration.
280
+
281
+ Args:
282
+ extractor_config: ProfileExtractorConfig configuration object from YAML
283
+ service_config: ProfileGenerationServiceConfig containing runtime parameters
284
+
285
+ Returns:
286
+ ProfileExtractor instance
287
+ """
288
+ return ProfileExtractor(
289
+ request_context=self.request_context,
290
+ llm_client=self.client,
291
+ extractor_config=extractor_config,
292
+ service_config=service_config,
293
+ agent_context=self.configurator.get_agent_context(),
294
+ )
295
+
296
+ def _build_should_run_prompt(
297
+ self,
298
+ scoped_config: ProfileExtractorConfig,
299
+ session_data_models: list[RequestInteractionDataModel],
300
+ ) -> str | None:
301
+ """
302
+ Build prompt for consolidated should_extract_profile check.
303
+
304
+ Renders the configured extractor's profile definition and override
305
+ condition for one LLM call.
306
+
307
+ Args:
308
+ scoped_config: Profile extractor config that had scoped interactions
309
+ session_data_models: Deduplicated request interaction data models
310
+
311
+ Returns:
312
+ str | None: The rendered prompt, or None if no criteria to check
313
+ """
314
+ new_interactions = format_sessions_to_history_string(session_data_models)
315
+ agent_context = self.configurator.get_agent_context()
316
+ prompt_manager = self.request_context.prompt_manager
317
+
318
+ criteria_parts = []
319
+ if scoped_config.extraction_definition_prompt:
320
+ criteria_parts.append(
321
+ f"definition: {scoped_config.extraction_definition_prompt.strip()}"
322
+ )
323
+ if scoped_config.should_extract_profile_prompt_override:
324
+ criteria_parts.append(
325
+ "condition: "
326
+ f"{scoped_config.should_extract_profile_prompt_override.strip()}"
327
+ )
328
+
329
+ combined_criteria = "; ".join(criteria_parts)
330
+ if not combined_criteria:
331
+ return None
332
+
333
+ return prompt_manager.render_prompt(
334
+ ProfileGenerationServiceConstants.PROFILE_SHOULD_GENERATE_PROMPT_ID,
335
+ {
336
+ "agent_context_prompt": agent_context,
337
+ "should_extract_profile_prompt": combined_criteria,
338
+ "new_interactions": new_interactions,
339
+ },
340
+ )
341
+
342
+ def _get_extractor_state_service_name(self) -> str:
343
+ """
344
+ Get the service name for stride_size bookmark lookups.
345
+
346
+ Returns:
347
+ str: "profile_extractor" for OperationStateManager stride_size checks
348
+ """
349
+ return "profile_extractor"
350
+
351
+ def _get_service_name(self) -> str:
352
+ """
353
+ Get the name of the service for logging and operation state tracking.
354
+
355
+ Returns:
356
+ Service name string - "rerun_profile_generation" for rerun operations,
357
+ "profile_generation" for regular operations
358
+ """
359
+ if self.output_pending_status:
360
+ return "rerun_profile_generation"
361
+ return "profile_generation"
362
+
363
+ def _get_base_service_name(self) -> str:
364
+ """
365
+ Get the base service name for OperationStateManager keys.
366
+
367
+ Returns:
368
+ str: "profile_generation"
369
+ """
370
+ return "profile_generation"
371
+
372
+ def _should_track_in_progress(self) -> bool:
373
+ """
374
+ Profile generation should track in-progress state to prevent duplicates.
375
+
376
+ Returns:
377
+ bool: True - profile generation tracks in-progress state
378
+ """
379
+ return True
380
+
381
+ def _get_lock_scope_id(self, request: ProfileGenerationRequest) -> str | None:
382
+ """
383
+ Get the scope ID for lock key construction.
384
+
385
+ Profile generation is user-scoped, so returns user_id.
386
+
387
+ Args:
388
+ request: The ProfileGenerationRequest
389
+
390
+ Returns:
391
+ str: The user_id from the request
392
+ """
393
+ return request.user_id
394
+
395
+ # ===============================
396
+ # Rerun hook implementations (override base class methods)
397
+ # ===============================
398
+
399
+ def _get_rerun_user_ids(self, request: RerunProfileGenerationRequest) -> list[str]:
400
+ """Get user IDs to process. Extractors collect their own data.
401
+
402
+ Identifies unique user_ids with matching requests via storage-level filtering.
403
+
404
+ Args:
405
+ request: RerunProfileGenerationRequest with optional filters
406
+
407
+ Returns:
408
+ List of user IDs to process
409
+ """
410
+ return self.storage.get_rerun_user_ids( # type: ignore[reportOptionalMemberAccess]
411
+ user_id=request.user_id,
412
+ start_time=(
413
+ int(request.start_time.timestamp()) if request.start_time else None
414
+ ),
415
+ end_time=(int(request.end_time.timestamp()) if request.end_time else None),
416
+ source=request.source,
417
+ )
418
+
419
+ def _build_rerun_request_params(
420
+ self, request: RerunProfileGenerationRequest
421
+ ) -> dict:
422
+ """Build request params dict for operation state tracking.
423
+
424
+ Args:
425
+ request: Original rerun request
426
+
427
+ Returns:
428
+ Dictionary of request parameters
429
+ """
430
+ return {
431
+ "user_id": request.user_id,
432
+ "start_time": (
433
+ request.start_time.isoformat() if request.start_time else None
434
+ ),
435
+ "end_time": request.end_time.isoformat() if request.end_time else None,
436
+ "source": request.source,
437
+ }
438
+
439
+ def _create_run_request_for_item(
440
+ self,
441
+ user_id: str,
442
+ request: RerunProfileGenerationRequest | ManualProfileGenerationRequest,
443
+ ) -> ProfileGenerationRequest:
444
+ """Create ProfileGenerationRequest for a single user.
445
+
446
+ Handles both rerun and manual request types.
447
+
448
+ Args:
449
+ user_id: The user ID to process
450
+ request: The original rerun or manual request
451
+
452
+ Returns:
453
+ ProfileGenerationRequest for this user with filter constraints
454
+ """
455
+ # Handle rerun requests (have start_time/end_time datetime objects)
456
+ if isinstance(request, RerunProfileGenerationRequest):
457
+ return ProfileGenerationRequest(
458
+ user_id=user_id,
459
+ request_id=f"rerun_{uuid.uuid4().hex[:8]}",
460
+ source=request.source,
461
+ rerun_start_time=(
462
+ int(request.start_time.timestamp()) if request.start_time else None
463
+ ),
464
+ rerun_end_time=(
465
+ int(request.end_time.timestamp()) if request.end_time else None
466
+ ),
467
+ auto_run=False,
468
+ )
469
+ # Handle manual requests (ManualProfileGenerationRequest)
470
+ return ProfileGenerationRequest(
471
+ user_id=user_id,
472
+ request_id=f"manual_{uuid.uuid4().hex[:8]}",
473
+ source=request.source,
474
+ auto_run=False,
475
+ )
476
+
477
+ def _create_rerun_response(
478
+ self, success: bool, msg: str, count: int
479
+ ) -> RerunProfileGenerationResponse:
480
+ """Create RerunProfileGenerationResponse.
481
+
482
+ Args:
483
+ success: Whether the operation succeeded
484
+ msg: Status message
485
+ count: Number of profiles generated
486
+
487
+ Returns:
488
+ RerunProfileGenerationResponse
489
+ """
490
+ return RerunProfileGenerationResponse(
491
+ success=success,
492
+ msg=msg,
493
+ profiles_generated=count,
494
+ )
495
+
496
+ def _get_generated_count(
497
+ self,
498
+ request: RerunProfileGenerationRequest,
499
+ processed_user_ids: list[str] | None = None,
500
+ ) -> int:
501
+ """Get the count of profiles generated during rerun.
502
+
503
+ Counts profiles with PENDING status for each processed user.
504
+
505
+ Args:
506
+ request: The rerun request object
507
+ processed_user_ids: List of user IDs processed in the batch
508
+
509
+ Returns:
510
+ Number of profiles generated
511
+ """
512
+ user_ids = processed_user_ids or ([request.user_id] if request.user_id else [])
513
+ total = 0
514
+ for user_id in user_ids:
515
+ profiles = self.storage.get_user_profile( # type: ignore[reportOptionalMemberAccess]
516
+ user_id=user_id,
517
+ status_filter=[Status.PENDING],
518
+ )
519
+ total += len(profiles)
520
+ return total
521
+
522
+ # ===============================
523
+ # Upgrade/Downgrade hook implementations (override base class methods)
524
+ # ===============================
525
+
526
+ def _has_items_with_status(
527
+ self,
528
+ status: Status | None,
529
+ request: ProfileGenerationRequest, # noqa: ARG002
530
+ ) -> bool:
531
+ """Check if profiles exist with given status.
532
+
533
+ Args:
534
+ status: The status to check for (None for CURRENT)
535
+ request: The upgrade/downgrade request object
536
+
537
+ Returns:
538
+ bool: True if any matching profiles exist
539
+ """
540
+ user_ids = self.storage.get_user_ids_with_status(status=status) # type: ignore[reportOptionalMemberAccess]
541
+ return bool(user_ids)
542
+
543
+ def _delete_items_by_status(
544
+ self,
545
+ status: Status,
546
+ request: ProfileGenerationRequest, # noqa: ARG002
547
+ ) -> int:
548
+ """Delete profiles with given status.
549
+
550
+ Args:
551
+ status: The status of profiles to delete
552
+ request: The upgrade/downgrade request object
553
+
554
+ Returns:
555
+ int: Number of profiles deleted
556
+ """
557
+ return self.storage.delete_all_profiles_by_status(status=status) # type: ignore[reportOptionalMemberAccess]
558
+
559
+ def _update_items_status(
560
+ self,
561
+ old_status: Status | None,
562
+ new_status: Status | None,
563
+ request: ProfileGenerationRequest, # noqa: ARG002
564
+ user_ids: list[str] | None = None, # noqa: ARG002
565
+ ) -> int:
566
+ """Update profiles from old_status to new_status.
567
+
568
+ Args:
569
+ old_status: The current status to match (None for CURRENT)
570
+ new_status: The new status to set (None for CURRENT)
571
+ request: The upgrade/downgrade request object
572
+ user_ids: Optional pre-computed list of user IDs to filter by
573
+
574
+ Returns:
575
+ int: Number of profiles updated
576
+ """
577
+ return self.storage.update_all_profiles_status( # type: ignore[reportOptionalMemberAccess]
578
+ old_status, new_status, user_ids=user_ids
579
+ )
580
+
581
+ def _get_affected_user_ids_for_upgrade(
582
+ self, request: ProfileGenerationRequest
583
+ ) -> list[str] | None:
584
+ """Get user IDs to filter by for upgrade operations.
585
+
586
+ Args:
587
+ request: The upgrade request object
588
+
589
+ Returns:
590
+ Optional[list[str]]: List of user IDs with PENDING profiles, or None for no filtering
591
+ """
592
+ if hasattr(request, "only_affected_users") and request.only_affected_users: # type: ignore[reportAttributeAccessIssue]
593
+ return self.storage.get_user_ids_with_status(Status.PENDING) # type: ignore[reportOptionalMemberAccess]
594
+ return None
595
+
596
+ def _get_affected_user_ids_for_downgrade(
597
+ self, request: ProfileGenerationRequest
598
+ ) -> list[str] | None:
599
+ """Get user IDs to filter by for downgrade operations.
600
+
601
+ Args:
602
+ request: The downgrade request object
603
+
604
+ Returns:
605
+ Optional[list[str]]: List of user IDs with ARCHIVED profiles, or None for no filtering
606
+ """
607
+ if hasattr(request, "only_affected_users") and request.only_affected_users: # type: ignore[reportAttributeAccessIssue]
608
+ return self.storage.get_user_ids_with_status(Status.ARCHIVED) # type: ignore[reportOptionalMemberAccess]
609
+ return None
610
+
611
+ def _create_status_change_response(
612
+ self,
613
+ operation: StatusChangeOperation,
614
+ success: bool,
615
+ counts: dict,
616
+ msg: str,
617
+ ) -> UpgradeProfilesResponse | DowngradeProfilesResponse:
618
+ """Create upgrade or downgrade response object for profiles.
619
+
620
+ Args:
621
+ operation: The operation type (UPGRADE or DOWNGRADE)
622
+ success: Whether the operation succeeded
623
+ counts: Dictionary of counts
624
+ msg: Status message
625
+
626
+ Returns:
627
+ UpgradeProfilesResponse or DowngradeProfilesResponse
628
+ """
629
+ if operation == StatusChangeOperation.UPGRADE:
630
+ return UpgradeProfilesResponse(
631
+ success=success,
632
+ profiles_deleted=counts.get("deleted", 0),
633
+ profiles_archived=counts.get("archived", 0),
634
+ profiles_promoted=counts.get("promoted", 0),
635
+ message=msg,
636
+ )
637
+ # DOWNGRADE
638
+ return DowngradeProfilesResponse(
639
+ success=success,
640
+ profiles_demoted=counts.get("demoted", 0),
641
+ profiles_restored=counts.get("restored", 0),
642
+ message=msg,
643
+ )
644
+
645
+ # ===============================
646
+ # Manual Regular Generation (window-sized, CURRENT output)
647
+ # ===============================
648
+
649
+ def run_manual_regular(
650
+ self, request: ManualProfileGenerationRequest
651
+ ) -> ManualProfileGenerationResponse:
652
+ """
653
+ Run profile generation with window-sized interactions and CURRENT output.
654
+
655
+ This is a manual trigger that behaves like regular generation
656
+ (uses window_size, outputs CURRENT profiles) but only runs
657
+ profile extraction (not feedback or agent success).
658
+
659
+ Each extractor collects its own data using its configured window_size.
660
+ Uses progress tracking via OperationStateManager.
661
+
662
+ Args:
663
+ request: ManualProfileGenerationRequest with optional user_id, source, and extractor_names
664
+
665
+ Returns:
666
+ ManualProfileGenerationResponse with success status and count
667
+ """
668
+ state_manager = self._create_state_manager()
669
+
670
+ try:
671
+ # Check for existing in-progress operation
672
+ error = state_manager.check_in_progress()
673
+ if error:
674
+ return ManualProfileGenerationResponse(
675
+ success=False, msg=error, profiles_generated=0
676
+ )
677
+
678
+ # 1. Get users to process
679
+ if request.user_id:
680
+ user_ids = [request.user_id]
681
+ else:
682
+ user_ids = self.storage.get_all_user_ids() # type: ignore[reportAttributeAccessIssue, reportOptionalMemberAccess]
683
+
684
+ if not user_ids:
685
+ return ManualProfileGenerationResponse(
686
+ success=True,
687
+ msg="No users found to process",
688
+ profiles_generated=0,
689
+ )
690
+
691
+ # 2. Run batch with progress tracking
692
+ request_params = {
693
+ "user_id": request.user_id,
694
+ "source": request.source,
695
+ "mode": "manual_regular",
696
+ }
697
+ users_processed, _ = self._run_batch_with_progress(
698
+ user_ids=user_ids,
699
+ request=request, # type: ignore[reportArgumentType]
700
+ request_params=request_params,
701
+ state_manager=state_manager,
702
+ )
703
+
704
+ # 3. Count generated profiles (CURRENT status = None)
705
+ total_profiles = self._count_manual_generated(request)
706
+
707
+ return ManualProfileGenerationResponse(
708
+ success=True,
709
+ msg=f"Generated {total_profiles} profiles for {users_processed} user(s)",
710
+ profiles_generated=total_profiles,
711
+ )
712
+
713
+ except Exception as e:
714
+ state_manager.mark_progress_failed(str(e))
715
+ return ManualProfileGenerationResponse(
716
+ success=False,
717
+ msg=f"Failed to run manual profile generation: {str(e)}",
718
+ profiles_generated=0,
719
+ )
720
+
721
+ def _count_manual_generated(self, request: ManualProfileGenerationRequest) -> int:
722
+ """
723
+ Count profiles generated during manual regular generation.
724
+
725
+ Counts profiles with CURRENT status (None), optionally filtered by user_id.
726
+
727
+ Args:
728
+ request: The manual generation request object
729
+
730
+ Returns:
731
+ Number of profiles with CURRENT status
732
+ """
733
+ profiles = self.storage.get_user_profile( # type: ignore[reportOptionalMemberAccess]
734
+ user_id=request.user_id, # type: ignore[reportArgumentType]
735
+ status_filter=[None], # CURRENT profiles
736
+ )
737
+ return len(profiles)