claude-smart 0.2.42 → 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.
- package/.claude-plugin/marketplace.json +3 -3
- package/README.md +1 -1
- 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 +2 -2
- package/plugin/pyproject.toml +2 -2
- package/plugin/scripts/_lib.sh +91 -0
- package/plugin/scripts/backend-service.sh +1 -0
- package/plugin/scripts/cli.sh +1 -0
- 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/hook_entry.sh +1 -0
- package/plugin/scripts/smart-install.sh +1 -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 +1 -1
- package/plugin/vendor/reflexio/.env.example +53 -0
- package/plugin/vendor/reflexio/LICENSE +201 -0
- package/plugin/vendor/reflexio/README.md +338 -0
- package/plugin/vendor/reflexio/pyproject.toml +271 -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 +266 -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 +961 -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 +1103 -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 +766 -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 +280 -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 +616 -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 +2714 -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 +540 -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 +110 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/image_utils.py +55 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/litellm_client.py +1595 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/llm_utils.py +112 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/model_defaults.py +469 -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 +210 -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 +255 -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 +177 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/rerank/llm_reranker.py +148 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/tools.py +699 -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_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 +279 -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 +127 -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/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 +340 -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 +1626 -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/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 +351 -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 +468 -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 +777 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/tools.py +1125 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extractor_config_utils.py +91 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extractor_interaction_utils.py +251 -0
- package/plugin/vendor/reflexio/reflexio/server/services/generation_service.py +689 -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 +960 -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 +741 -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 +734 -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 +800 -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 +70 -0
- package/plugin/vendor/reflexio/reflexio/server/services/search/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/service_utils.py +671 -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 +1253 -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 +372 -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 +568 -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,76 @@
|
|
|
1
|
+
"""Uvicorn log configuration for the Reflexio backend.
|
|
2
|
+
|
|
3
|
+
This module exposes :data:`UVICORN_LOG_CONFIG`, a ``logging.config.dictConfig``
|
|
4
|
+
dict that is handed to uvicorn at launch time (see
|
|
5
|
+
:mod:`reflexio.server.__main__` and
|
|
6
|
+
:func:`reflexio.cli.run_services.build_backend_service`).
|
|
7
|
+
|
|
8
|
+
Why it lives here and not as an in-memory override:
|
|
9
|
+
Uvicorn's default formatter pads short level names so ``INFO`` aligns
|
|
10
|
+
with ``CRITICAL``. That alignment helps on a single-process console
|
|
11
|
+
but adds noise to our multiplexed ``[backend ]`` dev-server stream.
|
|
12
|
+
Rather than mutate uvicorn's already-configured loggers from inside
|
|
13
|
+
the app module (which is invisible and fragile), we tell uvicorn the
|
|
14
|
+
format upfront via its native ``log_config`` parameter. The dict
|
|
15
|
+
stays discoverable — users who want a different format can edit
|
|
16
|
+
this file or pass their own ``--log-config`` (the CLI flag wins).
|
|
17
|
+
|
|
18
|
+
Downstream, :func:`reflexio.cli.log_format.highlight_log_level` colorises
|
|
19
|
+
``ERROR:`` / ``WARNING:`` / ``CRITICAL:`` prefixes when stdout is a TTY,
|
|
20
|
+
so this module deliberately stays color-neutral.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
from typing import Any
|
|
26
|
+
|
|
27
|
+
# Plain level/message format — no ``%(levelprefix)s`` padding.
|
|
28
|
+
LEVEL_FORMAT = "%(levelname)s: %(message)s"
|
|
29
|
+
|
|
30
|
+
# Access-log fields mirror uvicorn's built-in AccessFormatter message shape,
|
|
31
|
+
# minus the padded level prefix.
|
|
32
|
+
ACCESS_FORMAT = '%(levelname)s: %(client_addr)s - "%(request_line)s" %(status_code)s'
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
UVICORN_LOG_CONFIG: dict[str, Any] = {
|
|
36
|
+
"version": 1,
|
|
37
|
+
"disable_existing_loggers": False,
|
|
38
|
+
"formatters": {
|
|
39
|
+
# Access format references uvicorn-specific fields (client_addr,
|
|
40
|
+
# request_line, status_code) that only ``uvicorn.logging.AccessFormatter``
|
|
41
|
+
# knows how to populate from the log record's ``args`` tuple. The
|
|
42
|
+
# stdlib ``logging.Formatter`` raises ``KeyError: 'client_addr'`` on
|
|
43
|
+
# every request. Default formatter stays on stdlib because it uses
|
|
44
|
+
# only ``levelname`` / ``message``.
|
|
45
|
+
"default": {"format": LEVEL_FORMAT},
|
|
46
|
+
"access": {
|
|
47
|
+
"()": "uvicorn.logging.AccessFormatter",
|
|
48
|
+
"fmt": ACCESS_FORMAT,
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
"handlers": {
|
|
52
|
+
"default": {
|
|
53
|
+
"class": "logging.StreamHandler",
|
|
54
|
+
"formatter": "default",
|
|
55
|
+
"stream": "ext://sys.stderr",
|
|
56
|
+
},
|
|
57
|
+
"access": {
|
|
58
|
+
"class": "logging.StreamHandler",
|
|
59
|
+
"formatter": "access",
|
|
60
|
+
"stream": "ext://sys.stdout",
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
"loggers": {
|
|
64
|
+
"uvicorn": {
|
|
65
|
+
"handlers": ["default"],
|
|
66
|
+
"level": "INFO",
|
|
67
|
+
"propagate": False,
|
|
68
|
+
},
|
|
69
|
+
"uvicorn.error": {"level": "INFO"},
|
|
70
|
+
"uvicorn.access": {
|
|
71
|
+
"handlers": ["access"],
|
|
72
|
+
"level": "INFO",
|
|
73
|
+
"propagate": False,
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Shared test infrastructure for reflexio OS and enterprise test suites."""
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""Load recorded LLM response fixtures for replay-based tests.
|
|
2
|
+
|
|
3
|
+
Fixture files live in ``tests/fixtures/llm/<name>.json`` and contain the
|
|
4
|
+
full mock response structure matching ``litellm.completion`` output.
|
|
5
|
+
|
|
6
|
+
Usage::
|
|
7
|
+
|
|
8
|
+
from reflexio.test_support.llm_fixtures import load_llm_fixture
|
|
9
|
+
|
|
10
|
+
def test_with_recorded_response(monkeypatch):
|
|
11
|
+
fixture = load_llm_fixture("profile_extraction")
|
|
12
|
+
monkeypatch.setattr("litellm.completion", lambda **kw: fixture)
|
|
13
|
+
# ... exercise code under test ...
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import json
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from typing import Any
|
|
21
|
+
from unittest.mock import MagicMock
|
|
22
|
+
|
|
23
|
+
# reflexio/test_support/ -> repo root -> tests/fixtures/llm/
|
|
24
|
+
_FIXTURE_DIR = Path(__file__).resolve().parents[2] / "tests" / "fixtures" / "llm"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def load_llm_fixture(name: str) -> MagicMock:
|
|
28
|
+
"""Load a recorded LLM response fixture and return it as a MagicMock.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
name: Fixture name without extension (e.g. ``"profile_extraction"``).
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
MagicMock mimicking a ``litellm.completion`` response.
|
|
35
|
+
"""
|
|
36
|
+
fixture_path = _FIXTURE_DIR / f"{name}.json"
|
|
37
|
+
if not fixture_path.exists():
|
|
38
|
+
raise FileNotFoundError(f"LLM fixture '{name}' not found at {fixture_path}")
|
|
39
|
+
data: dict[str, Any] = json.loads(fixture_path.read_text())
|
|
40
|
+
|
|
41
|
+
choice = data["choices"][0]
|
|
42
|
+
mock = MagicMock()
|
|
43
|
+
mock.choices = [MagicMock()]
|
|
44
|
+
mock.choices[0].message.content = choice["message"]["content"]
|
|
45
|
+
mock.choices[0].finish_reason = choice.get("finish_reason", "stop")
|
|
46
|
+
return mock
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def load_llm_fixture_content(name: str) -> str:
|
|
50
|
+
"""Load just the content string from a recorded LLM fixture.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
name: Fixture name without extension.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
The raw content string from the fixture's first choice.
|
|
57
|
+
"""
|
|
58
|
+
fixture_path = _FIXTURE_DIR / f"{name}.json"
|
|
59
|
+
if not fixture_path.exists():
|
|
60
|
+
raise FileNotFoundError(f"LLM fixture '{name}' not found at {fixture_path}")
|
|
61
|
+
data: dict[str, Any] = json.loads(fixture_path.read_text())
|
|
62
|
+
return data["choices"][0]["message"]["content"]
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
"""Global LiteLLM mock for reflexio test suites.
|
|
2
|
+
|
|
3
|
+
Patches ``litellm.completion`` with a deterministic mock that returns
|
|
4
|
+
JSON responses based on prompt content heuristics. E2E tests are
|
|
5
|
+
excluded from the session-level autouse so they can make real API
|
|
6
|
+
calls — but an e2e test that wants determinism can opt in via the
|
|
7
|
+
``patched_litellm`` context manager (or the matching ``mock_llm``
|
|
8
|
+
pytest fixture wired into the e2e conftest).
|
|
9
|
+
|
|
10
|
+
Response payloads are sourced from the model registry
|
|
11
|
+
(``llm_model_registry.py``) so they always validate against the Pydantic
|
|
12
|
+
models that services expect.
|
|
13
|
+
|
|
14
|
+
Usage in conftest.py::
|
|
15
|
+
|
|
16
|
+
from reflexio.test_support.llm_mock import configure_llm_mock, cleanup_llm_mock
|
|
17
|
+
|
|
18
|
+
def pytest_configure(config):
|
|
19
|
+
configure_llm_mock(config)
|
|
20
|
+
|
|
21
|
+
def pytest_unconfigure(config):
|
|
22
|
+
cleanup_llm_mock(config)
|
|
23
|
+
|
|
24
|
+
Opt-in usage in one e2e test::
|
|
25
|
+
|
|
26
|
+
from reflexio.test_support.llm_mock import patched_litellm
|
|
27
|
+
|
|
28
|
+
def test_something_e2e():
|
|
29
|
+
with patched_litellm():
|
|
30
|
+
... # litellm.completion is mocked for the duration
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
from __future__ import annotations
|
|
34
|
+
|
|
35
|
+
import json
|
|
36
|
+
import os
|
|
37
|
+
from collections.abc import Iterator
|
|
38
|
+
from contextlib import contextmanager
|
|
39
|
+
from typing import Any
|
|
40
|
+
from unittest.mock import MagicMock, patch
|
|
41
|
+
|
|
42
|
+
from reflexio.test_support.llm_model_registry import get_model_registry
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _create_mock_completion(
|
|
46
|
+
prompt_content: str, parse_structured_output: bool = False
|
|
47
|
+
) -> MagicMock:
|
|
48
|
+
"""Create a mock LiteLLM completion response.
|
|
49
|
+
|
|
50
|
+
Routes on prompt content heuristics; payloads come from the model
|
|
51
|
+
registry to guarantee schema validity.
|
|
52
|
+
"""
|
|
53
|
+
registry = get_model_registry()
|
|
54
|
+
|
|
55
|
+
if "Output just a boolean value" in prompt_content:
|
|
56
|
+
content = str(registry["boolean_evaluation"].minimal_valid)
|
|
57
|
+
elif "policy consolidation" in prompt_content:
|
|
58
|
+
content = json.dumps(registry["playbook_aggregation"].minimal_valid)
|
|
59
|
+
elif (
|
|
60
|
+
"is_success to True" in prompt_content
|
|
61
|
+
and "is_escalated to True" in prompt_content
|
|
62
|
+
):
|
|
63
|
+
# Anchor on two markers from the agent_success_evaluation prompt
|
|
64
|
+
# body — present in every variant of the success-eval prompt.
|
|
65
|
+
content = json.dumps(registry["agent_success_evaluation"].minimal_valid)
|
|
66
|
+
elif '"playbooks"' in prompt_content:
|
|
67
|
+
# Anchor on the schema marker every playbook-extraction prompt MUST
|
|
68
|
+
# describe (the JSON output key the LLM is told to return). This is
|
|
69
|
+
# intrinsic to the schema, not stylistic, so it survives prompt
|
|
70
|
+
# rewrites better than matching on a tagline like "policy mining".
|
|
71
|
+
content = json.dumps(registry["playbook_extraction"].minimal_valid)
|
|
72
|
+
elif parse_structured_output:
|
|
73
|
+
content = json.dumps(registry["profile_extraction"].minimal_valid)
|
|
74
|
+
else:
|
|
75
|
+
default_payload = json.dumps(registry["profile_update"].minimal_valid)
|
|
76
|
+
content = f"```json\n{default_payload}\n```"
|
|
77
|
+
|
|
78
|
+
mock_response = MagicMock()
|
|
79
|
+
mock_response.choices = [MagicMock()]
|
|
80
|
+
mock_response.choices[0].message.content = content
|
|
81
|
+
mock_response.choices[0].finish_reason = "stop"
|
|
82
|
+
return mock_response
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _extraction_finish_args(prompt_content: str) -> dict[str, Any]:
|
|
86
|
+
"""Pick the ``finish_extraction`` payload for an extraction tool-loop turn.
|
|
87
|
+
|
|
88
|
+
Profile and playbook extraction both run the always-on ``finish_extraction``
|
|
89
|
+
tool loop, so the mock must return the structured output as the *arguments*
|
|
90
|
+
of a ``finish_extraction`` tool call (not as message content). Routes on the
|
|
91
|
+
same schema marker the content-mode path uses.
|
|
92
|
+
"""
|
|
93
|
+
registry = get_model_registry()
|
|
94
|
+
if '"playbooks"' in prompt_content:
|
|
95
|
+
return registry["playbook_extraction"].minimal_valid
|
|
96
|
+
return registry["profile_extraction"].minimal_valid
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _mock_completion(*args: Any, **kwargs: Any) -> MagicMock:
|
|
100
|
+
"""Mock implementation for litellm.completion."""
|
|
101
|
+
messages = kwargs.get("messages", args[0] if args else [])
|
|
102
|
+
prompt_content = ""
|
|
103
|
+
for message in messages:
|
|
104
|
+
if isinstance(message, dict) and "content" in message:
|
|
105
|
+
prompt_content += str(message["content"])
|
|
106
|
+
|
|
107
|
+
# Extraction now runs through the ``finish_extraction`` tool loop, which
|
|
108
|
+
# invokes ``litellm.completion`` with ``tools=``. In that mode the loop
|
|
109
|
+
# reads ``resp.tool_calls`` (not message content), so emit a single
|
|
110
|
+
# ``finish_extraction`` tool call carrying the structured output as args.
|
|
111
|
+
if kwargs.get("tools"):
|
|
112
|
+
# Imported lazily to avoid importing the extraction service stack at
|
|
113
|
+
# module load time (this module is imported by the root conftest).
|
|
114
|
+
from reflexio.server.services.extraction.resumable_agent import (
|
|
115
|
+
FINISH_EXTRACTION_TOOL_NAME,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
return make_tool_call_response(
|
|
119
|
+
FINISH_EXTRACTION_TOOL_NAME, _extraction_finish_args(prompt_content)
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
parse_structured = kwargs.get("response_format") is not None
|
|
123
|
+
return _create_mock_completion(prompt_content, parse_structured)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _is_e2e_test_run(config: Any) -> bool:
|
|
127
|
+
"""Check if this pytest run includes e2e tests.
|
|
128
|
+
|
|
129
|
+
Returns True if any of the test paths contain 'e2e_tests'.
|
|
130
|
+
"""
|
|
131
|
+
args = config.args if hasattr(config, "args") else []
|
|
132
|
+
for arg in args:
|
|
133
|
+
if "e2e_tests" in str(arg):
|
|
134
|
+
return True
|
|
135
|
+
|
|
136
|
+
if hasattr(config, "workerinput"):
|
|
137
|
+
worker_args = config.workerinput.get("args", [])
|
|
138
|
+
for arg in worker_args:
|
|
139
|
+
if "e2e_tests" in str(arg):
|
|
140
|
+
return True
|
|
141
|
+
|
|
142
|
+
return False
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
# Global patcher reference kept alive across the test session.
|
|
146
|
+
_litellm_patcher = None
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def configure_llm_mock(config: Any) -> None:
|
|
150
|
+
"""Call from ``pytest_configure`` to patch litellm for non-e2e tests."""
|
|
151
|
+
global _litellm_patcher # noqa: PLW0603
|
|
152
|
+
|
|
153
|
+
if _is_e2e_test_run(config):
|
|
154
|
+
return
|
|
155
|
+
|
|
156
|
+
os.environ["MOCK_LLM_RESPONSE"] = "true"
|
|
157
|
+
_litellm_patcher = patch("litellm.completion", side_effect=_mock_completion)
|
|
158
|
+
_litellm_patcher.start()
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def cleanup_llm_mock(config: Any) -> None: # noqa: ARG001
|
|
162
|
+
"""Call from ``pytest_unconfigure`` to stop the patcher."""
|
|
163
|
+
global _litellm_patcher # noqa: PLW0603
|
|
164
|
+
|
|
165
|
+
if _litellm_patcher:
|
|
166
|
+
_litellm_patcher.stop()
|
|
167
|
+
_litellm_patcher = None
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
@contextmanager
|
|
171
|
+
def patched_litellm() -> Iterator[None]:
|
|
172
|
+
"""Opt-in patch for one e2e test that wants deterministic LLM responses.
|
|
173
|
+
|
|
174
|
+
The session-level ``configure_llm_mock`` skips e2e runs entirely so
|
|
175
|
+
historical e2e tests can hit real APIs. This context manager
|
|
176
|
+
re-enables the same mock for the scope of one test (or one block) —
|
|
177
|
+
useful for new e2e tests that need a predictable LLM response and
|
|
178
|
+
don't want to pay for or wait on a real provider.
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
Iterator[None]: A context that patches ``litellm.completion``
|
|
182
|
+
on entry and restores the original on exit.
|
|
183
|
+
"""
|
|
184
|
+
os.environ["MOCK_LLM_RESPONSE"] = "true"
|
|
185
|
+
patcher = patch("litellm.completion", side_effect=_mock_completion)
|
|
186
|
+
patcher.start()
|
|
187
|
+
try:
|
|
188
|
+
yield
|
|
189
|
+
finally:
|
|
190
|
+
patcher.stop()
|
|
191
|
+
# Leave MOCK_LLM_RESPONSE as-is — tests that read it should not
|
|
192
|
+
# depend on its lifetime being tied to a single context block.
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def make_tool_call_response(tool_name: str, args: dict[str, Any]) -> MagicMock:
|
|
196
|
+
"""Build a litellm ModelResponse-shaped mock with a single tool_call.
|
|
197
|
+
|
|
198
|
+
Used by unit tests that drive tool loops against the patched
|
|
199
|
+
``litellm.completion``. Not routed automatically by prompt
|
|
200
|
+
heuristics — callers install it explicitly with ``side_effect``.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
tool_name (str): The name the assistant is calling.
|
|
204
|
+
args (dict[str, Any]): JSON-serialisable arguments passed to the tool.
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
MagicMock: A response object shaped like a litellm ModelResponse
|
|
208
|
+
whose first choice has ``finish_reason="tool_calls"`` and a
|
|
209
|
+
single tool call matching the given name and args.
|
|
210
|
+
"""
|
|
211
|
+
resp = MagicMock()
|
|
212
|
+
resp.choices = [MagicMock()]
|
|
213
|
+
resp.choices[0].finish_reason = "tool_calls"
|
|
214
|
+
resp.choices[0].message.content = None
|
|
215
|
+
tc = MagicMock()
|
|
216
|
+
tc.id = f"tc_{tool_name}"
|
|
217
|
+
tc.type = "function"
|
|
218
|
+
tc.function.name = tool_name
|
|
219
|
+
tc.function.arguments = json.dumps(args)
|
|
220
|
+
resp.choices[0].message.tool_calls = [tc]
|
|
221
|
+
return resp
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def make_finish_response(text: str = "done") -> MagicMock:
|
|
225
|
+
"""Build a normal (non-tool-call) assistant message.
|
|
226
|
+
|
|
227
|
+
Used to terminate a tool loop that was driven by repeated
|
|
228
|
+
``make_tool_call_response`` mocks.
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
text (str): Content of the terminal message.
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
MagicMock: A response object with ``finish_reason="stop"``,
|
|
235
|
+
the given text, and ``tool_calls=None``.
|
|
236
|
+
"""
|
|
237
|
+
resp = MagicMock()
|
|
238
|
+
resp.choices = [MagicMock()]
|
|
239
|
+
resp.choices[0].finish_reason = "stop"
|
|
240
|
+
resp.choices[0].message.content = text
|
|
241
|
+
resp.choices[0].message.tool_calls = None
|
|
242
|
+
return resp
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"""Registry mapping LLM operations to their expected Pydantic output models.
|
|
2
|
+
|
|
3
|
+
Each entry pairs a descriptive key with the Pydantic model class the service
|
|
4
|
+
expects and a minimal valid JSON instance that ``model_validate()`` must accept.
|
|
5
|
+
This serves as the single source of truth for mock response shapes, used by
|
|
6
|
+
both the heuristic mock (``llm_mock.py``) and schema compliance tests.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from dataclasses import dataclass
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
from pydantic import BaseModel
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass(frozen=True)
|
|
18
|
+
class ModelRegistryEntry:
|
|
19
|
+
"""A registry entry pairing a Pydantic model with a minimal valid instance.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
model_class: The Pydantic model class, or None for raw string responses.
|
|
23
|
+
minimal_valid: A dict (or raw value) that ``model_class.model_validate()`` accepts.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
model_class: type[BaseModel] | None
|
|
27
|
+
minimal_valid: dict[str, Any] | str
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _build_registry() -> dict[str, ModelRegistryEntry]:
|
|
31
|
+
"""Build the model registry with lazy imports to avoid circular dependencies."""
|
|
32
|
+
from reflexio.server.services.agent_success_evaluation.agent_success_evaluation_constants import (
|
|
33
|
+
AgentSuccessEvaluationOutput,
|
|
34
|
+
)
|
|
35
|
+
from reflexio.server.services.playbook.playbook_consolidator import (
|
|
36
|
+
PlaybookConsolidationOutput,
|
|
37
|
+
)
|
|
38
|
+
from reflexio.server.services.playbook.playbook_service_utils import (
|
|
39
|
+
PlaybookAggregationOutput,
|
|
40
|
+
StructuredPlaybookList,
|
|
41
|
+
)
|
|
42
|
+
from reflexio.server.services.profile.profile_deduplicator import (
|
|
43
|
+
ProfileDeduplicationOutput,
|
|
44
|
+
)
|
|
45
|
+
from reflexio.server.services.profile.profile_generation_service_utils import (
|
|
46
|
+
ProfileUpdateOutput,
|
|
47
|
+
StructuredProfilesOutput,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
"playbook_extraction": ModelRegistryEntry(
|
|
52
|
+
model_class=StructuredPlaybookList,
|
|
53
|
+
minimal_valid={
|
|
54
|
+
"playbooks": [
|
|
55
|
+
{
|
|
56
|
+
"content": "When user asks a question, provide a detailed answer rather than a brief response.",
|
|
57
|
+
"trigger": "when user asks a question",
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
),
|
|
62
|
+
"playbook_aggregation": ModelRegistryEntry(
|
|
63
|
+
model_class=PlaybookAggregationOutput,
|
|
64
|
+
minimal_valid={
|
|
65
|
+
"playbook": {
|
|
66
|
+
"content": "When user asks about implementation, provide step-by-step explanations rather than high-level overviews.",
|
|
67
|
+
"trigger": "when user asks about implementation",
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
),
|
|
71
|
+
"playbook_consolidation": ModelRegistryEntry(
|
|
72
|
+
model_class=PlaybookConsolidationOutput,
|
|
73
|
+
minimal_valid={
|
|
74
|
+
"decisions": [
|
|
75
|
+
{"kind": "independent", "new_id": "NEW-0"},
|
|
76
|
+
],
|
|
77
|
+
},
|
|
78
|
+
),
|
|
79
|
+
"profile_extraction": ModelRegistryEntry(
|
|
80
|
+
model_class=StructuredProfilesOutput,
|
|
81
|
+
minimal_valid={
|
|
82
|
+
"profiles": [
|
|
83
|
+
{"content": "likes sushi", "time_to_live": "one_month"},
|
|
84
|
+
],
|
|
85
|
+
},
|
|
86
|
+
),
|
|
87
|
+
"profile_update": ModelRegistryEntry(
|
|
88
|
+
model_class=ProfileUpdateOutput,
|
|
89
|
+
minimal_valid={
|
|
90
|
+
"add": [
|
|
91
|
+
{"content": "prefers dark mode", "time_to_live": "one_month"},
|
|
92
|
+
],
|
|
93
|
+
"delete": [],
|
|
94
|
+
"mention": [],
|
|
95
|
+
},
|
|
96
|
+
),
|
|
97
|
+
"profile_deduplication": ModelRegistryEntry(
|
|
98
|
+
model_class=ProfileDeduplicationOutput,
|
|
99
|
+
minimal_valid={
|
|
100
|
+
"duplicate_groups": [],
|
|
101
|
+
"unique_ids": ["NEW-0"],
|
|
102
|
+
},
|
|
103
|
+
),
|
|
104
|
+
"agent_success_evaluation": ModelRegistryEntry(
|
|
105
|
+
model_class=AgentSuccessEvaluationOutput,
|
|
106
|
+
minimal_valid={
|
|
107
|
+
"is_success": True,
|
|
108
|
+
"is_escalated": False,
|
|
109
|
+
},
|
|
110
|
+
),
|
|
111
|
+
# F1 cleanup: ``agent_success_evaluation_comparison`` was removed along
|
|
112
|
+
# with the session-level shadow comparison branch. Per-turn shadow
|
|
113
|
+
# comparison registers its own registry entry alongside its prompt.
|
|
114
|
+
"boolean_evaluation": ModelRegistryEntry(
|
|
115
|
+
model_class=None,
|
|
116
|
+
minimal_valid="true",
|
|
117
|
+
),
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
_REGISTRY: dict[str, ModelRegistryEntry] | None = None
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def get_model_registry() -> dict[str, ModelRegistryEntry]:
|
|
125
|
+
"""Return the model registry, building it on first access."""
|
|
126
|
+
global _REGISTRY # noqa: PLW0603
|
|
127
|
+
if _REGISTRY is None:
|
|
128
|
+
_REGISTRY = _build_registry()
|
|
129
|
+
return _REGISTRY
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Test skip decorators shared between OS and enterprise test suites."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import base64
|
|
6
|
+
import os
|
|
7
|
+
from collections.abc import Callable
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
import pytest
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def skip_in_precommit(func: Callable[..., Any]) -> Callable[..., Any]:
|
|
15
|
+
"""Decorator to skip tests during pre-commit hooks."""
|
|
16
|
+
return pytest.mark.skipif(
|
|
17
|
+
os.environ.get("PRECOMMIT") == "1", reason="Test skipped in pre-commit hook"
|
|
18
|
+
)(func)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def skip_low_priority(func: Callable[..., Any]) -> Callable[..., Any]:
|
|
22
|
+
"""Decorator to skip low priority tests unless explicitly requested.
|
|
23
|
+
|
|
24
|
+
These tests are skipped by default and only run when RUN_LOW_PRIORITY=1 is set.
|
|
25
|
+
|
|
26
|
+
Usage::
|
|
27
|
+
|
|
28
|
+
@skip_low_priority
|
|
29
|
+
def test_something_low_priority():
|
|
30
|
+
...
|
|
31
|
+
|
|
32
|
+
To run low priority tests::
|
|
33
|
+
|
|
34
|
+
RUN_LOW_PRIORITY=1 pytest ...
|
|
35
|
+
"""
|
|
36
|
+
return pytest.mark.skipif(
|
|
37
|
+
os.environ.get("RUN_LOW_PRIORITY") != "1",
|
|
38
|
+
reason="Low priority test - set RUN_LOW_PRIORITY=1 to run",
|
|
39
|
+
)(func)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def encode_image_to_base64(image_fp: str) -> str:
|
|
43
|
+
return base64.b64encode(Path(image_fp).read_bytes()).decode("utf-8")
|