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,217 @@
1
+ """Structured error handling for Reflexio CLI."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import contextlib
6
+ import functools
7
+ import json
8
+ import sys
9
+ from typing import Any
10
+
11
+ import requests
12
+ from pydantic import ValidationError
13
+
14
+ # Semantic exit codes (modeled on Lark CLI)
15
+ EXIT_SUCCESS = 0
16
+ EXIT_GENERAL = 1
17
+ EXIT_VALIDATION = 2
18
+ EXIT_AUTH = 3
19
+ EXIT_NETWORK = 4
20
+
21
+
22
+ class CliError(Exception):
23
+ """Structured CLI error with type, message, hint, and exit code.
24
+
25
+ Args:
26
+ error_type: Category of error (general, validation, auth, network, rate_limit)
27
+ message: Human-readable error description
28
+ hint: Actionable suggestion for fixing the error
29
+ exit_code: Process exit code (0-4)
30
+ """
31
+
32
+ def __init__(
33
+ self,
34
+ error_type: str = "general",
35
+ message: str = "An error occurred",
36
+ hint: str | None = None,
37
+ exit_code: int = EXIT_GENERAL,
38
+ ) -> None:
39
+ super().__init__(message)
40
+ self.error_type = error_type
41
+ self.message = message
42
+ self.hint = hint
43
+ self.exit_code = exit_code
44
+
45
+
46
+ def _classify_http_error(exc: requests.HTTPError) -> CliError:
47
+ """Map HTTP status codes to structured CliError instances.
48
+
49
+ Args:
50
+ exc: The HTTP error to classify
51
+
52
+ Returns:
53
+ CliError: Classified error with appropriate type, hint, and exit code
54
+ """
55
+ status = exc.response.status_code if exc.response is not None else 0
56
+
57
+ if status in (401, 403):
58
+ return CliError(
59
+ error_type="auth",
60
+ message=f"Authentication failed (HTTP {status})",
61
+ hint="Run: reflexio auth login --api-key <key> --server-url <url>",
62
+ exit_code=EXIT_AUTH,
63
+ )
64
+ if status == 422:
65
+ detail = ""
66
+ with contextlib.suppress(ValueError, AttributeError):
67
+ detail = exc.response.json().get("detail", "")
68
+ return CliError(
69
+ error_type="validation",
70
+ message=f"Invalid request: {detail or exc}",
71
+ exit_code=EXIT_VALIDATION,
72
+ )
73
+ if status == 429:
74
+ return CliError(
75
+ error_type="rate_limit",
76
+ message="Rate limit exceeded",
77
+ hint="Wait a moment and retry",
78
+ exit_code=EXIT_GENERAL,
79
+ )
80
+ return CliError(
81
+ error_type="general",
82
+ message=f"HTTP error: {exc}",
83
+ exit_code=EXIT_GENERAL,
84
+ )
85
+
86
+
87
+ def raise_if_failed(resp: object, default: str = "operation failed") -> None:
88
+ """Raise a ``CliError`` if the API response envelope reports failure.
89
+
90
+ Intended for CLI mutation commands (``add`` / ``update`` /
91
+ ``update-status``) so that ``success=False`` envelopes do not get
92
+ reported as a success. The server's response schemas use either
93
+ ``message`` or ``msg`` for the human-readable error string; both
94
+ are checked. Call only in non-JSON mode — JSON-mode callers
95
+ introspect the response envelope themselves.
96
+
97
+ Args:
98
+ resp: Response object returned by the client.
99
+ default: Fallback message when neither ``message`` nor ``msg`` is set.
100
+
101
+ Raises:
102
+ CliError: If ``resp.success`` is falsy. The wrapped
103
+ ``handle_errors`` decorator will render the error and
104
+ exit with ``EXIT_GENERAL``.
105
+ """
106
+ if getattr(resp, "success", True):
107
+ return
108
+ message = getattr(resp, "message", None) or getattr(resp, "msg", None) or default
109
+ raise CliError(
110
+ error_type="api",
111
+ message=message,
112
+ exit_code=EXIT_GENERAL,
113
+ )
114
+
115
+
116
+ def render_error(error: CliError, json_mode: bool = False) -> None:
117
+ """Render an error to stderr in structured or human-readable format.
118
+
119
+ Args:
120
+ error: The CLI error to render
121
+ json_mode: If True, output JSON envelope; otherwise plain text
122
+ """
123
+ if json_mode:
124
+ envelope: dict[str, Any] = {
125
+ "ok": False,
126
+ "error": {
127
+ "type": error.error_type,
128
+ "message": error.message,
129
+ },
130
+ }
131
+ if error.hint:
132
+ envelope["error"]["hint"] = error.hint
133
+ print(json.dumps(envelope, indent=2), file=sys.stderr)
134
+ else:
135
+ print(f"Error: {error.message}", file=sys.stderr)
136
+ if error.hint:
137
+ print(f"Hint: {error.hint}", file=sys.stderr)
138
+
139
+
140
+ def handle_errors(fn): # noqa: ANN001, ANN201
141
+ """Decorator that catches common exceptions and renders structured errors.
142
+
143
+ Catches ``CliError``, ``ConnectionError``, ``HTTPError``, and the
144
+ client's ``ReflexioAPIError`` (for "2xx with non-JSON body"
145
+ failures, typically a misconfigured ``REFLEXIO_URL`` pointing at a
146
+ marketing site or misrouting proxy), rendering them through the
147
+ structured error system before exiting with the appropriate code.
148
+ """
149
+ # Imported lazily to avoid a circular import: client.py → cli.output
150
+ # → cli.errors. The import only fires when the decorator is built.
151
+ from reflexio.client.client import ReflexioAPIError
152
+
153
+ @functools.wraps(fn)
154
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
155
+ # Determine json_mode from context if available
156
+ import typer
157
+
158
+ ctx = None
159
+ for arg in args:
160
+ if isinstance(arg, typer.Context):
161
+ ctx = arg
162
+ break
163
+
164
+ json_mode = False
165
+ if ctx and ctx.obj:
166
+ json_mode = getattr(ctx.obj, "json_mode", False)
167
+
168
+ try:
169
+ return fn(*args, **kwargs)
170
+ except CliError as exc:
171
+ # CliError must be caught first so its subclasses don't
172
+ # get swallowed by the generic ValueError branch below.
173
+ render_error(exc, json_mode=json_mode)
174
+ raise SystemExit(exc.exit_code) from None
175
+ except ValidationError as exc:
176
+ err = CliError(
177
+ error_type="validation",
178
+ message=str(exc),
179
+ exit_code=EXIT_VALIDATION,
180
+ )
181
+ render_error(err, json_mode=json_mode)
182
+ raise SystemExit(err.exit_code) from None
183
+ except ValueError as exc:
184
+ err = CliError(
185
+ error_type="validation",
186
+ message=str(exc),
187
+ exit_code=EXIT_VALIDATION,
188
+ )
189
+ render_error(err, json_mode=json_mode)
190
+ raise SystemExit(err.exit_code) from None
191
+ except requests.ConnectionError as exc:
192
+ err = CliError(
193
+ error_type="network",
194
+ message=f"Connection failed: {exc}",
195
+ hint="Is the Reflexio server running? Try: reflexio services start",
196
+ exit_code=EXIT_NETWORK,
197
+ )
198
+ render_error(err, json_mode=json_mode)
199
+ raise SystemExit(err.exit_code) from None
200
+ except requests.HTTPError as exc:
201
+ err = _classify_http_error(exc)
202
+ render_error(err, json_mode=json_mode)
203
+ raise SystemExit(err.exit_code) from None
204
+ except ReflexioAPIError as exc:
205
+ err = CliError(
206
+ error_type="api",
207
+ message=str(exc),
208
+ hint=(
209
+ "Double-check REFLEXIO_URL — it should point at your "
210
+ "Reflexio API host, not a marketing site or proxy."
211
+ ),
212
+ exit_code=EXIT_GENERAL,
213
+ )
214
+ render_error(err, json_mode=json_mode)
215
+ raise SystemExit(err.exit_code) from None
216
+
217
+ return wrapper
@@ -0,0 +1,247 @@
1
+ """Log formatting utilities for the dev server.
2
+
3
+ Provides colored service prefixes for subprocess output, a duplicate log filter,
4
+ and a startup banner for the multi-service dev server.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import itertools
10
+ import logging
11
+ import re
12
+ import sys
13
+ import threading
14
+ import time
15
+ from pathlib import Path
16
+
17
+ # ANSI color codes for service prefixes
18
+ SERVICE_COLORS: dict[str, str] = {
19
+ "backend": "34", # blue
20
+ "frontend": "32", # green
21
+ "docs": "35", # magenta
22
+ "supabase": "36", # cyan
23
+ }
24
+
25
+ # ANSI codes for log-level severity highlighting in service output.
26
+ # Keys are matched against the level token captured by `_LEVEL_RE`.
27
+ _LEVEL_COLORS: dict[str, str] = {
28
+ "ERROR": "31", # red
29
+ "CRITICAL": "1;31", # bold red
30
+ "WARNING": "33", # yellow
31
+ "WARN": "33", # yellow (Next.js / some loggers)
32
+ }
33
+
34
+ # Match a log-level token at the start of a line, optionally bracketed,
35
+ # followed by a typical separator (":", whitespace, or " - "). Covers
36
+ # uvicorn ("ERROR: msg"), stdlib logging ("[ERROR] msg"), and the
37
+ # "ERROR - msg" style used by Next.js / some custom loggers.
38
+ _LEVEL_RE = re.compile(r"^(?:\[)?(ERROR|CRITICAL|WARNING|WARN)(?:\])?(?::|\s+-\s+|\s+)")
39
+
40
+
41
+ # Canonical log file paths.
42
+ # Default: ~/.reflexio/logs/. The REFLEXIO_LOG_DIR env var overrides only the
43
+ # base directory (the ~ part) — the .reflexio/logs suffix is preserved so the
44
+ # on-disk layout stays consistent regardless of where the base points. Base
45
+ # resolution is delegated to ``reflexio_home`` so every ``~/.reflexio/*`` path
46
+ # honors the env var identically.
47
+ def _resolve_log_dir() -> Path:
48
+ """Return the directory log files are written to.
49
+
50
+ Resolved at module import time so the public ``DEV_LOG_FILE`` /
51
+ ``LLM_IO_LOG_FILE`` constants are stable across a server's lifetime —
52
+ change requires a restart.
53
+
54
+ Returns:
55
+ Path: Resolved log directory. Not created here — callers must
56
+ ``mkdir(parents=True, exist_ok=True)`` before opening any
57
+ file handler against ``DEV_LOG_FILE`` / ``LLM_IO_LOG_FILE``.
58
+ """
59
+ from .paths import reflexio_home
60
+
61
+ return reflexio_home() / "logs"
62
+
63
+
64
+ LOG_DIR: Path = _resolve_log_dir()
65
+ DEV_LOG_FILE: str = str(LOG_DIR / "dev_server.log")
66
+ LLM_IO_LOG_FILE: str = str(LOG_DIR / "llm_io.log")
67
+
68
+ # Thread-safe sequential entry counter for LLM prompt/response entries
69
+ _llm_entry_counter = itertools.count(1)
70
+ _llm_entry_lock = threading.Lock()
71
+
72
+
73
+ def next_llm_entry_id() -> int:
74
+ """Get the next sequential LLM log entry ID (thread-safe)."""
75
+ with _llm_entry_lock:
76
+ return next(_llm_entry_counter)
77
+
78
+
79
+ # Fixed-width for service prefix alignment
80
+ _PREFIX_WIDTH = 10
81
+
82
+
83
+ def colorize(text: str, ansi_code: str, *, bold: bool = False) -> str:
84
+ """Wrap text in ANSI escape sequences for terminal color.
85
+
86
+ Returns raw text when stdout is not a TTY (piped output, log files),
87
+ keeping output clean for AI agents and file parsing.
88
+
89
+ Args:
90
+ text: The text to colorize.
91
+ ansi_code: ANSI color code (e.g., "34" for blue).
92
+ bold: If True, also apply bold formatting.
93
+
94
+ Returns:
95
+ str: Colorized text if TTY, raw text otherwise.
96
+ """
97
+ if not sys.stdout.isatty():
98
+ return text
99
+ prefix = f"\033[1;{ansi_code}m" if bold else f"\033[{ansi_code}m"
100
+ return f"{prefix}{text}\033[0m"
101
+
102
+
103
+ def highlight_log_level(line: str) -> str:
104
+ """Wrap a line in a severity color if it starts with a log-level token.
105
+
106
+ Supports common formats: ``ERROR: msg``, ``[ERROR] msg``, ``ERROR - msg``.
107
+ Returns the line unchanged when stdout is not a TTY or no level matches,
108
+ keeping output clean for pipes, log files, and AI agents.
109
+
110
+ Args:
111
+ line: The log line content (without the service prefix).
112
+
113
+ Returns:
114
+ str: Color-wrapped line for ERROR/CRITICAL/WARNING; otherwise unchanged.
115
+ """
116
+ if not sys.stdout.isatty():
117
+ return line
118
+ match = _LEVEL_RE.match(line)
119
+ if not match:
120
+ return line
121
+ code = _LEVEL_COLORS[match.group(1)]
122
+ return f"\033[{code}m{line}\033[0m"
123
+
124
+
125
+ def format_service_line(service_name: str, line: str) -> str:
126
+ """Format a log line with a colored, fixed-width service prefix.
127
+
128
+ The line body is additionally wrapped in a severity color when it
129
+ starts with a recognised log-level token (ERROR/CRITICAL/WARNING),
130
+ so failures stand out against the scrolling dev-server output.
131
+
132
+ Args:
133
+ service_name: Name of the service (e.g., "backend", "frontend").
134
+ line: The log line content.
135
+
136
+ Returns:
137
+ str: Formatted line like "[backend ] message".
138
+ """
139
+ color = SERVICE_COLORS.get(service_name, "37") # default white
140
+ padded = service_name.ljust(_PREFIX_WIDTH - 2) # -2 for brackets
141
+ prefix = colorize(f"[{padded}]", color)
142
+ return f"{prefix} {highlight_log_level(line)}"
143
+
144
+
145
+ class DuplicateFilter(logging.Filter):
146
+ """Suppress duplicate log messages within a time window.
147
+
148
+ Keys on (logger_name, msg_template) — the message template string,
149
+ not the formatted output. This is stable across different args since
150
+ the template (e.g., "Supabase Storage for org %s uses URL %s") doesn't
151
+ change between calls.
152
+
153
+ Args:
154
+ window_seconds: Time window in seconds to suppress duplicates.
155
+ """
156
+
157
+ def __init__(self, window_seconds: int = 5) -> None:
158
+ super().__init__()
159
+ self._recent: dict[tuple[str, str], float] = {}
160
+ self._window = window_seconds
161
+ self._lock = threading.Lock()
162
+
163
+ def filter(self, record: logging.LogRecord) -> bool:
164
+ """Return False to suppress duplicate messages within the time window."""
165
+ # record.msg can be any object (callers sometimes pass a list/dict
166
+ # directly to logger.warning). Stringify so the key is always
167
+ # hashable — otherwise this filter raises TypeError and crashes
168
+ # whatever was being logged. Surfaced via the Nomic embedder
169
+ # pre-warm path that calls logger.warning(load_return_list).
170
+ key = (record.name, str(record.msg))
171
+ now = time.monotonic()
172
+
173
+ with self._lock:
174
+ # Evict stale entries periodically (every 100 checks)
175
+ if len(self._recent) > 200:
176
+ cutoff = now - self._window
177
+ self._recent = {k: v for k, v in self._recent.items() if v >= cutoff}
178
+
179
+ last_seen = self._recent.get(key)
180
+ if last_seen is not None and now - last_seen < self._window:
181
+ return False
182
+ self._recent[key] = now
183
+ return True
184
+
185
+
186
+ def print_startup_banner(
187
+ ports: dict[str, int],
188
+ *,
189
+ supabase_port: int | None = 54321,
190
+ log_file: str = DEV_LOG_FILE,
191
+ config_paths: dict[str, str] | None = None,
192
+ ) -> None:
193
+ """Print a consolidated startup summary banner with service URLs.
194
+
195
+ Args:
196
+ ports: Mapping of service name to port number.
197
+ supabase_port: Supabase port, or None if not running.
198
+ log_file: Path to the log file.
199
+ config_paths: Optional mapping of config-label → path string (e.g.
200
+ ``{"env": "~/.reflexio/.env", "config": "~/.reflexio/configs/config_default.json"}``).
201
+ Renders as a "Config" section above the "Logs" line so operators
202
+ can see at a glance which files the server actually loaded.
203
+ """
204
+ lines = []
205
+ width = 44
206
+
207
+ lines.append(f"\n{'=' * width}")
208
+ lines.append(colorize(" Reflexio Dev Server", "1", bold=True))
209
+ lines.append(f"{'-' * width}")
210
+
211
+ for name in ("backend", "frontend", "docs"):
212
+ if name in ports:
213
+ url = f"http://localhost:{ports[name]}"
214
+ color = SERVICE_COLORS.get(name, "37")
215
+ label = colorize(f" {name.capitalize():<11}", color)
216
+ status = colorize("ready", "32")
217
+ lines.append(f"{label}{url:<26}{status}")
218
+
219
+ if supabase_port is not None:
220
+ url = f"http://localhost:{supabase_port}"
221
+ label = colorize(" Supabase ", "36")
222
+ status = colorize("ready", "32")
223
+ lines.append(f"{label}{url:<26}{status}")
224
+
225
+ home = str(Path.home())
226
+
227
+ def _collapse_home(path: str) -> str:
228
+ # Collapse HOME to ~ for readability; absolute paths stay absolute
229
+ # so log scrapers and copy-paste still work when outside HOME.
230
+ return "~" + path[len(home) :] if path.startswith(home) else path
231
+
232
+ if config_paths:
233
+ lines.append(f"{'-' * width}")
234
+ for label, path in config_paths.items():
235
+ lines.append(f" {label:<11}{_collapse_home(str(path))}")
236
+
237
+ lines.append(f"{'-' * width}")
238
+ # Logs section — surface both the general dev log and the LLM I/O log.
239
+ # LLM_IO_LOG_FILE is the one operators hit first when debugging prompt /
240
+ # tool-call issues; it's opaque without this pointer.
241
+ lines.append(f" Dev log {_collapse_home(log_file)}")
242
+ lines.append(f" LLM I/O {_collapse_home(LLM_IO_LOG_FILE)}")
243
+ lines.append(f"{'=' * width}\n")
244
+
245
+ # Print all at once to avoid interleaving
246
+ sys.stdout.write("\n".join(lines) + "\n")
247
+ sys.stdout.flush()