claude-smart 0.2.42 → 0.2.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +3 -3
- package/README.md +1 -1
- package/package.json +9 -3
- package/plugin/.claude-plugin/plugin.json +9 -3
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/README.md +2 -2
- package/plugin/pyproject.toml +2 -2
- package/plugin/scripts/_lib.sh +91 -0
- package/plugin/scripts/backend-service.sh +1 -0
- package/plugin/scripts/cli.sh +1 -0
- package/plugin/scripts/codex-hook.js +72 -4
- package/plugin/scripts/dashboard-build.sh +1 -0
- package/plugin/scripts/dashboard-service.sh +1 -0
- package/plugin/scripts/hook_entry.sh +1 -0
- package/plugin/scripts/smart-install.sh +1 -0
- package/plugin/src/claude_smart/context_format.py +11 -12
- package/plugin/src/claude_smart/cs_cite.py +26 -12
- package/plugin/src/claude_smart/ids.py +13 -5
- package/plugin/uv.lock +1 -1
- package/plugin/vendor/reflexio/.env.example +53 -0
- package/plugin/vendor/reflexio/LICENSE +201 -0
- package/plugin/vendor/reflexio/README.md +338 -0
- package/plugin/vendor/reflexio/pyproject.toml +271 -0
- package/plugin/vendor/reflexio/reflexio/README.md +184 -0
- package/plugin/vendor/reflexio/reflexio/__init__.py +166 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/README.md +109 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/backends.py +175 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/bench.py +642 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/embed_cache.py +330 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/report.py +317 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/results/report.md +43 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/results/results.json +4478 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/scenarios.py +134 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/seed.py +255 -0
- package/plugin/vendor/reflexio/reflexio/cli/README.md +287 -0
- package/plugin/vendor/reflexio/reflexio/cli/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/cli/__main__.py +56 -0
- package/plugin/vendor/reflexio/reflexio/cli/_client.py +86 -0
- package/plugin/vendor/reflexio/reflexio/cli/app.py +127 -0
- package/plugin/vendor/reflexio/reflexio/cli/bootstrap_config.py +266 -0
- package/plugin/vendor/reflexio/reflexio/cli/codex_auth.py +503 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/admin_cmd.py +65 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/agent_playbooks.py +503 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/api.py +114 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/auth.py +109 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/config_cmd.py +511 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/doctor.py +127 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/embeddings.py +53 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/interactions.py +478 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/profiles.py +303 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/services.py +289 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/setup_cmd.py +961 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/shortcuts.py +285 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/status_cmd.py +143 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/user_playbooks.py +373 -0
- package/plugin/vendor/reflexio/reflexio/cli/env_loader.py +284 -0
- package/plugin/vendor/reflexio/reflexio/cli/errors.py +217 -0
- package/plugin/vendor/reflexio/reflexio/cli/log_format.py +247 -0
- package/plugin/vendor/reflexio/reflexio/cli/output.py +867 -0
- package/plugin/vendor/reflexio/reflexio/cli/paths.py +41 -0
- package/plugin/vendor/reflexio/reflexio/cli/run_services.py +391 -0
- package/plugin/vendor/reflexio/reflexio/cli/state.py +204 -0
- package/plugin/vendor/reflexio/reflexio/cli/stop_services.py +96 -0
- package/plugin/vendor/reflexio/reflexio/cli/utils.py +329 -0
- package/plugin/vendor/reflexio/reflexio/client/__init__.py +3 -0
- package/plugin/vendor/reflexio/reflexio/client/cache.py +150 -0
- package/plugin/vendor/reflexio/reflexio/client/client.py +2613 -0
- package/plugin/vendor/reflexio/reflexio/defaults.py +23 -0
- package/plugin/vendor/reflexio/reflexio/integrations/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/.clawhubignore +7 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/README.md +274 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/TESTING.md +517 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/hook/handler.js +473 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package-lock.json +2156 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package.json +18 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/handler.ts +241 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/setup.ts +140 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/index.ts +130 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/publish.ts +113 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/search.ts +52 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/server.ts +103 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/sqlite-buffer.ts +156 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/user-id.ts +134 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/openclaw.plugin.json +41 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/package.json +17 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/rules/reflexio.md +24 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/reflexio/SKILL.md +48 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/publish_clawhub.sh +278 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/references/HOOK.md +164 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/install.sh +36 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/uninstall.sh +35 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/publish.test.ts +27 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/search.test.ts +31 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/server.test.ts +42 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/setup.test.ts +49 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/sqlite-buffer.test.ts +91 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/user-id.test.ts +50 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tsconfig.json +16 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/types/openclaw.d.ts +230 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/vitest.config.ts +13 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/README.md +120 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/TESTING.md +168 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/package-lock.json +1657 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/package.json +16 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/HEARTBEAT.md +6 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/README.md +84 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/SKILL.md +194 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/_meta.json +6 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/agents/reflexio-extractor.md +45 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/hook/handler.ts +214 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/hook/setup.ts +55 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/index.ts +327 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/consolidate.ts +233 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/dedup.ts +80 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/io.ts +155 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/openclaw-cli.ts +67 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/search.ts +33 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/write-playbook.ts +76 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/write-profile.ts +79 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/openclaw.plugin.json +46 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/package.json +18 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/README.md +36 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/full_consolidation.md +56 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/playbook_extraction.md +217 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/profile_extraction.md +132 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/skills/reflexio-consolidate/SKILL.md +33 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/skills/reflexio-embedded/SKILL.md +194 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/HOOK.md +18 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/architecture.md +49 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/comparison.md +31 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/future-work.md +47 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/porting-notes.md +52 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/scripts/install.sh +52 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/scripts/uninstall.sh +36 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/consolidate.test.ts +135 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/dedup.test.ts +104 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/io.test.ts +175 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/search.test.ts +66 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/smoke-test.ts +140 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/write-playbook.test.ts +93 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/write-profile.test.ts +174 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tsconfig.json +16 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/types/openclaw.d.ts +230 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/vitest.config.ts +7 -0
- package/plugin/vendor/reflexio/reflexio/lib/__init__.py +23 -0
- package/plugin/vendor/reflexio/reflexio/lib/_agent_playbook.py +310 -0
- package/plugin/vendor/reflexio/reflexio/lib/_base.py +225 -0
- package/plugin/vendor/reflexio/reflexio/lib/_config.py +83 -0
- package/plugin/vendor/reflexio/reflexio/lib/_dashboard.py +266 -0
- package/plugin/vendor/reflexio/reflexio/lib/_generation.py +176 -0
- package/plugin/vendor/reflexio/reflexio/lib/_interactions.py +334 -0
- package/plugin/vendor/reflexio/reflexio/lib/_operations.py +153 -0
- package/plugin/vendor/reflexio/reflexio/lib/_profiles.py +545 -0
- package/plugin/vendor/reflexio/reflexio/lib/_reflection.py +52 -0
- package/plugin/vendor/reflexio/reflexio/lib/_search.py +167 -0
- package/plugin/vendor/reflexio/reflexio/lib/_storage_labels.py +103 -0
- package/plugin/vendor/reflexio/reflexio/lib/_user_playbook.py +288 -0
- package/plugin/vendor/reflexio/reflexio/lib/reflexio_lib.py +27 -0
- package/plugin/vendor/reflexio/reflexio/models/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/braintrust_schema.py +141 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/common.py +41 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/__init__.py +3 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/entities.py +1103 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/enums.py +63 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/eval_overview_schema.py +487 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/internal_schema.py +28 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/pending_tool_call_schema.py +83 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/retriever_schema.py +766 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/service_schemas.py +9 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/stall_state_schema.py +32 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/__init__.py +3 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/converters.py +177 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/entities.py +129 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/enums.py +25 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/validators.py +280 -0
- package/plugin/vendor/reflexio/reflexio/models/config_schema.py +908 -0
- package/plugin/vendor/reflexio/reflexio/models/py.typed +0 -0
- package/plugin/vendor/reflexio/reflexio/server/OVERVIEW.md +90 -0
- package/plugin/vendor/reflexio/reflexio/server/README.md +616 -0
- package/plugin/vendor/reflexio/reflexio/server/__init__.py +210 -0
- package/plugin/vendor/reflexio/reflexio/server/__main__.py +132 -0
- package/plugin/vendor/reflexio/reflexio/server/_auth.py +25 -0
- package/plugin/vendor/reflexio/reflexio/server/api.py +2714 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/account_api.py +143 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/health_api.py +91 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/pending_tool_call_api.py +572 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/precondition_checks.py +66 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/publisher_api.py +540 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/request_context.py +50 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/stall_state_api.py +100 -0
- package/plugin/vendor/reflexio/reflexio/server/cache/__init__.py +15 -0
- package/plugin/vendor/reflexio/reflexio/server/cache/reflexio_cache.py +208 -0
- package/plugin/vendor/reflexio/reflexio/server/correlation.py +46 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/__init__.py +30 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/embedding_service.py +110 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/image_utils.py +55 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/litellm_client.py +1595 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/llm_utils.py +112 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/model_defaults.py +469 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/claude_code_provider.py +1122 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/claude_code_stream_parser.py +197 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/embedding_service_provider.py +210 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/local_embedding_provider.py +213 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/nomic_embedding_provider.py +255 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/rerank/__init__.py +6 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/rerank/cross_encoder_reranker.py +177 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/rerank/llm_reranker.py +148 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/tools.py +699 -0
- package/plugin/vendor/reflexio/reflexio/server/operation_limiter.py +179 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/_dispatchers.py +54 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/README.md +121 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/agent_success_evaluation/v1.0.0.prompt.md +58 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/agent_success_evaluation_with_comparison/v1.0.0.prompt.md +76 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/answer_synthesis/v1.5.2.prompt.md +88 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/compress_session_for_query/v1.3.0.prompt.md +31 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/document_expansion/v1.0.0.prompt.md +20 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.0.0.prompt.md +53 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.1.0.prompt.md +57 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.2.0.prompt.md +68 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.3.0.prompt.md +70 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.4.0.prompt.md +77 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.5.0.prompt.md +82 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.6.0.prompt.md +83 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.1.0.prompt.md +193 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.2.0.prompt.md +206 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v1.0.0-deprecated.prompt.md +66 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v1.0.0.prompt.md +43 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v1.1.0.prompt.md +46 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.0.0-deprecated.prompt.md +64 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.0.0.prompt.md +39 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.1.0.prompt.md +39 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.2.0.prompt.md +47 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.0.prompt.md +58 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.0.2.prompt.md +254 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.1.0.prompt.md +274 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.2.0.prompt.md +279 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v1.0.0.prompt.md +73 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v2.0.0.prompt.md +86 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.0.0.prompt.md +97 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.1.0.prompt.md +119 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.2.0.prompt.md +123 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.3.0.prompt.md +127 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.0.0.prompt.md +14 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.1.0.prompt.md +24 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.2.0.prompt.md +29 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main_expert/v1.0.0.prompt.md +11 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main_expert/v1.1.0.prompt.md +21 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main_expert/v1.2.0.prompt.md +25 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_optimizer_judge/v1.0.0.prompt.md +37 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_optimizer_judge/v1.1.0.prompt.md +40 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_optimizer_judge/v1.2.0.prompt.md +36 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate/v1.0.0.prompt.md +45 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate/v2.0.0.prompt.md +81 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate/v3.0.0.prompt.md +80 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate_expert/v1.0.0.prompt.md +34 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_deduplication/v1.0.0.prompt.md +116 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_should_generate/v1.0.0.prompt.md +33 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_should_generate_override/v1.0.0.prompt.md +16 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.0.0.prompt.md +140 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.1.0.prompt.md +160 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_main/v1.0.0.prompt.md +14 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/query_reformulation/v1.0.0.prompt.md +19 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/rerank_relevance/v1.1.0.prompt.md +44 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/shadow_comparison/v1.0.0.prompt.md +43 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/shadow_content_evaluation/v1.0.0.prompt.md +33 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_evaluation/prompt_evaluation_dataset/feedback_extraction_main_v1.jsonl +10 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_evaluation/prompt_evaluation_dataset/profile_update_main_v1.jsonl +10 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_manager.py +280 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_schema.py +11 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/_eval_health.py +131 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_constants.py +60 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_service.py +228 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_utils.py +87 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluator.py +372 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/delayed_group_evaluator.py +156 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/group_evaluation_runner.py +340 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/regen_jobs.py +471 -0
- package/plugin/vendor/reflexio/reflexio/server/services/base_generation_service.py +1626 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/_cron.py +196 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/_encryption.py +101 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/client.py +167 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/service.py +281 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/base_configurator.py +179 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/config_storage.py +62 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/configurator.py +87 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/local_file_config_storage.py +187 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/test_config_storage.py +162 -0
- package/plugin/vendor/reflexio/reflexio/server/services/deduplication_utils.py +112 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/distribution.py +33 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/eval_sampler.py +126 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/group_aggregation.py +192 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/hero_state.py +75 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/rule_attribution.py +97 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/service.py +515 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/shadow_aggregation.py +90 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/agent_run_records.py +91 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/invariants.py +303 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/outcome.py +25 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/pending_tool_call_dispatch.py +351 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/plan.py +138 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/prior_answer_search.py +217 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/resumable_agent.py +468 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_scheduler.py +171 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_worker.py +777 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/tools.py +1125 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extractor_config_utils.py +91 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extractor_interaction_utils.py +251 -0
- package/plugin/vendor/reflexio/reflexio/server/services/generation_service.py +689 -0
- package/plugin/vendor/reflexio/reflexio/server/services/operation_state_utils.py +835 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/README.md +89 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_aggregator.py +1388 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_consolidator.py +960 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_extractor.py +436 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_generation_service.py +808 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_service_constants.py +28 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_service_utils.py +362 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/__init__.py +24 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/assistant_webhook.py +246 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/gepa_adapter.py +291 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/judge.py +97 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/models.py +96 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/optimizer.py +645 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/rollout.py +35 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/scenario_resolver.py +93 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/scheduler.py +174 -0
- package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/__init__.py +26 -0
- package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/_document_expander.py +179 -0
- package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/_query_reformulator.py +297 -0
- package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_deduplicator.py +741 -0
- package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_extractor.py +462 -0
- package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_generation_service.py +734 -0
- package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_generation_service_utils.py +290 -0
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/__init__.py +17 -0
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_extractor.py +247 -0
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_service.py +800 -0
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_service_utils.py +146 -0
- package/plugin/vendor/reflexio/reflexio/server/services/retrieval/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/retrieval/relevance_floor.py +70 -0
- package/plugin/vendor/reflexio/reflexio/server/services/search/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/service_utils.py +671 -0
- package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/judge.py +184 -0
- package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/outcome.py +81 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/constants.py +2 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/error.py +11 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/retention.py +154 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/retention_mixin.py +155 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/__init__.py +59 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_agent_run.py +1253 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_base.py +1945 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_extras.py +600 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_operations.py +346 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_playbook.py +1378 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_profiles.py +747 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_requests.py +263 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_shadow_verdicts.py +193 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_share_links.py +166 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_stall_state.py +217 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/__init__.py +153 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_agent_run.py +372 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_base.py +71 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_extras.py +235 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_operations.py +170 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_playbook.py +677 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_profiles.py +250 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_requests.py +154 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_shadow_verdicts.py +130 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_share_links.py +93 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_stall_state.py +76 -0
- package/plugin/vendor/reflexio/reflexio/server/services/unified_search_service.py +568 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/README.md +77 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/feature_flags.py +116 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_manager.py +263 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/feature_flags.json +13 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/llm_model_setting.json +7 -0
- package/plugin/vendor/reflexio/reflexio/server/tracing.py +158 -0
- package/plugin/vendor/reflexio/reflexio/server/usage_metrics.py +113 -0
- package/plugin/vendor/reflexio/reflexio/server/uvicorn_logging.py +76 -0
- package/plugin/vendor/reflexio/reflexio/test_support/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/test_support/llm_fixtures.py +62 -0
- package/plugin/vendor/reflexio/reflexio/test_support/llm_mock.py +242 -0
- package/plugin/vendor/reflexio/reflexio/test_support/llm_model_registry.py +129 -0
- package/plugin/vendor/reflexio/reflexio/test_support/skip_decorators.py +43 -0
package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_generation_service.py
ADDED
|
@@ -0,0 +1,808 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import uuid
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from reflexio.server.api_endpoints.request_context import RequestContext
|
|
10
|
+
from reflexio.server.llm.litellm_client import LiteLLMClient
|
|
11
|
+
|
|
12
|
+
from reflexio.models.api_schema.internal_schema import RequestInteractionDataModel
|
|
13
|
+
from reflexio.models.api_schema.service_schemas import (
|
|
14
|
+
DowngradeUserPlaybooksResponse,
|
|
15
|
+
ManualPlaybookGenerationRequest,
|
|
16
|
+
ManualPlaybookGenerationResponse,
|
|
17
|
+
RerunPlaybookGenerationRequest,
|
|
18
|
+
RerunPlaybookGenerationResponse,
|
|
19
|
+
Status,
|
|
20
|
+
UpgradeUserPlaybooksResponse,
|
|
21
|
+
UserPlaybook,
|
|
22
|
+
)
|
|
23
|
+
from reflexio.models.config_schema import PlaybookConfig
|
|
24
|
+
from reflexio.server.operation_limiter import run_with_operation_limit
|
|
25
|
+
from reflexio.server.services.base_generation_service import (
|
|
26
|
+
BaseGenerationService,
|
|
27
|
+
StatusChangeOperation,
|
|
28
|
+
)
|
|
29
|
+
from reflexio.server.services.playbook.playbook_aggregator import PlaybookAggregator
|
|
30
|
+
from reflexio.server.services.playbook.playbook_extractor import PlaybookExtractor
|
|
31
|
+
from reflexio.server.services.playbook.playbook_service_constants import (
|
|
32
|
+
PlaybookServiceConstants,
|
|
33
|
+
)
|
|
34
|
+
from reflexio.server.services.playbook.playbook_service_utils import (
|
|
35
|
+
PlaybookAggregatorRequest,
|
|
36
|
+
PlaybookGenerationRequest,
|
|
37
|
+
format_expert_comparison_pairs,
|
|
38
|
+
has_expert_content,
|
|
39
|
+
)
|
|
40
|
+
from reflexio.server.services.service_utils import (
|
|
41
|
+
extract_interactions_from_request_interaction_data_models,
|
|
42
|
+
format_sessions_to_history_string,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
logger = logging.getLogger(__name__)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass
|
|
49
|
+
class PlaybookGenerationServiceConfig:
|
|
50
|
+
"""Runtime configuration for playbook generation service shared across all extractors.
|
|
51
|
+
|
|
52
|
+
Attributes:
|
|
53
|
+
request_id: The request ID
|
|
54
|
+
agent_version: The agent version
|
|
55
|
+
user_id: The user ID for per-user playbook extraction
|
|
56
|
+
source: Source of the interactions
|
|
57
|
+
allow_manual_trigger: Whether to allow extractors with manual_trigger=True
|
|
58
|
+
rerun_start_time: Optional start time filter for rerun flows (Unix timestamp)
|
|
59
|
+
rerun_end_time: Optional end time filter for rerun flows (Unix timestamp)
|
|
60
|
+
auto_run: True for regular flow (checks stride_size), False for rerun/manual (skips stride_size)
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
request_id: str
|
|
64
|
+
agent_version: str
|
|
65
|
+
user_id: str | None = None
|
|
66
|
+
source: str | None = None
|
|
67
|
+
allow_manual_trigger: bool = False
|
|
68
|
+
rerun_start_time: int | None = None
|
|
69
|
+
rerun_end_time: int | None = None
|
|
70
|
+
auto_run: bool = True
|
|
71
|
+
force_extraction: bool = False
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class PlaybookGenerationService(
|
|
75
|
+
BaseGenerationService[
|
|
76
|
+
PlaybookConfig,
|
|
77
|
+
PlaybookExtractor,
|
|
78
|
+
PlaybookGenerationServiceConfig,
|
|
79
|
+
PlaybookGenerationRequest,
|
|
80
|
+
]
|
|
81
|
+
):
|
|
82
|
+
"""
|
|
83
|
+
Service for generating playbook entries from user interactions.
|
|
84
|
+
Runs the configured PlaybookExtractor for each generation request.
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
def __init__(
|
|
88
|
+
self,
|
|
89
|
+
llm_client: LiteLLMClient,
|
|
90
|
+
request_context: RequestContext,
|
|
91
|
+
allow_manual_trigger: bool = False,
|
|
92
|
+
output_pending_status: bool = False,
|
|
93
|
+
skip_aggregation: bool = False,
|
|
94
|
+
) -> None:
|
|
95
|
+
"""
|
|
96
|
+
Initialize the playbook generation service.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
llm_client: Unified LLM client supporting both OpenAI and Claude
|
|
100
|
+
request_context: Request context with storage, configurator, and org_id
|
|
101
|
+
allow_manual_trigger: Whether to allow extractors with manual_trigger=True
|
|
102
|
+
output_pending_status: Whether to output entries with PENDING status (for rerun)
|
|
103
|
+
skip_aggregation: Whether to skip playbook aggregation (extract only, no agent playbooks)
|
|
104
|
+
"""
|
|
105
|
+
super().__init__(llm_client=llm_client, request_context=request_context)
|
|
106
|
+
self.allow_manual_trigger = allow_manual_trigger
|
|
107
|
+
self.output_pending_status = output_pending_status
|
|
108
|
+
self.skip_aggregation = skip_aggregation
|
|
109
|
+
|
|
110
|
+
def _load_generation_service_config(
|
|
111
|
+
self, request: PlaybookGenerationRequest
|
|
112
|
+
) -> PlaybookGenerationServiceConfig:
|
|
113
|
+
"""
|
|
114
|
+
Extract request parameters from PlaybookGenerationRequest.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
request: PlaybookGenerationRequest containing evaluation parameters
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
PlaybookGenerationServiceConfig object
|
|
121
|
+
"""
|
|
122
|
+
return PlaybookGenerationServiceConfig(
|
|
123
|
+
request_id=request.request_id,
|
|
124
|
+
agent_version=request.agent_version,
|
|
125
|
+
user_id=request.user_id,
|
|
126
|
+
source=request.source,
|
|
127
|
+
allow_manual_trigger=self.allow_manual_trigger,
|
|
128
|
+
rerun_start_time=request.rerun_start_time,
|
|
129
|
+
rerun_end_time=request.rerun_end_time,
|
|
130
|
+
auto_run=request.auto_run,
|
|
131
|
+
force_extraction=request.force_extraction,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
def _configured_playbook_config(self) -> PlaybookConfig | None:
|
|
135
|
+
root_config = self.configurator.get_config()
|
|
136
|
+
return getattr(root_config, "user_playbook_extractor_config", None)
|
|
137
|
+
|
|
138
|
+
def _load_extractor_config(self) -> PlaybookConfig | None:
|
|
139
|
+
"""
|
|
140
|
+
Load the configured user playbook extractor from configurator.
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
PlaybookConfig | None: The configured user playbook extractor, if enabled.
|
|
144
|
+
"""
|
|
145
|
+
return self._configured_playbook_config()
|
|
146
|
+
|
|
147
|
+
def _create_extractor(
|
|
148
|
+
self,
|
|
149
|
+
extractor_config: PlaybookConfig,
|
|
150
|
+
service_config: PlaybookGenerationServiceConfig,
|
|
151
|
+
) -> PlaybookExtractor:
|
|
152
|
+
"""
|
|
153
|
+
Create a PlaybookExtractor instance from configuration.
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
extractor_config: PlaybookConfig configuration object from YAML
|
|
157
|
+
service_config: PlaybookGenerationServiceConfig containing runtime parameters
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
PlaybookExtractor instance
|
|
161
|
+
"""
|
|
162
|
+
return PlaybookExtractor(
|
|
163
|
+
request_context=self.request_context,
|
|
164
|
+
llm_client=self.client,
|
|
165
|
+
extractor_config=extractor_config,
|
|
166
|
+
service_config=service_config,
|
|
167
|
+
agent_context=self.configurator.get_agent_context(),
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
def _build_should_run_prompt(
|
|
171
|
+
self,
|
|
172
|
+
scoped_config: PlaybookConfig,
|
|
173
|
+
session_data_models: list[RequestInteractionDataModel],
|
|
174
|
+
) -> str | None:
|
|
175
|
+
"""
|
|
176
|
+
Build prompt for consolidated should_generate check.
|
|
177
|
+
|
|
178
|
+
Renders the configured playbook definition for one LLM call.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
scoped_config: Playbook extractor config that had scoped interactions
|
|
182
|
+
session_data_models: Deduplicated request interaction data models
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
str | None: The rendered prompt, or None if no definitions to check
|
|
186
|
+
"""
|
|
187
|
+
# Check for expert content — use expert-specific should-generate prompt
|
|
188
|
+
all_interactions = extract_interactions_from_request_interaction_data_models(
|
|
189
|
+
session_data_models
|
|
190
|
+
)
|
|
191
|
+
if has_expert_content(all_interactions):
|
|
192
|
+
agent_context = self.configurator.get_agent_context()
|
|
193
|
+
comparison_pairs = format_expert_comparison_pairs(session_data_models)
|
|
194
|
+
return self.request_context.prompt_manager.render_prompt(
|
|
195
|
+
PlaybookServiceConstants.PLAYBOOK_SHOULD_GENERATE_EXPERT_PROMPT_ID,
|
|
196
|
+
{
|
|
197
|
+
"agent_context_prompt": agent_context,
|
|
198
|
+
"comparison_pairs": comparison_pairs,
|
|
199
|
+
},
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
new_interactions = format_sessions_to_history_string(session_data_models)
|
|
203
|
+
|
|
204
|
+
combined_definition = (
|
|
205
|
+
scoped_config.extraction_definition_prompt.strip()
|
|
206
|
+
if scoped_config.extraction_definition_prompt
|
|
207
|
+
else ""
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
if not combined_definition:
|
|
211
|
+
return None
|
|
212
|
+
|
|
213
|
+
# Get tool_can_use from root config
|
|
214
|
+
root_config = self.request_context.configurator.get_config()
|
|
215
|
+
tool_can_use_str = ""
|
|
216
|
+
if root_config and root_config.tool_can_use:
|
|
217
|
+
tool_can_use_str = "\n".join(
|
|
218
|
+
f"{tool.tool_name}: {tool.tool_description}"
|
|
219
|
+
for tool in root_config.tool_can_use
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
agent_context = self.configurator.get_agent_context()
|
|
223
|
+
prompt_manager = self.request_context.prompt_manager
|
|
224
|
+
|
|
225
|
+
return prompt_manager.render_prompt(
|
|
226
|
+
PlaybookServiceConstants.PLAYBOOK_SHOULD_GENERATE_PROMPT_ID,
|
|
227
|
+
{
|
|
228
|
+
"agent_context_prompt": agent_context,
|
|
229
|
+
"extraction_definition_prompt": combined_definition,
|
|
230
|
+
"new_interactions": new_interactions,
|
|
231
|
+
"tool_can_use": tool_can_use_str,
|
|
232
|
+
},
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
def _get_precheck_interaction_query_kwargs(self) -> dict:
|
|
236
|
+
"""Return agent_version filter for non-auto runs."""
|
|
237
|
+
return {
|
|
238
|
+
"agent_version": (
|
|
239
|
+
self.service_config.agent_version # type: ignore[reportOptionalMemberAccess]
|
|
240
|
+
if not self.service_config.auto_run # type: ignore[reportOptionalMemberAccess]
|
|
241
|
+
else None
|
|
242
|
+
),
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
def _process_results(self, results: list[list[UserPlaybook]]) -> None:
|
|
246
|
+
"""
|
|
247
|
+
Process, deduplicate, and save all results. Called once after all extractors complete.
|
|
248
|
+
|
|
249
|
+
Args:
|
|
250
|
+
results: List of UserPlaybook results from extractors (one list per extractor)
|
|
251
|
+
"""
|
|
252
|
+
all_playbooks = []
|
|
253
|
+
for result in results:
|
|
254
|
+
if isinstance(result, list):
|
|
255
|
+
all_playbooks.extend(result)
|
|
256
|
+
self._finalize_extracted_items(all_playbooks)
|
|
257
|
+
|
|
258
|
+
def _finalize_extracted_items(self, all_playbooks: list[UserPlaybook]) -> None:
|
|
259
|
+
"""Deduplicate, persist, and aggregate extracted user playbook items."""
|
|
260
|
+
# Deduplicate against existing entries in DB when deduplicator is enabled
|
|
261
|
+
existing_ids_to_delete: list[int] = []
|
|
262
|
+
from reflexio.server.site_var.feature_flags import is_deduplicator_enabled
|
|
263
|
+
|
|
264
|
+
if is_deduplicator_enabled(self.org_id):
|
|
265
|
+
from reflexio.server.services.playbook.playbook_consolidator import (
|
|
266
|
+
PlaybookConsolidator,
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
playbook_config = self._configured_playbook_config()
|
|
270
|
+
dedup_config = (
|
|
271
|
+
playbook_config.deduplication_config if playbook_config else None
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
consolidator = PlaybookConsolidator(
|
|
275
|
+
request_context=self.request_context,
|
|
276
|
+
llm_client=self.client,
|
|
277
|
+
dedup_config=dedup_config,
|
|
278
|
+
)
|
|
279
|
+
deduplicated_playbooks, existing_ids_to_delete = consolidator.deduplicate(
|
|
280
|
+
[all_playbooks],
|
|
281
|
+
self.service_config.request_id, # type: ignore[reportOptionalMemberAccess]
|
|
282
|
+
self.service_config.agent_version, # type: ignore[reportOptionalMemberAccess]
|
|
283
|
+
user_id=self.service_config.user_id, # type: ignore[reportOptionalMemberAccess]
|
|
284
|
+
)
|
|
285
|
+
logger.info(
|
|
286
|
+
"User playbook entries after deduplication: %d",
|
|
287
|
+
len(deduplicated_playbooks),
|
|
288
|
+
)
|
|
289
|
+
if deduplicated_playbooks:
|
|
290
|
+
all_playbooks = deduplicated_playbooks
|
|
291
|
+
|
|
292
|
+
# Set status and source for all entries
|
|
293
|
+
for playbook in all_playbooks:
|
|
294
|
+
playbook.status = Status.PENDING if self.output_pending_status else None
|
|
295
|
+
playbook.source = self.service_config.source # type: ignore[reportOptionalMemberAccess]
|
|
296
|
+
|
|
297
|
+
logger.info("All user playbook entries: %s", all_playbooks)
|
|
298
|
+
|
|
299
|
+
logger.info(
|
|
300
|
+
"Successfully completed %d %s playbook generation for request id: %s",
|
|
301
|
+
len(all_playbooks),
|
|
302
|
+
self._get_service_name(),
|
|
303
|
+
self.service_config.request_id, # type: ignore[reportOptionalMemberAccess]
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
# Save results
|
|
307
|
+
if all_playbooks:
|
|
308
|
+
try:
|
|
309
|
+
self.storage.save_user_playbooks(all_playbooks) # type: ignore[reportOptionalMemberAccess]
|
|
310
|
+
self._enqueue_user_playbook_optimization(all_playbooks)
|
|
311
|
+
|
|
312
|
+
# Delete superseded existing entries only after save succeeds
|
|
313
|
+
if existing_ids_to_delete:
|
|
314
|
+
try:
|
|
315
|
+
deleted_count = self.storage.delete_user_playbooks_by_ids( # type: ignore[reportOptionalMemberAccess]
|
|
316
|
+
existing_ids_to_delete
|
|
317
|
+
)
|
|
318
|
+
logger.info(
|
|
319
|
+
"Deleted %d superseded existing entries", deleted_count
|
|
320
|
+
)
|
|
321
|
+
except Exception as e:
|
|
322
|
+
logger.error(
|
|
323
|
+
"Failed to delete superseded existing entries: %s",
|
|
324
|
+
str(e),
|
|
325
|
+
)
|
|
326
|
+
except Exception as e:
|
|
327
|
+
logger.error(
|
|
328
|
+
"Failed to save %s results for request id: %s due to %s, exception type: %s",
|
|
329
|
+
self._get_service_name(),
|
|
330
|
+
self.service_config.request_id, # type: ignore[reportOptionalMemberAccess]
|
|
331
|
+
str(e),
|
|
332
|
+
type(e).__name__,
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
# Trigger playbook aggregation
|
|
336
|
+
if not self.output_pending_status and not self.skip_aggregation:
|
|
337
|
+
logger.info("Trigger playbook aggregation")
|
|
338
|
+
self._trigger_playbook_aggregation()
|
|
339
|
+
|
|
340
|
+
def _enqueue_user_playbook_optimization(
|
|
341
|
+
self, saved_playbooks: list[UserPlaybook]
|
|
342
|
+
) -> None:
|
|
343
|
+
config = self.configurator.get_config().playbook_optimizer_config
|
|
344
|
+
if (
|
|
345
|
+
not config.enabled
|
|
346
|
+
or not config.optimize_user_playbooks
|
|
347
|
+
or not saved_playbooks
|
|
348
|
+
):
|
|
349
|
+
return
|
|
350
|
+
from reflexio.server.services.playbook_optimizer import (
|
|
351
|
+
PlaybookOptimizationScheduler,
|
|
352
|
+
PlaybookOptimizationTarget,
|
|
353
|
+
PlaybookOptimizer,
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
scheduler = PlaybookOptimizationScheduler.get_instance()
|
|
357
|
+
for playbook in saved_playbooks:
|
|
358
|
+
if (
|
|
359
|
+
not playbook.user_playbook_id
|
|
360
|
+
or playbook.status is not None
|
|
361
|
+
or not playbook.source_interaction_ids
|
|
362
|
+
):
|
|
363
|
+
continue
|
|
364
|
+
target = PlaybookOptimizationTarget(
|
|
365
|
+
kind="user_playbook", target_id=playbook.user_playbook_id
|
|
366
|
+
)
|
|
367
|
+
scheduler.enqueue(
|
|
368
|
+
org_id=self.request_context.org_id,
|
|
369
|
+
target=target,
|
|
370
|
+
callback=lambda target=target: PlaybookOptimizer(
|
|
371
|
+
self.request_context, self.client
|
|
372
|
+
).optimize(target),
|
|
373
|
+
jitter_seconds=config.scheduler_jitter_seconds,
|
|
374
|
+
abort_cooldown_threshold=config.abort_cooldown_threshold,
|
|
375
|
+
cooldown_after_aborts_seconds=config.cooldown_after_aborts_seconds,
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
def _get_extractor_state_service_name(self) -> str:
|
|
379
|
+
"""
|
|
380
|
+
Get the service name for stride_size bookmark lookups.
|
|
381
|
+
|
|
382
|
+
Returns:
|
|
383
|
+
str: "playbook_extractor" for OperationStateManager stride_size checks
|
|
384
|
+
"""
|
|
385
|
+
return "playbook_extractor"
|
|
386
|
+
|
|
387
|
+
def _get_service_name(self) -> str:
|
|
388
|
+
"""
|
|
389
|
+
Get the name of the service for logging and operation state tracking.
|
|
390
|
+
|
|
391
|
+
Returns:
|
|
392
|
+
Service name string - "rerun_playbook_generation" for rerun operations,
|
|
393
|
+
"playbook_generation" for regular operations
|
|
394
|
+
"""
|
|
395
|
+
if self.output_pending_status:
|
|
396
|
+
return "rerun_playbook_generation"
|
|
397
|
+
return "playbook_generation"
|
|
398
|
+
|
|
399
|
+
def _get_base_service_name(self) -> str:
|
|
400
|
+
"""
|
|
401
|
+
Get the base service name for OperationStateManager keys.
|
|
402
|
+
|
|
403
|
+
Returns:
|
|
404
|
+
str: "playbook_generation"
|
|
405
|
+
"""
|
|
406
|
+
return "playbook_generation"
|
|
407
|
+
|
|
408
|
+
def _should_track_in_progress(self) -> bool:
|
|
409
|
+
"""
|
|
410
|
+
Playbook generation should track in-progress state to prevent duplicates.
|
|
411
|
+
|
|
412
|
+
Returns:
|
|
413
|
+
bool: True - playbook generation tracks in-progress state
|
|
414
|
+
"""
|
|
415
|
+
return True
|
|
416
|
+
|
|
417
|
+
def _get_lock_scope_id(self, request: PlaybookGenerationRequest) -> str | None: # noqa: ARG002
|
|
418
|
+
"""
|
|
419
|
+
Get the scope ID for lock key construction.
|
|
420
|
+
|
|
421
|
+
Playbook generation is org-scoped, so returns None (no user scope).
|
|
422
|
+
|
|
423
|
+
Args:
|
|
424
|
+
request: The PlaybookGenerationRequest
|
|
425
|
+
|
|
426
|
+
Returns:
|
|
427
|
+
None: Playbook uses org-level scope only
|
|
428
|
+
"""
|
|
429
|
+
return None
|
|
430
|
+
|
|
431
|
+
def _trigger_playbook_aggregation(self) -> None:
|
|
432
|
+
"""
|
|
433
|
+
Trigger playbook aggregation for playbook types that have aggregator config.
|
|
434
|
+
This is called after raw user playbook entries are saved to check if aggregation should run.
|
|
435
|
+
"""
|
|
436
|
+
playbook_config = self._configured_playbook_config()
|
|
437
|
+
if not playbook_config or not playbook_config.aggregation_config:
|
|
438
|
+
return
|
|
439
|
+
|
|
440
|
+
logger.info("Triggering aggregation")
|
|
441
|
+
|
|
442
|
+
# Create aggregator request. Aggregation is singleton — it operates on the
|
|
443
|
+
# user's whole playbook set, so no name selector is threaded.
|
|
444
|
+
aggregator_request = PlaybookAggregatorRequest(
|
|
445
|
+
agent_version=self.service_config.agent_version, # type: ignore[reportOptionalMemberAccess]
|
|
446
|
+
)
|
|
447
|
+
|
|
448
|
+
# Initialize and run aggregator (synchronous)
|
|
449
|
+
aggregator = PlaybookAggregator(
|
|
450
|
+
llm_client=self.client,
|
|
451
|
+
request_context=self.request_context,
|
|
452
|
+
agent_version=self.service_config.agent_version, # type: ignore[reportOptionalMemberAccess]
|
|
453
|
+
)
|
|
454
|
+
try:
|
|
455
|
+
run_with_operation_limit(
|
|
456
|
+
org_id=self.request_context.org_id,
|
|
457
|
+
operation="aggregation",
|
|
458
|
+
fn=lambda: aggregator.run(aggregator_request),
|
|
459
|
+
)
|
|
460
|
+
except TimeoutError:
|
|
461
|
+
logger.info(
|
|
462
|
+
"Skipping inline aggregation for agent_version=%s: aggregation limiter is saturated",
|
|
463
|
+
self.service_config.agent_version, # type: ignore[reportOptionalMemberAccess]
|
|
464
|
+
)
|
|
465
|
+
|
|
466
|
+
# ===============================
|
|
467
|
+
# Rerun hook implementations (override base class methods)
|
|
468
|
+
# ===============================
|
|
469
|
+
|
|
470
|
+
def _pre_process_rerun(self, request: RerunPlaybookGenerationRequest) -> None:
|
|
471
|
+
"""Delete existing pending raw entries before generating new ones.
|
|
472
|
+
|
|
473
|
+
This ensures that each rerun starts fresh without accumulating pending entries
|
|
474
|
+
from previous reruns.
|
|
475
|
+
|
|
476
|
+
Args:
|
|
477
|
+
request: RerunPlaybookGenerationRequest with optional agent_version filter
|
|
478
|
+
"""
|
|
479
|
+
deleted_count = self.storage.delete_all_user_playbooks_by_status( # type: ignore[reportOptionalMemberAccess]
|
|
480
|
+
status=Status.PENDING,
|
|
481
|
+
agent_version=request.agent_version,
|
|
482
|
+
)
|
|
483
|
+
logger.info(
|
|
484
|
+
"Deleted %d existing pending raw entries before rerun (agent_version=%s)",
|
|
485
|
+
deleted_count,
|
|
486
|
+
request.agent_version,
|
|
487
|
+
)
|
|
488
|
+
|
|
489
|
+
def _get_rerun_user_ids(self, request: RerunPlaybookGenerationRequest) -> list[str]:
|
|
490
|
+
"""Get user IDs to process. Extractors collect their own data.
|
|
491
|
+
|
|
492
|
+
Identifies unique user_ids with matching requests via storage-level filtering.
|
|
493
|
+
|
|
494
|
+
Args:
|
|
495
|
+
request: RerunPlaybookGenerationRequest with optional time and source filters
|
|
496
|
+
|
|
497
|
+
Returns:
|
|
498
|
+
List of user IDs to process
|
|
499
|
+
"""
|
|
500
|
+
return self.storage.get_rerun_user_ids( # type: ignore[reportOptionalMemberAccess]
|
|
501
|
+
user_id=None,
|
|
502
|
+
start_time=(
|
|
503
|
+
int(request.start_time.timestamp()) if request.start_time else None
|
|
504
|
+
),
|
|
505
|
+
end_time=(int(request.end_time.timestamp()) if request.end_time else None),
|
|
506
|
+
source=request.source,
|
|
507
|
+
agent_version=request.agent_version,
|
|
508
|
+
)
|
|
509
|
+
|
|
510
|
+
def _build_rerun_request_params(
|
|
511
|
+
self, request: RerunPlaybookGenerationRequest
|
|
512
|
+
) -> dict:
|
|
513
|
+
"""Build request params dict for operation state tracking.
|
|
514
|
+
|
|
515
|
+
Args:
|
|
516
|
+
request: Original rerun request
|
|
517
|
+
|
|
518
|
+
Returns:
|
|
519
|
+
Dictionary of request parameters
|
|
520
|
+
"""
|
|
521
|
+
return {
|
|
522
|
+
"agent_version": request.agent_version,
|
|
523
|
+
"start_time": (
|
|
524
|
+
request.start_time.isoformat() if request.start_time else None
|
|
525
|
+
),
|
|
526
|
+
"end_time": request.end_time.isoformat() if request.end_time else None,
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
def _create_run_request_for_item(
|
|
530
|
+
self,
|
|
531
|
+
user_id: str,
|
|
532
|
+
request: RerunPlaybookGenerationRequest | ManualPlaybookGenerationRequest,
|
|
533
|
+
) -> PlaybookGenerationRequest:
|
|
534
|
+
"""Create PlaybookGenerationRequest for a single user.
|
|
535
|
+
|
|
536
|
+
Handles both rerun and manual request types.
|
|
537
|
+
|
|
538
|
+
Args:
|
|
539
|
+
user_id: The user ID to process
|
|
540
|
+
request: The original rerun or manual request
|
|
541
|
+
|
|
542
|
+
Returns:
|
|
543
|
+
PlaybookGenerationRequest for this user with filter constraints
|
|
544
|
+
"""
|
|
545
|
+
# Handle rerun requests (have start_time/end_time datetime objects)
|
|
546
|
+
if isinstance(request, RerunPlaybookGenerationRequest):
|
|
547
|
+
return PlaybookGenerationRequest(
|
|
548
|
+
request_id=f"rerun_playbook_{uuid.uuid4().hex[:8]}",
|
|
549
|
+
agent_version=request.agent_version,
|
|
550
|
+
user_id=user_id,
|
|
551
|
+
source=request.source,
|
|
552
|
+
rerun_start_time=(
|
|
553
|
+
int(request.start_time.timestamp()) if request.start_time else None
|
|
554
|
+
),
|
|
555
|
+
rerun_end_time=(
|
|
556
|
+
int(request.end_time.timestamp()) if request.end_time else None
|
|
557
|
+
),
|
|
558
|
+
auto_run=False,
|
|
559
|
+
)
|
|
560
|
+
# Handle manual requests (ManualPlaybookGenerationRequest)
|
|
561
|
+
return PlaybookGenerationRequest(
|
|
562
|
+
request_id=f"manual_{uuid.uuid4().hex[:8]}",
|
|
563
|
+
agent_version=request.agent_version,
|
|
564
|
+
user_id=user_id,
|
|
565
|
+
source=request.source,
|
|
566
|
+
auto_run=False,
|
|
567
|
+
)
|
|
568
|
+
|
|
569
|
+
def _create_rerun_response(
|
|
570
|
+
self, success: bool, msg: str, count: int
|
|
571
|
+
) -> RerunPlaybookGenerationResponse:
|
|
572
|
+
"""Create RerunPlaybookGenerationResponse.
|
|
573
|
+
|
|
574
|
+
Args:
|
|
575
|
+
success: Whether the operation succeeded
|
|
576
|
+
msg: Status message
|
|
577
|
+
count: Number of entries generated
|
|
578
|
+
|
|
579
|
+
Returns:
|
|
580
|
+
RerunPlaybookGenerationResponse
|
|
581
|
+
"""
|
|
582
|
+
return RerunPlaybookGenerationResponse(
|
|
583
|
+
success=success,
|
|
584
|
+
msg=msg,
|
|
585
|
+
playbooks_generated=count,
|
|
586
|
+
)
|
|
587
|
+
|
|
588
|
+
def _get_generated_count(
|
|
589
|
+
self,
|
|
590
|
+
request: RerunPlaybookGenerationRequest,
|
|
591
|
+
processed_user_ids: list[str] | None = None, # noqa: ARG002
|
|
592
|
+
) -> int:
|
|
593
|
+
"""Get the count of entries generated during rerun.
|
|
594
|
+
|
|
595
|
+
Counts entries with pending status, filtered by agent_version.
|
|
596
|
+
|
|
597
|
+
Args:
|
|
598
|
+
request: The rerun request object
|
|
599
|
+
|
|
600
|
+
Returns:
|
|
601
|
+
Number of entries generated
|
|
602
|
+
"""
|
|
603
|
+
playbooks = self.storage.get_user_playbooks( # type: ignore[reportOptionalMemberAccess]
|
|
604
|
+
agent_version=request.agent_version,
|
|
605
|
+
status_filter=[Status.PENDING],
|
|
606
|
+
limit=10000,
|
|
607
|
+
)
|
|
608
|
+
return len(playbooks)
|
|
609
|
+
|
|
610
|
+
# ===============================
|
|
611
|
+
# Manual Regular Generation (window-sized, CURRENT output)
|
|
612
|
+
# ===============================
|
|
613
|
+
|
|
614
|
+
def run_manual_regular(
|
|
615
|
+
self, request: ManualPlaybookGenerationRequest
|
|
616
|
+
) -> ManualPlaybookGenerationResponse:
|
|
617
|
+
"""
|
|
618
|
+
Run playbook generation with window-sized interactions and CURRENT output.
|
|
619
|
+
|
|
620
|
+
Processes entries per-user. Each extractor collects its own data
|
|
621
|
+
using its configured window_size.
|
|
622
|
+
Uses progress tracking via OperationStateManager.
|
|
623
|
+
|
|
624
|
+
Args:
|
|
625
|
+
request: ManualPlaybookGenerationRequest with agent_version and optional source
|
|
626
|
+
|
|
627
|
+
Returns:
|
|
628
|
+
ManualPlaybookGenerationResponse with success status and count
|
|
629
|
+
"""
|
|
630
|
+
state_manager = self._create_state_manager()
|
|
631
|
+
|
|
632
|
+
try:
|
|
633
|
+
# Check for existing in-progress operation
|
|
634
|
+
error = state_manager.check_in_progress()
|
|
635
|
+
if error:
|
|
636
|
+
return ManualPlaybookGenerationResponse(
|
|
637
|
+
success=False, msg=error, playbooks_generated=0
|
|
638
|
+
)
|
|
639
|
+
|
|
640
|
+
# 1. Get user_ids with recent interactions
|
|
641
|
+
requests_dict = self.storage.get_sessions( # type: ignore[reportOptionalMemberAccess]
|
|
642
|
+
user_id=None, # All users
|
|
643
|
+
top_k=1000, # Get recent sessions to find users
|
|
644
|
+
)
|
|
645
|
+
|
|
646
|
+
# Get unique user_ids
|
|
647
|
+
user_ids_set: set[str] = set()
|
|
648
|
+
for session_requests in requests_dict.values():
|
|
649
|
+
for rig in session_requests:
|
|
650
|
+
# Apply source filter if provided
|
|
651
|
+
if request.source and rig.request.source != request.source:
|
|
652
|
+
continue
|
|
653
|
+
user_ids_set.add(rig.request.user_id)
|
|
654
|
+
|
|
655
|
+
user_ids = list(user_ids_set)
|
|
656
|
+
|
|
657
|
+
if not user_ids:
|
|
658
|
+
return ManualPlaybookGenerationResponse(
|
|
659
|
+
success=True,
|
|
660
|
+
msg="No interactions found to process",
|
|
661
|
+
playbooks_generated=0,
|
|
662
|
+
)
|
|
663
|
+
|
|
664
|
+
# 2. Run batch with progress tracking
|
|
665
|
+
request_params = {
|
|
666
|
+
"agent_version": request.agent_version,
|
|
667
|
+
"source": request.source,
|
|
668
|
+
"mode": "manual_regular",
|
|
669
|
+
}
|
|
670
|
+
self._run_batch_with_progress(
|
|
671
|
+
user_ids=user_ids,
|
|
672
|
+
request=request, # type: ignore[reportArgumentType]
|
|
673
|
+
request_params=request_params,
|
|
674
|
+
state_manager=state_manager,
|
|
675
|
+
)
|
|
676
|
+
|
|
677
|
+
# 3. Count generated entries (CURRENT status = None)
|
|
678
|
+
total_playbooks = self._count_manual_generated(request)
|
|
679
|
+
|
|
680
|
+
return ManualPlaybookGenerationResponse(
|
|
681
|
+
success=True,
|
|
682
|
+
msg=f"Generated {total_playbooks} playbook entries",
|
|
683
|
+
playbooks_generated=total_playbooks,
|
|
684
|
+
)
|
|
685
|
+
|
|
686
|
+
except Exception as e:
|
|
687
|
+
state_manager.mark_progress_failed(str(e))
|
|
688
|
+
return ManualPlaybookGenerationResponse(
|
|
689
|
+
success=False,
|
|
690
|
+
msg=f"Failed to generate playbook entries: {str(e)}",
|
|
691
|
+
playbooks_generated=0,
|
|
692
|
+
)
|
|
693
|
+
|
|
694
|
+
def _count_manual_generated(self, request: ManualPlaybookGenerationRequest) -> int:
|
|
695
|
+
"""
|
|
696
|
+
Count entries generated during manual regular generation.
|
|
697
|
+
|
|
698
|
+
Counts entries with CURRENT status (None), filtered by agent_version.
|
|
699
|
+
|
|
700
|
+
Args:
|
|
701
|
+
request: The manual generation request object
|
|
702
|
+
|
|
703
|
+
Returns:
|
|
704
|
+
Number of entries with CURRENT status
|
|
705
|
+
"""
|
|
706
|
+
playbooks = self.storage.get_user_playbooks( # type: ignore[reportOptionalMemberAccess]
|
|
707
|
+
agent_version=request.agent_version,
|
|
708
|
+
status_filter=[None], # CURRENT entries
|
|
709
|
+
limit=10000,
|
|
710
|
+
)
|
|
711
|
+
return len(playbooks)
|
|
712
|
+
|
|
713
|
+
# ===============================
|
|
714
|
+
# Upgrade/Downgrade hook implementations (override base class methods)
|
|
715
|
+
# ===============================
|
|
716
|
+
|
|
717
|
+
def _has_items_with_status(
|
|
718
|
+
self, status: Status | None, request: PlaybookGenerationRequest
|
|
719
|
+
) -> bool:
|
|
720
|
+
"""Check if raw entries exist with given status.
|
|
721
|
+
|
|
722
|
+
Args:
|
|
723
|
+
status: The status to check for (None for CURRENT)
|
|
724
|
+
request: The upgrade/downgrade request object
|
|
725
|
+
|
|
726
|
+
Returns:
|
|
727
|
+
bool: True if any matching raw entries exist
|
|
728
|
+
"""
|
|
729
|
+
return self.storage.has_user_playbooks_with_status( # type: ignore[reportOptionalMemberAccess]
|
|
730
|
+
status=status,
|
|
731
|
+
agent_version=getattr(request, "agent_version", None),
|
|
732
|
+
)
|
|
733
|
+
|
|
734
|
+
def _delete_items_by_status(
|
|
735
|
+
self, status: Status, request: PlaybookGenerationRequest
|
|
736
|
+
) -> int:
|
|
737
|
+
"""Delete raw entries with given status.
|
|
738
|
+
|
|
739
|
+
Args:
|
|
740
|
+
status: The status of raw entries to delete
|
|
741
|
+
request: The upgrade/downgrade request object
|
|
742
|
+
|
|
743
|
+
Returns:
|
|
744
|
+
int: Number of raw entries deleted
|
|
745
|
+
"""
|
|
746
|
+
return self.storage.delete_all_user_playbooks_by_status( # type: ignore[reportOptionalMemberAccess]
|
|
747
|
+
status=status,
|
|
748
|
+
agent_version=getattr(request, "agent_version", None),
|
|
749
|
+
)
|
|
750
|
+
|
|
751
|
+
def _update_items_status(
|
|
752
|
+
self,
|
|
753
|
+
old_status: Status | None,
|
|
754
|
+
new_status: Status | None,
|
|
755
|
+
request: PlaybookGenerationRequest,
|
|
756
|
+
user_ids: list[str] | None = None, # noqa: ARG002
|
|
757
|
+
) -> int:
|
|
758
|
+
"""Update raw entries from old_status to new_status with request filters.
|
|
759
|
+
|
|
760
|
+
Args:
|
|
761
|
+
old_status: The current status to match (None for CURRENT)
|
|
762
|
+
new_status: The new status to set (None for CURRENT)
|
|
763
|
+
request: The upgrade/downgrade request object with filters
|
|
764
|
+
user_ids: Optional pre-computed list of user IDs (not used for playbook service)
|
|
765
|
+
|
|
766
|
+
Returns:
|
|
767
|
+
int: Number of raw entries updated
|
|
768
|
+
"""
|
|
769
|
+
# Note: user_ids is ignored for playbook service as it uses agent_version filters
|
|
770
|
+
return self.storage.update_all_user_playbooks_status( # type: ignore[reportOptionalMemberAccess]
|
|
771
|
+
old_status=old_status,
|
|
772
|
+
new_status=new_status,
|
|
773
|
+
agent_version=getattr(request, "agent_version", None),
|
|
774
|
+
)
|
|
775
|
+
|
|
776
|
+
def _create_status_change_response(
|
|
777
|
+
self,
|
|
778
|
+
operation: StatusChangeOperation,
|
|
779
|
+
success: bool,
|
|
780
|
+
counts: dict,
|
|
781
|
+
msg: str,
|
|
782
|
+
) -> UpgradeUserPlaybooksResponse | DowngradeUserPlaybooksResponse:
|
|
783
|
+
"""Create upgrade or downgrade response object for raw entries.
|
|
784
|
+
|
|
785
|
+
Args:
|
|
786
|
+
operation: The operation type (UPGRADE or DOWNGRADE)
|
|
787
|
+
success: Whether the operation succeeded
|
|
788
|
+
counts: Dictionary of counts
|
|
789
|
+
msg: Status message
|
|
790
|
+
|
|
791
|
+
Returns:
|
|
792
|
+
UpgradeUserPlaybooksResponse or DowngradeUserPlaybooksResponse
|
|
793
|
+
"""
|
|
794
|
+
if operation == StatusChangeOperation.UPGRADE:
|
|
795
|
+
return UpgradeUserPlaybooksResponse(
|
|
796
|
+
success=success,
|
|
797
|
+
user_playbooks_deleted=counts.get("deleted", 0),
|
|
798
|
+
user_playbooks_archived=counts.get("archived", 0),
|
|
799
|
+
user_playbooks_promoted=counts.get("promoted", 0),
|
|
800
|
+
message=msg,
|
|
801
|
+
)
|
|
802
|
+
# DOWNGRADE
|
|
803
|
+
return DowngradeUserPlaybooksResponse(
|
|
804
|
+
success=success,
|
|
805
|
+
user_playbooks_demoted=counts.get("demoted", 0),
|
|
806
|
+
user_playbooks_restored=counts.get("restored", 0),
|
|
807
|
+
message=msg,
|
|
808
|
+
)
|