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,545 @@
1
+ import logging
2
+
3
+ logger = logging.getLogger(__name__)
4
+
5
+ from datetime import UTC, datetime
6
+
7
+ from reflexio.lib._base import (
8
+ STORAGE_NOT_CONFIGURED_MSG,
9
+ ReflexioBase,
10
+ _require_storage,
11
+ )
12
+ from reflexio.models.api_schema.retriever_schema import (
13
+ GetProfileStatisticsResponse,
14
+ GetUserProfilesRequest,
15
+ GetUserProfilesResponse,
16
+ RerankUserProfilesRequest,
17
+ RerankUserProfilesResponse,
18
+ SearchUserProfileRequest,
19
+ SearchUserProfileResponse,
20
+ StorageStatsRequest,
21
+ StorageStatsResponse,
22
+ UpdateUserProfileRequest,
23
+ UpdateUserProfileResponse,
24
+ )
25
+ from reflexio.models.api_schema.service_schemas import (
26
+ AddUserProfileRequest,
27
+ AddUserProfileResponse,
28
+ BulkDeleteResponse,
29
+ DeleteProfilesByIdsRequest,
30
+ DeleteUserProfileRequest,
31
+ DeleteUserProfileResponse,
32
+ DowngradeProfilesRequest,
33
+ DowngradeProfilesResponse,
34
+ ProfileChangeLogResponse,
35
+ Status,
36
+ UpgradeProfilesRequest,
37
+ UpgradeProfilesResponse,
38
+ )
39
+ from reflexio.server.services.profile.profile_generation_service import (
40
+ ProfileGenerationService,
41
+ )
42
+ from reflexio.server.tracing import profile_step
43
+
44
+
45
+ class ProfilesMixin(ReflexioBase):
46
+ def search_user_profiles(
47
+ self,
48
+ request: SearchUserProfileRequest | dict,
49
+ status_filter: list[Status | None] | None = None,
50
+ ) -> SearchUserProfileResponse:
51
+ """Search for user profiles.
52
+
53
+ Args:
54
+ request (SearchUserProfileRequest): The search request
55
+ status_filter (Optional[list[Optional[Status]]]): Filter profiles by status. Defaults to [None] for current profiles only.
56
+
57
+ Returns:
58
+ SearchUserProfileResponse: Response containing matching profiles
59
+ """
60
+ if not self._is_storage_configured():
61
+ return SearchUserProfileResponse(
62
+ success=True, user_profiles=[], msg=STORAGE_NOT_CONFIGURED_MSG
63
+ )
64
+ if isinstance(request, dict):
65
+ request = SearchUserProfileRequest(**request)
66
+ if status_filter is None:
67
+ status_filter = [None] # Default to current profiles
68
+ rewritten = self._reformulate_query(
69
+ request.query, enabled=bool(request.enable_reformulation)
70
+ )
71
+ if rewritten:
72
+ request = request.model_copy(update={"query": rewritten})
73
+ query_embedding = self._maybe_get_query_embedding(
74
+ request.query, request.search_mode
75
+ )
76
+ logger.info(
77
+ "search_user_profiles: query=%r, search_mode=%s, embedding_generated=%s",
78
+ request.query,
79
+ request.search_mode,
80
+ query_embedding is not None,
81
+ )
82
+ with profile_step(
83
+ "search.storage",
84
+ entity_type="profiles",
85
+ search_mode=request.search_mode,
86
+ top_k=request.top_k,
87
+ ) as span:
88
+ profiles = self._get_storage().search_user_profile(
89
+ request, status_filter=status_filter, query_embedding=query_embedding
90
+ )
91
+ span.set_data("result_count", len(profiles))
92
+ return SearchUserProfileResponse(
93
+ success=True,
94
+ user_profiles=profiles,
95
+ msg=f"Found {len(profiles)} matching profile(s)",
96
+ )
97
+
98
+ def rerank_user_profiles(
99
+ self,
100
+ request: RerankUserProfilesRequest | dict,
101
+ ) -> RerankUserProfilesResponse:
102
+ """Rerank a list of profile ids by query relevance using a cross-encoder.
103
+
104
+ Fetches each profile's full content (filtered by ``user_id``), scores
105
+ ``(query, content)`` pairs with ``cross-encoder/ms-marco-MiniLM-L-6-v2``,
106
+ and returns the top_k profiles sorted by descending score. Profile ids
107
+ that don't exist for the user are silently dropped.
108
+
109
+ Args:
110
+ request (Union[RerankUserProfilesRequest, dict]): The rerank
111
+ request — must contain ``user_id``, ``query``, and
112
+ ``profile_ids``.
113
+
114
+ Returns:
115
+ RerankUserProfilesResponse: Profiles sorted by descending
116
+ relevance score, capped at ``request.top_k``.
117
+ """
118
+ if not self._is_storage_configured():
119
+ return RerankUserProfilesResponse(
120
+ success=True, user_profiles=[], msg=STORAGE_NOT_CONFIGURED_MSG
121
+ )
122
+ if isinstance(request, dict):
123
+ request = RerankUserProfilesRequest(**request)
124
+ if not request.profile_ids:
125
+ return RerankUserProfilesResponse(
126
+ success=True, user_profiles=[], msg="No profile_ids provided"
127
+ )
128
+
129
+ # Fetch every profile for the user — including PENDING and ARCHIVED —
130
+ # because callers may want to rerank historical context, not just
131
+ # the currently-published set.
132
+ all_profiles = self._get_storage().get_user_profile(
133
+ request.user_id, status_filter=[None, Status.PENDING, Status.ARCHIVED]
134
+ )
135
+ wanted = set(request.profile_ids)
136
+ candidates = [p for p in all_profiles if p.profile_id in wanted]
137
+ dropped = len(request.profile_ids) - len(candidates)
138
+
139
+ # Lazy import keeps test collection fast; the cross-encoder pulls in
140
+ # torch + sentence-transformers on first call.
141
+ from reflexio.server.llm.rerank import score_pairs
142
+
143
+ scores = score_pairs(request.query, [p.content for p in candidates])
144
+ ranked = sorted(
145
+ zip(candidates, scores, strict=True),
146
+ key=lambda pair: pair[1],
147
+ reverse=True,
148
+ )
149
+ top = [profile for profile, _score in ranked[: request.top_k]]
150
+ msg = f"Reranked {len(candidates)} profile(s); dropped {dropped} unknown id(s)"
151
+ return RerankUserProfilesResponse(success=True, user_profiles=top, msg=msg)
152
+
153
+ def storage_stats(
154
+ self,
155
+ request: StorageStatsRequest | dict,
156
+ ) -> StorageStatsResponse:
157
+ """Return lightweight metadata about a user's stored profiles + playbooks.
158
+
159
+ Provides counts and the last-modified timestamp range across every
160
+ status, suitable for sizing ``top_k`` before retrieval.
161
+
162
+ Args:
163
+ request (Union[StorageStatsRequest, dict]): The stats request —
164
+ must contain ``user_id``.
165
+
166
+ Returns:
167
+ StorageStatsResponse: Counts and timestamp range for the user.
168
+ """
169
+ if not self._is_storage_configured():
170
+ return StorageStatsResponse(
171
+ success=True,
172
+ profile_count=0,
173
+ playbook_count=0,
174
+ msg=STORAGE_NOT_CONFIGURED_MSG,
175
+ )
176
+ if isinstance(request, dict):
177
+ request = StorageStatsRequest(**request)
178
+ storage = self._get_storage()
179
+ # Walk every status — agent callers care about total surface area,
180
+ # not just CURRENT entries.
181
+ all_statuses: list[Status | None] = [None, Status.PENDING, Status.ARCHIVED]
182
+ profiles = storage.get_user_profile(request.user_id, status_filter=all_statuses)
183
+ oldest_ts: datetime | None = None
184
+ newest_ts: datetime | None = None
185
+ if profiles:
186
+ timestamps = [p.last_modified_timestamp for p in profiles]
187
+ oldest_ts = datetime.fromtimestamp(min(timestamps), tz=UTC)
188
+ newest_ts = datetime.fromtimestamp(max(timestamps), tz=UTC)
189
+ playbook_count = storage.count_user_playbooks(
190
+ user_id=request.user_id, status_filter=all_statuses
191
+ )
192
+ return StorageStatsResponse(
193
+ success=True,
194
+ profile_count=len(profiles),
195
+ playbook_count=playbook_count,
196
+ oldest_profile_modified=oldest_ts,
197
+ newest_profile_modified=newest_ts,
198
+ msg=f"Found {len(profiles)} profile(s) and {playbook_count} playbook(s)",
199
+ )
200
+
201
+ def get_profile_change_logs(self) -> ProfileChangeLogResponse:
202
+ """Get profile change logs.
203
+
204
+ Returns:
205
+ ProfileChangeLogResponse: Response containing profile change logs
206
+ """
207
+ if not self._is_storage_configured():
208
+ return ProfileChangeLogResponse(success=True, profile_change_logs=[])
209
+ changelogs = self._get_storage().get_profile_change_logs()
210
+ return ProfileChangeLogResponse(success=True, profile_change_logs=changelogs)
211
+
212
+ @_require_storage(DeleteUserProfileResponse)
213
+ def delete_profile(
214
+ self,
215
+ request: DeleteUserProfileRequest | dict,
216
+ ) -> DeleteUserProfileResponse:
217
+ """Delete user profiles.
218
+
219
+ Args:
220
+ request (DeleteUserProfileRequest): The delete request
221
+
222
+ Returns:
223
+ DeleteUserProfileResponse: Response containing success status and message
224
+ """
225
+ if isinstance(request, dict):
226
+ request = DeleteUserProfileRequest(**request)
227
+ self._get_storage().delete_user_profile(request)
228
+ return DeleteUserProfileResponse(success=True, message="Deleted successfully")
229
+
230
+ @_require_storage(UpdateUserProfileResponse, msg_field="msg")
231
+ def update_user_profile(
232
+ self,
233
+ request: UpdateUserProfileRequest | dict,
234
+ ) -> UpdateUserProfileResponse:
235
+ """Apply a partial update to an existing user profile.
236
+
237
+ Fetches the current profile by ``(user_id, profile_id)``, applies the
238
+ non-None fields from ``request``, refreshes ``last_modified_timestamp``,
239
+ and persists the whole record via
240
+ :meth:`BaseStorage.update_user_profile_by_id`. The storage layer
241
+ regenerates the embedding for the updated content.
242
+
243
+ Args:
244
+ request (Union[UpdateUserProfileRequest, dict]): The update request.
245
+ ``user_id`` and ``profile_id`` are required; ``content`` and
246
+ ``custom_features`` are optional — only non-None fields are
247
+ applied.
248
+
249
+ Returns:
250
+ UpdateUserProfileResponse: ``success=True`` when the profile was
251
+ updated, ``success=False`` with a descriptive ``msg`` when it
252
+ could not be found.
253
+ """
254
+ if isinstance(request, dict):
255
+ request = UpdateUserProfileRequest(**request)
256
+ storage = self._get_storage()
257
+ profiles = storage.get_user_profile(request.user_id)
258
+ existing = next(
259
+ (p for p in profiles if p.profile_id == request.profile_id), None
260
+ )
261
+ if existing is None:
262
+ return UpdateUserProfileResponse(
263
+ success=False,
264
+ msg=(
265
+ f"Profile not found: user_id={request.user_id!r} "
266
+ f"profile_id={request.profile_id!r}"
267
+ ),
268
+ )
269
+ if request.content is not None:
270
+ existing.content = request.content
271
+ if request.custom_features is not None:
272
+ existing.custom_features = request.custom_features
273
+ existing.last_modified_timestamp = int(datetime.now(UTC).timestamp())
274
+ storage.update_user_profile_by_id(request.user_id, request.profile_id, existing)
275
+ return UpdateUserProfileResponse(
276
+ success=True, msg="User profile updated successfully"
277
+ )
278
+
279
+ @_require_storage(BulkDeleteResponse)
280
+ def delete_all_profiles_bulk(self) -> BulkDeleteResponse:
281
+ """Delete all profiles.
282
+
283
+ Returns:
284
+ BulkDeleteResponse: Response containing success status and deleted count
285
+ """
286
+ self._get_storage().delete_all_profiles()
287
+ return BulkDeleteResponse(success=True, message="Deleted successfully")
288
+
289
+ @_require_storage(BulkDeleteResponse)
290
+ def delete_profiles_by_ids(
291
+ self,
292
+ request: DeleteProfilesByIdsRequest | dict,
293
+ ) -> BulkDeleteResponse:
294
+ """Delete profiles by their IDs.
295
+
296
+ Args:
297
+ request (DeleteProfilesByIdsRequest): The delete request containing profile_ids
298
+
299
+ Returns:
300
+ BulkDeleteResponse: Response containing success status and deleted count
301
+ """
302
+ if isinstance(request, dict):
303
+ request = DeleteProfilesByIdsRequest(**request)
304
+ deleted = self._get_storage().delete_profiles_by_ids(request.profile_ids)
305
+ return BulkDeleteResponse(
306
+ success=True, deleted_count=deleted, message=f"Deleted {deleted} item(s)"
307
+ )
308
+
309
+ def add_user_profile(
310
+ self,
311
+ request: AddUserProfileRequest | dict,
312
+ ) -> AddUserProfileResponse:
313
+ """Add user profiles directly to storage, bypassing inference.
314
+
315
+ Mirrors :meth:`add_user_playbook` — useful for seeding a known
316
+ fact about a user (testing, migration, manual fact injection)
317
+ without going through the interaction-based generation pipeline.
318
+ The storage layer's ``add_user_profile`` populates the embedding
319
+ automatically.
320
+
321
+ Args:
322
+ request (Union[AddUserProfileRequest, dict]): The add
323
+ request containing user profiles. Profiles must each
324
+ have a non-empty ``content`` field.
325
+
326
+ Returns:
327
+ AddUserProfileResponse: Response containing success status,
328
+ message, and count of profiles added.
329
+ """
330
+ if not self._is_storage_configured():
331
+ return AddUserProfileResponse(
332
+ success=False, message=STORAGE_NOT_CONFIGURED_MSG
333
+ )
334
+ if isinstance(request, dict):
335
+ request = AddUserProfileRequest(**request)
336
+
337
+ # Group by user_id since storage.add_user_profile takes
338
+ # (user_id, list[UserProfile]) and we want one storage call
339
+ # per user.
340
+ by_user: dict[str, list] = {}
341
+ for p in request.user_profiles:
342
+ by_user.setdefault(p.user_id, []).append(p)
343
+
344
+ # Per-user try/except so we can surface partial-success in
345
+ # the response message instead of silently losing track of
346
+ # which users were persisted before a later failure.
347
+ persisted_profiles = 0
348
+ for persisted_users, (user_id, profiles) in enumerate(by_user.items()):
349
+ try:
350
+ self._get_storage().add_user_profile(user_id, profiles)
351
+ except Exception:
352
+ # Log the full exception for operators (storage errors
353
+ # may contain SQL text, file paths, table names); return
354
+ # a generic message to the caller to avoid information
355
+ # disclosure over HTTP.
356
+ logger.exception("add_user_profile failed for user_id=%s", user_id)
357
+ if persisted_users == 0:
358
+ message = "Failed to add user profile"
359
+ else:
360
+ message = (
361
+ f"Partially persisted {persisted_profiles} profile(s) "
362
+ f"for {persisted_users} user(s) before failing on "
363
+ f"user {user_id}"
364
+ )
365
+ return AddUserProfileResponse(success=False, message=message)
366
+ persisted_profiles += len(profiles)
367
+
368
+ return AddUserProfileResponse(
369
+ success=True,
370
+ added_count=persisted_profiles,
371
+ message=f"Added {persisted_profiles} profile(s)",
372
+ )
373
+
374
+ def get_profiles(
375
+ self,
376
+ request: GetUserProfilesRequest | dict,
377
+ status_filter: list[Status | None] | None = None,
378
+ ) -> GetUserProfilesResponse:
379
+ """Get user profiles.
380
+
381
+ Args:
382
+ request (GetUserProfilesRequest): The get request
383
+ status_filter (Optional[list[Optional[Status]]]): Filter profiles by status. Defaults to [None] for current profiles only.
384
+ If provided, takes precedence over request.status_filter.
385
+
386
+ Returns:
387
+ GetUserProfilesResponse: Response containing user profiles
388
+ """
389
+ if not self._is_storage_configured():
390
+ return GetUserProfilesResponse(
391
+ success=True, user_profiles=[], msg=STORAGE_NOT_CONFIGURED_MSG
392
+ )
393
+ if isinstance(request, dict):
394
+ request = GetUserProfilesRequest(**request)
395
+
396
+ # Priority: parameter > request.status_filter > default [None]
397
+ if status_filter is None:
398
+ if hasattr(request, "status_filter") and request.status_filter is not None:
399
+ status_filter = request.status_filter
400
+ else:
401
+ status_filter = [None] # Default to current profiles
402
+
403
+ profiles = self._get_storage().get_user_profile(
404
+ request.user_id, status_filter=status_filter
405
+ )
406
+ profiles = sorted(
407
+ profiles, key=lambda x: x.last_modified_timestamp, reverse=True
408
+ )
409
+
410
+ # Apply time filters
411
+ if request.start_time:
412
+ profiles = [
413
+ p
414
+ for p in profiles
415
+ if p.last_modified_timestamp >= int(request.start_time.timestamp())
416
+ ]
417
+ if request.end_time:
418
+ profiles = [
419
+ p
420
+ for p in profiles
421
+ if p.last_modified_timestamp <= int(request.end_time.timestamp())
422
+ ]
423
+
424
+ # Apply top_k limit
425
+ if request.top_k:
426
+ profiles = sorted(
427
+ profiles, key=lambda x: x.last_modified_timestamp, reverse=True
428
+ )[: request.top_k]
429
+
430
+ return GetUserProfilesResponse(
431
+ success=True,
432
+ user_profiles=profiles,
433
+ msg=f"Found {len(profiles)} profile(s)",
434
+ )
435
+
436
+ def get_all_profiles(
437
+ self,
438
+ limit: int = 100,
439
+ status_filter: list[Status | None] | None = None,
440
+ ) -> GetUserProfilesResponse:
441
+ """Get all user profiles across all users.
442
+
443
+ Args:
444
+ limit (int, optional): Maximum number of profiles to return. Defaults to 100.
445
+ status_filter (Optional[list[Optional[Status]]]): Filter profiles by status. Defaults to [None] for current profiles only.
446
+
447
+ Returns:
448
+ GetUserProfilesResponse: Response containing all user profiles
449
+ """
450
+ if not self._is_storage_configured():
451
+ return GetUserProfilesResponse(
452
+ success=True, user_profiles=[], msg=STORAGE_NOT_CONFIGURED_MSG
453
+ )
454
+ if status_filter is None:
455
+ status_filter = [None] # Default to current profiles
456
+ profiles = self._get_storage().get_all_profiles(
457
+ limit=limit, status_filter=status_filter
458
+ )
459
+ profiles = sorted(
460
+ profiles, key=lambda x: x.last_modified_timestamp, reverse=True
461
+ )
462
+ return GetUserProfilesResponse(
463
+ success=True,
464
+ user_profiles=profiles,
465
+ msg=f"Found {len(profiles)} profile(s)",
466
+ )
467
+
468
+ def upgrade_all_profiles(
469
+ self,
470
+ request: UpgradeProfilesRequest | dict | None = None,
471
+ ) -> UpgradeProfilesResponse:
472
+ """Upgrade all profiles by deleting old ARCHIVED, archiving CURRENT, and promoting PENDING.
473
+
474
+ Args:
475
+ request (Union[UpgradeProfilesRequest, dict], optional): The upgrade request
476
+
477
+ Returns:
478
+ UpgradeProfilesResponse: Response containing success status and counts
479
+ """
480
+ if not self._is_storage_configured():
481
+ return UpgradeProfilesResponse(
482
+ success=False, message=STORAGE_NOT_CONFIGURED_MSG
483
+ )
484
+ if isinstance(request, dict):
485
+ request = UpgradeProfilesRequest(**request)
486
+ elif request is None:
487
+ request = UpgradeProfilesRequest(user_id=None, only_affected_users=False)
488
+
489
+ service = ProfileGenerationService(
490
+ llm_client=self.llm_client,
491
+ request_context=self.request_context,
492
+ )
493
+ return service.run_upgrade(request) # type: ignore[reportArgumentType]
494
+
495
+ def downgrade_all_profiles(
496
+ self,
497
+ request: DowngradeProfilesRequest | dict | None = None,
498
+ ) -> DowngradeProfilesResponse:
499
+ """Downgrade all profiles by archiving CURRENT and restoring ARCHIVED.
500
+
501
+ Args:
502
+ request (Union[DowngradeProfilesRequest, dict], optional): The downgrade request
503
+
504
+ Returns:
505
+ DowngradeProfilesResponse: Response containing success status and counts
506
+ """
507
+ if not self._is_storage_configured():
508
+ return DowngradeProfilesResponse(
509
+ success=False, message=STORAGE_NOT_CONFIGURED_MSG
510
+ )
511
+ if isinstance(request, dict):
512
+ request = DowngradeProfilesRequest(**request)
513
+ elif request is None:
514
+ request = DowngradeProfilesRequest(user_id=None, only_affected_users=False)
515
+
516
+ service = ProfileGenerationService(
517
+ llm_client=self.llm_client,
518
+ request_context=self.request_context,
519
+ )
520
+ return service.run_downgrade(request) # type: ignore[reportArgumentType]
521
+
522
+ def get_profile_statistics(self) -> GetProfileStatisticsResponse:
523
+ """Get profile count statistics by status.
524
+
525
+ Returns:
526
+ GetProfileStatisticsResponse: Response containing profile counts
527
+ """
528
+ if not self._is_storage_configured():
529
+ return GetProfileStatisticsResponse(
530
+ success=True,
531
+ current_count=0,
532
+ pending_count=0,
533
+ archived_count=0,
534
+ expiring_soon_count=0,
535
+ msg=STORAGE_NOT_CONFIGURED_MSG,
536
+ )
537
+ try:
538
+ stats = self._get_storage().get_profile_statistics()
539
+ return GetProfileStatisticsResponse(
540
+ success=True, msg="Retrieved profile statistics successfully", **stats
541
+ )
542
+ except Exception as e:
543
+ return GetProfileStatisticsResponse(
544
+ success=False, msg=f"Failed to get profile statistics: {str(e)}"
545
+ )
@@ -0,0 +1,52 @@
1
+ """Reflection mixin: post-publish critique-and-revise of cited memories."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from reflexio.lib._base import STORAGE_NOT_CONFIGURED_MSG, ReflexioBase
6
+ from reflexio.server.services.reflection.reflection_service_utils import (
7
+ ReflectionResult,
8
+ ReflectionServiceRequest,
9
+ )
10
+
11
+
12
+ class ReflectionMixin(ReflexioBase):
13
+ """Expose ``run_reflection`` on the Reflexio facade."""
14
+
15
+ def run_reflection(
16
+ self,
17
+ request: ReflectionServiceRequest | dict,
18
+ ) -> ReflectionResult:
19
+ """Run one reflection pass for the given request.
20
+
21
+ Best-effort: returns a ``ReflectionResult`` describing what
22
+ happened. Storage must be configured; raises otherwise so the
23
+ caller (the publish-time hook) can swallow it via its own
24
+ ``try/except`` wrapper.
25
+
26
+ Args:
27
+ request (ReflectionServiceRequest | dict): The reflection
28
+ request. Dicts are coerced.
29
+
30
+ Returns:
31
+ ReflectionResult: Counts of cited / considered / replaced /
32
+ skipped / failed decisions for logging and tests.
33
+
34
+ Raises:
35
+ ValueError: If storage is not configured.
36
+ """
37
+ if not self._is_storage_configured():
38
+ raise ValueError(STORAGE_NOT_CONFIGURED_MSG)
39
+ if isinstance(request, dict):
40
+ request = ReflectionServiceRequest(**request)
41
+
42
+ # Local import keeps the heavy service module out of facade
43
+ # cold-start when reflection is disabled.
44
+ from reflexio.server.services.reflection.reflection_service import (
45
+ ReflectionService,
46
+ )
47
+
48
+ service = ReflectionService(
49
+ request_context=self.request_context,
50
+ llm_client=self.llm_client,
51
+ )
52
+ return service.run(request)