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,96 @@
1
+ """Stop reflexio services."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+
7
+ from dotenv import load_dotenv
8
+
9
+ from reflexio.cli.run_services import parse_only_flag, resolve_ports
10
+ from reflexio.cli.utils import stop_services
11
+
12
+
13
+ def add_arguments(parser: argparse.ArgumentParser) -> None:
14
+ """Add stop-services arguments to the parser."""
15
+ parser.add_argument(
16
+ "--backend-port",
17
+ type=int,
18
+ default=None,
19
+ help="Backend port (default: 8081, env: BACKEND_PORT)",
20
+ )
21
+ parser.add_argument(
22
+ "--docs-port",
23
+ type=int,
24
+ default=None,
25
+ help="Docs port (default: 8082, env: DOCS_PORT)",
26
+ )
27
+ parser.add_argument(
28
+ "--embedding-port",
29
+ type=int,
30
+ default=None,
31
+ help="Embedding service port (default: 8072, env: EMBEDDING_PORT)",
32
+ )
33
+ parser.add_argument(
34
+ "--only",
35
+ type=str,
36
+ default=None,
37
+ help="Comma-separated list of services to stop: backend,docs,embedding",
38
+ )
39
+ parser.add_argument(
40
+ "--force",
41
+ action="store_true",
42
+ help="SIGKILL immediately (skip graceful shutdown)",
43
+ )
44
+
45
+
46
+ def build_stop_targets(
47
+ only: set[str],
48
+ ports: dict[str, int],
49
+ *,
50
+ backend_pattern: str = "uvicorn reflexio.server.api:app",
51
+ ) -> tuple[dict[str, int], dict[str, str]]:
52
+ """Build port_map and process_patterns for stopping services.
53
+
54
+ Args:
55
+ only: Set of service names to stop
56
+ ports: Resolved port map
57
+ backend_pattern: Process pattern for the backend service
58
+
59
+ Returns:
60
+ Tuple of (port_map, process_patterns)
61
+ """
62
+ port_map: dict[str, int] = {}
63
+ process_patterns: dict[str, str] = {}
64
+
65
+ if "backend" in only:
66
+ port_map["backend"] = ports["backend"]
67
+ process_patterns["backend"] = backend_pattern
68
+
69
+ if "docs" in only:
70
+ port_map["docs"] = ports["docs"]
71
+ process_patterns["docs"] = f"next dev.*-p {ports['docs']}"
72
+
73
+ if "embedding" in only:
74
+ port_map["embedding"] = ports["embedding"]
75
+ process_patterns["embedding"] = "reflexio.server.llm.embedding_service:app"
76
+
77
+ return port_map, process_patterns
78
+
79
+
80
+ def execute(args: argparse.Namespace) -> None:
81
+ """Execute the stop-services command."""
82
+ load_dotenv()
83
+
84
+ ports = resolve_ports(
85
+ args, defaults={"backend": 8081, "docs": 8082, "embedding": 8072}
86
+ )
87
+ only = parse_only_flag(args.only, {"backend", "docs", "embedding"})
88
+ port_map, process_patterns = build_stop_targets(only, ports)
89
+
90
+ if not port_map:
91
+ print("No services selected. Available: backend, docs, embedding")
92
+ return
93
+
94
+ print("Stopping services...")
95
+ stop_services(port_map, process_patterns, force=args.force)
96
+ print("All services stopped.")
@@ -0,0 +1,329 @@
1
+ """Shared utilities for service process management."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import contextlib
6
+ import dataclasses
7
+ import hashlib
8
+ import json
9
+ import os
10
+ import signal
11
+ import subprocess
12
+ import sys
13
+ import tempfile
14
+ import threading
15
+ import time
16
+ from collections.abc import Callable
17
+ from pathlib import Path
18
+
19
+ from reflexio.cli.log_format import format_service_line
20
+
21
+
22
+ @dataclasses.dataclass
23
+ class ServiceConfig:
24
+ """Configuration for a single service to launch."""
25
+
26
+ name: str
27
+ command: list[str]
28
+ cwd: str | None = None
29
+ env: dict[str, str] | None = None
30
+
31
+
32
+ def get_env_port(name: str, default: int) -> int:
33
+ """Read a port from an environment variable, falling back to default."""
34
+ val = os.environ.get(name)
35
+ if val is not None:
36
+ try:
37
+ return int(val)
38
+ except ValueError:
39
+ print(f"Warning: invalid {name}={val!r}, using default {default}")
40
+ return default
41
+
42
+
43
+ def find_pids_on_port(port: int) -> list[int]:
44
+ """Find process IDs listening on the given port using lsof."""
45
+ try:
46
+ result = subprocess.run(
47
+ ["lsof", "-t", f"-i:{port}"],
48
+ capture_output=True,
49
+ text=True,
50
+ check=False,
51
+ )
52
+ if result.returncode == 0 and result.stdout.strip():
53
+ return [
54
+ int(p) for p in result.stdout.strip().split("\n") if p.strip().isdigit()
55
+ ]
56
+ except FileNotFoundError:
57
+ pass
58
+ return []
59
+
60
+
61
+ def find_pids_by_pattern(pattern: str) -> list[int]:
62
+ """Find process IDs matching a command pattern using pgrep."""
63
+ try:
64
+ result = subprocess.run(
65
+ ["pgrep", "-f", pattern],
66
+ capture_output=True,
67
+ text=True,
68
+ check=False,
69
+ )
70
+ if result.returncode == 0 and result.stdout.strip():
71
+ return [
72
+ int(p) for p in result.stdout.strip().split("\n") if p.strip().isdigit()
73
+ ]
74
+ except FileNotFoundError:
75
+ pass
76
+ return []
77
+
78
+
79
+ def kill_processes(
80
+ pids: list[int], graceful_timeout: float = 2.0, force: bool = False
81
+ ) -> None:
82
+ """Kill processes: SIGTERM first, then SIGKILL survivors after timeout."""
83
+ if not pids:
84
+ return
85
+
86
+ unique_pids = list(set(pids))
87
+ my_pid = os.getpid()
88
+ unique_pids = [p for p in unique_pids if p != my_pid]
89
+
90
+ if not unique_pids:
91
+ return
92
+
93
+ sig = signal.SIGKILL if force else signal.SIGTERM
94
+ for pid in unique_pids:
95
+ try:
96
+ os.kill(pid, sig)
97
+ except ProcessLookupError:
98
+ pass
99
+ except PermissionError:
100
+ print(f"Warning: no permission to kill PID {pid}")
101
+
102
+ if force:
103
+ return
104
+
105
+ time.sleep(graceful_timeout)
106
+
107
+ for pid in unique_pids:
108
+ try:
109
+ os.kill(pid, signal.SIGKILL)
110
+ except ProcessLookupError:
111
+ pass
112
+ except PermissionError:
113
+ pass
114
+
115
+
116
+ def get_pidfile_path(ports: dict[str, int]) -> Path:
117
+ """Get a unique pidfile path based on the port combination."""
118
+ port_str = json.dumps(ports, sort_keys=True)
119
+ port_hash = hashlib.md5(port_str.encode()).hexdigest()[:8] # noqa: S324
120
+ return Path(tempfile.gettempdir()) / f"reflexio_services_{port_hash}.json"
121
+
122
+
123
+ def write_pidfile(pidfile: Path, service_pids: dict[str, int]) -> None:
124
+ """Write service PIDs to the pidfile."""
125
+ pidfile.write_text(json.dumps(service_pids, indent=2))
126
+
127
+
128
+ def read_pidfile(pidfile: Path) -> dict[str, int]:
129
+ """Read service PIDs from the pidfile. Returns empty dict if not found."""
130
+ if not pidfile.exists():
131
+ return {}
132
+ try:
133
+ return json.loads(pidfile.read_text())
134
+ except (json.JSONDecodeError, OSError): # fmt: skip
135
+ return {}
136
+
137
+
138
+ def remove_pidfile(pidfile: Path) -> None:
139
+ """Remove the pidfile if it exists."""
140
+ with contextlib.suppress(OSError):
141
+ pidfile.unlink(missing_ok=True)
142
+
143
+
144
+ # Patterns that indicate a service is ready to accept requests
145
+ _READY_PATTERNS: dict[str, list[str]] = {
146
+ "backend": ["Application startup complete"],
147
+ "embedding": ["Application startup complete"],
148
+ "frontend": ["Ready in"],
149
+ "docs": ["Ready in"],
150
+ }
151
+
152
+ # Extra env vars to suppress noise from subprocesses at source
153
+ _NOISE_SUPPRESSION_ENV: dict[str, dict[str, str]] = {
154
+ "backend": {"LITELLM_LOG": "ERROR"},
155
+ "embedding": {"LITELLM_LOG": "ERROR"},
156
+ "frontend": {"NODE_NO_WARNINGS": "1"},
157
+ "docs": {"NODE_NO_WARNINGS": "1"},
158
+ }
159
+
160
+
161
+ def _stream_output(
162
+ proc: subprocess.Popen[bytes],
163
+ service_name: str,
164
+ lock: threading.Lock,
165
+ ready_event: threading.Event,
166
+ ) -> None:
167
+ """Read subprocess stdout line by line, prefix, and write to stdout.
168
+
169
+ Args:
170
+ proc: The subprocess to read from.
171
+ service_name: Name of the service for prefixing.
172
+ lock: Lock to prevent interleaved partial lines.
173
+ ready_event: Event to set when the service is ready.
174
+ """
175
+ ready_patterns = _READY_PATTERNS.get(service_name, [])
176
+ assert proc.stdout is not None # noqa: S101
177
+ for raw_line in proc.stdout:
178
+ line = raw_line.decode("utf-8", errors="replace").rstrip()
179
+ if not line:
180
+ continue
181
+ formatted = format_service_line(service_name, line)
182
+ with lock:
183
+ sys.stdout.write(formatted + "\n")
184
+ sys.stdout.flush()
185
+ # Check for ready patterns
186
+ if not ready_event.is_set() and any(p in line for p in ready_patterns):
187
+ ready_event.set()
188
+
189
+
190
+ def run_services(
191
+ services: list[ServiceConfig],
192
+ ports: dict[str, int],
193
+ *,
194
+ on_all_ready: Callable[[dict[str, int]], None] | None = None,
195
+ ) -> None:
196
+ """Launch services, pipe output with prefixes, and manage lifecycle.
197
+
198
+ Each service's stdout/stderr is captured and prefixed with a colored
199
+ service tag (e.g., [backend]). A callback is invoked when all services
200
+ report ready (or after a timeout).
201
+
202
+ Args:
203
+ services: List of service configurations to launch.
204
+ ports: Port mapping for pidfile identification.
205
+ on_all_ready: Optional callback invoked with ports when all services are ready.
206
+ """
207
+ processes: dict[str, subprocess.Popen[bytes]] = {}
208
+ threads: list[threading.Thread] = []
209
+ ready_events: dict[str, threading.Event] = {}
210
+ output_lock = threading.RLock()
211
+ pidfile = get_pidfile_path(ports)
212
+
213
+ def shutdown(_signum: int | None = None, _frame: object = None) -> None:
214
+ with output_lock:
215
+ sys.stdout.write("\nShutting down services...\n")
216
+ sys.stdout.flush()
217
+ for proc in processes.values():
218
+ with contextlib.suppress(OSError):
219
+ proc.terminate()
220
+ deadline = time.time() + 3.0
221
+ for proc in processes.values():
222
+ remaining = max(0, deadline - time.time())
223
+ try:
224
+ proc.wait(timeout=remaining)
225
+ except subprocess.TimeoutExpired:
226
+ with contextlib.suppress(OSError):
227
+ proc.kill()
228
+ for t in threads:
229
+ t.join(timeout=1.0)
230
+ remove_pidfile(pidfile)
231
+ sys.exit(0)
232
+
233
+ signal.signal(signal.SIGINT, shutdown)
234
+ signal.signal(signal.SIGTERM, shutdown)
235
+
236
+ for svc in services:
237
+ noise_env = _NOISE_SUPPRESSION_ENV.get(svc.name, {})
238
+ merged_env = {**os.environ, **(svc.env or {}), **noise_env}
239
+ with output_lock:
240
+ sys.stdout.write(f"Starting {svc.name}...\n")
241
+ sys.stdout.flush()
242
+ proc = subprocess.Popen(
243
+ svc.command,
244
+ cwd=svc.cwd,
245
+ env=merged_env,
246
+ stdout=subprocess.PIPE,
247
+ stderr=subprocess.STDOUT,
248
+ )
249
+ processes[svc.name] = proc
250
+ ready_event = threading.Event()
251
+ ready_events[svc.name] = ready_event
252
+ t = threading.Thread(
253
+ target=_stream_output,
254
+ args=(proc, svc.name, output_lock, ready_event),
255
+ daemon=True,
256
+ )
257
+ t.start()
258
+ threads.append(t)
259
+ with output_lock:
260
+ sys.stdout.write(f" {svc.name} started (PID {proc.pid})\n")
261
+ sys.stdout.flush()
262
+
263
+ # Write pidfile
264
+ pids = {name: proc.pid for name, proc in processes.items()}
265
+ write_pidfile(pidfile, pids)
266
+
267
+ # Wait for all services to be ready (or timeout with shared deadline)
268
+ if on_all_ready:
269
+ deadline = time.monotonic() + 60
270
+ all_ready = all(
271
+ evt.wait(timeout=max(0, deadline - time.monotonic()))
272
+ for evt in ready_events.values()
273
+ )
274
+ if all_ready:
275
+ on_all_ready(ports)
276
+
277
+ # Wait for any child to exit
278
+ try:
279
+ while processes:
280
+ for name, proc in list(processes.items()):
281
+ ret = proc.poll()
282
+ if ret is not None:
283
+ with output_lock:
284
+ sys.stdout.write(
285
+ format_service_line(name, f"exited with code {ret}") + "\n"
286
+ )
287
+ sys.stdout.flush()
288
+ del processes[name]
289
+ if processes:
290
+ time.sleep(0.5)
291
+ except KeyboardInterrupt:
292
+ shutdown()
293
+
294
+ remove_pidfile(pidfile)
295
+
296
+
297
+ def stop_services(
298
+ port_map: dict[str, int],
299
+ process_patterns: dict[str, str],
300
+ force: bool = False,
301
+ ) -> None:
302
+ """Stop services by port and process pattern.
303
+
304
+ Args:
305
+ port_map: Mapping of service name to port number.
306
+ process_patterns: Mapping of service name to pgrep pattern.
307
+ force: If True, send SIGKILL immediately instead of graceful shutdown.
308
+ """
309
+ pidfile = get_pidfile_path(port_map)
310
+ saved_pids = read_pidfile(pidfile)
311
+
312
+ for name, port in port_map.items():
313
+ pids_from_port = find_pids_on_port(port)
314
+ pids_from_pattern = (
315
+ find_pids_by_pattern(process_patterns[name])
316
+ if name in process_patterns
317
+ else []
318
+ )
319
+ pids_from_saved = [saved_pids[name]] if name in saved_pids else []
320
+
321
+ all_pids = list(set(pids_from_port + pids_from_pattern + pids_from_saved))
322
+
323
+ if all_pids:
324
+ kill_processes(all_pids, force=force)
325
+ print(f"Stopped {name} (port {port})")
326
+ else:
327
+ print(f"{name} (port {port}) not running")
328
+
329
+ remove_pidfile(pidfile)
@@ -0,0 +1,3 @@
1
+ from .client import ReflexioClient
2
+
3
+ __all__ = ["ReflexioClient"]
@@ -0,0 +1,150 @@
1
+ """In-memory cache module for Reflexio client."""
2
+
3
+ import hashlib
4
+ import json
5
+ import threading
6
+ from datetime import datetime, timedelta
7
+ from typing import Any
8
+
9
+
10
+ class InMemoryCache:
11
+ """
12
+ Thread-safe in-memory cache with time-based expiration.
13
+
14
+ Stores function results in memory to avoid redundant API calls.
15
+ Cache entries expire after a specified TTL (default: 10 minutes).
16
+ """
17
+
18
+ def __init__(self, ttl_seconds: int = 600):
19
+ """
20
+ Initialize the in-memory cache.
21
+
22
+ Args:
23
+ ttl_seconds (int): Time-to-live for cache entries in seconds. Default is 600 (10 minutes).
24
+ """
25
+ self._cache: dict[str, dict[str, Any]] = {}
26
+ self._lock = threading.Lock()
27
+ self._ttl_seconds = ttl_seconds
28
+
29
+ def _generate_cache_key(self, method_name: str, **kwargs) -> str:
30
+ """
31
+ Generate a unique cache key from method name and parameters.
32
+
33
+ Handles datetime objects, None values, and nested dictionaries.
34
+
35
+ Args:
36
+ method_name (str): Name of the cached method
37
+ **kwargs: Method parameters to include in the cache key
38
+
39
+ Returns:
40
+ str: Unique cache key hash
41
+ """
42
+ # Create a normalized representation of the parameters
43
+ normalized_params = {}
44
+ for key, value in sorted(kwargs.items()):
45
+ if isinstance(value, datetime):
46
+ # Convert datetime to ISO format string
47
+ normalized_params[key] = value.isoformat()
48
+ elif value is None:
49
+ normalized_params[key] = None
50
+ elif hasattr(value, "model_dump"):
51
+ # Handle Pydantic models
52
+ normalized_params[key] = value.model_dump()
53
+ elif isinstance(value, dict):
54
+ normalized_params[key] = value
55
+ else:
56
+ normalized_params[key] = value
57
+
58
+ # Create a stable JSON representation
59
+ key_data = {"method": method_name, "params": normalized_params}
60
+ key_string = json.dumps(key_data, sort_keys=True, default=str)
61
+
62
+ # Generate hash for the cache key
63
+ return hashlib.sha256(key_string.encode()).hexdigest()
64
+
65
+ def get(self, method_name: str, **kwargs) -> Any | None:
66
+ """
67
+ Retrieve a cached value if it exists and is not expired.
68
+
69
+ Args:
70
+ method_name (str): Name of the cached method
71
+ **kwargs: Method parameters used to generate cache key
72
+
73
+ Returns:
74
+ Optional[Any]: Cached value if found and valid, None otherwise
75
+ """
76
+ cache_key = self._generate_cache_key(method_name, **kwargs)
77
+
78
+ with self._lock:
79
+ if cache_key not in self._cache:
80
+ return None
81
+
82
+ entry = self._cache[cache_key]
83
+
84
+ # Check if entry has expired
85
+ if datetime.now() > entry["expires_at"]:
86
+ # Remove expired entry
87
+ del self._cache[cache_key]
88
+ return None
89
+
90
+ return entry["data"]
91
+
92
+ def set(self, method_name: str, value: Any, **kwargs) -> None:
93
+ """
94
+ Store a value in the cache with automatic expiration.
95
+
96
+ Args:
97
+ method_name (str): Name of the cached method
98
+ value (Any): Value to cache
99
+ **kwargs: Method parameters used to generate cache key
100
+ """
101
+ cache_key = self._generate_cache_key(method_name, **kwargs)
102
+
103
+ with self._lock:
104
+ self._cache[cache_key] = {
105
+ "data": value,
106
+ "method_name": method_name,
107
+ "timestamp": datetime.now(),
108
+ "expires_at": datetime.now() + timedelta(seconds=self._ttl_seconds),
109
+ }
110
+
111
+ # Cleanup expired entries periodically (every 100 sets)
112
+ if len(self._cache) % 100 == 0:
113
+ self._cleanup_expired()
114
+
115
+ def clear(self) -> None:
116
+ """Remove all entries from the cache."""
117
+ with self._lock:
118
+ self._cache.clear()
119
+
120
+ def invalidate(self, method_name: str) -> int:
121
+ """Remove all entries cached under a given method name.
122
+
123
+ Args:
124
+ method_name: The method name whose entries should be removed.
125
+
126
+ Returns:
127
+ int: Number of entries removed.
128
+ """
129
+ with self._lock:
130
+ keys_to_remove = [
131
+ key
132
+ for key, entry in self._cache.items()
133
+ if entry.get("method_name") == method_name
134
+ ]
135
+ for key in keys_to_remove:
136
+ del self._cache[key]
137
+ return len(keys_to_remove)
138
+
139
+ def _cleanup_expired(self) -> None:
140
+ """
141
+ Remove all expired entries from the cache.
142
+
143
+ Note: This method assumes the lock is already acquired by the caller.
144
+ """
145
+ now = datetime.now()
146
+ expired_keys = [
147
+ key for key, entry in self._cache.items() if now > entry["expires_at"]
148
+ ]
149
+ for key in expired_keys:
150
+ del self._cache[key]