claude-smart 0.2.41 → 0.2.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +17 -0
- package/README.md +1 -1
- package/bin/claude-smart.js +86 -48
- package/package.json +10 -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/dashboard/next.config.ts +9 -1
- package/plugin/pyproject.toml +2 -2
- package/plugin/scripts/_lib.sh +91 -0
- package/plugin/scripts/backend-service.sh +46 -15
- package/plugin/scripts/cli.sh +29 -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 +7 -14
- package/plugin/scripts/hook_entry.sh +1 -0
- package/plugin/scripts/smart-install.sh +18 -2
- package/plugin/src/claude_smart/cli.py +72 -38
- 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,208 @@
|
|
|
1
|
+
"""Reflexio instance cache with explicit invalidation and version-based auto-eviction."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import threading
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Any, Final
|
|
7
|
+
|
|
8
|
+
from cachetools import TTLCache
|
|
9
|
+
|
|
10
|
+
from reflexio.lib.reflexio_lib import Reflexio
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
# Cache configuration
|
|
15
|
+
REFLEXIO_CACHE_MAX_SIZE = 100
|
|
16
|
+
REFLEXIO_CACHE_TTL_SECONDS = 3600 # 1 hour safety net
|
|
17
|
+
|
|
18
|
+
# Type alias for cache key: (org_id, storage_base_dir)
|
|
19
|
+
CacheKey = tuple[str, str | None]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# Sentinel returned by ``_probe_version_safe`` when the underlying probe
|
|
23
|
+
# raised an exception. Distinguishing "probe failed transiently" from
|
|
24
|
+
# "backend can't probe" matters: the former should NOT promote the entry
|
|
25
|
+
# to permanent unprobeable state, otherwise a single transient error
|
|
26
|
+
# (e.g. brief Postgres reconnect, file lock contention) would silently
|
|
27
|
+
# disable version-based auto-eviction for the lifetime of the entry.
|
|
28
|
+
_PROBE_FAILED: Final = object()
|
|
29
|
+
|
|
30
|
+
# Type alias for ``current_config_version()`` return values plus our
|
|
31
|
+
# private sentinel. ``None`` means "backend doesn't support probing"
|
|
32
|
+
# (permanent), the sentinel means "probe raised this time" (transient).
|
|
33
|
+
_ProbeResult = tuple[str, Any] | None | object
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dataclass
|
|
37
|
+
class _CacheEntry:
|
|
38
|
+
"""Per-org cache entry pairing a Reflexio instance with the config version stamped at load time.
|
|
39
|
+
|
|
40
|
+
The ``cached_version`` is whatever ``Reflexio.current_config_version()``
|
|
41
|
+
returned when the instance was constructed. On each cache hit we
|
|
42
|
+
re-probe and evict the entry if the value changed — this catches
|
|
43
|
+
out-of-band config mutations (file edits, sibling-replica writes,
|
|
44
|
+
direct DB updates) that don't go through ``invalidate_reflexio_cache``.
|
|
45
|
+
|
|
46
|
+
Attributes:
|
|
47
|
+
reflexio (Reflexio): The cached Reflexio instance.
|
|
48
|
+
cached_version (tuple[str, Any] | None): The version stamp
|
|
49
|
+
captured at load time. ``None`` means "no probe available";
|
|
50
|
+
entries with ``None`` are never auto-evicted (they fall
|
|
51
|
+
through to the TTL safety net). Probe failures during
|
|
52
|
+
construction never produce ``None`` here — they're recorded
|
|
53
|
+
as the same value the next probe attempt would compare
|
|
54
|
+
against, so a later successful probe can still evict the
|
|
55
|
+
stale entry.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
reflexio: Reflexio
|
|
59
|
+
cached_version: tuple[str, Any] | None
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
# Module-level cache and lock
|
|
63
|
+
_reflexio_cache: TTLCache = TTLCache(
|
|
64
|
+
maxsize=REFLEXIO_CACHE_MAX_SIZE, ttl=REFLEXIO_CACHE_TTL_SECONDS
|
|
65
|
+
)
|
|
66
|
+
_reflexio_cache_lock = threading.Lock()
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _probe_version_safe(reflexio: Reflexio) -> _ProbeResult:
|
|
70
|
+
"""Probe the current config version, distinguishing failure from "no probe".
|
|
71
|
+
|
|
72
|
+
A failing probe must never break a cache hit, but it also must not
|
|
73
|
+
be conflated with a backend that legitimately can't probe (which
|
|
74
|
+
returns ``None``). Conflating the two would let a single transient
|
|
75
|
+
failure permanently disable auto-eviction for the entry.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
reflexio (Reflexio): The cached Reflexio instance to probe.
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
``tuple[str, Any]`` on success, ``None`` when the backend
|
|
82
|
+
intentionally doesn't expose a version (permanent), or the
|
|
83
|
+
``_PROBE_FAILED`` sentinel when the call raised (transient).
|
|
84
|
+
"""
|
|
85
|
+
try:
|
|
86
|
+
return reflexio.current_config_version()
|
|
87
|
+
except Exception as exc: # noqa: BLE001 - intentional broad catch
|
|
88
|
+
logger.warning(
|
|
89
|
+
"Failed to probe config version for org %s: %s — keeping entry warm",
|
|
90
|
+
reflexio.org_id,
|
|
91
|
+
exc,
|
|
92
|
+
)
|
|
93
|
+
return _PROBE_FAILED
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def get_reflexio(org_id: str, storage_base_dir: str | None = None) -> Reflexio:
|
|
97
|
+
"""Get or create a cached Reflexio instance.
|
|
98
|
+
|
|
99
|
+
On cache hit, the entry's stamped config version is re-probed. If
|
|
100
|
+
the persisted version has changed (e.g. config file mtime bumped,
|
|
101
|
+
sibling replica wrote new DB version), the entry is evicted and a
|
|
102
|
+
fresh instance is constructed.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
org_id (str): Organization ID
|
|
106
|
+
storage_base_dir (Optional[str]): Base directory for storage (self-host mode)
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
Reflexio: Cached or newly created instance
|
|
110
|
+
"""
|
|
111
|
+
cache_key: CacheKey = (org_id, storage_base_dir)
|
|
112
|
+
|
|
113
|
+
# Cache lookup — held briefly to extract the entry, then released
|
|
114
|
+
# before doing any I/O (file stat, DB query) for the version probe.
|
|
115
|
+
with _reflexio_cache_lock:
|
|
116
|
+
entry: _CacheEntry | None = _reflexio_cache.get(cache_key)
|
|
117
|
+
|
|
118
|
+
if entry is not None:
|
|
119
|
+
cached_version = entry.cached_version
|
|
120
|
+
# Skip probing when we have nothing to compare against — a
|
|
121
|
+
# ``None`` stamp means the backend can't probe cheaply, so we
|
|
122
|
+
# rely on TTL + explicit invalidation instead.
|
|
123
|
+
if cached_version is None:
|
|
124
|
+
return entry.reflexio
|
|
125
|
+
current_version = _probe_version_safe(entry.reflexio)
|
|
126
|
+
# Transient probe failure: keep the cached instance for this
|
|
127
|
+
# request but DON'T mutate the stamp — the next request will
|
|
128
|
+
# try again, so a brief outage doesn't permanently disable
|
|
129
|
+
# eviction the way collapsing failures into ``None`` would.
|
|
130
|
+
if current_version is _PROBE_FAILED:
|
|
131
|
+
return entry.reflexio
|
|
132
|
+
if current_version == cached_version:
|
|
133
|
+
return entry.reflexio
|
|
134
|
+
# Stale entry. Evict only if the cached version still matches
|
|
135
|
+
# the one we just compared against — another thread may have
|
|
136
|
+
# already replaced the entry while we were probing.
|
|
137
|
+
with _reflexio_cache_lock:
|
|
138
|
+
existing = _reflexio_cache.get(cache_key)
|
|
139
|
+
if existing is not None and existing.cached_version == cached_version:
|
|
140
|
+
del _reflexio_cache[cache_key]
|
|
141
|
+
|
|
142
|
+
# Cache miss (or just-evicted stale entry) - create a new instance
|
|
143
|
+
# outside the lock to avoid blocking concurrent requests for other orgs.
|
|
144
|
+
reflexio = Reflexio(org_id=org_id, storage_base_dir=storage_base_dir)
|
|
145
|
+
new_version = _probe_version_safe(reflexio)
|
|
146
|
+
|
|
147
|
+
# Construction-time probe failure: serve this request from the
|
|
148
|
+
# newly-built instance but DON'T cache it. Caching with
|
|
149
|
+
# ``cached_version=None`` would conflate the entry with a
|
|
150
|
+
# legitimately-unprobeable backend and permanently disable
|
|
151
|
+
# auto-eviction. Skipping the cache means the next request pays a
|
|
152
|
+
# construction cost, but version-based eviction is preserved as
|
|
153
|
+
# soon as the backend recovers.
|
|
154
|
+
if new_version is _PROBE_FAILED:
|
|
155
|
+
return reflexio
|
|
156
|
+
|
|
157
|
+
new_entry = _CacheEntry(
|
|
158
|
+
reflexio=reflexio,
|
|
159
|
+
cached_version=new_version, # type: ignore[arg-type]
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
with _reflexio_cache_lock:
|
|
163
|
+
# Double-check in case another thread populated while we were constructing.
|
|
164
|
+
existing = _reflexio_cache.get(cache_key)
|
|
165
|
+
if existing is None:
|
|
166
|
+
_reflexio_cache[cache_key] = new_entry
|
|
167
|
+
return reflexio
|
|
168
|
+
return existing.reflexio
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def invalidate_reflexio_cache(org_id: str, storage_base_dir: str | None = None) -> bool:
|
|
172
|
+
"""Invalidate cached Reflexio for specific org.
|
|
173
|
+
|
|
174
|
+
Call this after set_config to ensure next request gets fresh instance.
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
org_id (str): Organization ID to invalidate
|
|
178
|
+
storage_base_dir (Optional[str]): Base directory for storage
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
bool: True if entry was removed, False if not found
|
|
182
|
+
"""
|
|
183
|
+
cache_key: CacheKey = (org_id, storage_base_dir)
|
|
184
|
+
with _reflexio_cache_lock:
|
|
185
|
+
if cache_key in _reflexio_cache:
|
|
186
|
+
del _reflexio_cache[cache_key]
|
|
187
|
+
return True
|
|
188
|
+
return False
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def clear_reflexio_cache() -> None:
|
|
192
|
+
"""Clear entire cache (for testing/admin)."""
|
|
193
|
+
with _reflexio_cache_lock:
|
|
194
|
+
_reflexio_cache.clear()
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def get_cache_stats() -> dict:
|
|
198
|
+
"""Get cache statistics for monitoring.
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
dict: Cache statistics including current size, max size, and TTL
|
|
202
|
+
"""
|
|
203
|
+
with _reflexio_cache_lock:
|
|
204
|
+
return {
|
|
205
|
+
"current_size": len(_reflexio_cache),
|
|
206
|
+
"max_size": REFLEXIO_CACHE_MAX_SIZE,
|
|
207
|
+
"ttl_seconds": REFLEXIO_CACHE_TTL_SECONDS,
|
|
208
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Request correlation ID for tracing concurrent operations.
|
|
2
|
+
|
|
3
|
+
Stores a short hex ID in a ContextVar so every log line emitted during a
|
|
4
|
+
single HTTP request (including ThreadPoolExecutor worker threads) can be
|
|
5
|
+
correlated back to the originating request.
|
|
6
|
+
|
|
7
|
+
Usage in worker threads::
|
|
8
|
+
|
|
9
|
+
ctx = contextvars.copy_context()
|
|
10
|
+
executor.submit(ctx.run, fn, *args)
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import contextvars
|
|
16
|
+
import logging
|
|
17
|
+
import uuid
|
|
18
|
+
|
|
19
|
+
# ContextVar holds the correlation ID for the current request.
|
|
20
|
+
# Default is empty string (non-request contexts like startup, CLI).
|
|
21
|
+
correlation_id_var: contextvars.ContextVar[str] = contextvars.ContextVar(
|
|
22
|
+
"correlation_id", default=""
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def generate_correlation_id() -> str:
|
|
27
|
+
"""Generate a short 8-character hex correlation ID."""
|
|
28
|
+
return uuid.uuid4().hex[:8]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class CorrelationIdFilter(logging.Filter):
|
|
32
|
+
"""Logging filter that injects correlation fields into every log record.
|
|
33
|
+
|
|
34
|
+
Attach this filter to handlers so formatters can use:
|
|
35
|
+
|
|
36
|
+
- ``%(correlation_id)s`` — the raw ID (empty string outside request context).
|
|
37
|
+
- ``%(correlation_tag)s`` — a ready-to-embed ``"[<cid>] "`` string that
|
|
38
|
+
collapses to ``""`` when there is no correlation ID. Use this in format
|
|
39
|
+
strings to avoid rendering an empty ``[]`` at startup / CLI time.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def filter(self, record: logging.LogRecord) -> bool:
|
|
43
|
+
cid = correlation_id_var.get("")
|
|
44
|
+
record.correlation_id = cid # type: ignore[attr-defined]
|
|
45
|
+
record.correlation_tag = f"[{cid}] " if cid else "" # type: ignore[attr-defined]
|
|
46
|
+
return True
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""
|
|
2
|
+
LLM client package providing unified access to multiple LLM providers.
|
|
3
|
+
|
|
4
|
+
This package uses LiteLLM as the backend to provide a consistent interface
|
|
5
|
+
for OpenAI, Claude, Azure OpenAI, and other LLM providers.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .litellm_client import (
|
|
9
|
+
LiteLLMClient,
|
|
10
|
+
LiteLLMClientError,
|
|
11
|
+
LiteLLMConfig,
|
|
12
|
+
ToolCallingChatResponse,
|
|
13
|
+
create_litellm_client,
|
|
14
|
+
)
|
|
15
|
+
from .model_defaults import (
|
|
16
|
+
ModelRole,
|
|
17
|
+
resolve_model_name,
|
|
18
|
+
validate_llm_availability,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
"LiteLLMClient",
|
|
23
|
+
"LiteLLMConfig",
|
|
24
|
+
"LiteLLMClientError",
|
|
25
|
+
"ModelRole",
|
|
26
|
+
"ToolCallingChatResponse",
|
|
27
|
+
"create_litellm_client",
|
|
28
|
+
"resolve_model_name",
|
|
29
|
+
"validate_llm_availability",
|
|
30
|
+
]
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""OpenAI-compatible local embedding service."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import math
|
|
6
|
+
import threading
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from fastapi import FastAPI, HTTPException
|
|
10
|
+
from pydantic import BaseModel, Field
|
|
11
|
+
|
|
12
|
+
from reflexio.server.llm.providers.local_embedding_provider import LocalEmbedder
|
|
13
|
+
from reflexio.server.llm.providers.nomic_embedding_provider import (
|
|
14
|
+
NomicEmbedder,
|
|
15
|
+
is_nomic_model,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
_MINILM_MODEL = "local/minilm-l6-v2"
|
|
19
|
+
_SUPPORTED_MODELS = {
|
|
20
|
+
_MINILM_MODEL,
|
|
21
|
+
"local/nomic-embed-v1.5",
|
|
22
|
+
"local/nomic-embed-text-v1.5",
|
|
23
|
+
}
|
|
24
|
+
_ACTIVE_MODEL: str | None = None
|
|
25
|
+
_ACTIVE_MODEL_LOCK = threading.Lock()
|
|
26
|
+
|
|
27
|
+
app = FastAPI(title="Reflexio Embedding Service")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class EmbeddingRequest(BaseModel):
|
|
31
|
+
model: str
|
|
32
|
+
input: str | list[str]
|
|
33
|
+
dimensions: int | None = Field(default=None, gt=0)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class EmbeddingData(BaseModel):
|
|
37
|
+
object: str = "embedding"
|
|
38
|
+
embedding: list[float]
|
|
39
|
+
index: int
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class EmbeddingResponse(BaseModel):
|
|
43
|
+
object: str = "list"
|
|
44
|
+
data: list[EmbeddingData]
|
|
45
|
+
model: str
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@app.get("/health")
|
|
49
|
+
def health() -> dict[str, Any]:
|
|
50
|
+
"""Health check endpoint."""
|
|
51
|
+
return {"status": "ok", "active_model": _ACTIVE_MODEL}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@app.post("/v1/embeddings")
|
|
55
|
+
def create_embeddings(request: EmbeddingRequest) -> EmbeddingResponse:
|
|
56
|
+
"""Create embeddings using the daemon's single active local model."""
|
|
57
|
+
_activate_model(request.model)
|
|
58
|
+
texts = [request.input] if isinstance(request.input, str) else list(request.input)
|
|
59
|
+
if is_nomic_model(request.model):
|
|
60
|
+
embeddings = NomicEmbedder.get().embed(texts)
|
|
61
|
+
elif request.model == _MINILM_MODEL:
|
|
62
|
+
embeddings = LocalEmbedder.get().embed(texts)
|
|
63
|
+
else:
|
|
64
|
+
raise HTTPException(
|
|
65
|
+
status_code=400, detail=f"Unsupported model: {request.model}"
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
if request.dimensions:
|
|
69
|
+
embeddings = [_resize_embedding(vec, request.dimensions) for vec in embeddings]
|
|
70
|
+
|
|
71
|
+
return EmbeddingResponse(
|
|
72
|
+
data=[
|
|
73
|
+
EmbeddingData(embedding=embedding, index=index)
|
|
74
|
+
for index, embedding in enumerate(embeddings)
|
|
75
|
+
],
|
|
76
|
+
model=request.model,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _activate_model(model: str) -> None:
|
|
81
|
+
if model not in _SUPPORTED_MODELS:
|
|
82
|
+
raise HTTPException(status_code=400, detail=f"Unsupported model: {model}")
|
|
83
|
+
global _ACTIVE_MODEL
|
|
84
|
+
with _ACTIVE_MODEL_LOCK:
|
|
85
|
+
if _ACTIVE_MODEL is None:
|
|
86
|
+
_ACTIVE_MODEL = model
|
|
87
|
+
return
|
|
88
|
+
if model != _ACTIVE_MODEL:
|
|
89
|
+
raise HTTPException(
|
|
90
|
+
status_code=409,
|
|
91
|
+
detail=(
|
|
92
|
+
"Embedding daemon already owns model "
|
|
93
|
+
f"{_ACTIVE_MODEL}; start a separate daemon for {model}"
|
|
94
|
+
),
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _resize_embedding(vec: list[float], dimensions: int) -> list[float]:
|
|
99
|
+
if dimensions == len(vec):
|
|
100
|
+
return vec
|
|
101
|
+
if dimensions > len(vec):
|
|
102
|
+
raise HTTPException(
|
|
103
|
+
status_code=400,
|
|
104
|
+
detail=f"dimensions={dimensions} exceeds model output length {len(vec)}",
|
|
105
|
+
)
|
|
106
|
+
sliced = vec[:dimensions]
|
|
107
|
+
norm = math.sqrt(sum(value * value for value in sliced))
|
|
108
|
+
if norm <= 0:
|
|
109
|
+
return sliced
|
|
110
|
+
return [value / norm for value in sliced]
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Shared image encoding utilities for LLM clients."""
|
|
2
|
+
|
|
3
|
+
import base64
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
# Mapping from file extension to MIME type for supported image formats.
|
|
7
|
+
SUPPORTED_IMAGE_MIME_TYPES: dict[str, str] = {
|
|
8
|
+
".jpg": "image/jpeg",
|
|
9
|
+
".jpeg": "image/jpeg",
|
|
10
|
+
".png": "image/png",
|
|
11
|
+
".gif": "image/gif",
|
|
12
|
+
".webp": "image/webp",
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ImageEncodingError(Exception):
|
|
17
|
+
"""Raised when an image file cannot be encoded to base64."""
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def encode_image_to_base64(image_path: str | Path) -> tuple[str, str]:
|
|
21
|
+
"""
|
|
22
|
+
Encode an image file to a base64 string with MIME type detection.
|
|
23
|
+
|
|
24
|
+
Reads the file at *image_path*, validates that the format is supported,
|
|
25
|
+
and returns the base64-encoded contents together with the corresponding
|
|
26
|
+
MIME type string.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
image_path (str | Path): Filesystem path to the image file.
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
tuple[str, str]: A ``(base64_data, media_type)`` pair.
|
|
33
|
+
|
|
34
|
+
Raises:
|
|
35
|
+
ImageEncodingError: If the file does not exist or has an unsupported
|
|
36
|
+
extension.
|
|
37
|
+
"""
|
|
38
|
+
path = Path(image_path)
|
|
39
|
+
|
|
40
|
+
if not path.exists():
|
|
41
|
+
raise ImageEncodingError(f"Image file not found: {image_path}")
|
|
42
|
+
|
|
43
|
+
suffix = path.suffix.lower()
|
|
44
|
+
if suffix not in SUPPORTED_IMAGE_MIME_TYPES:
|
|
45
|
+
raise ImageEncodingError(
|
|
46
|
+
f"Unsupported image format: {suffix}. "
|
|
47
|
+
f"Supported formats: {', '.join(sorted(SUPPORTED_IMAGE_MIME_TYPES))}"
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
media_type = SUPPORTED_IMAGE_MIME_TYPES[suffix]
|
|
51
|
+
|
|
52
|
+
with path.open("rb") as f:
|
|
53
|
+
base64_data = base64.b64encode(f.read()).decode("utf-8")
|
|
54
|
+
|
|
55
|
+
return base64_data, media_type
|