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,779 @@
1
+ """Follow-up resume worker for resolved async extraction tool calls."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+ import uuid
7
+ from collections import defaultdict
8
+ from datetime import UTC, datetime, timedelta
9
+ from typing import Any
10
+
11
+ from pydantic import BaseModel
12
+
13
+ from reflexio.models.api_schema.internal_schema import RequestInteractionDataModel
14
+ from reflexio.models.api_schema.service_schemas import Interaction, Request
15
+ from reflexio.models.config_schema import PlaybookConfig, ProfileExtractorConfig
16
+ from reflexio.server.api_endpoints.request_context import RequestContext
17
+ from reflexio.server.llm.litellm_client import LiteLLMClient, LiteLLMConfig
18
+ from reflexio.server.llm.model_defaults import ModelRole, resolve_model_name
19
+ from reflexio.server.services.extraction.agent_run_records import build_scope_hash
20
+ from reflexio.server.services.extraction.pending_tool_call_dispatch import (
21
+ PendingToolCallToolContext,
22
+ )
23
+ from reflexio.server.services.extraction.prior_answer_search import (
24
+ append_prior_knowledge_context,
25
+ )
26
+ from reflexio.server.services.extraction.resumable_agent import (
27
+ AgentRunResult,
28
+ ResumableExtractionAgent,
29
+ create_pending_info_tools_for_extractor_kind,
30
+ )
31
+ from reflexio.server.services.playbook.playbook_extractor import PlaybookExtractor
32
+ from reflexio.server.services.playbook.playbook_generation_service import (
33
+ PlaybookGenerationService,
34
+ PlaybookGenerationServiceConfig,
35
+ )
36
+ from reflexio.server.services.playbook.playbook_service_utils import (
37
+ StructuredPlaybookList,
38
+ construct_expert_playbook_extraction_messages,
39
+ construct_playbook_extraction_messages_from_sessions,
40
+ has_expert_content,
41
+ )
42
+ from reflexio.server.services.profile.profile_extractor import (
43
+ MAX_EXISTING_PROFILES_FOR_CONTEXT,
44
+ ProfileExtractor,
45
+ )
46
+ from reflexio.server.services.profile.profile_generation_service import (
47
+ ProfileGenerationService,
48
+ ProfileGenerationServiceConfig,
49
+ )
50
+ from reflexio.server.services.profile.profile_generation_service_utils import (
51
+ StructuredProfilesOutput,
52
+ construct_profile_extraction_messages_from_sessions,
53
+ )
54
+ from reflexio.server.services.service_utils import (
55
+ extract_interactions_from_request_interaction_data_models,
56
+ )
57
+ from reflexio.server.services.storage.storage_base import (
58
+ AgentRunRecord,
59
+ AgentRunStatus,
60
+ BaseStorage,
61
+ PendingToolCallRecord,
62
+ PendingToolCallStatus,
63
+ )
64
+ from reflexio.server.site_var.site_var_manager import SiteVarManager
65
+ from reflexio.server.tracing import sentry_tags
66
+
67
+ logger = logging.getLogger(__name__)
68
+
69
+
70
+ class ResumeWorkerError(RuntimeError):
71
+ """Base error for retryable resume-worker failures."""
72
+
73
+
74
+ def _next_retry_at(attempt_count: int) -> datetime:
75
+ delay_seconds = min(300, max(1, 2 ** max(0, attempt_count - 1)))
76
+ return datetime.now(UTC) + timedelta(seconds=delay_seconds)
77
+
78
+
79
+ def _create_llm_client(request_context: RequestContext) -> LiteLLMClient:
80
+ # The tool loop re-resolves the model per call via ModelRole.EXTRACTION_AGENT
81
+ # (see run_tool_loop); this client's model name is only a fallback. We resolve
82
+ # the GENERATION model here so the client still carries a sensible default and
83
+ # the org's api_key_config, which the loop reuses for provider routing.
84
+ model_setting = SiteVarManager().get_site_var("llm_model_setting")
85
+ site_var = model_setting if isinstance(model_setting, dict) else {}
86
+ config = request_context.configurator.get_config()
87
+ api_key_config = config.api_key_config if config else None
88
+ llm_config = config.llm_config if config else None
89
+ model_name = resolve_model_name(
90
+ ModelRole.GENERATION,
91
+ site_var_value=site_var.get("default_generation_model_name"),
92
+ config_override=llm_config.generation_model_name if llm_config else None,
93
+ api_key_config=api_key_config,
94
+ )
95
+ return LiteLLMClient(LiteLLMConfig(model=model_name, api_key_config=api_key_config))
96
+
97
+
98
+ def _storage(request_context: RequestContext) -> BaseStorage:
99
+ storage = request_context.storage
100
+ if storage is None:
101
+ raise ResumeWorkerError("Storage not configured")
102
+ return storage
103
+
104
+
105
+ def _request_interaction_models_from_ids(
106
+ storage: BaseStorage,
107
+ interaction_ids: list[int],
108
+ *,
109
+ fallback_source: str | None,
110
+ fallback_agent_version: str | None,
111
+ ) -> list[RequestInteractionDataModel]:
112
+ interactions = storage.get_interactions_by_ids(interaction_ids)
113
+ if not interactions:
114
+ raise ResumeWorkerError("No source interactions found for resumed run")
115
+
116
+ by_request: dict[str, list[Interaction]] = defaultdict(list)
117
+ for interaction in interactions:
118
+ by_request[interaction.request_id].append(interaction)
119
+
120
+ models: list[RequestInteractionDataModel] = []
121
+ for request_id, request_interactions in by_request.items():
122
+ ordered = sorted(request_interactions, key=lambda item: item.created_at)
123
+ request = storage.get_request(request_id)
124
+ if request is None:
125
+ first = ordered[0]
126
+ request = Request(
127
+ request_id=request_id,
128
+ user_id=first.user_id,
129
+ created_at=first.created_at,
130
+ source=fallback_source or "",
131
+ agent_version=fallback_agent_version or "",
132
+ session_id=request_id,
133
+ )
134
+ models.append(
135
+ RequestInteractionDataModel(
136
+ session_id=request.session_id or request.request_id,
137
+ request=request,
138
+ interactions=ordered,
139
+ )
140
+ )
141
+ return sorted(
142
+ models,
143
+ key=lambda model: min(
144
+ (interaction.created_at for interaction in model.interactions),
145
+ default=0,
146
+ ),
147
+ )
148
+
149
+
150
+ def _select_current_extractor_config(
151
+ request_context: RequestContext,
152
+ run: AgentRunRecord,
153
+ ) -> ProfileExtractorConfig | PlaybookConfig:
154
+ root_config = request_context.configurator.get_config()
155
+ if run.binding.extractor_kind == "profile":
156
+ config = getattr(root_config, "profile_extractor_config", None)
157
+ elif run.binding.extractor_kind == "playbook":
158
+ config = getattr(root_config, "user_playbook_extractor_config", None)
159
+ else:
160
+ raise ResumeWorkerError(
161
+ f"Unsupported extractor kind {run.binding.extractor_kind!r}"
162
+ )
163
+
164
+ if config is not None and isinstance(
165
+ config, ProfileExtractorConfig | PlaybookConfig
166
+ ):
167
+ return config
168
+ raise ResumeWorkerError(
169
+ f"Current extractor config not found for {run.binding.extractor_kind}"
170
+ )
171
+
172
+
173
+ def _log_config_hash_drift(
174
+ run: AgentRunRecord,
175
+ extractor_config: BaseModel,
176
+ ) -> None:
177
+ current_hash = build_scope_hash(extractor_config.model_dump(mode="json"))
178
+ if run.binding.extractor_config_hash and (
179
+ current_hash != run.binding.extractor_config_hash
180
+ ):
181
+ logger.info(
182
+ "event=resumable_extraction_config_hash_drift run_id=%s extractor_kind=%s "
183
+ "stored_hash=%s current_hash=%s",
184
+ run.id,
185
+ run.binding.extractor_kind,
186
+ run.binding.extractor_config_hash,
187
+ current_hash,
188
+ )
189
+
190
+
191
+ class ExtractionResumeWorker:
192
+ """Claim and resume finalized extraction runs with resolved tool results."""
193
+
194
+ def __init__(
195
+ self,
196
+ *,
197
+ request_context: RequestContext,
198
+ llm_client: LiteLLMClient | None = None,
199
+ worker_id: str | None = None,
200
+ ) -> None:
201
+ self.request_context = request_context
202
+ self.storage = _storage(request_context)
203
+ self.client = llm_client or _create_llm_client(request_context)
204
+ self.worker_id = worker_id or f"resume_worker_{uuid.uuid4().hex}"
205
+
206
+ def drain(self, *, max_runs: int = 10) -> int:
207
+ """Resume up to ``max_runs`` ready rows for this request context."""
208
+ resumed = 0
209
+ for _ in range(max_runs):
210
+ if self.run_once() is None:
211
+ break
212
+ resumed += 1
213
+ return resumed
214
+
215
+ def run_once(self) -> AgentRunRecord | None:
216
+ config = self.request_context.configurator.get_config()
217
+ pending_config = config.pending_tool_call_config
218
+ finalization_retry = self.storage.claim_finalization_failed_agent_run(
219
+ org_id=self.request_context.org_id,
220
+ worker_id=self.worker_id,
221
+ claim_ttl_seconds=pending_config.resume_claim_ttl_seconds,
222
+ )
223
+ if finalization_retry is not None:
224
+ return self._retry_finalization(finalization_retry)
225
+
226
+ run = self.storage.claim_ready_agent_run(
227
+ org_id=self.request_context.org_id,
228
+ worker_id=self.worker_id,
229
+ claim_ttl_seconds=pending_config.resume_claim_ttl_seconds,
230
+ )
231
+ if run is None:
232
+ return None
233
+
234
+ if run.max_steps_remaining is not None and run.max_steps_remaining <= 0:
235
+ return self.storage.update_agent_run_status(
236
+ run.id,
237
+ AgentRunStatus.FAILED,
238
+ last_error="Resumable extraction max-step budget exhausted",
239
+ )
240
+
241
+ try:
242
+ resolved_calls = self._load_resolved_tool_calls(run)
243
+ if not resolved_calls:
244
+ raise ResumeWorkerError(
245
+ f"Run {run.id} has no resolved, unconsumed tool calls"
246
+ )
247
+ items, pending_tool_call_ids = self._resume_run(run, resolved_calls)
248
+ except Exception as exc:
249
+ with sentry_tags(
250
+ subsystem="extraction",
251
+ op="resume_run",
252
+ org_id=self.request_context.org_id,
253
+ run_id=run.id,
254
+ error_type=type(exc).__name__,
255
+ ):
256
+ logger.exception(
257
+ "event=resumable_extraction_resume_failed run_id=%s",
258
+ run.id,
259
+ )
260
+ failed_status = (
261
+ AgentRunStatus.FAILED
262
+ if run.resume_attempts >= pending_config.max_resume_attempts
263
+ else AgentRunStatus.RESUME_READY
264
+ )
265
+ return self.storage.update_agent_run_status(
266
+ run.id,
267
+ failed_status,
268
+ next_resume_at=_next_retry_at(run.resume_attempts),
269
+ last_error=str(exc),
270
+ )
271
+
272
+ try:
273
+ self.storage.update_agent_run_status(run.id, AgentRunStatus.FINALIZING)
274
+ self._finalize_items(run, items)
275
+ self.storage.consume_run_tool_dependencies(run.id)
276
+ finalized_status = (
277
+ AgentRunStatus.FINALIZED_PENDING_TOOL
278
+ if pending_tool_call_ids
279
+ else AgentRunStatus.FINALIZED
280
+ )
281
+ return self.storage.update_agent_run_status(
282
+ run.id,
283
+ finalized_status,
284
+ pending_tool_call_ids=pending_tool_call_ids,
285
+ )
286
+ except Exception as exc:
287
+ with sentry_tags(
288
+ subsystem="extraction",
289
+ op="finalize_run",
290
+ org_id=self.request_context.org_id,
291
+ run_id=run.id,
292
+ error_type=type(exc).__name__,
293
+ ):
294
+ logger.exception(
295
+ "event=resumable_extraction_finalization_failed run_id=%s",
296
+ run.id,
297
+ )
298
+ next_attempt_count = run.finalization_attempts + 1
299
+ failed_status = (
300
+ AgentRunStatus.FAILED
301
+ if next_attempt_count >= pending_config.max_finalization_attempts
302
+ else AgentRunStatus.FINALIZATION_FAILED
303
+ )
304
+ return self.storage.update_agent_run_status(
305
+ run.id,
306
+ failed_status,
307
+ next_resume_at=_next_retry_at(next_attempt_count),
308
+ last_error=str(exc),
309
+ increment_finalization_attempts=True,
310
+ )
311
+
312
+ def _retry_finalization(self, run: AgentRunRecord) -> AgentRunRecord | None:
313
+ config = self.request_context.configurator.get_config()
314
+ pending_config = config.pending_tool_call_config
315
+ try:
316
+ items, pending_tool_call_ids = self._items_from_committed_output(run)
317
+ self._finalize_items(run, items)
318
+ self.storage.consume_run_tool_dependencies(run.id)
319
+ finalized_status = (
320
+ AgentRunStatus.FINALIZED_PENDING_TOOL
321
+ if pending_tool_call_ids
322
+ else AgentRunStatus.FINALIZED
323
+ )
324
+ return self.storage.update_agent_run_status(
325
+ run.id,
326
+ finalized_status,
327
+ pending_tool_call_ids=pending_tool_call_ids,
328
+ )
329
+ except Exception as exc:
330
+ with sentry_tags(
331
+ subsystem="extraction",
332
+ op="finalize_run_retry",
333
+ org_id=self.request_context.org_id,
334
+ run_id=run.id,
335
+ error_type=type(exc).__name__,
336
+ ):
337
+ logger.exception(
338
+ "event=resumable_extraction_finalization_retry_failed run_id=%s",
339
+ run.id,
340
+ )
341
+ next_attempt_count = run.finalization_attempts + 1
342
+ failed_status = (
343
+ AgentRunStatus.FAILED
344
+ if next_attempt_count >= pending_config.max_finalization_attempts
345
+ else AgentRunStatus.FINALIZATION_FAILED
346
+ )
347
+ return self.storage.update_agent_run_status(
348
+ run.id,
349
+ failed_status,
350
+ next_resume_at=_next_retry_at(next_attempt_count),
351
+ last_error=str(exc),
352
+ increment_finalization_attempts=True,
353
+ )
354
+
355
+ def _load_resolved_tool_calls(
356
+ self,
357
+ run: AgentRunRecord,
358
+ ) -> list[PendingToolCallRecord]:
359
+ records: list[PendingToolCallRecord] = []
360
+ for dependency in self.storage.list_run_tool_dependencies(run.id):
361
+ if dependency.consumed_at is not None or dependency.resolved_at is None:
362
+ continue
363
+ record = self.storage.get_pending_tool_call(dependency.pending_tool_call_id)
364
+ if record and record.status == PendingToolCallStatus.RESOLVED:
365
+ records.append(record)
366
+ return sorted(
367
+ records,
368
+ key=lambda record: record.resolved_at or datetime.max.replace(tzinfo=UTC),
369
+ )
370
+
371
+ def _extra_tools_for_run(
372
+ self,
373
+ run: AgentRunRecord,
374
+ ) -> tuple[list[Any], PendingToolCallToolContext | None]:
375
+ pending_config = (
376
+ self.request_context.configurator.get_config().pending_tool_call_config
377
+ )
378
+ tools = create_pending_info_tools_for_extractor_kind(run.binding.extractor_kind)
379
+ return tools, PendingToolCallToolContext(
380
+ storage=self.storage,
381
+ run_id=run.id,
382
+ org_id=self.request_context.org_id,
383
+ extractor_kind=run.binding.extractor_kind,
384
+ user_id=run.binding.user_id,
385
+ config=pending_config,
386
+ )
387
+
388
+ def _resume_run(
389
+ self,
390
+ run: AgentRunRecord,
391
+ resolved_calls: list[PendingToolCallRecord],
392
+ ) -> tuple[list[Any], list[str]]:
393
+ request_interaction_data_models = _request_interaction_models_from_ids(
394
+ self.storage,
395
+ run.binding.source_interaction_ids,
396
+ fallback_source=run.binding.source,
397
+ fallback_agent_version=run.binding.agent_version,
398
+ )
399
+ extractor_config = _select_current_extractor_config(self.request_context, run)
400
+ _log_config_hash_drift(run, extractor_config)
401
+ if run.binding.extractor_kind == "profile":
402
+ return self._resume_profile(
403
+ run,
404
+ extractor_config,
405
+ request_interaction_data_models,
406
+ resolved_calls,
407
+ )
408
+ if run.binding.extractor_kind == "playbook":
409
+ return self._resume_playbook(
410
+ run,
411
+ extractor_config,
412
+ request_interaction_data_models,
413
+ resolved_calls,
414
+ )
415
+ raise ResumeWorkerError(
416
+ f"Unsupported extractor kind {run.binding.extractor_kind!r}"
417
+ )
418
+
419
+ def _resume_profile(
420
+ self,
421
+ run: AgentRunRecord,
422
+ extractor_config: ProfileExtractorConfig | PlaybookConfig,
423
+ request_interaction_data_models: list[RequestInteractionDataModel],
424
+ resolved_calls: list[PendingToolCallRecord],
425
+ ) -> tuple[list[Any], list[str]]:
426
+ if not isinstance(extractor_config, ProfileExtractorConfig):
427
+ raise ResumeWorkerError("Expected profile extractor config")
428
+ if run.binding.user_id is None:
429
+ raise ResumeWorkerError("Profile resume requires user_id")
430
+
431
+ existing_profiles = self.storage.get_user_profile(run.binding.user_id)
432
+ context_profiles = sorted(
433
+ existing_profiles,
434
+ key=lambda profile: profile.last_modified_timestamp,
435
+ reverse=True,
436
+ )[:MAX_EXISTING_PROFILES_FOR_CONTEXT]
437
+ agent_context = self.request_context.configurator.get_agent_context()
438
+ service_config = ProfileGenerationServiceConfig(
439
+ user_id=run.binding.user_id,
440
+ request_id=run.binding.request_id,
441
+ source=run.binding.source,
442
+ existing_data=existing_profiles,
443
+ auto_run=False,
444
+ force_extraction=True,
445
+ )
446
+ extractor = ProfileExtractor(
447
+ request_context=self.request_context,
448
+ llm_client=self.client,
449
+ extractor_config=extractor_config,
450
+ service_config=service_config,
451
+ agent_context=agent_context,
452
+ )
453
+ messages = construct_profile_extraction_messages_from_sessions(
454
+ prompt_manager=self.request_context.prompt_manager,
455
+ request_interaction_data_models=request_interaction_data_models,
456
+ agent_context_prompt=agent_context,
457
+ context_prompt=(
458
+ extractor_config.context_prompt.strip()
459
+ if extractor_config.context_prompt
460
+ else ""
461
+ ),
462
+ extraction_definition_prompt=extractor_config.extraction_definition_prompt.strip(),
463
+ metadata_definition_prompt=(
464
+ extractor_config.metadata_definition_prompt.strip()
465
+ if extractor_config.metadata_definition_prompt
466
+ else None
467
+ ),
468
+ existing_profiles=context_profiles,
469
+ )
470
+ result = self._resume_agent(
471
+ run=run,
472
+ messages=self._messages_with_prior_knowledge(
473
+ run=run,
474
+ messages=messages,
475
+ extractor_config=extractor_config,
476
+ resolved_calls=resolved_calls,
477
+ ),
478
+ output_schema=StructuredProfilesOutput,
479
+ resolved_calls=resolved_calls,
480
+ log_label="Profile extraction resume",
481
+ )
482
+ if not isinstance(result.output, StructuredProfilesOutput):
483
+ raise ResumeWorkerError(
484
+ f"Profile resume did not finish: {result.finished_reason}"
485
+ )
486
+ raw_profiles = [
487
+ profile.model_dump() for profile in result.output.profiles or []
488
+ ]
489
+ return (
490
+ extractor._convert_raw_to_user_profiles(
491
+ raw_profiles=raw_profiles,
492
+ user_id=run.binding.user_id,
493
+ request_id=run.binding.request_id,
494
+ ),
495
+ result.pending_tool_call_ids,
496
+ )
497
+
498
+ def _resume_playbook(
499
+ self,
500
+ run: AgentRunRecord,
501
+ extractor_config: ProfileExtractorConfig | PlaybookConfig,
502
+ request_interaction_data_models: list[RequestInteractionDataModel],
503
+ resolved_calls: list[PendingToolCallRecord],
504
+ ) -> tuple[list[Any], list[str]]:
505
+ if not isinstance(extractor_config, PlaybookConfig):
506
+ raise ResumeWorkerError("Expected playbook extractor config")
507
+
508
+ agent_context = self.request_context.configurator.get_agent_context()
509
+ service_config = PlaybookGenerationServiceConfig(
510
+ request_id=run.binding.request_id,
511
+ agent_version=run.binding.agent_version or "",
512
+ user_id=run.binding.user_id,
513
+ source=run.binding.source,
514
+ auto_run=False,
515
+ force_extraction=True,
516
+ )
517
+ extractor = PlaybookExtractor(
518
+ request_context=self.request_context,
519
+ llm_client=self.client,
520
+ extractor_config=extractor_config,
521
+ service_config=service_config,
522
+ agent_context=agent_context,
523
+ )
524
+ source_interaction_ids = [
525
+ interaction.interaction_id
526
+ for data_model in request_interaction_data_models
527
+ for interaction in data_model.interactions
528
+ if interaction.interaction_id
529
+ ]
530
+ playbook_definition = (
531
+ extractor_config.extraction_definition_prompt.strip()
532
+ if extractor_config.extraction_definition_prompt
533
+ else ""
534
+ )
535
+ all_interactions = extract_interactions_from_request_interaction_data_models(
536
+ request_interaction_data_models
537
+ )
538
+ prompt_manager = self.request_context.prompt_manager
539
+ if has_expert_content(all_interactions):
540
+ messages = construct_expert_playbook_extraction_messages(
541
+ prompt_manager=prompt_manager,
542
+ request_interaction_data_models=request_interaction_data_models,
543
+ agent_context_prompt=agent_context,
544
+ extraction_definition_prompt=playbook_definition,
545
+ )
546
+ else:
547
+ root_config = self.request_context.configurator.get_config()
548
+ tool_can_use = ""
549
+ if root_config and root_config.tool_can_use:
550
+ tool_can_use = "\n".join(
551
+ [
552
+ f"{tool.tool_name}: {tool.tool_description}"
553
+ for tool in root_config.tool_can_use
554
+ ]
555
+ )
556
+ messages = construct_playbook_extraction_messages_from_sessions(
557
+ prompt_manager=prompt_manager,
558
+ request_interaction_data_models=request_interaction_data_models,
559
+ agent_context_prompt=agent_context,
560
+ extraction_definition_prompt=playbook_definition,
561
+ tool_can_use=tool_can_use,
562
+ )
563
+ result = self._resume_agent(
564
+ run=run,
565
+ messages=self._messages_with_prior_knowledge(
566
+ run=run,
567
+ messages=messages,
568
+ extractor_config=extractor_config,
569
+ resolved_calls=resolved_calls,
570
+ ),
571
+ output_schema=StructuredPlaybookList,
572
+ resolved_calls=resolved_calls,
573
+ log_label="Playbook extraction resume",
574
+ )
575
+ if not isinstance(result.output, StructuredPlaybookList):
576
+ raise ResumeWorkerError(
577
+ f"Playbook resume did not finish: {result.finished_reason}"
578
+ )
579
+ return (
580
+ extractor._process_structured_response_list(
581
+ result.output,
582
+ source_interaction_ids=source_interaction_ids,
583
+ ),
584
+ result.pending_tool_call_ids,
585
+ )
586
+
587
+ def _messages_with_prior_knowledge(
588
+ self,
589
+ *,
590
+ run: AgentRunRecord,
591
+ messages: list[dict[str, Any]],
592
+ extractor_config: BaseModel,
593
+ resolved_calls: list[PendingToolCallRecord] | None = None,
594
+ ) -> list[dict[str, Any]]:
595
+ pending_config = (
596
+ self.request_context.configurator.get_config().pending_tool_call_config
597
+ )
598
+ # Prior-knowledge context is always injected within the resumable path.
599
+ return append_prior_knowledge_context(
600
+ messages=messages,
601
+ storage=self.storage,
602
+ org_id=self.request_context.org_id,
603
+ extractor_kind=run.binding.extractor_kind,
604
+ extractor_config=extractor_config,
605
+ source=run.binding.source,
606
+ agent_version=run.binding.agent_version,
607
+ similarity_threshold=pending_config.for_tool(
608
+ "ask_human"
609
+ ).similarity_threshold,
610
+ # Avoid re-surfacing the run's own just-resolved answers, which are
611
+ # injected separately as explicit resolved-tool-result messages.
612
+ exclude_pending_tool_call_ids={call.id for call in resolved_calls or []},
613
+ )
614
+
615
+ def _resume_agent(
616
+ self,
617
+ *,
618
+ run: AgentRunRecord,
619
+ messages: list[dict[str, Any]],
620
+ output_schema: type[BaseModel],
621
+ resolved_calls: list[PendingToolCallRecord],
622
+ log_label: str,
623
+ ) -> AgentRunResult:
624
+ extra_tools, extra_context = self._extra_tools_for_run(run)
625
+ return ResumableExtractionAgent(
626
+ client=self.client,
627
+ storage=self.storage,
628
+ ).resume(
629
+ run=run,
630
+ messages=messages,
631
+ output_schema=output_schema,
632
+ resolved_tool_calls=resolved_calls,
633
+ extra_tools=extra_tools,
634
+ extra_tool_context=extra_context,
635
+ log_label=log_label,
636
+ )
637
+
638
+ def _items_from_committed_output(
639
+ self,
640
+ run: AgentRunRecord,
641
+ ) -> tuple[list[Any], list[str]]:
642
+ if run.committed_output is None:
643
+ raise ResumeWorkerError(
644
+ f"Run {run.id} cannot retry finalization without committed output"
645
+ )
646
+ request_interaction_data_models = _request_interaction_models_from_ids(
647
+ self.storage,
648
+ run.binding.source_interaction_ids,
649
+ fallback_source=run.binding.source,
650
+ fallback_agent_version=run.binding.agent_version,
651
+ )
652
+ extractor_config = _select_current_extractor_config(self.request_context, run)
653
+ if run.binding.extractor_kind == "profile":
654
+ return self._profile_items_from_output(
655
+ run,
656
+ extractor_config,
657
+ run.committed_output,
658
+ )
659
+ if run.binding.extractor_kind == "playbook":
660
+ return self._playbook_items_from_output(
661
+ run,
662
+ extractor_config,
663
+ request_interaction_data_models,
664
+ run.committed_output,
665
+ )
666
+ raise ResumeWorkerError(
667
+ f"Unsupported extractor kind {run.binding.extractor_kind!r}"
668
+ )
669
+
670
+ def _profile_items_from_output(
671
+ self,
672
+ run: AgentRunRecord,
673
+ extractor_config: ProfileExtractorConfig | PlaybookConfig,
674
+ committed_output: dict[str, Any],
675
+ ) -> tuple[list[Any], list[str]]:
676
+ if not isinstance(extractor_config, ProfileExtractorConfig):
677
+ raise ResumeWorkerError("Expected profile extractor config")
678
+ if run.binding.user_id is None:
679
+ raise ResumeWorkerError("Profile finalization retry requires user_id")
680
+ output = StructuredProfilesOutput.model_validate(committed_output)
681
+ agent_context = self.request_context.configurator.get_agent_context()
682
+ service_config = ProfileGenerationServiceConfig(
683
+ user_id=run.binding.user_id,
684
+ request_id=run.binding.request_id,
685
+ source=run.binding.source,
686
+ existing_data=self.storage.get_user_profile(run.binding.user_id),
687
+ auto_run=False,
688
+ force_extraction=True,
689
+ )
690
+ extractor = ProfileExtractor(
691
+ request_context=self.request_context,
692
+ llm_client=self.client,
693
+ extractor_config=extractor_config,
694
+ service_config=service_config,
695
+ agent_context=agent_context,
696
+ )
697
+ raw_profiles = [profile.model_dump() for profile in output.profiles or []]
698
+ return (
699
+ extractor._convert_raw_to_user_profiles(
700
+ raw_profiles=raw_profiles,
701
+ user_id=run.binding.user_id,
702
+ request_id=run.binding.request_id,
703
+ ),
704
+ run.pending_tool_call_ids,
705
+ )
706
+
707
+ def _playbook_items_from_output(
708
+ self,
709
+ run: AgentRunRecord,
710
+ extractor_config: ProfileExtractorConfig | PlaybookConfig,
711
+ request_interaction_data_models: list[RequestInteractionDataModel],
712
+ committed_output: dict[str, Any],
713
+ ) -> tuple[list[Any], list[str]]:
714
+ if not isinstance(extractor_config, PlaybookConfig):
715
+ raise ResumeWorkerError("Expected playbook extractor config")
716
+ output = StructuredPlaybookList.model_validate(committed_output)
717
+ agent_context = self.request_context.configurator.get_agent_context()
718
+ service_config = PlaybookGenerationServiceConfig(
719
+ request_id=run.binding.request_id,
720
+ agent_version=run.binding.agent_version or "",
721
+ user_id=run.binding.user_id,
722
+ source=run.binding.source,
723
+ auto_run=False,
724
+ force_extraction=True,
725
+ )
726
+ extractor = PlaybookExtractor(
727
+ request_context=self.request_context,
728
+ llm_client=self.client,
729
+ extractor_config=extractor_config,
730
+ service_config=service_config,
731
+ agent_context=agent_context,
732
+ )
733
+ source_interaction_ids = [
734
+ interaction.interaction_id
735
+ for data_model in request_interaction_data_models
736
+ for interaction in data_model.interactions
737
+ if interaction.interaction_id
738
+ ]
739
+ return (
740
+ extractor._process_structured_response_list(
741
+ output,
742
+ source_interaction_ids=source_interaction_ids,
743
+ ),
744
+ run.pending_tool_call_ids,
745
+ )
746
+
747
+ def _finalize_items(self, run: AgentRunRecord, items: list[Any]) -> None:
748
+ if run.binding.extractor_kind == "profile":
749
+ service = ProfileGenerationService(
750
+ llm_client=self.client,
751
+ request_context=self.request_context,
752
+ )
753
+ service.service_config = ProfileGenerationServiceConfig(
754
+ user_id=run.binding.user_id or "",
755
+ request_id=run.binding.request_id,
756
+ source=run.binding.source,
757
+ auto_run=False,
758
+ force_extraction=True,
759
+ )
760
+ service._finalize_extracted_items(items)
761
+ return
762
+ if run.binding.extractor_kind == "playbook":
763
+ service = PlaybookGenerationService(
764
+ llm_client=self.client,
765
+ request_context=self.request_context,
766
+ )
767
+ service.service_config = PlaybookGenerationServiceConfig(
768
+ request_id=run.binding.request_id,
769
+ agent_version=run.binding.agent_version or "",
770
+ user_id=run.binding.user_id,
771
+ source=run.binding.source,
772
+ auto_run=False,
773
+ force_extraction=True,
774
+ )
775
+ service._finalize_extracted_items(items)
776
+ return
777
+ raise ResumeWorkerError(
778
+ f"Unsupported extractor kind {run.binding.extractor_kind!r}"
779
+ )