claude-smart 0.2.41 → 0.2.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (396) hide show
  1. package/.claude-plugin/marketplace.json +17 -0
  2. package/README.md +1 -1
  3. package/bin/claude-smart.js +86 -48
  4. package/package.json +10 -3
  5. package/plugin/.claude-plugin/plugin.json +9 -3
  6. package/plugin/.codex-plugin/plugin.json +1 -1
  7. package/plugin/README.md +2 -2
  8. package/plugin/dashboard/next.config.ts +9 -1
  9. package/plugin/pyproject.toml +2 -2
  10. package/plugin/scripts/_lib.sh +91 -0
  11. package/plugin/scripts/backend-service.sh +46 -15
  12. package/plugin/scripts/cli.sh +29 -1
  13. package/plugin/scripts/codex-hook.js +72 -4
  14. package/plugin/scripts/dashboard-build.sh +1 -0
  15. package/plugin/scripts/dashboard-service.sh +1 -0
  16. package/plugin/scripts/ensure-plugin-root.sh +7 -14
  17. package/plugin/scripts/hook_entry.sh +1 -0
  18. package/plugin/scripts/smart-install.sh +18 -2
  19. package/plugin/src/claude_smart/cli.py +72 -38
  20. package/plugin/src/claude_smart/context_format.py +11 -12
  21. package/plugin/src/claude_smart/cs_cite.py +26 -12
  22. package/plugin/src/claude_smart/ids.py +13 -5
  23. package/plugin/uv.lock +1 -1
  24. package/plugin/vendor/reflexio/.env.example +53 -0
  25. package/plugin/vendor/reflexio/LICENSE +201 -0
  26. package/plugin/vendor/reflexio/README.md +338 -0
  27. package/plugin/vendor/reflexio/pyproject.toml +271 -0
  28. package/plugin/vendor/reflexio/reflexio/README.md +184 -0
  29. package/plugin/vendor/reflexio/reflexio/__init__.py +166 -0
  30. package/plugin/vendor/reflexio/reflexio/benchmarks/__init__.py +1 -0
  31. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/README.md +109 -0
  32. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/__init__.py +1 -0
  33. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/backends.py +175 -0
  34. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/bench.py +642 -0
  35. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/embed_cache.py +330 -0
  36. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/report.py +317 -0
  37. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/results/report.md +43 -0
  38. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/results/results.json +4478 -0
  39. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/scenarios.py +134 -0
  40. package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/seed.py +255 -0
  41. package/plugin/vendor/reflexio/reflexio/cli/README.md +287 -0
  42. package/plugin/vendor/reflexio/reflexio/cli/__init__.py +0 -0
  43. package/plugin/vendor/reflexio/reflexio/cli/__main__.py +56 -0
  44. package/plugin/vendor/reflexio/reflexio/cli/_client.py +86 -0
  45. package/plugin/vendor/reflexio/reflexio/cli/app.py +127 -0
  46. package/plugin/vendor/reflexio/reflexio/cli/bootstrap_config.py +266 -0
  47. package/plugin/vendor/reflexio/reflexio/cli/codex_auth.py +503 -0
  48. package/plugin/vendor/reflexio/reflexio/cli/commands/__init__.py +0 -0
  49. package/plugin/vendor/reflexio/reflexio/cli/commands/admin_cmd.py +65 -0
  50. package/plugin/vendor/reflexio/reflexio/cli/commands/agent_playbooks.py +503 -0
  51. package/plugin/vendor/reflexio/reflexio/cli/commands/api.py +114 -0
  52. package/plugin/vendor/reflexio/reflexio/cli/commands/auth.py +109 -0
  53. package/plugin/vendor/reflexio/reflexio/cli/commands/config_cmd.py +511 -0
  54. package/plugin/vendor/reflexio/reflexio/cli/commands/doctor.py +127 -0
  55. package/plugin/vendor/reflexio/reflexio/cli/commands/embeddings.py +53 -0
  56. package/plugin/vendor/reflexio/reflexio/cli/commands/interactions.py +478 -0
  57. package/plugin/vendor/reflexio/reflexio/cli/commands/profiles.py +303 -0
  58. package/plugin/vendor/reflexio/reflexio/cli/commands/services.py +289 -0
  59. package/plugin/vendor/reflexio/reflexio/cli/commands/setup_cmd.py +961 -0
  60. package/plugin/vendor/reflexio/reflexio/cli/commands/shortcuts.py +285 -0
  61. package/plugin/vendor/reflexio/reflexio/cli/commands/status_cmd.py +143 -0
  62. package/plugin/vendor/reflexio/reflexio/cli/commands/user_playbooks.py +373 -0
  63. package/plugin/vendor/reflexio/reflexio/cli/env_loader.py +284 -0
  64. package/plugin/vendor/reflexio/reflexio/cli/errors.py +217 -0
  65. package/plugin/vendor/reflexio/reflexio/cli/log_format.py +247 -0
  66. package/plugin/vendor/reflexio/reflexio/cli/output.py +867 -0
  67. package/plugin/vendor/reflexio/reflexio/cli/paths.py +41 -0
  68. package/plugin/vendor/reflexio/reflexio/cli/run_services.py +391 -0
  69. package/plugin/vendor/reflexio/reflexio/cli/state.py +204 -0
  70. package/plugin/vendor/reflexio/reflexio/cli/stop_services.py +96 -0
  71. package/plugin/vendor/reflexio/reflexio/cli/utils.py +329 -0
  72. package/plugin/vendor/reflexio/reflexio/client/__init__.py +3 -0
  73. package/plugin/vendor/reflexio/reflexio/client/cache.py +150 -0
  74. package/plugin/vendor/reflexio/reflexio/client/client.py +2613 -0
  75. package/plugin/vendor/reflexio/reflexio/defaults.py +23 -0
  76. package/plugin/vendor/reflexio/reflexio/integrations/__init__.py +0 -0
  77. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/.clawhubignore +7 -0
  78. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/README.md +274 -0
  79. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/TESTING.md +517 -0
  80. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/hook/handler.js +473 -0
  81. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package-lock.json +2156 -0
  82. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package.json +18 -0
  83. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/handler.ts +241 -0
  84. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/setup.ts +140 -0
  85. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/index.ts +130 -0
  86. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/publish.ts +113 -0
  87. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/search.ts +52 -0
  88. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/server.ts +103 -0
  89. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/sqlite-buffer.ts +156 -0
  90. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/user-id.ts +134 -0
  91. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/openclaw.plugin.json +41 -0
  92. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/package.json +17 -0
  93. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/rules/reflexio.md +24 -0
  94. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/reflexio/SKILL.md +48 -0
  95. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/publish_clawhub.sh +278 -0
  96. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/references/HOOK.md +164 -0
  97. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/install.sh +36 -0
  98. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/uninstall.sh +35 -0
  99. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/publish.test.ts +27 -0
  100. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/search.test.ts +31 -0
  101. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/server.test.ts +42 -0
  102. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/setup.test.ts +49 -0
  103. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/sqlite-buffer.test.ts +91 -0
  104. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/user-id.test.ts +50 -0
  105. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tsconfig.json +16 -0
  106. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/types/openclaw.d.ts +230 -0
  107. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/vitest.config.ts +13 -0
  108. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/README.md +120 -0
  109. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/TESTING.md +168 -0
  110. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/package-lock.json +1657 -0
  111. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/package.json +16 -0
  112. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/HEARTBEAT.md +6 -0
  113. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/README.md +84 -0
  114. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/SKILL.md +194 -0
  115. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/_meta.json +6 -0
  116. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/agents/reflexio-extractor.md +45 -0
  117. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/hook/handler.ts +214 -0
  118. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/hook/setup.ts +55 -0
  119. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/index.ts +327 -0
  120. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/consolidate.ts +233 -0
  121. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/dedup.ts +80 -0
  122. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/io.ts +155 -0
  123. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/openclaw-cli.ts +67 -0
  124. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/search.ts +33 -0
  125. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/write-playbook.ts +76 -0
  126. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/write-profile.ts +79 -0
  127. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/openclaw.plugin.json +46 -0
  128. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/package.json +18 -0
  129. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/README.md +36 -0
  130. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/full_consolidation.md +56 -0
  131. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/playbook_extraction.md +217 -0
  132. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/profile_extraction.md +132 -0
  133. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/skills/reflexio-consolidate/SKILL.md +33 -0
  134. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/skills/reflexio-embedded/SKILL.md +194 -0
  135. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/HOOK.md +18 -0
  136. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/architecture.md +49 -0
  137. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/comparison.md +31 -0
  138. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/future-work.md +47 -0
  139. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/porting-notes.md +52 -0
  140. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/scripts/install.sh +52 -0
  141. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/scripts/uninstall.sh +36 -0
  142. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/consolidate.test.ts +135 -0
  143. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/dedup.test.ts +104 -0
  144. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/io.test.ts +175 -0
  145. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/search.test.ts +66 -0
  146. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/smoke-test.ts +140 -0
  147. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/write-playbook.test.ts +93 -0
  148. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/write-profile.test.ts +174 -0
  149. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tsconfig.json +16 -0
  150. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/types/openclaw.d.ts +230 -0
  151. package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/vitest.config.ts +7 -0
  152. package/plugin/vendor/reflexio/reflexio/lib/__init__.py +23 -0
  153. package/plugin/vendor/reflexio/reflexio/lib/_agent_playbook.py +310 -0
  154. package/plugin/vendor/reflexio/reflexio/lib/_base.py +225 -0
  155. package/plugin/vendor/reflexio/reflexio/lib/_config.py +83 -0
  156. package/plugin/vendor/reflexio/reflexio/lib/_dashboard.py +266 -0
  157. package/plugin/vendor/reflexio/reflexio/lib/_generation.py +176 -0
  158. package/plugin/vendor/reflexio/reflexio/lib/_interactions.py +334 -0
  159. package/plugin/vendor/reflexio/reflexio/lib/_operations.py +153 -0
  160. package/plugin/vendor/reflexio/reflexio/lib/_profiles.py +545 -0
  161. package/plugin/vendor/reflexio/reflexio/lib/_reflection.py +52 -0
  162. package/plugin/vendor/reflexio/reflexio/lib/_search.py +167 -0
  163. package/plugin/vendor/reflexio/reflexio/lib/_storage_labels.py +103 -0
  164. package/plugin/vendor/reflexio/reflexio/lib/_user_playbook.py +288 -0
  165. package/plugin/vendor/reflexio/reflexio/lib/reflexio_lib.py +27 -0
  166. package/plugin/vendor/reflexio/reflexio/models/__init__.py +0 -0
  167. package/plugin/vendor/reflexio/reflexio/models/api_schema/__init__.py +0 -0
  168. package/plugin/vendor/reflexio/reflexio/models/api_schema/braintrust_schema.py +141 -0
  169. package/plugin/vendor/reflexio/reflexio/models/api_schema/common.py +41 -0
  170. package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/__init__.py +3 -0
  171. package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/entities.py +1103 -0
  172. package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/enums.py +63 -0
  173. package/plugin/vendor/reflexio/reflexio/models/api_schema/eval_overview_schema.py +487 -0
  174. package/plugin/vendor/reflexio/reflexio/models/api_schema/internal_schema.py +28 -0
  175. package/plugin/vendor/reflexio/reflexio/models/api_schema/pending_tool_call_schema.py +83 -0
  176. package/plugin/vendor/reflexio/reflexio/models/api_schema/retriever_schema.py +766 -0
  177. package/plugin/vendor/reflexio/reflexio/models/api_schema/service_schemas.py +9 -0
  178. package/plugin/vendor/reflexio/reflexio/models/api_schema/stall_state_schema.py +32 -0
  179. package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/__init__.py +3 -0
  180. package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/converters.py +177 -0
  181. package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/entities.py +129 -0
  182. package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/enums.py +25 -0
  183. package/plugin/vendor/reflexio/reflexio/models/api_schema/validators.py +280 -0
  184. package/plugin/vendor/reflexio/reflexio/models/config_schema.py +908 -0
  185. package/plugin/vendor/reflexio/reflexio/models/py.typed +0 -0
  186. package/plugin/vendor/reflexio/reflexio/server/OVERVIEW.md +90 -0
  187. package/plugin/vendor/reflexio/reflexio/server/README.md +616 -0
  188. package/plugin/vendor/reflexio/reflexio/server/__init__.py +210 -0
  189. package/plugin/vendor/reflexio/reflexio/server/__main__.py +132 -0
  190. package/plugin/vendor/reflexio/reflexio/server/_auth.py +25 -0
  191. package/plugin/vendor/reflexio/reflexio/server/api.py +2714 -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 +540 -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 +110 -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 +1595 -0
  206. package/plugin/vendor/reflexio/reflexio/server/llm/llm_utils.py +112 -0
  207. package/plugin/vendor/reflexio/reflexio/server/llm/model_defaults.py +469 -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 +210 -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 +255 -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 +177 -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 +699 -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_extraction_context/v4.0.2.prompt.md +254 -0
  245. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.1.0.prompt.md +274 -0
  246. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.2.0.prompt.md +279 -0
  247. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v1.0.0.prompt.md +73 -0
  248. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v2.0.0.prompt.md +86 -0
  249. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.0.0.prompt.md +97 -0
  250. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.1.0.prompt.md +119 -0
  251. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.2.0.prompt.md +123 -0
  252. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.3.0.prompt.md +127 -0
  253. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.0.0.prompt.md +14 -0
  254. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.1.0.prompt.md +24 -0
  255. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.2.0.prompt.md +29 -0
  256. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main_expert/v1.0.0.prompt.md +11 -0
  257. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main_expert/v1.1.0.prompt.md +21 -0
  258. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main_expert/v1.2.0.prompt.md +25 -0
  259. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_optimizer_judge/v1.0.0.prompt.md +37 -0
  260. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_optimizer_judge/v1.1.0.prompt.md +40 -0
  261. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_optimizer_judge/v1.2.0.prompt.md +36 -0
  262. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate/v1.0.0.prompt.md +45 -0
  263. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate/v2.0.0.prompt.md +81 -0
  264. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate/v3.0.0.prompt.md +80 -0
  265. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate_expert/v1.0.0.prompt.md +34 -0
  266. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_deduplication/v1.0.0.prompt.md +116 -0
  267. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_should_generate/v1.0.0.prompt.md +33 -0
  268. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_should_generate_override/v1.0.0.prompt.md +16 -0
  269. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.0.0.prompt.md +140 -0
  270. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.1.0.prompt.md +160 -0
  271. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_main/v1.0.0.prompt.md +14 -0
  272. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/query_reformulation/v1.0.0.prompt.md +19 -0
  273. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/rerank_relevance/v1.1.0.prompt.md +44 -0
  274. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/shadow_comparison/v1.0.0.prompt.md +43 -0
  275. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/shadow_content_evaluation/v1.0.0.prompt.md +33 -0
  276. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_evaluation/prompt_evaluation_dataset/feedback_extraction_main_v1.jsonl +10 -0
  277. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_evaluation/prompt_evaluation_dataset/profile_update_main_v1.jsonl +10 -0
  278. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_manager.py +280 -0
  279. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_schema.py +11 -0
  280. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/_eval_health.py +131 -0
  281. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_constants.py +60 -0
  282. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_service.py +228 -0
  283. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_utils.py +87 -0
  284. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluator.py +372 -0
  285. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/delayed_group_evaluator.py +156 -0
  286. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/group_evaluation_runner.py +340 -0
  287. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/regen_jobs.py +471 -0
  288. package/plugin/vendor/reflexio/reflexio/server/services/base_generation_service.py +1626 -0
  289. package/plugin/vendor/reflexio/reflexio/server/services/braintrust/__init__.py +0 -0
  290. package/plugin/vendor/reflexio/reflexio/server/services/braintrust/_cron.py +196 -0
  291. package/plugin/vendor/reflexio/reflexio/server/services/braintrust/_encryption.py +101 -0
  292. package/plugin/vendor/reflexio/reflexio/server/services/braintrust/client.py +167 -0
  293. package/plugin/vendor/reflexio/reflexio/server/services/braintrust/service.py +281 -0
  294. package/plugin/vendor/reflexio/reflexio/server/services/configurator/base_configurator.py +179 -0
  295. package/plugin/vendor/reflexio/reflexio/server/services/configurator/config_storage.py +62 -0
  296. package/plugin/vendor/reflexio/reflexio/server/services/configurator/configurator.py +87 -0
  297. package/plugin/vendor/reflexio/reflexio/server/services/configurator/local_file_config_storage.py +187 -0
  298. package/plugin/vendor/reflexio/reflexio/server/services/configurator/test_config_storage.py +162 -0
  299. package/plugin/vendor/reflexio/reflexio/server/services/deduplication_utils.py +112 -0
  300. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/__init__.py +0 -0
  301. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/distribution.py +33 -0
  302. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/eval_sampler.py +126 -0
  303. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/group_aggregation.py +192 -0
  304. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/hero_state.py +75 -0
  305. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/rule_attribution.py +97 -0
  306. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/service.py +515 -0
  307. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/shadow_aggregation.py +90 -0
  308. package/plugin/vendor/reflexio/reflexio/server/services/extraction/__init__.py +0 -0
  309. package/plugin/vendor/reflexio/reflexio/server/services/extraction/agent_run_records.py +91 -0
  310. package/plugin/vendor/reflexio/reflexio/server/services/extraction/invariants.py +303 -0
  311. package/plugin/vendor/reflexio/reflexio/server/services/extraction/outcome.py +25 -0
  312. package/plugin/vendor/reflexio/reflexio/server/services/extraction/pending_tool_call_dispatch.py +351 -0
  313. package/plugin/vendor/reflexio/reflexio/server/services/extraction/plan.py +138 -0
  314. package/plugin/vendor/reflexio/reflexio/server/services/extraction/prior_answer_search.py +217 -0
  315. package/plugin/vendor/reflexio/reflexio/server/services/extraction/resumable_agent.py +468 -0
  316. package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_scheduler.py +171 -0
  317. package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_worker.py +777 -0
  318. package/plugin/vendor/reflexio/reflexio/server/services/extraction/tools.py +1125 -0
  319. package/plugin/vendor/reflexio/reflexio/server/services/extractor_config_utils.py +91 -0
  320. package/plugin/vendor/reflexio/reflexio/server/services/extractor_interaction_utils.py +251 -0
  321. package/plugin/vendor/reflexio/reflexio/server/services/generation_service.py +689 -0
  322. package/plugin/vendor/reflexio/reflexio/server/services/operation_state_utils.py +835 -0
  323. package/plugin/vendor/reflexio/reflexio/server/services/playbook/README.md +89 -0
  324. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_aggregator.py +1388 -0
  325. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_consolidator.py +960 -0
  326. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_extractor.py +436 -0
  327. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_generation_service.py +808 -0
  328. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_service_constants.py +28 -0
  329. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_service_utils.py +362 -0
  330. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/__init__.py +24 -0
  331. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/assistant_webhook.py +246 -0
  332. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/gepa_adapter.py +291 -0
  333. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/judge.py +97 -0
  334. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/models.py +96 -0
  335. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/optimizer.py +645 -0
  336. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/rollout.py +35 -0
  337. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/scenario_resolver.py +93 -0
  338. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/scheduler.py +174 -0
  339. package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/__init__.py +26 -0
  340. package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/_document_expander.py +179 -0
  341. package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/_query_reformulator.py +297 -0
  342. package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_deduplicator.py +741 -0
  343. package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_extractor.py +462 -0
  344. package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_generation_service.py +734 -0
  345. package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_generation_service_utils.py +290 -0
  346. package/plugin/vendor/reflexio/reflexio/server/services/reflection/__init__.py +17 -0
  347. package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_extractor.py +247 -0
  348. package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_service.py +800 -0
  349. package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_service_utils.py +146 -0
  350. package/plugin/vendor/reflexio/reflexio/server/services/retrieval/__init__.py +0 -0
  351. package/plugin/vendor/reflexio/reflexio/server/services/retrieval/relevance_floor.py +70 -0
  352. package/plugin/vendor/reflexio/reflexio/server/services/search/__init__.py +0 -0
  353. package/plugin/vendor/reflexio/reflexio/server/services/service_utils.py +671 -0
  354. package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/__init__.py +1 -0
  355. package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/judge.py +184 -0
  356. package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/outcome.py +81 -0
  357. package/plugin/vendor/reflexio/reflexio/server/services/storage/constants.py +2 -0
  358. package/plugin/vendor/reflexio/reflexio/server/services/storage/error.py +11 -0
  359. package/plugin/vendor/reflexio/reflexio/server/services/storage/retention.py +154 -0
  360. package/plugin/vendor/reflexio/reflexio/server/services/storage/retention_mixin.py +155 -0
  361. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/__init__.py +59 -0
  362. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_agent_run.py +1253 -0
  363. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_base.py +1945 -0
  364. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_extras.py +600 -0
  365. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_operations.py +346 -0
  366. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_playbook.py +1378 -0
  367. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_profiles.py +747 -0
  368. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_requests.py +263 -0
  369. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_shadow_verdicts.py +193 -0
  370. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_share_links.py +166 -0
  371. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_stall_state.py +217 -0
  372. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/__init__.py +153 -0
  373. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_agent_run.py +372 -0
  374. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_base.py +71 -0
  375. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_extras.py +235 -0
  376. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_operations.py +170 -0
  377. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_playbook.py +677 -0
  378. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_profiles.py +250 -0
  379. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_requests.py +154 -0
  380. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_shadow_verdicts.py +130 -0
  381. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_share_links.py +93 -0
  382. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_stall_state.py +76 -0
  383. package/plugin/vendor/reflexio/reflexio/server/services/unified_search_service.py +568 -0
  384. package/plugin/vendor/reflexio/reflexio/server/site_var/README.md +77 -0
  385. package/plugin/vendor/reflexio/reflexio/server/site_var/feature_flags.py +116 -0
  386. package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_manager.py +263 -0
  387. package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/feature_flags.json +13 -0
  388. package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/llm_model_setting.json +7 -0
  389. package/plugin/vendor/reflexio/reflexio/server/tracing.py +158 -0
  390. package/plugin/vendor/reflexio/reflexio/server/usage_metrics.py +113 -0
  391. package/plugin/vendor/reflexio/reflexio/server/uvicorn_logging.py +76 -0
  392. package/plugin/vendor/reflexio/reflexio/test_support/__init__.py +1 -0
  393. package/plugin/vendor/reflexio/reflexio/test_support/llm_fixtures.py +62 -0
  394. package/plugin/vendor/reflexio/reflexio/test_support/llm_mock.py +242 -0
  395. package/plugin/vendor/reflexio/reflexio/test_support/llm_model_registry.py +129 -0
  396. package/plugin/vendor/reflexio/reflexio/test_support/skip_decorators.py +43 -0
