claude-smart 0.2.42 → 0.2.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +3 -3
- package/README.md +1 -1
- package/bin/claude-smart.js +2 -2
- package/package.json +9 -3
- package/plugin/.claude-plugin/plugin.json +9 -3
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/README.md +23 -3
- package/plugin/pyproject.toml +3 -3
- package/plugin/scripts/_lib.sh +91 -0
- package/plugin/scripts/backend-service.sh +51 -4
- package/plugin/scripts/cli.sh +3 -1
- package/plugin/scripts/codex-hook.js +72 -4
- package/plugin/scripts/dashboard-build.sh +1 -0
- package/plugin/scripts/dashboard-service.sh +1 -0
- package/plugin/scripts/ensure-plugin-root.sh +1 -0
- package/plugin/scripts/hook_entry.sh +6 -3
- package/plugin/scripts/smart-install.sh +3 -2
- package/plugin/src/README.md +57 -0
- package/plugin/src/claude_smart/context_format.py +11 -12
- package/plugin/src/claude_smart/cs_cite.py +26 -12
- package/plugin/src/claude_smart/ids.py +13 -5
- package/plugin/uv.lock +126 -5
- package/plugin/vendor/reflexio/.env.example +62 -0
- package/plugin/vendor/reflexio/LICENSE +201 -0
- package/plugin/vendor/reflexio/README.md +338 -0
- package/plugin/vendor/reflexio/pyproject.toml +274 -0
- package/plugin/vendor/reflexio/reflexio/README.md +184 -0
- package/plugin/vendor/reflexio/reflexio/__init__.py +166 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/README.md +109 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/backends.py +175 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/bench.py +642 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/embed_cache.py +330 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/report.py +317 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/results/report.md +43 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/results/results.json +4478 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/scenarios.py +134 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/seed.py +255 -0
- package/plugin/vendor/reflexio/reflexio/cli/README.md +287 -0
- package/plugin/vendor/reflexio/reflexio/cli/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/cli/__main__.py +56 -0
- package/plugin/vendor/reflexio/reflexio/cli/_client.py +86 -0
- package/plugin/vendor/reflexio/reflexio/cli/app.py +127 -0
- package/plugin/vendor/reflexio/reflexio/cli/bootstrap_config.py +265 -0
- package/plugin/vendor/reflexio/reflexio/cli/codex_auth.py +503 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/admin_cmd.py +65 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/agent_playbooks.py +503 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/api.py +114 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/auth.py +109 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/config_cmd.py +511 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/doctor.py +127 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/embeddings.py +53 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/interactions.py +478 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/profiles.py +303 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/services.py +289 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/setup_cmd.py +964 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/shortcuts.py +285 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/status_cmd.py +143 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/user_playbooks.py +373 -0
- package/plugin/vendor/reflexio/reflexio/cli/env_loader.py +284 -0
- package/plugin/vendor/reflexio/reflexio/cli/errors.py +217 -0
- package/plugin/vendor/reflexio/reflexio/cli/log_format.py +247 -0
- package/plugin/vendor/reflexio/reflexio/cli/output.py +867 -0
- package/plugin/vendor/reflexio/reflexio/cli/paths.py +41 -0
- package/plugin/vendor/reflexio/reflexio/cli/run_services.py +391 -0
- package/plugin/vendor/reflexio/reflexio/cli/state.py +204 -0
- package/plugin/vendor/reflexio/reflexio/cli/stop_services.py +96 -0
- package/plugin/vendor/reflexio/reflexio/cli/utils.py +329 -0
- package/plugin/vendor/reflexio/reflexio/client/__init__.py +3 -0
- package/plugin/vendor/reflexio/reflexio/client/cache.py +150 -0
- package/plugin/vendor/reflexio/reflexio/client/client.py +2613 -0
- package/plugin/vendor/reflexio/reflexio/defaults.py +23 -0
- package/plugin/vendor/reflexio/reflexio/integrations/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/.clawhubignore +7 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/README.md +274 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/TESTING.md +517 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/hook/handler.js +473 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package-lock.json +2156 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package.json +18 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/handler.ts +241 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/setup.ts +140 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/index.ts +130 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/publish.ts +113 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/search.ts +52 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/server.ts +103 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/sqlite-buffer.ts +156 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/user-id.ts +134 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/openclaw.plugin.json +41 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/package.json +17 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/rules/reflexio.md +24 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/reflexio/SKILL.md +48 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/publish_clawhub.sh +278 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/references/HOOK.md +164 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/install.sh +36 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/uninstall.sh +35 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/publish.test.ts +27 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/search.test.ts +31 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/server.test.ts +42 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/setup.test.ts +49 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/sqlite-buffer.test.ts +91 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/user-id.test.ts +50 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tsconfig.json +16 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/types/openclaw.d.ts +230 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/vitest.config.ts +13 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/README.md +120 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/TESTING.md +168 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/package-lock.json +1657 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/package.json +16 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/HEARTBEAT.md +6 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/README.md +84 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/SKILL.md +194 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/_meta.json +6 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/agents/reflexio-extractor.md +45 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/hook/handler.ts +214 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/hook/setup.ts +55 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/index.ts +327 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/consolidate.ts +233 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/dedup.ts +80 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/io.ts +155 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/openclaw-cli.ts +67 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/search.ts +33 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/write-playbook.ts +76 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/write-profile.ts +79 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/openclaw.plugin.json +46 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/package.json +18 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/README.md +36 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/full_consolidation.md +56 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/playbook_extraction.md +217 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/profile_extraction.md +132 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/skills/reflexio-consolidate/SKILL.md +33 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/skills/reflexio-embedded/SKILL.md +194 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/HOOK.md +18 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/architecture.md +49 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/comparison.md +31 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/future-work.md +47 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/porting-notes.md +52 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/scripts/install.sh +52 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/scripts/uninstall.sh +36 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/consolidate.test.ts +135 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/dedup.test.ts +104 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/io.test.ts +175 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/search.test.ts +66 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/smoke-test.ts +140 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/write-playbook.test.ts +93 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/write-profile.test.ts +174 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tsconfig.json +16 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/types/openclaw.d.ts +230 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/vitest.config.ts +7 -0
- package/plugin/vendor/reflexio/reflexio/lib/__init__.py +23 -0
- package/plugin/vendor/reflexio/reflexio/lib/_agent_playbook.py +310 -0
- package/plugin/vendor/reflexio/reflexio/lib/_base.py +225 -0
- package/plugin/vendor/reflexio/reflexio/lib/_config.py +83 -0
- package/plugin/vendor/reflexio/reflexio/lib/_dashboard.py +266 -0
- package/plugin/vendor/reflexio/reflexio/lib/_generation.py +176 -0
- package/plugin/vendor/reflexio/reflexio/lib/_interactions.py +334 -0
- package/plugin/vendor/reflexio/reflexio/lib/_operations.py +153 -0
- package/plugin/vendor/reflexio/reflexio/lib/_profiles.py +545 -0
- package/plugin/vendor/reflexio/reflexio/lib/_reflection.py +52 -0
- package/plugin/vendor/reflexio/reflexio/lib/_search.py +167 -0
- package/plugin/vendor/reflexio/reflexio/lib/_storage_labels.py +103 -0
- package/plugin/vendor/reflexio/reflexio/lib/_user_playbook.py +288 -0
- package/plugin/vendor/reflexio/reflexio/lib/reflexio_lib.py +27 -0
- package/plugin/vendor/reflexio/reflexio/models/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/braintrust_schema.py +141 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/common.py +41 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/__init__.py +3 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/entities.py +1112 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/enums.py +63 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/eval_overview_schema.py +487 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/internal_schema.py +28 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/pending_tool_call_schema.py +83 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/retriever_schema.py +768 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/service_schemas.py +9 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/stall_state_schema.py +32 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/__init__.py +3 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/converters.py +177 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/entities.py +129 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/enums.py +25 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/validators.py +333 -0
- package/plugin/vendor/reflexio/reflexio/models/config_schema.py +908 -0
- package/plugin/vendor/reflexio/reflexio/models/py.typed +0 -0
- package/plugin/vendor/reflexio/reflexio/server/OVERVIEW.md +90 -0
- package/plugin/vendor/reflexio/reflexio/server/README.md +622 -0
- package/plugin/vendor/reflexio/reflexio/server/__init__.py +210 -0
- package/plugin/vendor/reflexio/reflexio/server/__main__.py +132 -0
- package/plugin/vendor/reflexio/reflexio/server/_auth.py +25 -0
- package/plugin/vendor/reflexio/reflexio/server/api.py +2868 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/README.md +34 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/account_api.py +143 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/health_api.py +91 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/pending_tool_call_api.py +572 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/precondition_checks.py +66 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/publisher_api.py +562 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/request_context.py +50 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/stall_state_api.py +100 -0
- package/plugin/vendor/reflexio/reflexio/server/cache/__init__.py +15 -0
- package/plugin/vendor/reflexio/reflexio/server/cache/reflexio_cache.py +208 -0
- package/plugin/vendor/reflexio/reflexio/server/correlation.py +46 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/__init__.py +30 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/embedding_service.py +359 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/image_utils.py +55 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/litellm_client.py +1871 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/llm_utils.py +140 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/model_defaults.py +479 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/claude_code_provider.py +1122 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/claude_code_stream_parser.py +197 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/embedding_service_provider.py +338 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/local_embedding_provider.py +213 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/nomic_embedding_provider.py +288 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/rerank/__init__.py +6 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/rerank/cross_encoder_reranker.py +187 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/rerank/llm_reranker.py +148 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/tools.py +716 -0
- package/plugin/vendor/reflexio/reflexio/server/operation_limiter.py +179 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/_dispatchers.py +54 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/README.md +121 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/agent_success_evaluation/v1.0.0.prompt.md +58 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/agent_success_evaluation_with_comparison/v1.0.0.prompt.md +76 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/answer_synthesis/v1.5.2.prompt.md +88 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/compress_session_for_query/v1.3.0.prompt.md +31 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/document_expansion/v1.0.0.prompt.md +20 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.0.0.prompt.md +53 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.1.0.prompt.md +57 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.2.0.prompt.md +68 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.3.0.prompt.md +70 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.4.0.prompt.md +77 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.5.0.prompt.md +82 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.6.0.prompt.md +83 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.1.0.prompt.md +193 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.2.0.prompt.md +206 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v1.0.0-deprecated.prompt.md +66 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v1.0.0.prompt.md +43 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v1.1.0.prompt.md +46 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.0.0-deprecated.prompt.md +64 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.0.0.prompt.md +39 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.1.0.prompt.md +39 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.2.0.prompt.md +47 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.0.prompt.md +58 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.1.prompt.md +69 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.2.prompt.md +71 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.0.2.prompt.md +254 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.1.0.prompt.md +274 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.2.0.prompt.md +283 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.2.2.prompt.md +234 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.2.3.prompt.md +244 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v1.0.0.prompt.md +73 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v2.0.0.prompt.md +86 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.0.0.prompt.md +97 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.1.0.prompt.md +119 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.2.0.prompt.md +123 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.3.0.prompt.md +137 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.0.0.prompt.md +14 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.1.0.prompt.md +24 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.2.0.prompt.md +29 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main_expert/v1.0.0.prompt.md +11 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main_expert/v1.1.0.prompt.md +21 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main_expert/v1.2.0.prompt.md +25 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_optimizer_judge/v1.0.0.prompt.md +37 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_optimizer_judge/v1.1.0.prompt.md +40 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_optimizer_judge/v1.2.0.prompt.md +36 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate/v1.0.0.prompt.md +45 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate/v2.0.0.prompt.md +81 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate/v3.0.0.prompt.md +80 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate_expert/v1.0.0.prompt.md +34 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_deduplication/v1.0.0.prompt.md +116 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_should_generate/v1.0.0.prompt.md +33 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_should_generate_override/v1.0.0.prompt.md +16 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.0.0.prompt.md +140 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.1.0.prompt.md +160 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_main/v1.0.0.prompt.md +14 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/query_reformulation/v1.0.0.prompt.md +19 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/rerank_relevance/v1.1.0.prompt.md +44 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/shadow_comparison/v1.0.0.prompt.md +43 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/shadow_content_evaluation/v1.0.0.prompt.md +33 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_evaluation/prompt_evaluation_dataset/feedback_extraction_main_v1.jsonl +10 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_evaluation/prompt_evaluation_dataset/profile_update_main_v1.jsonl +10 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_manager.py +280 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_schema.py +11 -0
- package/plugin/vendor/reflexio/reflexio/server/services/README.md +58 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/_eval_health.py +131 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_constants.py +60 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_service.py +228 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_utils.py +87 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluator.py +372 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/delayed_group_evaluator.py +156 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/group_evaluation_runner.py +336 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/regen_jobs.py +471 -0
- package/plugin/vendor/reflexio/reflexio/server/services/base_generation_service.py +1668 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/_cron.py +196 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/_encryption.py +101 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/client.py +167 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/service.py +281 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/base_configurator.py +179 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/config_storage.py +62 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/configurator.py +87 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/local_file_config_storage.py +187 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/test_config_storage.py +162 -0
- package/plugin/vendor/reflexio/reflexio/server/services/deduplication_utils.py +112 -0
- package/plugin/vendor/reflexio/reflexio/server/services/embedding_text.py +62 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/distribution.py +33 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/eval_sampler.py +126 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/group_aggregation.py +192 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/hero_state.py +75 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/rule_attribution.py +97 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/service.py +515 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/shadow_aggregation.py +90 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/agent_run_records.py +91 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/invariants.py +303 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/outcome.py +25 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/pending_tool_call_dispatch.py +358 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/plan.py +138 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/prior_answer_search.py +217 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/resumable_agent.py +535 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_scheduler.py +171 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_worker.py +779 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/tools.py +1125 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extractor_config_utils.py +94 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extractor_interaction_utils.py +251 -0
- package/plugin/vendor/reflexio/reflexio/server/services/generation_service.py +702 -0
- package/plugin/vendor/reflexio/reflexio/server/services/operation_state_utils.py +835 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/README.md +89 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_aggregator.py +1388 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_consolidator.py +1045 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_extractor.py +436 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_generation_service.py +808 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_service_constants.py +28 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_service_utils.py +362 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/__init__.py +24 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/assistant_webhook.py +246 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/gepa_adapter.py +291 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/judge.py +97 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/models.py +96 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/optimizer.py +645 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/rollout.py +35 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/scenario_resolver.py +93 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/scheduler.py +174 -0
- package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/__init__.py +26 -0
- package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/_document_expander.py +179 -0
- package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/_query_reformulator.py +297 -0
- package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_deduplicator.py +772 -0
- package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_extractor.py +462 -0
- package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_generation_service.py +737 -0
- package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_generation_service_utils.py +290 -0
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/__init__.py +17 -0
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_extractor.py +247 -0
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_service.py +803 -0
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_service_utils.py +146 -0
- package/plugin/vendor/reflexio/reflexio/server/services/retrieval/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/retrieval/relevance_floor.py +80 -0
- package/plugin/vendor/reflexio/reflexio/server/services/search/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/service_utils.py +756 -0
- package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/judge.py +184 -0
- package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/outcome.py +81 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/constants.py +2 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/error.py +11 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/retention.py +154 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/retention_mixin.py +155 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/__init__.py +59 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_agent_run.py +1298 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_base.py +1945 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_extras.py +600 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_operations.py +346 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_playbook.py +1378 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_profiles.py +747 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_requests.py +263 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_shadow_verdicts.py +193 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_share_links.py +166 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_stall_state.py +217 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/__init__.py +153 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_agent_run.py +384 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_base.py +71 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_extras.py +235 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_operations.py +170 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_playbook.py +677 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_profiles.py +250 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_requests.py +154 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_shadow_verdicts.py +130 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_share_links.py +93 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_stall_state.py +76 -0
- package/plugin/vendor/reflexio/reflexio/server/services/unified_search_service.py +572 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/README.md +77 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/feature_flags.py +116 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_manager.py +263 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/feature_flags.json +13 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/llm_model_setting.json +7 -0
- package/plugin/vendor/reflexio/reflexio/server/tracing.py +158 -0
- package/plugin/vendor/reflexio/reflexio/server/usage_metrics.py +113 -0
- package/plugin/vendor/reflexio/reflexio/server/uvicorn_logging.py +76 -0
- package/plugin/vendor/reflexio/reflexio/test_support/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/test_support/llm_fixtures.py +62 -0
- package/plugin/vendor/reflexio/reflexio/test_support/llm_mock.py +242 -0
- package/plugin/vendor/reflexio/reflexio/test_support/llm_model_registry.py +129 -0
- package/plugin/vendor/reflexio/reflexio/test_support/skip_decorators.py +43 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"""Singleton scheduler for delayed session evaluation.
|
|
2
|
+
|
|
3
|
+
Uses a single daemon thread with a min-heap priority queue.
|
|
4
|
+
Each new request upserts the fire time for its group.
|
|
5
|
+
When the fire time arrives, a daemon thread runs the evaluation callback.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import heapq
|
|
11
|
+
import logging
|
|
12
|
+
import os
|
|
13
|
+
import threading
|
|
14
|
+
import time
|
|
15
|
+
from collections.abc import Callable
|
|
16
|
+
|
|
17
|
+
from reflexio.server.services.agent_success_evaluation import _eval_health
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
# Delay in seconds before evaluating a group after the last request
|
|
22
|
+
GROUP_EVALUATION_DELAY_SECONDS = 600 # 10 minutes
|
|
23
|
+
|
|
24
|
+
IS_TEST_ENV = os.environ.get("IS_TEST_ENV", "false").strip() == "true"
|
|
25
|
+
_EFFECTIVE_DELAY_SECONDS = 30 if IS_TEST_ENV else GROUP_EVALUATION_DELAY_SECONDS
|
|
26
|
+
|
|
27
|
+
# Type alias for the scheduling key
|
|
28
|
+
GroupKey = tuple[str, str, str] # (org_id, user_id, session_id)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class GroupEvaluationScheduler:
|
|
32
|
+
"""Singleton scheduler that fires group evaluations after a period of inactivity.
|
|
33
|
+
|
|
34
|
+
Uses one daemon thread with a min-heap. Each new request upserts the fire time
|
|
35
|
+
for its group. Handles hundreds of concurrent groups efficiently.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
_instance = None
|
|
39
|
+
_lock = threading.Lock()
|
|
40
|
+
|
|
41
|
+
@classmethod
|
|
42
|
+
def get_instance(cls) -> GroupEvaluationScheduler:
|
|
43
|
+
"""Get or create the singleton scheduler instance.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
GroupEvaluationScheduler: The singleton instance
|
|
47
|
+
"""
|
|
48
|
+
if cls._instance is None:
|
|
49
|
+
with cls._lock:
|
|
50
|
+
if cls._instance is None:
|
|
51
|
+
cls._instance = cls()
|
|
52
|
+
return cls._instance
|
|
53
|
+
|
|
54
|
+
def __init__(self) -> None:
|
|
55
|
+
self._scheduled: dict[GroupKey, tuple[float, Callable]] = {}
|
|
56
|
+
self._heap: list[tuple[float, GroupKey]] = []
|
|
57
|
+
self._mutex = threading.Lock()
|
|
58
|
+
self._wake_event = threading.Event()
|
|
59
|
+
self._thread = threading.Thread(
|
|
60
|
+
target=self._scheduler_loop, daemon=True, name="group-eval-scheduler"
|
|
61
|
+
)
|
|
62
|
+
self._thread.start()
|
|
63
|
+
logger.info("GroupEvaluationScheduler started")
|
|
64
|
+
|
|
65
|
+
def schedule(self, key: GroupKey, callback: Callable) -> None:
|
|
66
|
+
"""Schedule or reschedule a group evaluation.
|
|
67
|
+
|
|
68
|
+
If the group already has a pending evaluation, its fire time is updated
|
|
69
|
+
(slid forward). The callback will be invoked after GROUP_EVALUATION_DELAY_SECONDS
|
|
70
|
+
of inactivity.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
key: Tuple of (org_id, user_id, session_id)
|
|
74
|
+
callback: Zero-argument callable to run when the timer fires
|
|
75
|
+
"""
|
|
76
|
+
fire_time = time.monotonic() + _EFFECTIVE_DELAY_SECONDS
|
|
77
|
+
with self._mutex:
|
|
78
|
+
self._scheduled[key] = (fire_time, callback)
|
|
79
|
+
heapq.heappush(self._heap, (fire_time, key))
|
|
80
|
+
self._wake_event.set()
|
|
81
|
+
logger.info(
|
|
82
|
+
"Scheduled group evaluation for key=%s fire_time=%.1f", key, fire_time
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
def _scheduler_loop(self) -> None:
|
|
86
|
+
"""Main loop for the scheduler thread.
|
|
87
|
+
|
|
88
|
+
Pops due items from the heap, verifies they are still current
|
|
89
|
+
(not superseded by a newer schedule), and spawns daemon threads
|
|
90
|
+
to run the callback.
|
|
91
|
+
"""
|
|
92
|
+
while True:
|
|
93
|
+
try:
|
|
94
|
+
_eval_health.record_tick()
|
|
95
|
+
with self._mutex:
|
|
96
|
+
next_fire_time = self._heap[0][0] if self._heap else None
|
|
97
|
+
|
|
98
|
+
if next_fire_time is None:
|
|
99
|
+
# Nothing scheduled, wait for a wake signal
|
|
100
|
+
self._wake_event.wait()
|
|
101
|
+
self._wake_event.clear()
|
|
102
|
+
continue
|
|
103
|
+
|
|
104
|
+
now = time.monotonic()
|
|
105
|
+
wait_seconds = next_fire_time - now
|
|
106
|
+
|
|
107
|
+
if wait_seconds > 0:
|
|
108
|
+
# Wait until the next fire time or a wake signal
|
|
109
|
+
self._wake_event.wait(timeout=wait_seconds)
|
|
110
|
+
self._wake_event.clear()
|
|
111
|
+
continue
|
|
112
|
+
|
|
113
|
+
# Process due items
|
|
114
|
+
with self._mutex:
|
|
115
|
+
while self._heap and self._heap[0][0] <= time.monotonic():
|
|
116
|
+
fire_time, key = heapq.heappop(self._heap)
|
|
117
|
+
|
|
118
|
+
# Check if this entry is still current (not superseded)
|
|
119
|
+
current = self._scheduled.get(key)
|
|
120
|
+
if current is None:
|
|
121
|
+
continue
|
|
122
|
+
current_fire_time, callback = current
|
|
123
|
+
if abs(current_fire_time - fire_time) > 0.001:
|
|
124
|
+
# This entry was superseded by a newer schedule
|
|
125
|
+
continue
|
|
126
|
+
|
|
127
|
+
# Remove from scheduled map and fire
|
|
128
|
+
del self._scheduled[key]
|
|
129
|
+
|
|
130
|
+
# Spawn daemon thread for the callback
|
|
131
|
+
t = threading.Thread(
|
|
132
|
+
target=self._run_callback,
|
|
133
|
+
args=(key, callback),
|
|
134
|
+
daemon=True,
|
|
135
|
+
name=f"group-eval-{key[2][:20]}",
|
|
136
|
+
)
|
|
137
|
+
t.start()
|
|
138
|
+
|
|
139
|
+
except Exception:
|
|
140
|
+
logger.exception("Error in group evaluation scheduler loop")
|
|
141
|
+
# Brief sleep to avoid tight error loops
|
|
142
|
+
time.sleep(1)
|
|
143
|
+
|
|
144
|
+
@staticmethod
|
|
145
|
+
def _run_callback(key: GroupKey, callback: Callable) -> None:
|
|
146
|
+
"""Run the evaluation callback, catching any exceptions.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
key: The group key for logging
|
|
150
|
+
callback: The evaluation callback to run
|
|
151
|
+
"""
|
|
152
|
+
try:
|
|
153
|
+
logger.info("Firing group evaluation for key=%s", key)
|
|
154
|
+
callback()
|
|
155
|
+
except Exception:
|
|
156
|
+
logger.exception("Group evaluation callback failed for key=%s", key)
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
"""Runner for group-level agent success evaluation.
|
|
2
|
+
|
|
3
|
+
Fetches all requests and interactions for a session,
|
|
4
|
+
checks completion status, runs evaluation, and marks the group as evaluated.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
import random
|
|
9
|
+
from collections import defaultdict
|
|
10
|
+
from datetime import UTC, datetime
|
|
11
|
+
|
|
12
|
+
from reflexio.models.api_schema.domain.entities import Interaction
|
|
13
|
+
from reflexio.models.api_schema.internal_schema import RequestInteractionDataModel
|
|
14
|
+
from reflexio.server.api_endpoints.request_context import RequestContext
|
|
15
|
+
from reflexio.server.llm.litellm_client import LiteLLMClient
|
|
16
|
+
from reflexio.server.services.agent_success_evaluation import _eval_health
|
|
17
|
+
from reflexio.server.services.agent_success_evaluation._eval_health import SkipReason
|
|
18
|
+
from reflexio.server.services.agent_success_evaluation.agent_success_evaluation_service import (
|
|
19
|
+
AgentSuccessEvaluationService,
|
|
20
|
+
)
|
|
21
|
+
from reflexio.server.services.agent_success_evaluation.agent_success_evaluation_utils import (
|
|
22
|
+
AgentSuccessEvaluationRequest,
|
|
23
|
+
)
|
|
24
|
+
from reflexio.server.services.agent_success_evaluation.delayed_group_evaluator import (
|
|
25
|
+
_EFFECTIVE_DELAY_SECONDS,
|
|
26
|
+
)
|
|
27
|
+
from reflexio.server.services.shadow_comparison.judge import ShadowComparisonJudge
|
|
28
|
+
|
|
29
|
+
logger = logging.getLogger(__name__)
|
|
30
|
+
|
|
31
|
+
# Key prefix for operation state tracking
|
|
32
|
+
OPERATION_STATE_KEY_PREFIX = "agent_success_group_eval"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _build_state_key(org_id: str, user_id: str, session_id: str) -> str:
|
|
36
|
+
"""Build the operation state key for a session.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
org_id: Organization ID
|
|
40
|
+
user_id: User ID
|
|
41
|
+
session_id: Session identifier
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
str: The operation state key
|
|
45
|
+
"""
|
|
46
|
+
return f"{OPERATION_STATE_KEY_PREFIX}::{org_id}::{user_id}::{session_id}"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def run_group_evaluation(
|
|
50
|
+
org_id: str,
|
|
51
|
+
user_id: str,
|
|
52
|
+
session_id: str,
|
|
53
|
+
agent_version: str,
|
|
54
|
+
source: str | None,
|
|
55
|
+
request_context: RequestContext,
|
|
56
|
+
llm_client: LiteLLMClient,
|
|
57
|
+
*,
|
|
58
|
+
force_regenerate: bool = False,
|
|
59
|
+
) -> None:
|
|
60
|
+
"""Run agent success evaluation for an entire session.
|
|
61
|
+
|
|
62
|
+
Steps:
|
|
63
|
+
1. Check if already evaluated via operation state (skipped when force_regenerate)
|
|
64
|
+
2. Fetch all requests for the session
|
|
65
|
+
3. Verify completion (latest request created_at >= delay ago; skipped when force_regenerate)
|
|
66
|
+
4. Fetch interactions and build data models
|
|
67
|
+
5. Capture prior result_ids (when regenerating) so they
|
|
68
|
+
can be removed AFTER the new save lands
|
|
69
|
+
6. Run evaluation service (which saves new rows)
|
|
70
|
+
7. On success, delete the captured prior rows by id — the new rows have
|
|
71
|
+
fresh auto-increment ids that do not overlap. A failure here leaves
|
|
72
|
+
the session in a consistent pre-regen state instead of zero rows.
|
|
73
|
+
8. Mark as evaluated in operation state
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
org_id: Organization ID
|
|
77
|
+
user_id: User ID who owns the requests
|
|
78
|
+
session_id: Session identifier
|
|
79
|
+
agent_version: Agent version string
|
|
80
|
+
source: Source of the interactions
|
|
81
|
+
request_context: Request context with storage and configurator
|
|
82
|
+
llm_client: LLM client for evaluation
|
|
83
|
+
force_regenerate: When True, bypass the already-evaluated short-circuit
|
|
84
|
+
and the completeness delay gate so the regenerate worker can
|
|
85
|
+
re-evaluate sessions of any age regardless of prior state.
|
|
86
|
+
"""
|
|
87
|
+
storage = request_context.storage
|
|
88
|
+
state_key = _build_state_key(org_id, user_id, session_id)
|
|
89
|
+
|
|
90
|
+
# 1. Check if already evaluated — skipped in force_regenerate mode so the
|
|
91
|
+
# regenerate worker can re-evaluate a session that's already been marked.
|
|
92
|
+
if not force_regenerate:
|
|
93
|
+
existing_state = storage.get_operation_state(state_key) # type: ignore[reportOptionalMemberAccess]
|
|
94
|
+
if existing_state and isinstance(existing_state.get("operation_state"), dict):
|
|
95
|
+
op_state = existing_state["operation_state"]
|
|
96
|
+
if op_state.get("evaluated"):
|
|
97
|
+
_eval_health.record_skip(SkipReason.ALREADY_EVALUATED)
|
|
98
|
+
logger.info("Session %s already evaluated, skipping", session_id)
|
|
99
|
+
return
|
|
100
|
+
|
|
101
|
+
# 2. Fetch all requests for the session
|
|
102
|
+
requests = storage.get_requests_by_session(user_id, session_id) # type: ignore[reportOptionalMemberAccess]
|
|
103
|
+
if not requests:
|
|
104
|
+
_eval_health.record_skip(SkipReason.NO_REQUESTS)
|
|
105
|
+
logger.info("No requests found for session %s, skipping", session_id)
|
|
106
|
+
return
|
|
107
|
+
|
|
108
|
+
# 3. Verify completion: latest request must be >= delay ago — skipped in
|
|
109
|
+
# force_regenerate mode so the operator can re-evaluate any session.
|
|
110
|
+
if not force_regenerate:
|
|
111
|
+
latest_created_at = max(r.created_at for r in requests)
|
|
112
|
+
now = int(datetime.now(UTC).timestamp())
|
|
113
|
+
elapsed = now - latest_created_at
|
|
114
|
+
if elapsed < _EFFECTIVE_DELAY_SECONDS:
|
|
115
|
+
_eval_health.record_skip(SkipReason.NOT_YET_COMPLETE)
|
|
116
|
+
logger.info(
|
|
117
|
+
"Session %s not yet complete (latest request %ds ago, need %ds), skipping",
|
|
118
|
+
session_id,
|
|
119
|
+
elapsed,
|
|
120
|
+
_EFFECTIVE_DELAY_SECONDS,
|
|
121
|
+
)
|
|
122
|
+
return
|
|
123
|
+
|
|
124
|
+
# 4. Fetch interactions for all requests
|
|
125
|
+
request_ids = [r.request_id for r in requests]
|
|
126
|
+
all_interactions = storage.get_interactions_by_request_ids(request_ids) # type: ignore[reportOptionalMemberAccess]
|
|
127
|
+
if not all_interactions:
|
|
128
|
+
_eval_health.record_skip(SkipReason.NO_INTERACTIONS)
|
|
129
|
+
logger.info("No interactions found for session %s, skipping", session_id)
|
|
130
|
+
return
|
|
131
|
+
|
|
132
|
+
# Group interactions by request_id
|
|
133
|
+
interactions_by_request: dict[str, list] = defaultdict(list)
|
|
134
|
+
for interaction in all_interactions:
|
|
135
|
+
interactions_by_request[interaction.request_id].append(interaction)
|
|
136
|
+
|
|
137
|
+
# Build RequestInteractionDataModel list, sorted by request created_at
|
|
138
|
+
requests_sorted = sorted(requests, key=lambda r: r.created_at)
|
|
139
|
+
request_interaction_data_models = []
|
|
140
|
+
for req in requests_sorted:
|
|
141
|
+
req_interactions = interactions_by_request.get(req.request_id, [])
|
|
142
|
+
if req_interactions:
|
|
143
|
+
# Sort interactions by created_at within each request
|
|
144
|
+
req_interactions.sort(key=lambda i: i.created_at)
|
|
145
|
+
request_interaction_data_models.append(
|
|
146
|
+
RequestInteractionDataModel(
|
|
147
|
+
session_id=session_id,
|
|
148
|
+
request=req,
|
|
149
|
+
interactions=req_interactions,
|
|
150
|
+
)
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
if not request_interaction_data_models:
|
|
154
|
+
_eval_health.record_skip(SkipReason.NO_DATA_MODELS)
|
|
155
|
+
logger.info(
|
|
156
|
+
"No request interaction data models built for session %s, skipping",
|
|
157
|
+
session_id,
|
|
158
|
+
)
|
|
159
|
+
return
|
|
160
|
+
|
|
161
|
+
# 5. When regenerating, capture the prior result_ids
|
|
162
|
+
# so we can delete ONLY them AFTER the new rows have been saved. Doing
|
|
163
|
+
# the delete before the LLM call risks wiping the session's rows if the
|
|
164
|
+
# call fails (rate limit, network) and nothing replaces them. The new
|
|
165
|
+
# rows always get fresh auto-increment ids, so deleting the captured set
|
|
166
|
+
# afterwards cannot remove the new rows.
|
|
167
|
+
old_result_ids: list[int] = []
|
|
168
|
+
if force_regenerate:
|
|
169
|
+
# Eval rows per session are tiny (usually 1), so pulling a
|
|
170
|
+
# generous limit and filtering in-process is cheap and avoids adding
|
|
171
|
+
# a third query shape to the storage contract.
|
|
172
|
+
prior_rows = storage.get_agent_success_evaluation_results( # type: ignore[reportOptionalMemberAccess]
|
|
173
|
+
limit=10000, agent_version=agent_version
|
|
174
|
+
)
|
|
175
|
+
old_result_ids = [r.result_id for r in prior_rows if r.session_id == session_id]
|
|
176
|
+
|
|
177
|
+
logger.info(
|
|
178
|
+
"Running group evaluation for session=%s with %d requests and %d interactions"
|
|
179
|
+
" (force_regenerate=%s, prior_result_ids=%d)",
|
|
180
|
+
session_id,
|
|
181
|
+
len(request_interaction_data_models),
|
|
182
|
+
len(all_interactions),
|
|
183
|
+
force_regenerate,
|
|
184
|
+
len(old_result_ids),
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
evaluation_request = AgentSuccessEvaluationRequest(
|
|
188
|
+
session_id=session_id,
|
|
189
|
+
agent_version=agent_version,
|
|
190
|
+
source=source,
|
|
191
|
+
request_interaction_data_models=request_interaction_data_models,
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
evaluation_service = AgentSuccessEvaluationService(
|
|
195
|
+
llm_client=llm_client, request_context=request_context
|
|
196
|
+
)
|
|
197
|
+
evaluation_service.run(evaluation_request)
|
|
198
|
+
|
|
199
|
+
if evaluation_service.has_run_failures():
|
|
200
|
+
logger.warning(
|
|
201
|
+
"Group evaluation for session=%s had failures (save_failed=%s);"
|
|
202
|
+
" preserving %d prior result row(s) and skipping evaluated marker",
|
|
203
|
+
session_id,
|
|
204
|
+
evaluation_service.last_run_save_failed,
|
|
205
|
+
len(old_result_ids),
|
|
206
|
+
)
|
|
207
|
+
return
|
|
208
|
+
|
|
209
|
+
if evaluation_service.last_run_saved_result_count == 0:
|
|
210
|
+
logger.warning(
|
|
211
|
+
"Group evaluation for session=%s saved no results;"
|
|
212
|
+
" preserving %d prior result row(s) and skipping evaluated marker",
|
|
213
|
+
session_id,
|
|
214
|
+
len(old_result_ids),
|
|
215
|
+
)
|
|
216
|
+
return
|
|
217
|
+
|
|
218
|
+
# F1: per-turn shadow comparison. Dispatched only AFTER the regular
|
|
219
|
+
# success eval succeeds — a session whose success grade is unreliable
|
|
220
|
+
# would yield noisy verdicts that mislead the headline metric. The
|
|
221
|
+
# dispatch loop swallows per-interaction failures so one judge call
|
|
222
|
+
# cannot abort an entire batch.
|
|
223
|
+
_dispatch_shadow_comparison_judge(
|
|
224
|
+
storage=storage,
|
|
225
|
+
interactions=all_interactions,
|
|
226
|
+
session_id=session_id,
|
|
227
|
+
agent_version=agent_version,
|
|
228
|
+
request_context=request_context,
|
|
229
|
+
llm_client=llm_client,
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
# 6. New rows saved successfully — now safe to remove the captured prior
|
|
233
|
+
# rows. New rows have fresh auto-increment result_ids that do not overlap
|
|
234
|
+
# with old_result_ids, so this cannot delete the regenerated verdict.
|
|
235
|
+
if old_result_ids:
|
|
236
|
+
deleted = storage.delete_agent_success_evaluation_results_by_ids( # type: ignore[reportOptionalMemberAccess]
|
|
237
|
+
old_result_ids
|
|
238
|
+
)
|
|
239
|
+
logger.info(
|
|
240
|
+
"Regenerate cleanup: deleted %d prior result row(s) for session=%s"
|
|
241
|
+
" (expected %d)",
|
|
242
|
+
deleted,
|
|
243
|
+
session_id,
|
|
244
|
+
len(old_result_ids),
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
# 7. Mark as evaluated
|
|
248
|
+
evaluated_at = int(datetime.now(UTC).timestamp())
|
|
249
|
+
storage.upsert_operation_state( # type: ignore[reportOptionalMemberAccess]
|
|
250
|
+
state_key,
|
|
251
|
+
{"evaluated": True, "evaluated_at": evaluated_at},
|
|
252
|
+
)
|
|
253
|
+
logger.info("Marked session %s as evaluated at %d", session_id, evaluated_at)
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def _dispatch_shadow_comparison_judge(
|
|
257
|
+
*,
|
|
258
|
+
storage, # noqa: ANN001 — BaseStorage; imported lazily to avoid cycles
|
|
259
|
+
interactions: list[Interaction],
|
|
260
|
+
session_id: str,
|
|
261
|
+
agent_version: str,
|
|
262
|
+
request_context: RequestContext,
|
|
263
|
+
llm_client: LiteLLMClient,
|
|
264
|
+
) -> None:
|
|
265
|
+
"""F1: grade each shadow-bearing interaction with the per-turn judge.
|
|
266
|
+
|
|
267
|
+
Iterates the session's interactions, skips any without ``shadow_content``,
|
|
268
|
+
invokes :class:`ShadowComparisonJudge.judge_turn`, and persists each
|
|
269
|
+
returned verdict via ``storage.save_shadow_comparison_verdict``. Per-
|
|
270
|
+
interaction exceptions are logged and the loop continues — partial
|
|
271
|
+
verdict sets are strictly better than nothing for the headline metric.
|
|
272
|
+
|
|
273
|
+
Args:
|
|
274
|
+
storage: The session storage. Must implement
|
|
275
|
+
``save_shadow_comparison_verdict`` (currently SQLite + Supabase
|
|
276
|
+
+ disk; backends without it surface ``NotImplementedError`` at
|
|
277
|
+
save time and the loop logs+continues).
|
|
278
|
+
interactions (list[Interaction]): Every interaction in the session,
|
|
279
|
+
in chronological order. Only those with non-empty
|
|
280
|
+
``shadow_content`` are graded.
|
|
281
|
+
session_id (str): Denormalized onto each verdict.
|
|
282
|
+
agent_version (str): Denormalized onto each verdict.
|
|
283
|
+
request_context (RequestContext): Provides the configurator (for
|
|
284
|
+
the pinned ``shadow_comparison_judge_prompt_version``) and the
|
|
285
|
+
shared ``prompt_manager``.
|
|
286
|
+
llm_client (LiteLLMClient): The unified LLM client the judge uses
|
|
287
|
+
for the structured-output call.
|
|
288
|
+
|
|
289
|
+
Returns:
|
|
290
|
+
None: Verdicts are persisted as a side effect; the caller does not
|
|
291
|
+
need the count for control flow.
|
|
292
|
+
"""
|
|
293
|
+
config = request_context.configurator.get_config() # type: ignore[reportOptionalMemberAccess]
|
|
294
|
+
judge = ShadowComparisonJudge(
|
|
295
|
+
llm_client=llm_client,
|
|
296
|
+
prompt_manager=request_context.prompt_manager, # type: ignore[reportOptionalMemberAccess]
|
|
297
|
+
prompt_version=config.shadow_comparison_judge_prompt_version,
|
|
298
|
+
)
|
|
299
|
+
rng = random.Random() # noqa: S311 — position randomization, not crypto
|
|
300
|
+
saved_count = 0
|
|
301
|
+
|
|
302
|
+
for interaction in interactions:
|
|
303
|
+
if not interaction.shadow_content:
|
|
304
|
+
continue
|
|
305
|
+
try:
|
|
306
|
+
verdict = judge.judge_turn(
|
|
307
|
+
interaction=interaction,
|
|
308
|
+
session_id=session_id,
|
|
309
|
+
agent_version=agent_version,
|
|
310
|
+
rng=rng,
|
|
311
|
+
)
|
|
312
|
+
except Exception as exc: # noqa: BLE001 — judge failure must not abort batch
|
|
313
|
+
logger.warning(
|
|
314
|
+
"F1 shadow_comparison dispatch failed for interaction %s: %s",
|
|
315
|
+
interaction.interaction_id,
|
|
316
|
+
exc,
|
|
317
|
+
)
|
|
318
|
+
continue
|
|
319
|
+
if verdict is None:
|
|
320
|
+
continue
|
|
321
|
+
try:
|
|
322
|
+
storage.save_shadow_comparison_verdict(verdict)
|
|
323
|
+
saved_count += 1
|
|
324
|
+
except Exception as exc: # noqa: BLE001 — single-row save failure must not abort batch
|
|
325
|
+
logger.warning(
|
|
326
|
+
"F1 shadow_comparison verdict save failed for interaction %s: %s",
|
|
327
|
+
interaction.interaction_id,
|
|
328
|
+
exc,
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
if saved_count:
|
|
332
|
+
logger.info(
|
|
333
|
+
"F1: saved %d shadow_comparison verdict(s) for session=%s",
|
|
334
|
+
saved_count,
|
|
335
|
+
session_id,
|
|
336
|
+
)
|