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.
- package/.claude-plugin/marketplace.json +3 -3
- package/README.md +1 -1
- package/bin/claude-smart.js +2 -2
- package/package.json +9 -3
- package/plugin/.claude-plugin/plugin.json +9 -3
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/README.md +23 -3
- package/plugin/pyproject.toml +3 -3
- package/plugin/scripts/_lib.sh +91 -0
- package/plugin/scripts/backend-service.sh +51 -4
- package/plugin/scripts/cli.sh +3 -1
- package/plugin/scripts/codex-hook.js +72 -4
- package/plugin/scripts/dashboard-build.sh +1 -0
- package/plugin/scripts/dashboard-service.sh +1 -0
- package/plugin/scripts/ensure-plugin-root.sh +1 -0
- package/plugin/scripts/hook_entry.sh +6 -3
- package/plugin/scripts/smart-install.sh +3 -2
- package/plugin/src/README.md +57 -0
- package/plugin/src/claude_smart/context_format.py +11 -12
- package/plugin/src/claude_smart/cs_cite.py +26 -12
- package/plugin/src/claude_smart/ids.py +13 -5
- package/plugin/uv.lock +126 -5
- package/plugin/vendor/reflexio/.env.example +62 -0
- package/plugin/vendor/reflexio/LICENSE +201 -0
- package/plugin/vendor/reflexio/README.md +338 -0
- package/plugin/vendor/reflexio/pyproject.toml +274 -0
- package/plugin/vendor/reflexio/reflexio/README.md +184 -0
- package/plugin/vendor/reflexio/reflexio/__init__.py +166 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/README.md +109 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/backends.py +175 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/bench.py +642 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/embed_cache.py +330 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/report.py +317 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/results/report.md +43 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/results/results.json +4478 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/scenarios.py +134 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/seed.py +255 -0
- package/plugin/vendor/reflexio/reflexio/cli/README.md +287 -0
- package/plugin/vendor/reflexio/reflexio/cli/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/cli/__main__.py +56 -0
- package/plugin/vendor/reflexio/reflexio/cli/_client.py +86 -0
- package/plugin/vendor/reflexio/reflexio/cli/app.py +127 -0
- package/plugin/vendor/reflexio/reflexio/cli/bootstrap_config.py +265 -0
- package/plugin/vendor/reflexio/reflexio/cli/codex_auth.py +503 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/admin_cmd.py +65 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/agent_playbooks.py +503 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/api.py +114 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/auth.py +109 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/config_cmd.py +511 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/doctor.py +127 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/embeddings.py +53 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/interactions.py +478 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/profiles.py +303 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/services.py +289 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/setup_cmd.py +964 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/shortcuts.py +285 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/status_cmd.py +143 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/user_playbooks.py +373 -0
- package/plugin/vendor/reflexio/reflexio/cli/env_loader.py +284 -0
- package/plugin/vendor/reflexio/reflexio/cli/errors.py +217 -0
- package/plugin/vendor/reflexio/reflexio/cli/log_format.py +247 -0
- package/plugin/vendor/reflexio/reflexio/cli/output.py +867 -0
- package/plugin/vendor/reflexio/reflexio/cli/paths.py +41 -0
- package/plugin/vendor/reflexio/reflexio/cli/run_services.py +391 -0
- package/plugin/vendor/reflexio/reflexio/cli/state.py +204 -0
- package/plugin/vendor/reflexio/reflexio/cli/stop_services.py +96 -0
- package/plugin/vendor/reflexio/reflexio/cli/utils.py +329 -0
- package/plugin/vendor/reflexio/reflexio/client/__init__.py +3 -0
- package/plugin/vendor/reflexio/reflexio/client/cache.py +150 -0
- package/plugin/vendor/reflexio/reflexio/client/client.py +2613 -0
- package/plugin/vendor/reflexio/reflexio/defaults.py +23 -0
- package/plugin/vendor/reflexio/reflexio/integrations/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/.clawhubignore +7 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/README.md +274 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/TESTING.md +517 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/hook/handler.js +473 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package-lock.json +2156 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package.json +18 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/handler.ts +241 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/setup.ts +140 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/index.ts +130 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/publish.ts +113 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/search.ts +52 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/server.ts +103 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/sqlite-buffer.ts +156 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/user-id.ts +134 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/openclaw.plugin.json +41 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/package.json +17 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/rules/reflexio.md +24 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/reflexio/SKILL.md +48 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/publish_clawhub.sh +278 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/references/HOOK.md +164 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/install.sh +36 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/uninstall.sh +35 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/publish.test.ts +27 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/search.test.ts +31 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/server.test.ts +42 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/setup.test.ts +49 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/sqlite-buffer.test.ts +91 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/user-id.test.ts +50 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tsconfig.json +16 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/types/openclaw.d.ts +230 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/vitest.config.ts +13 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/README.md +120 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/TESTING.md +168 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/package-lock.json +1657 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/package.json +16 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/HEARTBEAT.md +6 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/README.md +84 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/SKILL.md +194 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/_meta.json +6 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/agents/reflexio-extractor.md +45 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/hook/handler.ts +214 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/hook/setup.ts +55 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/index.ts +327 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/consolidate.ts +233 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/dedup.ts +80 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/io.ts +155 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/openclaw-cli.ts +67 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/search.ts +33 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/write-playbook.ts +76 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/write-profile.ts +79 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/openclaw.plugin.json +46 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/package.json +18 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/README.md +36 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/full_consolidation.md +56 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/playbook_extraction.md +217 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/profile_extraction.md +132 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/skills/reflexio-consolidate/SKILL.md +33 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/skills/reflexio-embedded/SKILL.md +194 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/HOOK.md +18 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/architecture.md +49 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/comparison.md +31 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/future-work.md +47 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/porting-notes.md +52 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/scripts/install.sh +52 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/scripts/uninstall.sh +36 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/consolidate.test.ts +135 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/dedup.test.ts +104 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/io.test.ts +175 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/search.test.ts +66 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/smoke-test.ts +140 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/write-playbook.test.ts +93 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/write-profile.test.ts +174 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tsconfig.json +16 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/types/openclaw.d.ts +230 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/vitest.config.ts +7 -0
- package/plugin/vendor/reflexio/reflexio/lib/__init__.py +23 -0
- package/plugin/vendor/reflexio/reflexio/lib/_agent_playbook.py +310 -0
- package/plugin/vendor/reflexio/reflexio/lib/_base.py +225 -0
- package/plugin/vendor/reflexio/reflexio/lib/_config.py +83 -0
- package/plugin/vendor/reflexio/reflexio/lib/_dashboard.py +266 -0
- package/plugin/vendor/reflexio/reflexio/lib/_generation.py +176 -0
- package/plugin/vendor/reflexio/reflexio/lib/_interactions.py +334 -0
- package/plugin/vendor/reflexio/reflexio/lib/_operations.py +153 -0
- package/plugin/vendor/reflexio/reflexio/lib/_profiles.py +545 -0
- package/plugin/vendor/reflexio/reflexio/lib/_reflection.py +52 -0
- package/plugin/vendor/reflexio/reflexio/lib/_search.py +167 -0
- package/plugin/vendor/reflexio/reflexio/lib/_storage_labels.py +103 -0
- package/plugin/vendor/reflexio/reflexio/lib/_user_playbook.py +288 -0
- package/plugin/vendor/reflexio/reflexio/lib/reflexio_lib.py +27 -0
- package/plugin/vendor/reflexio/reflexio/models/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/braintrust_schema.py +141 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/common.py +41 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/__init__.py +3 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/entities.py +1112 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/enums.py +63 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/eval_overview_schema.py +487 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/internal_schema.py +28 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/pending_tool_call_schema.py +83 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/retriever_schema.py +768 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/service_schemas.py +9 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/stall_state_schema.py +32 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/__init__.py +3 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/converters.py +177 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/entities.py +129 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/enums.py +25 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/validators.py +333 -0
- package/plugin/vendor/reflexio/reflexio/models/config_schema.py +908 -0
- package/plugin/vendor/reflexio/reflexio/models/py.typed +0 -0
- package/plugin/vendor/reflexio/reflexio/server/OVERVIEW.md +90 -0
- package/plugin/vendor/reflexio/reflexio/server/README.md +622 -0
- package/plugin/vendor/reflexio/reflexio/server/__init__.py +210 -0
- package/plugin/vendor/reflexio/reflexio/server/__main__.py +132 -0
- package/plugin/vendor/reflexio/reflexio/server/_auth.py +25 -0
- package/plugin/vendor/reflexio/reflexio/server/api.py +2868 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/README.md +34 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/account_api.py +143 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/health_api.py +91 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/pending_tool_call_api.py +572 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/precondition_checks.py +66 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/publisher_api.py +562 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/request_context.py +50 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/stall_state_api.py +100 -0
- package/plugin/vendor/reflexio/reflexio/server/cache/__init__.py +15 -0
- package/plugin/vendor/reflexio/reflexio/server/cache/reflexio_cache.py +208 -0
- package/plugin/vendor/reflexio/reflexio/server/correlation.py +46 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/__init__.py +30 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/embedding_service.py +359 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/image_utils.py +55 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/litellm_client.py +1871 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/llm_utils.py +140 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/model_defaults.py +479 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/claude_code_provider.py +1122 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/claude_code_stream_parser.py +197 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/embedding_service_provider.py +338 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/local_embedding_provider.py +213 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/nomic_embedding_provider.py +288 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/rerank/__init__.py +6 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/rerank/cross_encoder_reranker.py +187 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/rerank/llm_reranker.py +148 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/tools.py +716 -0
- package/plugin/vendor/reflexio/reflexio/server/operation_limiter.py +179 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/_dispatchers.py +54 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/README.md +121 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/agent_success_evaluation/v1.0.0.prompt.md +58 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/agent_success_evaluation_with_comparison/v1.0.0.prompt.md +76 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/answer_synthesis/v1.5.2.prompt.md +88 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/compress_session_for_query/v1.3.0.prompt.md +31 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/document_expansion/v1.0.0.prompt.md +20 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.0.0.prompt.md +53 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.1.0.prompt.md +57 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.2.0.prompt.md +68 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.3.0.prompt.md +70 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.4.0.prompt.md +77 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.5.0.prompt.md +82 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.6.0.prompt.md +83 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.1.0.prompt.md +193 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.2.0.prompt.md +206 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v1.0.0-deprecated.prompt.md +66 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v1.0.0.prompt.md +43 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v1.1.0.prompt.md +46 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.0.0-deprecated.prompt.md +64 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.0.0.prompt.md +39 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.1.0.prompt.md +39 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.2.0.prompt.md +47 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.0.prompt.md +58 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.1.prompt.md +69 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.2.prompt.md +71 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.0.2.prompt.md +254 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.1.0.prompt.md +274 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.2.0.prompt.md +283 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.2.2.prompt.md +234 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.2.3.prompt.md +244 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v1.0.0.prompt.md +73 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v2.0.0.prompt.md +86 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.0.0.prompt.md +97 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.1.0.prompt.md +119 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.2.0.prompt.md +123 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.3.0.prompt.md +137 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.0.0.prompt.md +14 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.1.0.prompt.md +24 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.2.0.prompt.md +29 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main_expert/v1.0.0.prompt.md +11 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main_expert/v1.1.0.prompt.md +21 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main_expert/v1.2.0.prompt.md +25 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_optimizer_judge/v1.0.0.prompt.md +37 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_optimizer_judge/v1.1.0.prompt.md +40 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_optimizer_judge/v1.2.0.prompt.md +36 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate/v1.0.0.prompt.md +45 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate/v2.0.0.prompt.md +81 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate/v3.0.0.prompt.md +80 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate_expert/v1.0.0.prompt.md +34 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_deduplication/v1.0.0.prompt.md +116 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_should_generate/v1.0.0.prompt.md +33 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_should_generate_override/v1.0.0.prompt.md +16 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.0.0.prompt.md +140 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.1.0.prompt.md +160 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_main/v1.0.0.prompt.md +14 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/query_reformulation/v1.0.0.prompt.md +19 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/rerank_relevance/v1.1.0.prompt.md +44 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/shadow_comparison/v1.0.0.prompt.md +43 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/shadow_content_evaluation/v1.0.0.prompt.md +33 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_evaluation/prompt_evaluation_dataset/feedback_extraction_main_v1.jsonl +10 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_evaluation/prompt_evaluation_dataset/profile_update_main_v1.jsonl +10 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_manager.py +280 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_schema.py +11 -0
- package/plugin/vendor/reflexio/reflexio/server/services/README.md +58 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/_eval_health.py +131 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_constants.py +60 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_service.py +228 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_utils.py +87 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluator.py +372 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/delayed_group_evaluator.py +156 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/group_evaluation_runner.py +336 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/regen_jobs.py +471 -0
- package/plugin/vendor/reflexio/reflexio/server/services/base_generation_service.py +1668 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/_cron.py +196 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/_encryption.py +101 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/client.py +167 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/service.py +281 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/base_configurator.py +179 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/config_storage.py +62 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/configurator.py +87 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/local_file_config_storage.py +187 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/test_config_storage.py +162 -0
- package/plugin/vendor/reflexio/reflexio/server/services/deduplication_utils.py +112 -0
- package/plugin/vendor/reflexio/reflexio/server/services/embedding_text.py +62 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/distribution.py +33 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/eval_sampler.py +126 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/group_aggregation.py +192 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/hero_state.py +75 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/rule_attribution.py +97 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/service.py +515 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/shadow_aggregation.py +90 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/agent_run_records.py +91 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/invariants.py +303 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/outcome.py +25 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/pending_tool_call_dispatch.py +358 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/plan.py +138 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/prior_answer_search.py +217 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/resumable_agent.py +535 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_scheduler.py +171 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_worker.py +779 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/tools.py +1125 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extractor_config_utils.py +94 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extractor_interaction_utils.py +251 -0
- package/plugin/vendor/reflexio/reflexio/server/services/generation_service.py +702 -0
- package/plugin/vendor/reflexio/reflexio/server/services/operation_state_utils.py +835 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/README.md +89 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_aggregator.py +1388 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_consolidator.py +1045 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_extractor.py +436 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_generation_service.py +808 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_service_constants.py +28 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_service_utils.py +362 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/__init__.py +24 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/assistant_webhook.py +246 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/gepa_adapter.py +291 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/judge.py +97 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/models.py +96 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/optimizer.py +645 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/rollout.py +35 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/scenario_resolver.py +93 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/scheduler.py +174 -0
- package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/__init__.py +26 -0
- package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/_document_expander.py +179 -0
- package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/_query_reformulator.py +297 -0
- package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_deduplicator.py +772 -0
- package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_extractor.py +462 -0
- package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_generation_service.py +737 -0
- package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_generation_service_utils.py +290 -0
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/__init__.py +17 -0
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_extractor.py +247 -0
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_service.py +803 -0
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_service_utils.py +146 -0
- package/plugin/vendor/reflexio/reflexio/server/services/retrieval/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/retrieval/relevance_floor.py +80 -0
- package/plugin/vendor/reflexio/reflexio/server/services/search/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/service_utils.py +756 -0
- package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/judge.py +184 -0
- package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/outcome.py +81 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/constants.py +2 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/error.py +11 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/retention.py +154 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/retention_mixin.py +155 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/__init__.py +59 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_agent_run.py +1298 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_base.py +1945 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_extras.py +600 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_operations.py +346 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_playbook.py +1378 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_profiles.py +747 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_requests.py +263 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_shadow_verdicts.py +193 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_share_links.py +166 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_stall_state.py +217 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/__init__.py +153 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_agent_run.py +384 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_base.py +71 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_extras.py +235 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_operations.py +170 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_playbook.py +677 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_profiles.py +250 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_requests.py +154 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_shadow_verdicts.py +130 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_share_links.py +93 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_stall_state.py +76 -0
- package/plugin/vendor/reflexio/reflexio/server/services/unified_search_service.py +572 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/README.md +77 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/feature_flags.py +116 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_manager.py +263 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/feature_flags.json +13 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/llm_model_setting.json +7 -0
- package/plugin/vendor/reflexio/reflexio/server/tracing.py +158 -0
- package/plugin/vendor/reflexio/reflexio/server/usage_metrics.py +113 -0
- package/plugin/vendor/reflexio/reflexio/server/uvicorn_logging.py +76 -0
- package/plugin/vendor/reflexio/reflexio/test_support/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/test_support/llm_fixtures.py +62 -0
- package/plugin/vendor/reflexio/reflexio/test_support/llm_mock.py +242 -0
- package/plugin/vendor/reflexio/reflexio/test_support/llm_model_registry.py +129 -0
- 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()
|