@@ -0,0 +1,777 @@
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(config, ProfileExtractorConfig | PlaybookConfig):
165
+ return config
166
+ raise ResumeWorkerError(
167
+ f"Current extractor config not found for {run.binding.extractor_kind}"
168
+ )
169
+
170
+
171
+ def _log_config_hash_drift(
172
+ run: AgentRunRecord,
173
+ extractor_config: BaseModel,
174
+ ) -> None:
175
+ current_hash = build_scope_hash(extractor_config.model_dump(mode="json"))
176
+ if run.binding.extractor_config_hash and (
177
+ current_hash != run.binding.extractor_config_hash
178
+ ):
179
+ logger.info(
180
+ "event=resumable_extraction_config_hash_drift run_id=%s extractor_kind=%s "
181
+ "stored_hash=%s current_hash=%s",
182
+ run.id,
183
+ run.binding.extractor_kind,
184
+ run.binding.extractor_config_hash,
185
+ current_hash,
186
+ )
187
+
188
+
189
+ class ExtractionResumeWorker:
190
+ """Claim and resume finalized extraction runs with resolved tool results."""
191
+
192
+ def __init__(
193
+ self,
194
+ *,
195
+ request_context: RequestContext,
196
+ llm_client: LiteLLMClient | None = None,
197
+ worker_id: str | None = None,
198
+ ) -> None:
199
+ self.request_context = request_context
200
+ self.storage = _storage(request_context)
201
+ self.client = llm_client or _create_llm_client(request_context)
202
+ self.worker_id = worker_id or f"resume_worker_{uuid.uuid4().hex}"
203
+
204
+ def drain(self, *, max_runs: int = 10) -> int:
205
+ """Resume up to ``max_runs`` ready rows for this request context."""
206
+ resumed = 0
207
+ for _ in range(max_runs):
208
+ if self.run_once() is None:
209
+ break
210
+ resumed += 1
211
+ return resumed
212
+
213
+ def run_once(self) -> AgentRunRecord | None:
214
+ config = self.request_context.configurator.get_config()
215
+ pending_config = config.pending_tool_call_config
216
+ finalization_retry = self.storage.claim_finalization_failed_agent_run(
217
+ org_id=self.request_context.org_id,
218
+ worker_id=self.worker_id,
219
+ claim_ttl_seconds=pending_config.resume_claim_ttl_seconds,
220
+ )
221
+ if finalization_retry is not None:
222
+ return self._retry_finalization(finalization_retry)
223
+
224
+ run = self.storage.claim_ready_agent_run(
225
+ org_id=self.request_context.org_id,
226
+ worker_id=self.worker_id,
227
+ claim_ttl_seconds=pending_config.resume_claim_ttl_seconds,
228
+ )
229
+ if run is None:
230
+ return None
231
+
232
+ if run.max_steps_remaining is not None and run.max_steps_remaining <= 0:
233
+ return self.storage.update_agent_run_status(
234
+ run.id,
235
+ AgentRunStatus.FAILED,
236
+ last_error="Resumable extraction max-step budget exhausted",
237
+ )
238
+
239
+ try:
240
+ resolved_calls = self._load_resolved_tool_calls(run)
241
+ if not resolved_calls:
242
+ raise ResumeWorkerError(
243
+ f"Run {run.id} has no resolved, unconsumed tool calls"
244
+ )
245
+ items, pending_tool_call_ids = self._resume_run(run, resolved_calls)
246
+ except Exception as exc:
247
+ with sentry_tags(
248
+ subsystem="extraction",
249
+ op="resume_run",
250
+ org_id=self.request_context.org_id,
251
+ run_id=run.id,
252
+ error_type=type(exc).__name__,
253
+ ):
254
+ logger.exception(
255
+ "event=resumable_extraction_resume_failed run_id=%s",
256
+ run.id,
257
+ )
258
+ failed_status = (
259
+ AgentRunStatus.FAILED
260
+ if run.resume_attempts >= pending_config.max_resume_attempts
261
+ else AgentRunStatus.RESUME_READY
262
+ )
263
+ return self.storage.update_agent_run_status(
264
+ run.id,
265
+ failed_status,
266
+ next_resume_at=_next_retry_at(run.resume_attempts),
267
+ last_error=str(exc),
268
+ )
269
+
270
+ try:
271
+ self.storage.update_agent_run_status(run.id, AgentRunStatus.FINALIZING)
272
+ self._finalize_items(run, items)
273
+ self.storage.consume_run_tool_dependencies(run.id)
274
+ finalized_status = (
275
+ AgentRunStatus.FINALIZED_PENDING_TOOL
276
+ if pending_tool_call_ids
277
+ else AgentRunStatus.FINALIZED
278
+ )
279
+ return self.storage.update_agent_run_status(
280
+ run.id,
281
+ finalized_status,
282
+ pending_tool_call_ids=pending_tool_call_ids,
283
+ )
284
+ except Exception as exc:
285
+ with sentry_tags(
286
+ subsystem="extraction",
287
+ op="finalize_run",
288
+ org_id=self.request_context.org_id,
289
+ run_id=run.id,
290
+ error_type=type(exc).__name__,
291
+ ):
292
+ logger.exception(
293
+ "event=resumable_extraction_finalization_failed run_id=%s",
294
+ run.id,
295
+ )
296
+ next_attempt_count = run.finalization_attempts + 1
297
+ failed_status = (
298
+ AgentRunStatus.FAILED
299
+ if next_attempt_count >= pending_config.max_finalization_attempts
300
+ else AgentRunStatus.FINALIZATION_FAILED
301
+ )
302
+ return self.storage.update_agent_run_status(
303
+ run.id,
304
+ failed_status,
305
+ next_resume_at=_next_retry_at(next_attempt_count),
306
+ last_error=str(exc),
307
+ increment_finalization_attempts=True,
308
+ )
309
+
310
+ def _retry_finalization(self, run: AgentRunRecord) -> AgentRunRecord | None:
311
+ config = self.request_context.configurator.get_config()
312
+ pending_config = config.pending_tool_call_config
313
+ try:
314
+ items, pending_tool_call_ids = self._items_from_committed_output(run)
315
+ self._finalize_items(run, items)
316
+ self.storage.consume_run_tool_dependencies(run.id)
317
+ finalized_status = (
318
+ AgentRunStatus.FINALIZED_PENDING_TOOL
319
+ if pending_tool_call_ids
320
+ else AgentRunStatus.FINALIZED
321
+ )
322
+ return self.storage.update_agent_run_status(
323
+ run.id,
324
+ finalized_status,
325
+ pending_tool_call_ids=pending_tool_call_ids,
326
+ )
327
+ except Exception as exc:
328
+ with sentry_tags(
329
+ subsystem="extraction",
330
+ op="finalize_run_retry",
331
+ org_id=self.request_context.org_id,
332
+ run_id=run.id,
333
+ error_type=type(exc).__name__,
334
+ ):
335
+ logger.exception(
336
+ "event=resumable_extraction_finalization_retry_failed run_id=%s",
337
+ run.id,
338
+ )
339
+ next_attempt_count = run.finalization_attempts + 1
340
+ failed_status = (
341
+ AgentRunStatus.FAILED
342
+ if next_attempt_count >= pending_config.max_finalization_attempts
343
+ else AgentRunStatus.FINALIZATION_FAILED
344
+ )
345
+ return self.storage.update_agent_run_status(
346
+ run.id,
347
+ failed_status,
348
+ next_resume_at=_next_retry_at(next_attempt_count),
349
+ last_error=str(exc),
350
+ increment_finalization_attempts=True,
351
+ )
352
+
353
+ def _load_resolved_tool_calls(
354
+ self,
355
+ run: AgentRunRecord,
356
+ ) -> list[PendingToolCallRecord]:
357
+ records: list[PendingToolCallRecord] = []
358
+ for dependency in self.storage.list_run_tool_dependencies(run.id):
359
+ if dependency.consumed_at is not None or dependency.resolved_at is None:
360
+ continue
361
+ record = self.storage.get_pending_tool_call(dependency.pending_tool_call_id)
362
+ if record and record.status == PendingToolCallStatus.RESOLVED:
363
+ records.append(record)
364
+ return sorted(
365
+ records,
366
+ key=lambda record: record.resolved_at or datetime.max.replace(tzinfo=UTC),
367
+ )
368
+
369
+ def _extra_tools_for_run(
370
+ self,
371
+ run: AgentRunRecord,
372
+ ) -> tuple[list[Any], PendingToolCallToolContext | None]:
373
+ pending_config = (
374
+ self.request_context.configurator.get_config().pending_tool_call_config
375
+ )
376
+ tools = create_pending_info_tools_for_extractor_kind(run.binding.extractor_kind)
377
+ return tools, PendingToolCallToolContext(
378
+ storage=self.storage,
379
+ run_id=run.id,
380
+ org_id=self.request_context.org_id,
381
+ extractor_kind=run.binding.extractor_kind,
382
+ user_id=run.binding.user_id,
383
+ config=pending_config,
384
+ )
385
+
386
+ def _resume_run(
387
+ self,
388
+ run: AgentRunRecord,
389
+ resolved_calls: list[PendingToolCallRecord],
390
+ ) -> tuple[list[Any], list[str]]:
391
+ request_interaction_data_models = _request_interaction_models_from_ids(
392
+ self.storage,
393
+ run.binding.source_interaction_ids,
394
+ fallback_source=run.binding.source,
395
+ fallback_agent_version=run.binding.agent_version,
396
+ )
397
+ extractor_config = _select_current_extractor_config(self.request_context, run)
398
+ _log_config_hash_drift(run, extractor_config)
399
+ if run.binding.extractor_kind == "profile":
400
+ return self._resume_profile(
401
+ run,
402
+ extractor_config,
403
+ request_interaction_data_models,
404
+ resolved_calls,
405
+ )
406
+ if run.binding.extractor_kind == "playbook":
407
+ return self._resume_playbook(
408
+ run,
409
+ extractor_config,
410
+ request_interaction_data_models,
411
+ resolved_calls,
412
+ )
413
+ raise ResumeWorkerError(
414
+ f"Unsupported extractor kind {run.binding.extractor_kind!r}"
415
+ )
416
+
417
+ def _resume_profile(
418
+ self,
419
+ run: AgentRunRecord,
420
+ extractor_config: ProfileExtractorConfig | PlaybookConfig,
421
+ request_interaction_data_models: list[RequestInteractionDataModel],
422
+ resolved_calls: list[PendingToolCallRecord],
423
+ ) -> tuple[list[Any], list[str]]:
424
+ if not isinstance(extractor_config, ProfileExtractorConfig):
425
+ raise ResumeWorkerError("Expected profile extractor config")
426
+ if run.binding.user_id is None:
427
+ raise ResumeWorkerError("Profile resume requires user_id")
428
+
429
+ existing_profiles = self.storage.get_user_profile(run.binding.user_id)
430
+ context_profiles = sorted(
431
+ existing_profiles,
432
+ key=lambda profile: profile.last_modified_timestamp,
433
+ reverse=True,
434
+ )[:MAX_EXISTING_PROFILES_FOR_CONTEXT]
435
+ agent_context = self.request_context.configurator.get_agent_context()
436
+ service_config = ProfileGenerationServiceConfig(
437
+ user_id=run.binding.user_id,
438
+ request_id=run.binding.request_id,
439
+ source=run.binding.source,
440
+ existing_data=existing_profiles,
441
+ auto_run=False,
442
+ force_extraction=True,
443
+ )
444
+ extractor = ProfileExtractor(
445
+ request_context=self.request_context,
446
+ llm_client=self.client,
447
+ extractor_config=extractor_config,
448
+ service_config=service_config,
449
+ agent_context=agent_context,
450
+ )
451
+ messages = construct_profile_extraction_messages_from_sessions(
452
+ prompt_manager=self.request_context.prompt_manager,
453
+ request_interaction_data_models=request_interaction_data_models,
454
+ agent_context_prompt=agent_context,
455
+ context_prompt=(
456
+ extractor_config.context_prompt.strip()
457
+ if extractor_config.context_prompt
458
+ else ""
459
+ ),
460
+ extraction_definition_prompt=extractor_config.extraction_definition_prompt.strip(),
461
+ metadata_definition_prompt=(
462
+ extractor_config.metadata_definition_prompt.strip()
463
+ if extractor_config.metadata_definition_prompt
464
+ else None
465
+ ),
466
+ existing_profiles=context_profiles,
467
+ )
468
+ result = self._resume_agent(
469
+ run=run,
470
+ messages=self._messages_with_prior_knowledge(
471
+ run=run,
472
+ messages=messages,
473
+ extractor_config=extractor_config,
474
+ resolved_calls=resolved_calls,
475
+ ),
476
+ output_schema=StructuredProfilesOutput,
477
+ resolved_calls=resolved_calls,
478
+ log_label="Profile extraction resume",
479
+ )
480
+ if not isinstance(result.output, StructuredProfilesOutput):
481
+ raise ResumeWorkerError(
482
+ f"Profile resume did not finish: {result.finished_reason}"
483
+ )
484
+ raw_profiles = [
485
+ profile.model_dump() for profile in result.output.profiles or []
486
+ ]
487
+ return (
488
+ extractor._convert_raw_to_user_profiles(
489
+ raw_profiles=raw_profiles,
490
+ user_id=run.binding.user_id,
491
+ request_id=run.binding.request_id,
492
+ ),
493
+ result.pending_tool_call_ids,
494
+ )
495
+
496
+ def _resume_playbook(
497
+ self,
498
+ run: AgentRunRecord,
499
+ extractor_config: ProfileExtractorConfig | PlaybookConfig,
500
+ request_interaction_data_models: list[RequestInteractionDataModel],
501
+ resolved_calls: list[PendingToolCallRecord],
502
+ ) -> tuple[list[Any], list[str]]:
503
+ if not isinstance(extractor_config, PlaybookConfig):
504
+ raise ResumeWorkerError("Expected playbook extractor config")
505
+
506
+ agent_context = self.request_context.configurator.get_agent_context()
507
+ service_config = PlaybookGenerationServiceConfig(
508
+ request_id=run.binding.request_id,
509
+ agent_version=run.binding.agent_version or "",
510
+ user_id=run.binding.user_id,
511
+ source=run.binding.source,
512
+ auto_run=False,
513
+ force_extraction=True,
514
+ )
515
+ extractor = PlaybookExtractor(
516
+ request_context=self.request_context,
517
+ llm_client=self.client,
518
+ extractor_config=extractor_config,
519
+ service_config=service_config,
520
+ agent_context=agent_context,
521
+ )
522
+ source_interaction_ids = [
523
+ interaction.interaction_id
524
+ for data_model in request_interaction_data_models
525
+ for interaction in data_model.interactions
526
+ if interaction.interaction_id
527
+ ]
528
+ playbook_definition = (
529
+ extractor_config.extraction_definition_prompt.strip()
530
+ if extractor_config.extraction_definition_prompt
531
+ else ""
532
+ )
533
+ all_interactions = extract_interactions_from_request_interaction_data_models(
534
+ request_interaction_data_models
535
+ )
536
+ prompt_manager = self.request_context.prompt_manager
537
+ if has_expert_content(all_interactions):
538
+ messages = construct_expert_playbook_extraction_messages(
539
+ prompt_manager=prompt_manager,
540
+ request_interaction_data_models=request_interaction_data_models,
541
+ agent_context_prompt=agent_context,
542
+ extraction_definition_prompt=playbook_definition,
543
+ )
544
+ else:
545
+ root_config = self.request_context.configurator.get_config()
546
+ tool_can_use = ""
547
+ if root_config and root_config.tool_can_use:
548
+ tool_can_use = "\n".join(
549
+ [
550
+ f"{tool.tool_name}: {tool.tool_description}"
551
+ for tool in root_config.tool_can_use
552
+ ]
553
+ )
554
+ messages = construct_playbook_extraction_messages_from_sessions(
555
+ prompt_manager=prompt_manager,
556
+ request_interaction_data_models=request_interaction_data_models,
557
+ agent_context_prompt=agent_context,
558
+ extraction_definition_prompt=playbook_definition,
559
+ tool_can_use=tool_can_use,
560
+ )
561
+ result = self._resume_agent(
562
+ run=run,
563
+ messages=self._messages_with_prior_knowledge(
564
+ run=run,
565
+ messages=messages,
566
+ extractor_config=extractor_config,
567
+ resolved_calls=resolved_calls,
568
+ ),
569
+ output_schema=StructuredPlaybookList,
570
+ resolved_calls=resolved_calls,
571
+ log_label="Playbook extraction resume",
572
+ )
573
+ if not isinstance(result.output, StructuredPlaybookList):
574
+ raise ResumeWorkerError(
575
+ f"Playbook resume did not finish: {result.finished_reason}"
576
+ )
577
+ return (
578
+ extractor._process_structured_response_list(
579
+ result.output,
580
+ source_interaction_ids=source_interaction_ids,
581
+ ),
582
+ result.pending_tool_call_ids,
583
+ )
584
+
585
+ def _messages_with_prior_knowledge(
586
+ self,
587
+ *,
588
+ run: AgentRunRecord,
589
+ messages: list[dict[str, Any]],
590
+ extractor_config: BaseModel,
591
+ resolved_calls: list[PendingToolCallRecord] | None = None,
592
+ ) -> list[dict[str, Any]]:
593
+ pending_config = (
594
+ self.request_context.configurator.get_config().pending_tool_call_config
595
+ )
596
+ # Prior-knowledge context is always injected within the resumable path.
597
+ return append_prior_knowledge_context(
598
+ messages=messages,
599
+ storage=self.storage,
600
+ org_id=self.request_context.org_id,
601
+ extractor_kind=run.binding.extractor_kind,
602
+ extractor_config=extractor_config,
603
+ source=run.binding.source,
604
+ agent_version=run.binding.agent_version,
605
+ similarity_threshold=pending_config.for_tool(
606
+ "ask_human"
607
+ ).similarity_threshold,
608
+ # Avoid re-surfacing the run's own just-resolved answers, which are
609
+ # injected separately as explicit resolved-tool-result messages.
610
+ exclude_pending_tool_call_ids={call.id for call in resolved_calls or []},
611
+ )
612
+
613
+ def _resume_agent(
614
+ self,
615
+ *,
616
+ run: AgentRunRecord,
617
+ messages: list[dict[str, Any]],
618
+ output_schema: type[BaseModel],
619
+ resolved_calls: list[PendingToolCallRecord],
620
+ log_label: str,
621
+ ) -> AgentRunResult:
622
+ extra_tools, extra_context = self._extra_tools_for_run(run)
623
+ return ResumableExtractionAgent(
624
+ client=self.client,
625
+ storage=self.storage,
626
+ ).resume(
627
+ run=run,
628
+ messages=messages,
629
+ output_schema=output_schema,
630
+ resolved_tool_calls=resolved_calls,
631
+ extra_tools=extra_tools,
632
+ extra_tool_context=extra_context,
633
+ log_label=log_label,
634
+ )
635
+
636
+ def _items_from_committed_output(
637
+ self,
638
+ run: AgentRunRecord,
639
+ ) -> tuple[list[Any], list[str]]:
640
+ if run.committed_output is None:
641
+ raise ResumeWorkerError(
642
+ f"Run {run.id} cannot retry finalization without committed output"
643
+ )
644
+ request_interaction_data_models = _request_interaction_models_from_ids(
645
+ self.storage,
646
+ run.binding.source_interaction_ids,
647
+ fallback_source=run.binding.source,
648
+ fallback_agent_version=run.binding.agent_version,
649
+ )
650
+ extractor_config = _select_current_extractor_config(self.request_context, run)
651
+ if run.binding.extractor_kind == "profile":
652
+ return self._profile_items_from_output(
653
+ run,
654
+ extractor_config,
655
+ run.committed_output,
656
+ )
657
+ if run.binding.extractor_kind == "playbook":
658
+ return self._playbook_items_from_output(
659
+ run,
660
+ extractor_config,
661
+ request_interaction_data_models,
662
+ run.committed_output,
663
+ )
664
+ raise ResumeWorkerError(
665
+ f"Unsupported extractor kind {run.binding.extractor_kind!r}"
666
+ )
667
+
668
+ def _profile_items_from_output(
669
+ self,
670
+ run: AgentRunRecord,
671
+ extractor_config: ProfileExtractorConfig | PlaybookConfig,
672
+ committed_output: dict[str, Any],
673
+ ) -> tuple[list[Any], list[str]]:
674
+ if not isinstance(extractor_config, ProfileExtractorConfig):
675
+ raise ResumeWorkerError("Expected profile extractor config")
676
+ if run.binding.user_id is None:
677
+ raise ResumeWorkerError("Profile finalization retry requires user_id")
678
+ output = StructuredProfilesOutput.model_validate(committed_output)
679
+ agent_context = self.request_context.configurator.get_agent_context()
680
+ service_config = ProfileGenerationServiceConfig(
681
+ user_id=run.binding.user_id,
682
+ request_id=run.binding.request_id,
683
+ source=run.binding.source,
684
+ existing_data=self.storage.get_user_profile(run.binding.user_id),
685
+ auto_run=False,
686
+ force_extraction=True,
687
+ )
688
+ extractor = ProfileExtractor(
689
+ request_context=self.request_context,
690
+ llm_client=self.client,
691
+ extractor_config=extractor_config,
692
+ service_config=service_config,
693
+ agent_context=agent_context,
694
+ )
695
+ raw_profiles = [profile.model_dump() for profile in output.profiles or []]
696
+ return (
697
+ extractor._convert_raw_to_user_profiles(
698
+ raw_profiles=raw_profiles,
699
+ user_id=run.binding.user_id,
700
+ request_id=run.binding.request_id,
701
+ ),
702
+ run.pending_tool_call_ids,
703
+ )
704
+
705
+ def _playbook_items_from_output(
706
+ self,
707
+ run: AgentRunRecord,
708
+ extractor_config: ProfileExtractorConfig | PlaybookConfig,
709
+ request_interaction_data_models: list[RequestInteractionDataModel],
710
+ committed_output: dict[str, Any],
711
+ ) -> tuple[list[Any], list[str]]:
712
+ if not isinstance(extractor_config, PlaybookConfig):
713
+ raise ResumeWorkerError("Expected playbook extractor config")
714
+ output = StructuredPlaybookList.model_validate(committed_output)
715
+ agent_context = self.request_context.configurator.get_agent_context()
716
+ service_config = PlaybookGenerationServiceConfig(
717
+ request_id=run.binding.request_id,
718
+ agent_version=run.binding.agent_version or "",
719
+ user_id=run.binding.user_id,
720
+ source=run.binding.source,
721
+ auto_run=False,
722
+ force_extraction=True,
723
+ )
724
+ extractor = PlaybookExtractor(
725
+ request_context=self.request_context,
726
+ llm_client=self.client,
727
+ extractor_config=extractor_config,
728
+ service_config=service_config,
729
+ agent_context=agent_context,
730
+ )
731
+ source_interaction_ids = [
732
+ interaction.interaction_id
733
+ for data_model in request_interaction_data_models
734
+ for interaction in data_model.interactions
735
+ if interaction.interaction_id
736
+ ]
737
+ return (
738
+ extractor._process_structured_response_list(
739
+ output,
740
+ source_interaction_ids=source_interaction_ids,
741
+ ),
742
+ run.pending_tool_call_ids,
743
+ )
744
+
745
+ def _finalize_items(self, run: AgentRunRecord, items: list[Any]) -> None:
746
+ if run.binding.extractor_kind == "profile":
747
+ service = ProfileGenerationService(
748
+ llm_client=self.client,
749
+ request_context=self.request_context,
750
+ )
751
+ service.service_config = ProfileGenerationServiceConfig(
752
+ user_id=run.binding.user_id or "",
753
+ request_id=run.binding.request_id,
754
+ source=run.binding.source,
755
+ auto_run=False,
756
+ force_extraction=True,
757
+ )
758
+ service._finalize_extracted_items(items)
759
+ return
760
+ if run.binding.extractor_kind == "playbook":
761
+ service = PlaybookGenerationService(
762
+ llm_client=self.client,
763
+ request_context=self.request_context,
764
+ )
765
+ service.service_config = PlaybookGenerationServiceConfig(
766
+ request_id=run.binding.request_id,
767
+ agent_version=run.binding.agent_version or "",
768
+ user_id=run.binding.user_id,
769
+ source=run.binding.source,
770
+ auto_run=False,
771
+ force_extraction=True,
772
+ )
773
+ service._finalize_extracted_items(items)
774
+ return
775
+ raise ResumeWorkerError(
776
+ f"Unsupported extractor kind {run.binding.extractor_kind!r}"
777
+ )