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,808 @@
1
+ from __future__ import annotations
2
+
3
+ import logging
4
+ import uuid
5
+ from dataclasses import dataclass
6
+ from typing import TYPE_CHECKING
7
+
8
+ if TYPE_CHECKING:
9
+ from reflexio.server.api_endpoints.request_context import RequestContext
10
+ from reflexio.server.llm.litellm_client import LiteLLMClient
11
+
12
+ from reflexio.models.api_schema.internal_schema import RequestInteractionDataModel
13
+ from reflexio.models.api_schema.service_schemas import (
14
+ DowngradeUserPlaybooksResponse,
15
+ ManualPlaybookGenerationRequest,
16
+ ManualPlaybookGenerationResponse,
17
+ RerunPlaybookGenerationRequest,
18
+ RerunPlaybookGenerationResponse,
19
+ Status,
20
+ UpgradeUserPlaybooksResponse,
21
+ UserPlaybook,
22
+ )
23
+ from reflexio.models.config_schema import PlaybookConfig
24
+ from reflexio.server.operation_limiter import run_with_operation_limit
25
+ from reflexio.server.services.base_generation_service import (
26
+ BaseGenerationService,
27
+ StatusChangeOperation,
28
+ )
29
+ from reflexio.server.services.playbook.playbook_aggregator import PlaybookAggregator
30
+ from reflexio.server.services.playbook.playbook_extractor import PlaybookExtractor
31
+ from reflexio.server.services.playbook.playbook_service_constants import (
32
+ PlaybookServiceConstants,
33
+ )
34
+ from reflexio.server.services.playbook.playbook_service_utils import (
35
+ PlaybookAggregatorRequest,
36
+ PlaybookGenerationRequest,
37
+ format_expert_comparison_pairs,
38
+ has_expert_content,
39
+ )
40
+ from reflexio.server.services.service_utils import (
41
+ extract_interactions_from_request_interaction_data_models,
42
+ format_sessions_to_history_string,
43
+ )
44
+
45
+ logger = logging.getLogger(__name__)
46
+
47
+
48
+ @dataclass
49
+ class PlaybookGenerationServiceConfig:
50
+ """Runtime configuration for playbook generation service shared across all extractors.
51
+
52
+ Attributes:
53
+ request_id: The request ID
54
+ agent_version: The agent version
55
+ user_id: The user ID for per-user playbook extraction
56
+ source: Source of the interactions
57
+ allow_manual_trigger: Whether to allow extractors with manual_trigger=True
58
+ rerun_start_time: Optional start time filter for rerun flows (Unix timestamp)
59
+ rerun_end_time: Optional end time filter for rerun flows (Unix timestamp)
60
+ auto_run: True for regular flow (checks stride_size), False for rerun/manual (skips stride_size)
61
+ """
62
+
63
+ request_id: str
64
+ agent_version: str
65
+ user_id: str | None = None
66
+ source: str | None = None
67
+ allow_manual_trigger: 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 PlaybookGenerationService(
75
+ BaseGenerationService[
76
+ PlaybookConfig,
77
+ PlaybookExtractor,
78
+ PlaybookGenerationServiceConfig,
79
+ PlaybookGenerationRequest,
80
+ ]
81
+ ):
82
+ """
83
+ Service for generating playbook entries from user interactions.
84
+ Runs the configured PlaybookExtractor for each generation request.
85
+ """
86
+
87
+ def __init__(
88
+ self,
89
+ llm_client: LiteLLMClient,
90
+ request_context: RequestContext,
91
+ allow_manual_trigger: bool = False,
92
+ output_pending_status: bool = False,
93
+ skip_aggregation: bool = False,
94
+ ) -> None:
95
+ """
96
+ Initialize the playbook generation service.
97
+
98
+ Args:
99
+ llm_client: Unified LLM client supporting both OpenAI and Claude
100
+ request_context: Request context with storage, configurator, and org_id
101
+ allow_manual_trigger: Whether to allow extractors with manual_trigger=True
102
+ output_pending_status: Whether to output entries with PENDING status (for rerun)
103
+ skip_aggregation: Whether to skip playbook aggregation (extract only, no agent playbooks)
104
+ """
105
+ super().__init__(llm_client=llm_client, request_context=request_context)
106
+ self.allow_manual_trigger = allow_manual_trigger
107
+ self.output_pending_status = output_pending_status
108
+ self.skip_aggregation = skip_aggregation
109
+
110
+ def _load_generation_service_config(
111
+ self, request: PlaybookGenerationRequest
112
+ ) -> PlaybookGenerationServiceConfig:
113
+ """
114
+ Extract request parameters from PlaybookGenerationRequest.
115
+
116
+ Args:
117
+ request: PlaybookGenerationRequest containing evaluation parameters
118
+
119
+ Returns:
120
+ PlaybookGenerationServiceConfig object
121
+ """
122
+ return PlaybookGenerationServiceConfig(
123
+ request_id=request.request_id,
124
+ agent_version=request.agent_version,
125
+ user_id=request.user_id,
126
+ source=request.source,
127
+ allow_manual_trigger=self.allow_manual_trigger,
128
+ rerun_start_time=request.rerun_start_time,
129
+ rerun_end_time=request.rerun_end_time,
130
+ auto_run=request.auto_run,
131
+ force_extraction=request.force_extraction,
132
+ )
133
+
134
+ def _configured_playbook_config(self) -> PlaybookConfig | None:
135
+ root_config = self.configurator.get_config()
136
+ return getattr(root_config, "user_playbook_extractor_config", None)
137
+
138
+ def _load_extractor_config(self) -> PlaybookConfig | None:
139
+ """
140
+ Load the configured user playbook extractor from configurator.
141
+
142
+ Returns:
143
+ PlaybookConfig | None: The configured user playbook extractor, if enabled.
144
+ """
145
+ return self._configured_playbook_config()
146
+
147
+ def _create_extractor(
148
+ self,
149
+ extractor_config: PlaybookConfig,
150
+ service_config: PlaybookGenerationServiceConfig,
151
+ ) -> PlaybookExtractor:
152
+ """
153
+ Create a PlaybookExtractor instance from configuration.
154
+
155
+ Args:
156
+ extractor_config: PlaybookConfig configuration object from YAML
157
+ service_config: PlaybookGenerationServiceConfig containing runtime parameters
158
+
159
+ Returns:
160
+ PlaybookExtractor instance
161
+ """
162
+ return PlaybookExtractor(
163
+ request_context=self.request_context,
164
+ llm_client=self.client,
165
+ extractor_config=extractor_config,
166
+ service_config=service_config,
167
+ agent_context=self.configurator.get_agent_context(),
168
+ )
169
+
170
+ def _build_should_run_prompt(
171
+ self,
172
+ scoped_config: PlaybookConfig,
173
+ session_data_models: list[RequestInteractionDataModel],
174
+ ) -> str | None:
175
+ """
176
+ Build prompt for consolidated should_generate check.
177
+
178
+ Renders the configured playbook definition for one LLM call.
179
+
180
+ Args:
181
+ scoped_config: Playbook extractor config that had scoped interactions
182
+ session_data_models: Deduplicated request interaction data models
183
+
184
+ Returns:
185
+ str | None: The rendered prompt, or None if no definitions to check
186
+ """
187
+ # Check for expert content — use expert-specific should-generate prompt
188
+ all_interactions = extract_interactions_from_request_interaction_data_models(
189
+ session_data_models
190
+ )
191
+ if has_expert_content(all_interactions):
192
+ agent_context = self.configurator.get_agent_context()
193
+ comparison_pairs = format_expert_comparison_pairs(session_data_models)
194
+ return self.request_context.prompt_manager.render_prompt(
195
+ PlaybookServiceConstants.PLAYBOOK_SHOULD_GENERATE_EXPERT_PROMPT_ID,
196
+ {
197
+ "agent_context_prompt": agent_context,
198
+ "comparison_pairs": comparison_pairs,
199
+ },
200
+ )
201
+
202
+ new_interactions = format_sessions_to_history_string(session_data_models)
203
+
204
+ combined_definition = (
205
+ scoped_config.extraction_definition_prompt.strip()
206
+ if scoped_config.extraction_definition_prompt
207
+ else ""
208
+ )
209
+
210
+ if not combined_definition:
211
+ return None
212
+
213
+ # Get tool_can_use from root config
214
+ root_config = self.request_context.configurator.get_config()
215
+ tool_can_use_str = ""
216
+ if root_config and root_config.tool_can_use:
217
+ tool_can_use_str = "\n".join(
218
+ f"{tool.tool_name}: {tool.tool_description}"
219
+ for tool in root_config.tool_can_use
220
+ )
221
+
222
+ agent_context = self.configurator.get_agent_context()
223
+ prompt_manager = self.request_context.prompt_manager
224
+
225
+ return prompt_manager.render_prompt(
226
+ PlaybookServiceConstants.PLAYBOOK_SHOULD_GENERATE_PROMPT_ID,
227
+ {
228
+ "agent_context_prompt": agent_context,
229
+ "extraction_definition_prompt": combined_definition,
230
+ "new_interactions": new_interactions,
231
+ "tool_can_use": tool_can_use_str,
232
+ },
233
+ )
234
+
235
+ def _get_precheck_interaction_query_kwargs(self) -> dict:
236
+ """Return agent_version filter for non-auto runs."""
237
+ return {
238
+ "agent_version": (
239
+ self.service_config.agent_version # type: ignore[reportOptionalMemberAccess]
240
+ if not self.service_config.auto_run # type: ignore[reportOptionalMemberAccess]
241
+ else None
242
+ ),
243
+ }
244
+
245
+ def _process_results(self, results: list[list[UserPlaybook]]) -> None:
246
+ """
247
+ Process, deduplicate, and save all results. Called once after all extractors complete.
248
+
249
+ Args:
250
+ results: List of UserPlaybook results from extractors (one list per extractor)
251
+ """
252
+ all_playbooks = []
253
+ for result in results:
254
+ if isinstance(result, list):
255
+ all_playbooks.extend(result)
256
+ self._finalize_extracted_items(all_playbooks)
257
+
258
+ def _finalize_extracted_items(self, all_playbooks: list[UserPlaybook]) -> None:
259
+ """Deduplicate, persist, and aggregate extracted user playbook items."""
260
+ # Deduplicate against existing entries in DB when deduplicator is enabled
261
+ existing_ids_to_delete: list[int] = []
262
+ from reflexio.server.site_var.feature_flags import is_deduplicator_enabled
263
+
264
+ if is_deduplicator_enabled(self.org_id):
265
+ from reflexio.server.services.playbook.playbook_consolidator import (
266
+ PlaybookConsolidator,
267
+ )
268
+
269
+ playbook_config = self._configured_playbook_config()
270
+ dedup_config = (
271
+ playbook_config.deduplication_config if playbook_config else None
272
+ )
273
+
274
+ consolidator = PlaybookConsolidator(
275
+ request_context=self.request_context,
276
+ llm_client=self.client,
277
+ dedup_config=dedup_config,
278
+ )
279
+ deduplicated_playbooks, existing_ids_to_delete = consolidator.deduplicate(
280
+ [all_playbooks],
281
+ self.service_config.request_id, # type: ignore[reportOptionalMemberAccess]
282
+ self.service_config.agent_version, # type: ignore[reportOptionalMemberAccess]
283
+ user_id=self.service_config.user_id, # type: ignore[reportOptionalMemberAccess]
284
+ )
285
+ logger.info(
286
+ "User playbook entries after deduplication: %d",
287
+ len(deduplicated_playbooks),
288
+ )
289
+ if deduplicated_playbooks:
290
+ all_playbooks = deduplicated_playbooks
291
+
292
+ # Set status and source for all entries
293
+ for playbook in all_playbooks:
294
+ playbook.status = Status.PENDING if self.output_pending_status else None
295
+ playbook.source = self.service_config.source # type: ignore[reportOptionalMemberAccess]
296
+
297
+ logger.info("All user playbook entries: %s", all_playbooks)
298
+
299
+ logger.info(
300
+ "Successfully completed %d %s playbook generation for request id: %s",
301
+ len(all_playbooks),
302
+ self._get_service_name(),
303
+ self.service_config.request_id, # type: ignore[reportOptionalMemberAccess]
304
+ )
305
+
306
+ # Save results
307
+ if all_playbooks:
308
+ try:
309
+ self.storage.save_user_playbooks(all_playbooks) # type: ignore[reportOptionalMemberAccess]
310
+ self._enqueue_user_playbook_optimization(all_playbooks)
311
+
312
+ # Delete superseded existing entries only after save succeeds
313
+ if existing_ids_to_delete:
314
+ try:
315
+ deleted_count = self.storage.delete_user_playbooks_by_ids( # type: ignore[reportOptionalMemberAccess]
316
+ existing_ids_to_delete
317
+ )
318
+ logger.info(
319
+ "Deleted %d superseded existing entries", deleted_count
320
+ )
321
+ except Exception as e:
322
+ logger.error(
323
+ "Failed to delete superseded existing entries: %s",
324
+ str(e),
325
+ )
326
+ except Exception as e:
327
+ logger.error(
328
+ "Failed to save %s results for request id: %s due to %s, exception type: %s",
329
+ self._get_service_name(),
330
+ self.service_config.request_id, # type: ignore[reportOptionalMemberAccess]
331
+ str(e),
332
+ type(e).__name__,
333
+ )
334
+
335
+ # Trigger playbook aggregation
336
+ if not self.output_pending_status and not self.skip_aggregation:
337
+ logger.info("Trigger playbook aggregation")
338
+ self._trigger_playbook_aggregation()
339
+
340
+ def _enqueue_user_playbook_optimization(
341
+ self, saved_playbooks: list[UserPlaybook]
342
+ ) -> None:
343
+ config = self.configurator.get_config().playbook_optimizer_config
344
+ if (
345
+ not config.enabled
346
+ or not config.optimize_user_playbooks
347
+ or not saved_playbooks
348
+ ):
349
+ return
350
+ from reflexio.server.services.playbook_optimizer import (
351
+ PlaybookOptimizationScheduler,
352
+ PlaybookOptimizationTarget,
353
+ PlaybookOptimizer,
354
+ )
355
+
356
+ scheduler = PlaybookOptimizationScheduler.get_instance()
357
+ for playbook in saved_playbooks:
358
+ if (
359
+ not playbook.user_playbook_id
360
+ or playbook.status is not None
361
+ or not playbook.source_interaction_ids
362
+ ):
363
+ continue
364
+ target = PlaybookOptimizationTarget(
365
+ kind="user_playbook", target_id=playbook.user_playbook_id
366
+ )
367
+ scheduler.enqueue(
368
+ org_id=self.request_context.org_id,
369
+ target=target,
370
+ callback=lambda target=target: PlaybookOptimizer(
371
+ self.request_context, self.client
372
+ ).optimize(target),
373
+ jitter_seconds=config.scheduler_jitter_seconds,
374
+ abort_cooldown_threshold=config.abort_cooldown_threshold,
375
+ cooldown_after_aborts_seconds=config.cooldown_after_aborts_seconds,
376
+ )
377
+
378
+ def _get_extractor_state_service_name(self) -> str:
379
+ """
380
+ Get the service name for stride_size bookmark lookups.
381
+
382
+ Returns:
383
+ str: "playbook_extractor" for OperationStateManager stride_size checks
384
+ """
385
+ return "playbook_extractor"
386
+
387
+ def _get_service_name(self) -> str:
388
+ """
389
+ Get the name of the service for logging and operation state tracking.
390
+
391
+ Returns:
392
+ Service name string - "rerun_playbook_generation" for rerun operations,
393
+ "playbook_generation" for regular operations
394
+ """
395
+ if self.output_pending_status:
396
+ return "rerun_playbook_generation"
397
+ return "playbook_generation"
398
+
399
+ def _get_base_service_name(self) -> str:
400
+ """
401
+ Get the base service name for OperationStateManager keys.
402
+
403
+ Returns:
404
+ str: "playbook_generation"
405
+ """
406
+ return "playbook_generation"
407
+
408
+ def _should_track_in_progress(self) -> bool:
409
+ """
410
+ Playbook generation should track in-progress state to prevent duplicates.
411
+
412
+ Returns:
413
+ bool: True - playbook generation tracks in-progress state
414
+ """
415
+ return True
416
+
417
+ def _get_lock_scope_id(self, request: PlaybookGenerationRequest) -> str | None: # noqa: ARG002
418
+ """
419
+ Get the scope ID for lock key construction.
420
+
421
+ Playbook generation is org-scoped, so returns None (no user scope).
422
+
423
+ Args:
424
+ request: The PlaybookGenerationRequest
425
+
426
+ Returns:
427
+ None: Playbook uses org-level scope only
428
+ """
429
+ return None
430
+
431
+ def _trigger_playbook_aggregation(self) -> None:
432
+ """
433
+ Trigger playbook aggregation for playbook types that have aggregator config.
434
+ This is called after raw user playbook entries are saved to check if aggregation should run.
435
+ """
436
+ playbook_config = self._configured_playbook_config()
437
+ if not playbook_config or not playbook_config.aggregation_config:
438
+ return
439
+
440
+ logger.info("Triggering aggregation")
441
+
442
+ # Create aggregator request. Aggregation is singleton — it operates on the
443
+ # user's whole playbook set, so no name selector is threaded.
444
+ aggregator_request = PlaybookAggregatorRequest(
445
+ agent_version=self.service_config.agent_version, # type: ignore[reportOptionalMemberAccess]
446
+ )
447
+
448
+ # Initialize and run aggregator (synchronous)
449
+ aggregator = PlaybookAggregator(
450
+ llm_client=self.client,
451
+ request_context=self.request_context,
452
+ agent_version=self.service_config.agent_version, # type: ignore[reportOptionalMemberAccess]
453
+ )
454
+ try:
455
+ run_with_operation_limit(
456
+ org_id=self.request_context.org_id,
457
+ operation="aggregation",
458
+ fn=lambda: aggregator.run(aggregator_request),
459
+ )
460
+ except TimeoutError:
461
+ logger.info(
462
+ "Skipping inline aggregation for agent_version=%s: aggregation limiter is saturated",
463
+ self.service_config.agent_version, # type: ignore[reportOptionalMemberAccess]
464
+ )
465
+
466
+ # ===============================
467
+ # Rerun hook implementations (override base class methods)
468
+ # ===============================
469
+
470
+ def _pre_process_rerun(self, request: RerunPlaybookGenerationRequest) -> None:
471
+ """Delete existing pending raw entries before generating new ones.
472
+
473
+ This ensures that each rerun starts fresh without accumulating pending entries
474
+ from previous reruns.
475
+
476
+ Args:
477
+ request: RerunPlaybookGenerationRequest with optional agent_version filter
478
+ """
479
+ deleted_count = self.storage.delete_all_user_playbooks_by_status( # type: ignore[reportOptionalMemberAccess]
480
+ status=Status.PENDING,
481
+ agent_version=request.agent_version,
482
+ )
483
+ logger.info(
484
+ "Deleted %d existing pending raw entries before rerun (agent_version=%s)",
485
+ deleted_count,
486
+ request.agent_version,
487
+ )
488
+
489
+ def _get_rerun_user_ids(self, request: RerunPlaybookGenerationRequest) -> list[str]:
490
+ """Get user IDs to process. Extractors collect their own data.
491
+
492
+ Identifies unique user_ids with matching requests via storage-level filtering.
493
+
494
+ Args:
495
+ request: RerunPlaybookGenerationRequest with optional time and source filters
496
+
497
+ Returns:
498
+ List of user IDs to process
499
+ """
500
+ return self.storage.get_rerun_user_ids( # type: ignore[reportOptionalMemberAccess]
501
+ user_id=None,
502
+ start_time=(
503
+ int(request.start_time.timestamp()) if request.start_time else None
504
+ ),
505
+ end_time=(int(request.end_time.timestamp()) if request.end_time else None),
506
+ source=request.source,
507
+ agent_version=request.agent_version,
508
+ )
509
+
510
+ def _build_rerun_request_params(
511
+ self, request: RerunPlaybookGenerationRequest
512
+ ) -> dict:
513
+ """Build request params dict for operation state tracking.
514
+
515
+ Args:
516
+ request: Original rerun request
517
+
518
+ Returns:
519
+ Dictionary of request parameters
520
+ """
521
+ return {
522
+ "agent_version": request.agent_version,
523
+ "start_time": (
524
+ request.start_time.isoformat() if request.start_time else None
525
+ ),
526
+ "end_time": request.end_time.isoformat() if request.end_time else None,
527
+ }
528
+
529
+ def _create_run_request_for_item(
530
+ self,
531
+ user_id: str,
532
+ request: RerunPlaybookGenerationRequest | ManualPlaybookGenerationRequest,
533
+ ) -> PlaybookGenerationRequest:
534
+ """Create PlaybookGenerationRequest for a single user.
535
+
536
+ Handles both rerun and manual request types.
537
+
538
+ Args:
539
+ user_id: The user ID to process
540
+ request: The original rerun or manual request
541
+
542
+ Returns:
543
+ PlaybookGenerationRequest for this user with filter constraints
544
+ """
545
+ # Handle rerun requests (have start_time/end_time datetime objects)
546
+ if isinstance(request, RerunPlaybookGenerationRequest):
547
+ return PlaybookGenerationRequest(
548
+ request_id=f"rerun_playbook_{uuid.uuid4().hex[:8]}",
549
+ agent_version=request.agent_version,
550
+ user_id=user_id,
551
+ source=request.source,
552
+ rerun_start_time=(
553
+ int(request.start_time.timestamp()) if request.start_time else None
554
+ ),
555
+ rerun_end_time=(
556
+ int(request.end_time.timestamp()) if request.end_time else None
557
+ ),
558
+ auto_run=False,
559
+ )
560
+ # Handle manual requests (ManualPlaybookGenerationRequest)
561
+ return PlaybookGenerationRequest(
562
+ request_id=f"manual_{uuid.uuid4().hex[:8]}",
563
+ agent_version=request.agent_version,
564
+ user_id=user_id,
565
+ source=request.source,
566
+ auto_run=False,
567
+ )
568
+
569
+ def _create_rerun_response(
570
+ self, success: bool, msg: str, count: int
571
+ ) -> RerunPlaybookGenerationResponse:
572
+ """Create RerunPlaybookGenerationResponse.
573
+
574
+ Args:
575
+ success: Whether the operation succeeded
576
+ msg: Status message
577
+ count: Number of entries generated
578
+
579
+ Returns:
580
+ RerunPlaybookGenerationResponse
581
+ """
582
+ return RerunPlaybookGenerationResponse(
583
+ success=success,
584
+ msg=msg,
585
+ playbooks_generated=count,
586
+ )
587
+
588
+ def _get_generated_count(
589
+ self,
590
+ request: RerunPlaybookGenerationRequest,
591
+ processed_user_ids: list[str] | None = None, # noqa: ARG002
592
+ ) -> int:
593
+ """Get the count of entries generated during rerun.
594
+
595
+ Counts entries with pending status, filtered by agent_version.
596
+
597
+ Args:
598
+ request: The rerun request object
599
+
600
+ Returns:
601
+ Number of entries generated
602
+ """
603
+ playbooks = self.storage.get_user_playbooks( # type: ignore[reportOptionalMemberAccess]
604
+ agent_version=request.agent_version,
605
+ status_filter=[Status.PENDING],
606
+ limit=10000,
607
+ )
608
+ return len(playbooks)
609
+
610
+ # ===============================
611
+ # Manual Regular Generation (window-sized, CURRENT output)
612
+ # ===============================
613
+
614
+ def run_manual_regular(
615
+ self, request: ManualPlaybookGenerationRequest
616
+ ) -> ManualPlaybookGenerationResponse:
617
+ """
618
+ Run playbook generation with window-sized interactions and CURRENT output.
619
+
620
+ Processes entries per-user. Each extractor collects its own data
621
+ using its configured window_size.
622
+ Uses progress tracking via OperationStateManager.
623
+
624
+ Args:
625
+ request: ManualPlaybookGenerationRequest with agent_version and optional source
626
+
627
+ Returns:
628
+ ManualPlaybookGenerationResponse with success status and count
629
+ """
630
+ state_manager = self._create_state_manager()
631
+
632
+ try:
633
+ # Check for existing in-progress operation
634
+ error = state_manager.check_in_progress()
635
+ if error:
636
+ return ManualPlaybookGenerationResponse(
637
+ success=False, msg=error, playbooks_generated=0
638
+ )
639
+
640
+ # 1. Get user_ids with recent interactions
641
+ requests_dict = self.storage.get_sessions( # type: ignore[reportOptionalMemberAccess]
642
+ user_id=None, # All users
643
+ top_k=1000, # Get recent sessions to find users
644
+ )
645
+
646
+ # Get unique user_ids
647
+ user_ids_set: set[str] = set()
648
+ for session_requests in requests_dict.values():
649
+ for rig in session_requests:
650
+ # Apply source filter if provided
651
+ if request.source and rig.request.source != request.source:
652
+ continue
653
+ user_ids_set.add(rig.request.user_id)
654
+
655
+ user_ids = list(user_ids_set)
656
+
657
+ if not user_ids:
658
+ return ManualPlaybookGenerationResponse(
659
+ success=True,
660
+ msg="No interactions found to process",
661
+ playbooks_generated=0,
662
+ )
663
+
664
+ # 2. Run batch with progress tracking
665
+ request_params = {
666
+ "agent_version": request.agent_version,
667
+ "source": request.source,
668
+ "mode": "manual_regular",
669
+ }
670
+ self._run_batch_with_progress(
671
+ user_ids=user_ids,
672
+ request=request, # type: ignore[reportArgumentType]
673
+ request_params=request_params,
674
+ state_manager=state_manager,
675
+ )
676
+
677
+ # 3. Count generated entries (CURRENT status = None)
678
+ total_playbooks = self._count_manual_generated(request)
679
+
680
+ return ManualPlaybookGenerationResponse(
681
+ success=True,
682
+ msg=f"Generated {total_playbooks} playbook entries",
683
+ playbooks_generated=total_playbooks,
684
+ )
685
+
686
+ except Exception as e:
687
+ state_manager.mark_progress_failed(str(e))
688
+ return ManualPlaybookGenerationResponse(
689
+ success=False,
690
+ msg=f"Failed to generate playbook entries: {str(e)}",
691
+ playbooks_generated=0,
692
+ )
693
+
694
+ def _count_manual_generated(self, request: ManualPlaybookGenerationRequest) -> int:
695
+ """
696
+ Count entries generated during manual regular generation.
697
+
698
+ Counts entries with CURRENT status (None), filtered by agent_version.
699
+
700
+ Args:
701
+ request: The manual generation request object
702
+
703
+ Returns:
704
+ Number of entries with CURRENT status
705
+ """
706
+ playbooks = self.storage.get_user_playbooks( # type: ignore[reportOptionalMemberAccess]
707
+ agent_version=request.agent_version,
708
+ status_filter=[None], # CURRENT entries
709
+ limit=10000,
710
+ )
711
+ return len(playbooks)
712
+
713
+ # ===============================
714
+ # Upgrade/Downgrade hook implementations (override base class methods)
715
+ # ===============================
716
+
717
+ def _has_items_with_status(
718
+ self, status: Status | None, request: PlaybookGenerationRequest
719
+ ) -> bool:
720
+ """Check if raw entries exist with given status.
721
+
722
+ Args:
723
+ status: The status to check for (None for CURRENT)
724
+ request: The upgrade/downgrade request object
725
+
726
+ Returns:
727
+ bool: True if any matching raw entries exist
728
+ """
729
+ return self.storage.has_user_playbooks_with_status( # type: ignore[reportOptionalMemberAccess]
730
+ status=status,
731
+ agent_version=getattr(request, "agent_version", None),
732
+ )
733
+
734
+ def _delete_items_by_status(
735
+ self, status: Status, request: PlaybookGenerationRequest
736
+ ) -> int:
737
+ """Delete raw entries with given status.
738
+
739
+ Args:
740
+ status: The status of raw entries to delete
741
+ request: The upgrade/downgrade request object
742
+
743
+ Returns:
744
+ int: Number of raw entries deleted
745
+ """
746
+ return self.storage.delete_all_user_playbooks_by_status( # type: ignore[reportOptionalMemberAccess]
747
+ status=status,
748
+ agent_version=getattr(request, "agent_version", None),
749
+ )
750
+
751
+ def _update_items_status(
752
+ self,
753
+ old_status: Status | None,
754
+ new_status: Status | None,
755
+ request: PlaybookGenerationRequest,
756
+ user_ids: list[str] | None = None, # noqa: ARG002
757
+ ) -> int:
758
+ """Update raw entries from old_status to new_status with request filters.
759
+
760
+ Args:
761
+ old_status: The current status to match (None for CURRENT)
762
+ new_status: The new status to set (None for CURRENT)
763
+ request: The upgrade/downgrade request object with filters
764
+ user_ids: Optional pre-computed list of user IDs (not used for playbook service)
765
+
766
+ Returns:
767
+ int: Number of raw entries updated
768
+ """
769
+ # Note: user_ids is ignored for playbook service as it uses agent_version filters
770
+ return self.storage.update_all_user_playbooks_status( # type: ignore[reportOptionalMemberAccess]
771
+ old_status=old_status,
772
+ new_status=new_status,
773
+ agent_version=getattr(request, "agent_version", None),
774
+ )
775
+
776
+ def _create_status_change_response(
777
+ self,
778
+ operation: StatusChangeOperation,
779
+ success: bool,
780
+ counts: dict,
781
+ msg: str,
782
+ ) -> UpgradeUserPlaybooksResponse | DowngradeUserPlaybooksResponse:
783
+ """Create upgrade or downgrade response object for raw entries.
784
+
785
+ Args:
786
+ operation: The operation type (UPGRADE or DOWNGRADE)
787
+ success: Whether the operation succeeded
788
+ counts: Dictionary of counts
789
+ msg: Status message
790
+
791
+ Returns:
792
+ UpgradeUserPlaybooksResponse or DowngradeUserPlaybooksResponse
793
+ """
794
+ if operation == StatusChangeOperation.UPGRADE:
795
+ return UpgradeUserPlaybooksResponse(
796
+ success=success,
797
+ user_playbooks_deleted=counts.get("deleted", 0),
798
+ user_playbooks_archived=counts.get("archived", 0),
799
+ user_playbooks_promoted=counts.get("promoted", 0),
800
+ message=msg,
801
+ )
802
+ # DOWNGRADE
803
+ return DowngradeUserPlaybooksResponse(
804
+ success=success,
805
+ user_playbooks_demoted=counts.get("demoted", 0),
806
+ user_playbooks_restored=counts.get("restored", 0),
807
+ message=msg,
808
+ )