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,545 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
logger = logging.getLogger(__name__)
|
|
4
|
+
|
|
5
|
+
from datetime import UTC, datetime
|
|
6
|
+
|
|
7
|
+
from reflexio.lib._base import (
|
|
8
|
+
STORAGE_NOT_CONFIGURED_MSG,
|
|
9
|
+
ReflexioBase,
|
|
10
|
+
_require_storage,
|
|
11
|
+
)
|
|
12
|
+
from reflexio.models.api_schema.retriever_schema import (
|
|
13
|
+
GetProfileStatisticsResponse,
|
|
14
|
+
GetUserProfilesRequest,
|
|
15
|
+
GetUserProfilesResponse,
|
|
16
|
+
RerankUserProfilesRequest,
|
|
17
|
+
RerankUserProfilesResponse,
|
|
18
|
+
SearchUserProfileRequest,
|
|
19
|
+
SearchUserProfileResponse,
|
|
20
|
+
StorageStatsRequest,
|
|
21
|
+
StorageStatsResponse,
|
|
22
|
+
UpdateUserProfileRequest,
|
|
23
|
+
UpdateUserProfileResponse,
|
|
24
|
+
)
|
|
25
|
+
from reflexio.models.api_schema.service_schemas import (
|
|
26
|
+
AddUserProfileRequest,
|
|
27
|
+
AddUserProfileResponse,
|
|
28
|
+
BulkDeleteResponse,
|
|
29
|
+
DeleteProfilesByIdsRequest,
|
|
30
|
+
DeleteUserProfileRequest,
|
|
31
|
+
DeleteUserProfileResponse,
|
|
32
|
+
DowngradeProfilesRequest,
|
|
33
|
+
DowngradeProfilesResponse,
|
|
34
|
+
ProfileChangeLogResponse,
|
|
35
|
+
Status,
|
|
36
|
+
UpgradeProfilesRequest,
|
|
37
|
+
UpgradeProfilesResponse,
|
|
38
|
+
)
|
|
39
|
+
from reflexio.server.services.profile.profile_generation_service import (
|
|
40
|
+
ProfileGenerationService,
|
|
41
|
+
)
|
|
42
|
+
from reflexio.server.tracing import profile_step
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class ProfilesMixin(ReflexioBase):
|
|
46
|
+
def search_user_profiles(
|
|
47
|
+
self,
|
|
48
|
+
request: SearchUserProfileRequest | dict,
|
|
49
|
+
status_filter: list[Status | None] | None = None,
|
|
50
|
+
) -> SearchUserProfileResponse:
|
|
51
|
+
"""Search for user profiles.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
request (SearchUserProfileRequest): The search request
|
|
55
|
+
status_filter (Optional[list[Optional[Status]]]): Filter profiles by status. Defaults to [None] for current profiles only.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
SearchUserProfileResponse: Response containing matching profiles
|
|
59
|
+
"""
|
|
60
|
+
if not self._is_storage_configured():
|
|
61
|
+
return SearchUserProfileResponse(
|
|
62
|
+
success=True, user_profiles=[], msg=STORAGE_NOT_CONFIGURED_MSG
|
|
63
|
+
)
|
|
64
|
+
if isinstance(request, dict):
|
|
65
|
+
request = SearchUserProfileRequest(**request)
|
|
66
|
+
if status_filter is None:
|
|
67
|
+
status_filter = [None] # Default to current profiles
|
|
68
|
+
rewritten = self._reformulate_query(
|
|
69
|
+
request.query, enabled=bool(request.enable_reformulation)
|
|
70
|
+
)
|
|
71
|
+
if rewritten:
|
|
72
|
+
request = request.model_copy(update={"query": rewritten})
|
|
73
|
+
query_embedding = self._maybe_get_query_embedding(
|
|
74
|
+
request.query, request.search_mode
|
|
75
|
+
)
|
|
76
|
+
logger.info(
|
|
77
|
+
"search_user_profiles: query=%r, search_mode=%s, embedding_generated=%s",
|
|
78
|
+
request.query,
|
|
79
|
+
request.search_mode,
|
|
80
|
+
query_embedding is not None,
|
|
81
|
+
)
|
|
82
|
+
with profile_step(
|
|
83
|
+
"search.storage",
|
|
84
|
+
entity_type="profiles",
|
|
85
|
+
search_mode=request.search_mode,
|
|
86
|
+
top_k=request.top_k,
|
|
87
|
+
) as span:
|
|
88
|
+
profiles = self._get_storage().search_user_profile(
|
|
89
|
+
request, status_filter=status_filter, query_embedding=query_embedding
|
|
90
|
+
)
|
|
91
|
+
span.set_data("result_count", len(profiles))
|
|
92
|
+
return SearchUserProfileResponse(
|
|
93
|
+
success=True,
|
|
94
|
+
user_profiles=profiles,
|
|
95
|
+
msg=f"Found {len(profiles)} matching profile(s)",
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
def rerank_user_profiles(
|
|
99
|
+
self,
|
|
100
|
+
request: RerankUserProfilesRequest | dict,
|
|
101
|
+
) -> RerankUserProfilesResponse:
|
|
102
|
+
"""Rerank a list of profile ids by query relevance using a cross-encoder.
|
|
103
|
+
|
|
104
|
+
Fetches each profile's full content (filtered by ``user_id``), scores
|
|
105
|
+
``(query, content)`` pairs with ``cross-encoder/ms-marco-MiniLM-L-6-v2``,
|
|
106
|
+
and returns the top_k profiles sorted by descending score. Profile ids
|
|
107
|
+
that don't exist for the user are silently dropped.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
request (Union[RerankUserProfilesRequest, dict]): The rerank
|
|
111
|
+
request — must contain ``user_id``, ``query``, and
|
|
112
|
+
``profile_ids``.
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
RerankUserProfilesResponse: Profiles sorted by descending
|
|
116
|
+
relevance score, capped at ``request.top_k``.
|
|
117
|
+
"""
|
|
118
|
+
if not self._is_storage_configured():
|
|
119
|
+
return RerankUserProfilesResponse(
|
|
120
|
+
success=True, user_profiles=[], msg=STORAGE_NOT_CONFIGURED_MSG
|
|
121
|
+
)
|
|
122
|
+
if isinstance(request, dict):
|
|
123
|
+
request = RerankUserProfilesRequest(**request)
|
|
124
|
+
if not request.profile_ids:
|
|
125
|
+
return RerankUserProfilesResponse(
|
|
126
|
+
success=True, user_profiles=[], msg="No profile_ids provided"
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
# Fetch every profile for the user — including PENDING and ARCHIVED —
|
|
130
|
+
# because callers may want to rerank historical context, not just
|
|
131
|
+
# the currently-published set.
|
|
132
|
+
all_profiles = self._get_storage().get_user_profile(
|
|
133
|
+
request.user_id, status_filter=[None, Status.PENDING, Status.ARCHIVED]
|
|
134
|
+
)
|
|
135
|
+
wanted = set(request.profile_ids)
|
|
136
|
+
candidates = [p for p in all_profiles if p.profile_id in wanted]
|
|
137
|
+
dropped = len(request.profile_ids) - len(candidates)
|
|
138
|
+
|
|
139
|
+
# Lazy import keeps test collection fast; the cross-encoder pulls in
|
|
140
|
+
# torch + sentence-transformers on first call.
|
|
141
|
+
from reflexio.server.llm.rerank import score_pairs
|
|
142
|
+
|
|
143
|
+
scores = score_pairs(request.query, [p.content for p in candidates])
|
|
144
|
+
ranked = sorted(
|
|
145
|
+
zip(candidates, scores, strict=True),
|
|
146
|
+
key=lambda pair: pair[1],
|
|
147
|
+
reverse=True,
|
|
148
|
+
)
|
|
149
|
+
top = [profile for profile, _score in ranked[: request.top_k]]
|
|
150
|
+
msg = f"Reranked {len(candidates)} profile(s); dropped {dropped} unknown id(s)"
|
|
151
|
+
return RerankUserProfilesResponse(success=True, user_profiles=top, msg=msg)
|
|
152
|
+
|
|
153
|
+
def storage_stats(
|
|
154
|
+
self,
|
|
155
|
+
request: StorageStatsRequest | dict,
|
|
156
|
+
) -> StorageStatsResponse:
|
|
157
|
+
"""Return lightweight metadata about a user's stored profiles + playbooks.
|
|
158
|
+
|
|
159
|
+
Provides counts and the last-modified timestamp range across every
|
|
160
|
+
status, suitable for sizing ``top_k`` before retrieval.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
request (Union[StorageStatsRequest, dict]): The stats request —
|
|
164
|
+
must contain ``user_id``.
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
StorageStatsResponse: Counts and timestamp range for the user.
|
|
168
|
+
"""
|
|
169
|
+
if not self._is_storage_configured():
|
|
170
|
+
return StorageStatsResponse(
|
|
171
|
+
success=True,
|
|
172
|
+
profile_count=0,
|
|
173
|
+
playbook_count=0,
|
|
174
|
+
msg=STORAGE_NOT_CONFIGURED_MSG,
|
|
175
|
+
)
|
|
176
|
+
if isinstance(request, dict):
|
|
177
|
+
request = StorageStatsRequest(**request)
|
|
178
|
+
storage = self._get_storage()
|
|
179
|
+
# Walk every status — agent callers care about total surface area,
|
|
180
|
+
# not just CURRENT entries.
|
|
181
|
+
all_statuses: list[Status | None] = [None, Status.PENDING, Status.ARCHIVED]
|
|
182
|
+
profiles = storage.get_user_profile(request.user_id, status_filter=all_statuses)
|
|
183
|
+
oldest_ts: datetime | None = None
|
|
184
|
+
newest_ts: datetime | None = None
|
|
185
|
+
if profiles:
|
|
186
|
+
timestamps = [p.last_modified_timestamp for p in profiles]
|
|
187
|
+
oldest_ts = datetime.fromtimestamp(min(timestamps), tz=UTC)
|
|
188
|
+
newest_ts = datetime.fromtimestamp(max(timestamps), tz=UTC)
|
|
189
|
+
playbook_count = storage.count_user_playbooks(
|
|
190
|
+
user_id=request.user_id, status_filter=all_statuses
|
|
191
|
+
)
|
|
192
|
+
return StorageStatsResponse(
|
|
193
|
+
success=True,
|
|
194
|
+
profile_count=len(profiles),
|
|
195
|
+
playbook_count=playbook_count,
|
|
196
|
+
oldest_profile_modified=oldest_ts,
|
|
197
|
+
newest_profile_modified=newest_ts,
|
|
198
|
+
msg=f"Found {len(profiles)} profile(s) and {playbook_count} playbook(s)",
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
def get_profile_change_logs(self) -> ProfileChangeLogResponse:
|
|
202
|
+
"""Get profile change logs.
|
|
203
|
+
|
|
204
|
+
Returns:
|
|
205
|
+
ProfileChangeLogResponse: Response containing profile change logs
|
|
206
|
+
"""
|
|
207
|
+
if not self._is_storage_configured():
|
|
208
|
+
return ProfileChangeLogResponse(success=True, profile_change_logs=[])
|
|
209
|
+
changelogs = self._get_storage().get_profile_change_logs()
|
|
210
|
+
return ProfileChangeLogResponse(success=True, profile_change_logs=changelogs)
|
|
211
|
+
|
|
212
|
+
@_require_storage(DeleteUserProfileResponse)
|
|
213
|
+
def delete_profile(
|
|
214
|
+
self,
|
|
215
|
+
request: DeleteUserProfileRequest | dict,
|
|
216
|
+
) -> DeleteUserProfileResponse:
|
|
217
|
+
"""Delete user profiles.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
request (DeleteUserProfileRequest): The delete request
|
|
221
|
+
|
|
222
|
+
Returns:
|
|
223
|
+
DeleteUserProfileResponse: Response containing success status and message
|
|
224
|
+
"""
|
|
225
|
+
if isinstance(request, dict):
|
|
226
|
+
request = DeleteUserProfileRequest(**request)
|
|
227
|
+
self._get_storage().delete_user_profile(request)
|
|
228
|
+
return DeleteUserProfileResponse(success=True, message="Deleted successfully")
|
|
229
|
+
|
|
230
|
+
@_require_storage(UpdateUserProfileResponse, msg_field="msg")
|
|
231
|
+
def update_user_profile(
|
|
232
|
+
self,
|
|
233
|
+
request: UpdateUserProfileRequest | dict,
|
|
234
|
+
) -> UpdateUserProfileResponse:
|
|
235
|
+
"""Apply a partial update to an existing user profile.
|
|
236
|
+
|
|
237
|
+
Fetches the current profile by ``(user_id, profile_id)``, applies the
|
|
238
|
+
non-None fields from ``request``, refreshes ``last_modified_timestamp``,
|
|
239
|
+
and persists the whole record via
|
|
240
|
+
:meth:`BaseStorage.update_user_profile_by_id`. The storage layer
|
|
241
|
+
regenerates the embedding for the updated content.
|
|
242
|
+
|
|
243
|
+
Args:
|
|
244
|
+
request (Union[UpdateUserProfileRequest, dict]): The update request.
|
|
245
|
+
``user_id`` and ``profile_id`` are required; ``content`` and
|
|
246
|
+
``custom_features`` are optional — only non-None fields are
|
|
247
|
+
applied.
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
UpdateUserProfileResponse: ``success=True`` when the profile was
|
|
251
|
+
updated, ``success=False`` with a descriptive ``msg`` when it
|
|
252
|
+
could not be found.
|
|
253
|
+
"""
|
|
254
|
+
if isinstance(request, dict):
|
|
255
|
+
request = UpdateUserProfileRequest(**request)
|
|
256
|
+
storage = self._get_storage()
|
|
257
|
+
profiles = storage.get_user_profile(request.user_id)
|
|
258
|
+
existing = next(
|
|
259
|
+
(p for p in profiles if p.profile_id == request.profile_id), None
|
|
260
|
+
)
|
|
261
|
+
if existing is None:
|
|
262
|
+
return UpdateUserProfileResponse(
|
|
263
|
+
success=False,
|
|
264
|
+
msg=(
|
|
265
|
+
f"Profile not found: user_id={request.user_id!r} "
|
|
266
|
+
f"profile_id={request.profile_id!r}"
|
|
267
|
+
),
|
|
268
|
+
)
|
|
269
|
+
if request.content is not None:
|
|
270
|
+
existing.content = request.content
|
|
271
|
+
if request.custom_features is not None:
|
|
272
|
+
existing.custom_features = request.custom_features
|
|
273
|
+
existing.last_modified_timestamp = int(datetime.now(UTC).timestamp())
|
|
274
|
+
storage.update_user_profile_by_id(request.user_id, request.profile_id, existing)
|
|
275
|
+
return UpdateUserProfileResponse(
|
|
276
|
+
success=True, msg="User profile updated successfully"
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
@_require_storage(BulkDeleteResponse)
|
|
280
|
+
def delete_all_profiles_bulk(self) -> BulkDeleteResponse:
|
|
281
|
+
"""Delete all profiles.
|
|
282
|
+
|
|
283
|
+
Returns:
|
|
284
|
+
BulkDeleteResponse: Response containing success status and deleted count
|
|
285
|
+
"""
|
|
286
|
+
self._get_storage().delete_all_profiles()
|
|
287
|
+
return BulkDeleteResponse(success=True, message="Deleted successfully")
|
|
288
|
+
|
|
289
|
+
@_require_storage(BulkDeleteResponse)
|
|
290
|
+
def delete_profiles_by_ids(
|
|
291
|
+
self,
|
|
292
|
+
request: DeleteProfilesByIdsRequest | dict,
|
|
293
|
+
) -> BulkDeleteResponse:
|
|
294
|
+
"""Delete profiles by their IDs.
|
|
295
|
+
|
|
296
|
+
Args:
|
|
297
|
+
request (DeleteProfilesByIdsRequest): The delete request containing profile_ids
|
|
298
|
+
|
|
299
|
+
Returns:
|
|
300
|
+
BulkDeleteResponse: Response containing success status and deleted count
|
|
301
|
+
"""
|
|
302
|
+
if isinstance(request, dict):
|
|
303
|
+
request = DeleteProfilesByIdsRequest(**request)
|
|
304
|
+
deleted = self._get_storage().delete_profiles_by_ids(request.profile_ids)
|
|
305
|
+
return BulkDeleteResponse(
|
|
306
|
+
success=True, deleted_count=deleted, message=f"Deleted {deleted} item(s)"
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
def add_user_profile(
|
|
310
|
+
self,
|
|
311
|
+
request: AddUserProfileRequest | dict,
|
|
312
|
+
) -> AddUserProfileResponse:
|
|
313
|
+
"""Add user profiles directly to storage, bypassing inference.
|
|
314
|
+
|
|
315
|
+
Mirrors :meth:`add_user_playbook` — useful for seeding a known
|
|
316
|
+
fact about a user (testing, migration, manual fact injection)
|
|
317
|
+
without going through the interaction-based generation pipeline.
|
|
318
|
+
The storage layer's ``add_user_profile`` populates the embedding
|
|
319
|
+
automatically.
|
|
320
|
+
|
|
321
|
+
Args:
|
|
322
|
+
request (Union[AddUserProfileRequest, dict]): The add
|
|
323
|
+
request containing user profiles. Profiles must each
|
|
324
|
+
have a non-empty ``content`` field.
|
|
325
|
+
|
|
326
|
+
Returns:
|
|
327
|
+
AddUserProfileResponse: Response containing success status,
|
|
328
|
+
message, and count of profiles added.
|
|
329
|
+
"""
|
|
330
|
+
if not self._is_storage_configured():
|
|
331
|
+
return AddUserProfileResponse(
|
|
332
|
+
success=False, message=STORAGE_NOT_CONFIGURED_MSG
|
|
333
|
+
)
|
|
334
|
+
if isinstance(request, dict):
|
|
335
|
+
request = AddUserProfileRequest(**request)
|
|
336
|
+
|
|
337
|
+
# Group by user_id since storage.add_user_profile takes
|
|
338
|
+
# (user_id, list[UserProfile]) and we want one storage call
|
|
339
|
+
# per user.
|
|
340
|
+
by_user: dict[str, list] = {}
|
|
341
|
+
for p in request.user_profiles:
|
|
342
|
+
by_user.setdefault(p.user_id, []).append(p)
|
|
343
|
+
|
|
344
|
+
# Per-user try/except so we can surface partial-success in
|
|
345
|
+
# the response message instead of silently losing track of
|
|
346
|
+
# which users were persisted before a later failure.
|
|
347
|
+
persisted_profiles = 0
|
|
348
|
+
for persisted_users, (user_id, profiles) in enumerate(by_user.items()):
|
|
349
|
+
try:
|
|
350
|
+
self._get_storage().add_user_profile(user_id, profiles)
|
|
351
|
+
except Exception:
|
|
352
|
+
# Log the full exception for operators (storage errors
|
|
353
|
+
# may contain SQL text, file paths, table names); return
|
|
354
|
+
# a generic message to the caller to avoid information
|
|
355
|
+
# disclosure over HTTP.
|
|
356
|
+
logger.exception("add_user_profile failed for user_id=%s", user_id)
|
|
357
|
+
if persisted_users == 0:
|
|
358
|
+
message = "Failed to add user profile"
|
|
359
|
+
else:
|
|
360
|
+
message = (
|
|
361
|
+
f"Partially persisted {persisted_profiles} profile(s) "
|
|
362
|
+
f"for {persisted_users} user(s) before failing on "
|
|
363
|
+
f"user {user_id}"
|
|
364
|
+
)
|
|
365
|
+
return AddUserProfileResponse(success=False, message=message)
|
|
366
|
+
persisted_profiles += len(profiles)
|
|
367
|
+
|
|
368
|
+
return AddUserProfileResponse(
|
|
369
|
+
success=True,
|
|
370
|
+
added_count=persisted_profiles,
|
|
371
|
+
message=f"Added {persisted_profiles} profile(s)",
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
def get_profiles(
|
|
375
|
+
self,
|
|
376
|
+
request: GetUserProfilesRequest | dict,
|
|
377
|
+
status_filter: list[Status | None] | None = None,
|
|
378
|
+
) -> GetUserProfilesResponse:
|
|
379
|
+
"""Get user profiles.
|
|
380
|
+
|
|
381
|
+
Args:
|
|
382
|
+
request (GetUserProfilesRequest): The get request
|
|
383
|
+
status_filter (Optional[list[Optional[Status]]]): Filter profiles by status. Defaults to [None] for current profiles only.
|
|
384
|
+
If provided, takes precedence over request.status_filter.
|
|
385
|
+
|
|
386
|
+
Returns:
|
|
387
|
+
GetUserProfilesResponse: Response containing user profiles
|
|
388
|
+
"""
|
|
389
|
+
if not self._is_storage_configured():
|
|
390
|
+
return GetUserProfilesResponse(
|
|
391
|
+
success=True, user_profiles=[], msg=STORAGE_NOT_CONFIGURED_MSG
|
|
392
|
+
)
|
|
393
|
+
if isinstance(request, dict):
|
|
394
|
+
request = GetUserProfilesRequest(**request)
|
|
395
|
+
|
|
396
|
+
# Priority: parameter > request.status_filter > default [None]
|
|
397
|
+
if status_filter is None:
|
|
398
|
+
if hasattr(request, "status_filter") and request.status_filter is not None:
|
|
399
|
+
status_filter = request.status_filter
|
|
400
|
+
else:
|
|
401
|
+
status_filter = [None] # Default to current profiles
|
|
402
|
+
|
|
403
|
+
profiles = self._get_storage().get_user_profile(
|
|
404
|
+
request.user_id, status_filter=status_filter
|
|
405
|
+
)
|
|
406
|
+
profiles = sorted(
|
|
407
|
+
profiles, key=lambda x: x.last_modified_timestamp, reverse=True
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
# Apply time filters
|
|
411
|
+
if request.start_time:
|
|
412
|
+
profiles = [
|
|
413
|
+
p
|
|
414
|
+
for p in profiles
|
|
415
|
+
if p.last_modified_timestamp >= int(request.start_time.timestamp())
|
|
416
|
+
]
|
|
417
|
+
if request.end_time:
|
|
418
|
+
profiles = [
|
|
419
|
+
p
|
|
420
|
+
for p in profiles
|
|
421
|
+
if p.last_modified_timestamp <= int(request.end_time.timestamp())
|
|
422
|
+
]
|
|
423
|
+
|
|
424
|
+
# Apply top_k limit
|
|
425
|
+
if request.top_k:
|
|
426
|
+
profiles = sorted(
|
|
427
|
+
profiles, key=lambda x: x.last_modified_timestamp, reverse=True
|
|
428
|
+
)[: request.top_k]
|
|
429
|
+
|
|
430
|
+
return GetUserProfilesResponse(
|
|
431
|
+
success=True,
|
|
432
|
+
user_profiles=profiles,
|
|
433
|
+
msg=f"Found {len(profiles)} profile(s)",
|
|
434
|
+
)
|
|
435
|
+
|
|
436
|
+
def get_all_profiles(
|
|
437
|
+
self,
|
|
438
|
+
limit: int = 100,
|
|
439
|
+
status_filter: list[Status | None] | None = None,
|
|
440
|
+
) -> GetUserProfilesResponse:
|
|
441
|
+
"""Get all user profiles across all users.
|
|
442
|
+
|
|
443
|
+
Args:
|
|
444
|
+
limit (int, optional): Maximum number of profiles to return. Defaults to 100.
|
|
445
|
+
status_filter (Optional[list[Optional[Status]]]): Filter profiles by status. Defaults to [None] for current profiles only.
|
|
446
|
+
|
|
447
|
+
Returns:
|
|
448
|
+
GetUserProfilesResponse: Response containing all user profiles
|
|
449
|
+
"""
|
|
450
|
+
if not self._is_storage_configured():
|
|
451
|
+
return GetUserProfilesResponse(
|
|
452
|
+
success=True, user_profiles=[], msg=STORAGE_NOT_CONFIGURED_MSG
|
|
453
|
+
)
|
|
454
|
+
if status_filter is None:
|
|
455
|
+
status_filter = [None] # Default to current profiles
|
|
456
|
+
profiles = self._get_storage().get_all_profiles(
|
|
457
|
+
limit=limit, status_filter=status_filter
|
|
458
|
+
)
|
|
459
|
+
profiles = sorted(
|
|
460
|
+
profiles, key=lambda x: x.last_modified_timestamp, reverse=True
|
|
461
|
+
)
|
|
462
|
+
return GetUserProfilesResponse(
|
|
463
|
+
success=True,
|
|
464
|
+
user_profiles=profiles,
|
|
465
|
+
msg=f"Found {len(profiles)} profile(s)",
|
|
466
|
+
)
|
|
467
|
+
|
|
468
|
+
def upgrade_all_profiles(
|
|
469
|
+
self,
|
|
470
|
+
request: UpgradeProfilesRequest | dict | None = None,
|
|
471
|
+
) -> UpgradeProfilesResponse:
|
|
472
|
+
"""Upgrade all profiles by deleting old ARCHIVED, archiving CURRENT, and promoting PENDING.
|
|
473
|
+
|
|
474
|
+
Args:
|
|
475
|
+
request (Union[UpgradeProfilesRequest, dict], optional): The upgrade request
|
|
476
|
+
|
|
477
|
+
Returns:
|
|
478
|
+
UpgradeProfilesResponse: Response containing success status and counts
|
|
479
|
+
"""
|
|
480
|
+
if not self._is_storage_configured():
|
|
481
|
+
return UpgradeProfilesResponse(
|
|
482
|
+
success=False, message=STORAGE_NOT_CONFIGURED_MSG
|
|
483
|
+
)
|
|
484
|
+
if isinstance(request, dict):
|
|
485
|
+
request = UpgradeProfilesRequest(**request)
|
|
486
|
+
elif request is None:
|
|
487
|
+
request = UpgradeProfilesRequest(user_id=None, only_affected_users=False)
|
|
488
|
+
|
|
489
|
+
service = ProfileGenerationService(
|
|
490
|
+
llm_client=self.llm_client,
|
|
491
|
+
request_context=self.request_context,
|
|
492
|
+
)
|
|
493
|
+
return service.run_upgrade(request) # type: ignore[reportArgumentType]
|
|
494
|
+
|
|
495
|
+
def downgrade_all_profiles(
|
|
496
|
+
self,
|
|
497
|
+
request: DowngradeProfilesRequest | dict | None = None,
|
|
498
|
+
) -> DowngradeProfilesResponse:
|
|
499
|
+
"""Downgrade all profiles by archiving CURRENT and restoring ARCHIVED.
|
|
500
|
+
|
|
501
|
+
Args:
|
|
502
|
+
request (Union[DowngradeProfilesRequest, dict], optional): The downgrade request
|
|
503
|
+
|
|
504
|
+
Returns:
|
|
505
|
+
DowngradeProfilesResponse: Response containing success status and counts
|
|
506
|
+
"""
|
|
507
|
+
if not self._is_storage_configured():
|
|
508
|
+
return DowngradeProfilesResponse(
|
|
509
|
+
success=False, message=STORAGE_NOT_CONFIGURED_MSG
|
|
510
|
+
)
|
|
511
|
+
if isinstance(request, dict):
|
|
512
|
+
request = DowngradeProfilesRequest(**request)
|
|
513
|
+
elif request is None:
|
|
514
|
+
request = DowngradeProfilesRequest(user_id=None, only_affected_users=False)
|
|
515
|
+
|
|
516
|
+
service = ProfileGenerationService(
|
|
517
|
+
llm_client=self.llm_client,
|
|
518
|
+
request_context=self.request_context,
|
|
519
|
+
)
|
|
520
|
+
return service.run_downgrade(request) # type: ignore[reportArgumentType]
|
|
521
|
+
|
|
522
|
+
def get_profile_statistics(self) -> GetProfileStatisticsResponse:
|
|
523
|
+
"""Get profile count statistics by status.
|
|
524
|
+
|
|
525
|
+
Returns:
|
|
526
|
+
GetProfileStatisticsResponse: Response containing profile counts
|
|
527
|
+
"""
|
|
528
|
+
if not self._is_storage_configured():
|
|
529
|
+
return GetProfileStatisticsResponse(
|
|
530
|
+
success=True,
|
|
531
|
+
current_count=0,
|
|
532
|
+
pending_count=0,
|
|
533
|
+
archived_count=0,
|
|
534
|
+
expiring_soon_count=0,
|
|
535
|
+
msg=STORAGE_NOT_CONFIGURED_MSG,
|
|
536
|
+
)
|
|
537
|
+
try:
|
|
538
|
+
stats = self._get_storage().get_profile_statistics()
|
|
539
|
+
return GetProfileStatisticsResponse(
|
|
540
|
+
success=True, msg="Retrieved profile statistics successfully", **stats
|
|
541
|
+
)
|
|
542
|
+
except Exception as e:
|
|
543
|
+
return GetProfileStatisticsResponse(
|
|
544
|
+
success=False, msg=f"Failed to get profile statistics: {str(e)}"
|
|
545
|
+
)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""Reflection mixin: post-publish critique-and-revise of cited memories."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from reflexio.lib._base import STORAGE_NOT_CONFIGURED_MSG, ReflexioBase
|
|
6
|
+
from reflexio.server.services.reflection.reflection_service_utils import (
|
|
7
|
+
ReflectionResult,
|
|
8
|
+
ReflectionServiceRequest,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ReflectionMixin(ReflexioBase):
|
|
13
|
+
"""Expose ``run_reflection`` on the Reflexio facade."""
|
|
14
|
+
|
|
15
|
+
def run_reflection(
|
|
16
|
+
self,
|
|
17
|
+
request: ReflectionServiceRequest | dict,
|
|
18
|
+
) -> ReflectionResult:
|
|
19
|
+
"""Run one reflection pass for the given request.
|
|
20
|
+
|
|
21
|
+
Best-effort: returns a ``ReflectionResult`` describing what
|
|
22
|
+
happened. Storage must be configured; raises otherwise so the
|
|
23
|
+
caller (the publish-time hook) can swallow it via its own
|
|
24
|
+
``try/except`` wrapper.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
request (ReflectionServiceRequest | dict): The reflection
|
|
28
|
+
request. Dicts are coerced.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
ReflectionResult: Counts of cited / considered / replaced /
|
|
32
|
+
skipped / failed decisions for logging and tests.
|
|
33
|
+
|
|
34
|
+
Raises:
|
|
35
|
+
ValueError: If storage is not configured.
|
|
36
|
+
"""
|
|
37
|
+
if not self._is_storage_configured():
|
|
38
|
+
raise ValueError(STORAGE_NOT_CONFIGURED_MSG)
|
|
39
|
+
if isinstance(request, dict):
|
|
40
|
+
request = ReflectionServiceRequest(**request)
|
|
41
|
+
|
|
42
|
+
# Local import keeps the heavy service module out of facade
|
|
43
|
+
# cold-start when reflection is disabled.
|
|
44
|
+
from reflexio.server.services.reflection.reflection_service import (
|
|
45
|
+
ReflectionService,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
service = ReflectionService(
|
|
49
|
+
request_context=self.request_context,
|
|
50
|
+
llm_client=self.llm_client,
|
|
51
|
+
)
|
|
52
|
+
return service.run(request)
|