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,96 @@
|
|
|
1
|
+
"""Stop reflexio services."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
|
|
7
|
+
from dotenv import load_dotenv
|
|
8
|
+
|
|
9
|
+
from reflexio.cli.run_services import parse_only_flag, resolve_ports
|
|
10
|
+
from reflexio.cli.utils import stop_services
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def add_arguments(parser: argparse.ArgumentParser) -> None:
|
|
14
|
+
"""Add stop-services arguments to the parser."""
|
|
15
|
+
parser.add_argument(
|
|
16
|
+
"--backend-port",
|
|
17
|
+
type=int,
|
|
18
|
+
default=None,
|
|
19
|
+
help="Backend port (default: 8081, env: BACKEND_PORT)",
|
|
20
|
+
)
|
|
21
|
+
parser.add_argument(
|
|
22
|
+
"--docs-port",
|
|
23
|
+
type=int,
|
|
24
|
+
default=None,
|
|
25
|
+
help="Docs port (default: 8082, env: DOCS_PORT)",
|
|
26
|
+
)
|
|
27
|
+
parser.add_argument(
|
|
28
|
+
"--embedding-port",
|
|
29
|
+
type=int,
|
|
30
|
+
default=None,
|
|
31
|
+
help="Embedding service port (default: 8072, env: EMBEDDING_PORT)",
|
|
32
|
+
)
|
|
33
|
+
parser.add_argument(
|
|
34
|
+
"--only",
|
|
35
|
+
type=str,
|
|
36
|
+
default=None,
|
|
37
|
+
help="Comma-separated list of services to stop: backend,docs,embedding",
|
|
38
|
+
)
|
|
39
|
+
parser.add_argument(
|
|
40
|
+
"--force",
|
|
41
|
+
action="store_true",
|
|
42
|
+
help="SIGKILL immediately (skip graceful shutdown)",
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def build_stop_targets(
|
|
47
|
+
only: set[str],
|
|
48
|
+
ports: dict[str, int],
|
|
49
|
+
*,
|
|
50
|
+
backend_pattern: str = "uvicorn reflexio.server.api:app",
|
|
51
|
+
) -> tuple[dict[str, int], dict[str, str]]:
|
|
52
|
+
"""Build port_map and process_patterns for stopping services.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
only: Set of service names to stop
|
|
56
|
+
ports: Resolved port map
|
|
57
|
+
backend_pattern: Process pattern for the backend service
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
Tuple of (port_map, process_patterns)
|
|
61
|
+
"""
|
|
62
|
+
port_map: dict[str, int] = {}
|
|
63
|
+
process_patterns: dict[str, str] = {}
|
|
64
|
+
|
|
65
|
+
if "backend" in only:
|
|
66
|
+
port_map["backend"] = ports["backend"]
|
|
67
|
+
process_patterns["backend"] = backend_pattern
|
|
68
|
+
|
|
69
|
+
if "docs" in only:
|
|
70
|
+
port_map["docs"] = ports["docs"]
|
|
71
|
+
process_patterns["docs"] = f"next dev.*-p {ports['docs']}"
|
|
72
|
+
|
|
73
|
+
if "embedding" in only:
|
|
74
|
+
port_map["embedding"] = ports["embedding"]
|
|
75
|
+
process_patterns["embedding"] = "reflexio.server.llm.embedding_service:app"
|
|
76
|
+
|
|
77
|
+
return port_map, process_patterns
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def execute(args: argparse.Namespace) -> None:
|
|
81
|
+
"""Execute the stop-services command."""
|
|
82
|
+
load_dotenv()
|
|
83
|
+
|
|
84
|
+
ports = resolve_ports(
|
|
85
|
+
args, defaults={"backend": 8081, "docs": 8082, "embedding": 8072}
|
|
86
|
+
)
|
|
87
|
+
only = parse_only_flag(args.only, {"backend", "docs", "embedding"})
|
|
88
|
+
port_map, process_patterns = build_stop_targets(only, ports)
|
|
89
|
+
|
|
90
|
+
if not port_map:
|
|
91
|
+
print("No services selected. Available: backend, docs, embedding")
|
|
92
|
+
return
|
|
93
|
+
|
|
94
|
+
print("Stopping services...")
|
|
95
|
+
stop_services(port_map, process_patterns, force=args.force)
|
|
96
|
+
print("All services stopped.")
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
"""Shared utilities for service process management."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import contextlib
|
|
6
|
+
import dataclasses
|
|
7
|
+
import hashlib
|
|
8
|
+
import json
|
|
9
|
+
import os
|
|
10
|
+
import signal
|
|
11
|
+
import subprocess
|
|
12
|
+
import sys
|
|
13
|
+
import tempfile
|
|
14
|
+
import threading
|
|
15
|
+
import time
|
|
16
|
+
from collections.abc import Callable
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
|
|
19
|
+
from reflexio.cli.log_format import format_service_line
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclasses.dataclass
|
|
23
|
+
class ServiceConfig:
|
|
24
|
+
"""Configuration for a single service to launch."""
|
|
25
|
+
|
|
26
|
+
name: str
|
|
27
|
+
command: list[str]
|
|
28
|
+
cwd: str | None = None
|
|
29
|
+
env: dict[str, str] | None = None
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get_env_port(name: str, default: int) -> int:
|
|
33
|
+
"""Read a port from an environment variable, falling back to default."""
|
|
34
|
+
val = os.environ.get(name)
|
|
35
|
+
if val is not None:
|
|
36
|
+
try:
|
|
37
|
+
return int(val)
|
|
38
|
+
except ValueError:
|
|
39
|
+
print(f"Warning: invalid {name}={val!r}, using default {default}")
|
|
40
|
+
return default
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def find_pids_on_port(port: int) -> list[int]:
|
|
44
|
+
"""Find process IDs listening on the given port using lsof."""
|
|
45
|
+
try:
|
|
46
|
+
result = subprocess.run(
|
|
47
|
+
["lsof", "-t", f"-i:{port}"],
|
|
48
|
+
capture_output=True,
|
|
49
|
+
text=True,
|
|
50
|
+
check=False,
|
|
51
|
+
)
|
|
52
|
+
if result.returncode == 0 and result.stdout.strip():
|
|
53
|
+
return [
|
|
54
|
+
int(p) for p in result.stdout.strip().split("\n") if p.strip().isdigit()
|
|
55
|
+
]
|
|
56
|
+
except FileNotFoundError:
|
|
57
|
+
pass
|
|
58
|
+
return []
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def find_pids_by_pattern(pattern: str) -> list[int]:
|
|
62
|
+
"""Find process IDs matching a command pattern using pgrep."""
|
|
63
|
+
try:
|
|
64
|
+
result = subprocess.run(
|
|
65
|
+
["pgrep", "-f", pattern],
|
|
66
|
+
capture_output=True,
|
|
67
|
+
text=True,
|
|
68
|
+
check=False,
|
|
69
|
+
)
|
|
70
|
+
if result.returncode == 0 and result.stdout.strip():
|
|
71
|
+
return [
|
|
72
|
+
int(p) for p in result.stdout.strip().split("\n") if p.strip().isdigit()
|
|
73
|
+
]
|
|
74
|
+
except FileNotFoundError:
|
|
75
|
+
pass
|
|
76
|
+
return []
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def kill_processes(
|
|
80
|
+
pids: list[int], graceful_timeout: float = 2.0, force: bool = False
|
|
81
|
+
) -> None:
|
|
82
|
+
"""Kill processes: SIGTERM first, then SIGKILL survivors after timeout."""
|
|
83
|
+
if not pids:
|
|
84
|
+
return
|
|
85
|
+
|
|
86
|
+
unique_pids = list(set(pids))
|
|
87
|
+
my_pid = os.getpid()
|
|
88
|
+
unique_pids = [p for p in unique_pids if p != my_pid]
|
|
89
|
+
|
|
90
|
+
if not unique_pids:
|
|
91
|
+
return
|
|
92
|
+
|
|
93
|
+
sig = signal.SIGKILL if force else signal.SIGTERM
|
|
94
|
+
for pid in unique_pids:
|
|
95
|
+
try:
|
|
96
|
+
os.kill(pid, sig)
|
|
97
|
+
except ProcessLookupError:
|
|
98
|
+
pass
|
|
99
|
+
except PermissionError:
|
|
100
|
+
print(f"Warning: no permission to kill PID {pid}")
|
|
101
|
+
|
|
102
|
+
if force:
|
|
103
|
+
return
|
|
104
|
+
|
|
105
|
+
time.sleep(graceful_timeout)
|
|
106
|
+
|
|
107
|
+
for pid in unique_pids:
|
|
108
|
+
try:
|
|
109
|
+
os.kill(pid, signal.SIGKILL)
|
|
110
|
+
except ProcessLookupError:
|
|
111
|
+
pass
|
|
112
|
+
except PermissionError:
|
|
113
|
+
pass
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def get_pidfile_path(ports: dict[str, int]) -> Path:
|
|
117
|
+
"""Get a unique pidfile path based on the port combination."""
|
|
118
|
+
port_str = json.dumps(ports, sort_keys=True)
|
|
119
|
+
port_hash = hashlib.md5(port_str.encode()).hexdigest()[:8] # noqa: S324
|
|
120
|
+
return Path(tempfile.gettempdir()) / f"reflexio_services_{port_hash}.json"
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def write_pidfile(pidfile: Path, service_pids: dict[str, int]) -> None:
|
|
124
|
+
"""Write service PIDs to the pidfile."""
|
|
125
|
+
pidfile.write_text(json.dumps(service_pids, indent=2))
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def read_pidfile(pidfile: Path) -> dict[str, int]:
|
|
129
|
+
"""Read service PIDs from the pidfile. Returns empty dict if not found."""
|
|
130
|
+
if not pidfile.exists():
|
|
131
|
+
return {}
|
|
132
|
+
try:
|
|
133
|
+
return json.loads(pidfile.read_text())
|
|
134
|
+
except (json.JSONDecodeError, OSError): # fmt: skip
|
|
135
|
+
return {}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def remove_pidfile(pidfile: Path) -> None:
|
|
139
|
+
"""Remove the pidfile if it exists."""
|
|
140
|
+
with contextlib.suppress(OSError):
|
|
141
|
+
pidfile.unlink(missing_ok=True)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
# Patterns that indicate a service is ready to accept requests
|
|
145
|
+
_READY_PATTERNS: dict[str, list[str]] = {
|
|
146
|
+
"backend": ["Application startup complete"],
|
|
147
|
+
"embedding": ["Application startup complete"],
|
|
148
|
+
"frontend": ["Ready in"],
|
|
149
|
+
"docs": ["Ready in"],
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
# Extra env vars to suppress noise from subprocesses at source
|
|
153
|
+
_NOISE_SUPPRESSION_ENV: dict[str, dict[str, str]] = {
|
|
154
|
+
"backend": {"LITELLM_LOG": "ERROR"},
|
|
155
|
+
"embedding": {"LITELLM_LOG": "ERROR"},
|
|
156
|
+
"frontend": {"NODE_NO_WARNINGS": "1"},
|
|
157
|
+
"docs": {"NODE_NO_WARNINGS": "1"},
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _stream_output(
|
|
162
|
+
proc: subprocess.Popen[bytes],
|
|
163
|
+
service_name: str,
|
|
164
|
+
lock: threading.Lock,
|
|
165
|
+
ready_event: threading.Event,
|
|
166
|
+
) -> None:
|
|
167
|
+
"""Read subprocess stdout line by line, prefix, and write to stdout.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
proc: The subprocess to read from.
|
|
171
|
+
service_name: Name of the service for prefixing.
|
|
172
|
+
lock: Lock to prevent interleaved partial lines.
|
|
173
|
+
ready_event: Event to set when the service is ready.
|
|
174
|
+
"""
|
|
175
|
+
ready_patterns = _READY_PATTERNS.get(service_name, [])
|
|
176
|
+
assert proc.stdout is not None # noqa: S101
|
|
177
|
+
for raw_line in proc.stdout:
|
|
178
|
+
line = raw_line.decode("utf-8", errors="replace").rstrip()
|
|
179
|
+
if not line:
|
|
180
|
+
continue
|
|
181
|
+
formatted = format_service_line(service_name, line)
|
|
182
|
+
with lock:
|
|
183
|
+
sys.stdout.write(formatted + "\n")
|
|
184
|
+
sys.stdout.flush()
|
|
185
|
+
# Check for ready patterns
|
|
186
|
+
if not ready_event.is_set() and any(p in line for p in ready_patterns):
|
|
187
|
+
ready_event.set()
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def run_services(
|
|
191
|
+
services: list[ServiceConfig],
|
|
192
|
+
ports: dict[str, int],
|
|
193
|
+
*,
|
|
194
|
+
on_all_ready: Callable[[dict[str, int]], None] | None = None,
|
|
195
|
+
) -> None:
|
|
196
|
+
"""Launch services, pipe output with prefixes, and manage lifecycle.
|
|
197
|
+
|
|
198
|
+
Each service's stdout/stderr is captured and prefixed with a colored
|
|
199
|
+
service tag (e.g., [backend]). A callback is invoked when all services
|
|
200
|
+
report ready (or after a timeout).
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
services: List of service configurations to launch.
|
|
204
|
+
ports: Port mapping for pidfile identification.
|
|
205
|
+
on_all_ready: Optional callback invoked with ports when all services are ready.
|
|
206
|
+
"""
|
|
207
|
+
processes: dict[str, subprocess.Popen[bytes]] = {}
|
|
208
|
+
threads: list[threading.Thread] = []
|
|
209
|
+
ready_events: dict[str, threading.Event] = {}
|
|
210
|
+
output_lock = threading.RLock()
|
|
211
|
+
pidfile = get_pidfile_path(ports)
|
|
212
|
+
|
|
213
|
+
def shutdown(_signum: int | None = None, _frame: object = None) -> None:
|
|
214
|
+
with output_lock:
|
|
215
|
+
sys.stdout.write("\nShutting down services...\n")
|
|
216
|
+
sys.stdout.flush()
|
|
217
|
+
for proc in processes.values():
|
|
218
|
+
with contextlib.suppress(OSError):
|
|
219
|
+
proc.terminate()
|
|
220
|
+
deadline = time.time() + 3.0
|
|
221
|
+
for proc in processes.values():
|
|
222
|
+
remaining = max(0, deadline - time.time())
|
|
223
|
+
try:
|
|
224
|
+
proc.wait(timeout=remaining)
|
|
225
|
+
except subprocess.TimeoutExpired:
|
|
226
|
+
with contextlib.suppress(OSError):
|
|
227
|
+
proc.kill()
|
|
228
|
+
for t in threads:
|
|
229
|
+
t.join(timeout=1.0)
|
|
230
|
+
remove_pidfile(pidfile)
|
|
231
|
+
sys.exit(0)
|
|
232
|
+
|
|
233
|
+
signal.signal(signal.SIGINT, shutdown)
|
|
234
|
+
signal.signal(signal.SIGTERM, shutdown)
|
|
235
|
+
|
|
236
|
+
for svc in services:
|
|
237
|
+
noise_env = _NOISE_SUPPRESSION_ENV.get(svc.name, {})
|
|
238
|
+
merged_env = {**os.environ, **(svc.env or {}), **noise_env}
|
|
239
|
+
with output_lock:
|
|
240
|
+
sys.stdout.write(f"Starting {svc.name}...\n")
|
|
241
|
+
sys.stdout.flush()
|
|
242
|
+
proc = subprocess.Popen(
|
|
243
|
+
svc.command,
|
|
244
|
+
cwd=svc.cwd,
|
|
245
|
+
env=merged_env,
|
|
246
|
+
stdout=subprocess.PIPE,
|
|
247
|
+
stderr=subprocess.STDOUT,
|
|
248
|
+
)
|
|
249
|
+
processes[svc.name] = proc
|
|
250
|
+
ready_event = threading.Event()
|
|
251
|
+
ready_events[svc.name] = ready_event
|
|
252
|
+
t = threading.Thread(
|
|
253
|
+
target=_stream_output,
|
|
254
|
+
args=(proc, svc.name, output_lock, ready_event),
|
|
255
|
+
daemon=True,
|
|
256
|
+
)
|
|
257
|
+
t.start()
|
|
258
|
+
threads.append(t)
|
|
259
|
+
with output_lock:
|
|
260
|
+
sys.stdout.write(f" {svc.name} started (PID {proc.pid})\n")
|
|
261
|
+
sys.stdout.flush()
|
|
262
|
+
|
|
263
|
+
# Write pidfile
|
|
264
|
+
pids = {name: proc.pid for name, proc in processes.items()}
|
|
265
|
+
write_pidfile(pidfile, pids)
|
|
266
|
+
|
|
267
|
+
# Wait for all services to be ready (or timeout with shared deadline)
|
|
268
|
+
if on_all_ready:
|
|
269
|
+
deadline = time.monotonic() + 60
|
|
270
|
+
all_ready = all(
|
|
271
|
+
evt.wait(timeout=max(0, deadline - time.monotonic()))
|
|
272
|
+
for evt in ready_events.values()
|
|
273
|
+
)
|
|
274
|
+
if all_ready:
|
|
275
|
+
on_all_ready(ports)
|
|
276
|
+
|
|
277
|
+
# Wait for any child to exit
|
|
278
|
+
try:
|
|
279
|
+
while processes:
|
|
280
|
+
for name, proc in list(processes.items()):
|
|
281
|
+
ret = proc.poll()
|
|
282
|
+
if ret is not None:
|
|
283
|
+
with output_lock:
|
|
284
|
+
sys.stdout.write(
|
|
285
|
+
format_service_line(name, f"exited with code {ret}") + "\n"
|
|
286
|
+
)
|
|
287
|
+
sys.stdout.flush()
|
|
288
|
+
del processes[name]
|
|
289
|
+
if processes:
|
|
290
|
+
time.sleep(0.5)
|
|
291
|
+
except KeyboardInterrupt:
|
|
292
|
+
shutdown()
|
|
293
|
+
|
|
294
|
+
remove_pidfile(pidfile)
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
def stop_services(
|
|
298
|
+
port_map: dict[str, int],
|
|
299
|
+
process_patterns: dict[str, str],
|
|
300
|
+
force: bool = False,
|
|
301
|
+
) -> None:
|
|
302
|
+
"""Stop services by port and process pattern.
|
|
303
|
+
|
|
304
|
+
Args:
|
|
305
|
+
port_map: Mapping of service name to port number.
|
|
306
|
+
process_patterns: Mapping of service name to pgrep pattern.
|
|
307
|
+
force: If True, send SIGKILL immediately instead of graceful shutdown.
|
|
308
|
+
"""
|
|
309
|
+
pidfile = get_pidfile_path(port_map)
|
|
310
|
+
saved_pids = read_pidfile(pidfile)
|
|
311
|
+
|
|
312
|
+
for name, port in port_map.items():
|
|
313
|
+
pids_from_port = find_pids_on_port(port)
|
|
314
|
+
pids_from_pattern = (
|
|
315
|
+
find_pids_by_pattern(process_patterns[name])
|
|
316
|
+
if name in process_patterns
|
|
317
|
+
else []
|
|
318
|
+
)
|
|
319
|
+
pids_from_saved = [saved_pids[name]] if name in saved_pids else []
|
|
320
|
+
|
|
321
|
+
all_pids = list(set(pids_from_port + pids_from_pattern + pids_from_saved))
|
|
322
|
+
|
|
323
|
+
if all_pids:
|
|
324
|
+
kill_processes(all_pids, force=force)
|
|
325
|
+
print(f"Stopped {name} (port {port})")
|
|
326
|
+
else:
|
|
327
|
+
print(f"{name} (port {port}) not running")
|
|
328
|
+
|
|
329
|
+
remove_pidfile(pidfile)
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"""In-memory cache module for Reflexio client."""
|
|
2
|
+
|
|
3
|
+
import hashlib
|
|
4
|
+
import json
|
|
5
|
+
import threading
|
|
6
|
+
from datetime import datetime, timedelta
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class InMemoryCache:
|
|
11
|
+
"""
|
|
12
|
+
Thread-safe in-memory cache with time-based expiration.
|
|
13
|
+
|
|
14
|
+
Stores function results in memory to avoid redundant API calls.
|
|
15
|
+
Cache entries expire after a specified TTL (default: 10 minutes).
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, ttl_seconds: int = 600):
|
|
19
|
+
"""
|
|
20
|
+
Initialize the in-memory cache.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
ttl_seconds (int): Time-to-live for cache entries in seconds. Default is 600 (10 minutes).
|
|
24
|
+
"""
|
|
25
|
+
self._cache: dict[str, dict[str, Any]] = {}
|
|
26
|
+
self._lock = threading.Lock()
|
|
27
|
+
self._ttl_seconds = ttl_seconds
|
|
28
|
+
|
|
29
|
+
def _generate_cache_key(self, method_name: str, **kwargs) -> str:
|
|
30
|
+
"""
|
|
31
|
+
Generate a unique cache key from method name and parameters.
|
|
32
|
+
|
|
33
|
+
Handles datetime objects, None values, and nested dictionaries.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
method_name (str): Name of the cached method
|
|
37
|
+
**kwargs: Method parameters to include in the cache key
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
str: Unique cache key hash
|
|
41
|
+
"""
|
|
42
|
+
# Create a normalized representation of the parameters
|
|
43
|
+
normalized_params = {}
|
|
44
|
+
for key, value in sorted(kwargs.items()):
|
|
45
|
+
if isinstance(value, datetime):
|
|
46
|
+
# Convert datetime to ISO format string
|
|
47
|
+
normalized_params[key] = value.isoformat()
|
|
48
|
+
elif value is None:
|
|
49
|
+
normalized_params[key] = None
|
|
50
|
+
elif hasattr(value, "model_dump"):
|
|
51
|
+
# Handle Pydantic models
|
|
52
|
+
normalized_params[key] = value.model_dump()
|
|
53
|
+
elif isinstance(value, dict):
|
|
54
|
+
normalized_params[key] = value
|
|
55
|
+
else:
|
|
56
|
+
normalized_params[key] = value
|
|
57
|
+
|
|
58
|
+
# Create a stable JSON representation
|
|
59
|
+
key_data = {"method": method_name, "params": normalized_params}
|
|
60
|
+
key_string = json.dumps(key_data, sort_keys=True, default=str)
|
|
61
|
+
|
|
62
|
+
# Generate hash for the cache key
|
|
63
|
+
return hashlib.sha256(key_string.encode()).hexdigest()
|
|
64
|
+
|
|
65
|
+
def get(self, method_name: str, **kwargs) -> Any | None:
|
|
66
|
+
"""
|
|
67
|
+
Retrieve a cached value if it exists and is not expired.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
method_name (str): Name of the cached method
|
|
71
|
+
**kwargs: Method parameters used to generate cache key
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
Optional[Any]: Cached value if found and valid, None otherwise
|
|
75
|
+
"""
|
|
76
|
+
cache_key = self._generate_cache_key(method_name, **kwargs)
|
|
77
|
+
|
|
78
|
+
with self._lock:
|
|
79
|
+
if cache_key not in self._cache:
|
|
80
|
+
return None
|
|
81
|
+
|
|
82
|
+
entry = self._cache[cache_key]
|
|
83
|
+
|
|
84
|
+
# Check if entry has expired
|
|
85
|
+
if datetime.now() > entry["expires_at"]:
|
|
86
|
+
# Remove expired entry
|
|
87
|
+
del self._cache[cache_key]
|
|
88
|
+
return None
|
|
89
|
+
|
|
90
|
+
return entry["data"]
|
|
91
|
+
|
|
92
|
+
def set(self, method_name: str, value: Any, **kwargs) -> None:
|
|
93
|
+
"""
|
|
94
|
+
Store a value in the cache with automatic expiration.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
method_name (str): Name of the cached method
|
|
98
|
+
value (Any): Value to cache
|
|
99
|
+
**kwargs: Method parameters used to generate cache key
|
|
100
|
+
"""
|
|
101
|
+
cache_key = self._generate_cache_key(method_name, **kwargs)
|
|
102
|
+
|
|
103
|
+
with self._lock:
|
|
104
|
+
self._cache[cache_key] = {
|
|
105
|
+
"data": value,
|
|
106
|
+
"method_name": method_name,
|
|
107
|
+
"timestamp": datetime.now(),
|
|
108
|
+
"expires_at": datetime.now() + timedelta(seconds=self._ttl_seconds),
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
# Cleanup expired entries periodically (every 100 sets)
|
|
112
|
+
if len(self._cache) % 100 == 0:
|
|
113
|
+
self._cleanup_expired()
|
|
114
|
+
|
|
115
|
+
def clear(self) -> None:
|
|
116
|
+
"""Remove all entries from the cache."""
|
|
117
|
+
with self._lock:
|
|
118
|
+
self._cache.clear()
|
|
119
|
+
|
|
120
|
+
def invalidate(self, method_name: str) -> int:
|
|
121
|
+
"""Remove all entries cached under a given method name.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
method_name: The method name whose entries should be removed.
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
int: Number of entries removed.
|
|
128
|
+
"""
|
|
129
|
+
with self._lock:
|
|
130
|
+
keys_to_remove = [
|
|
131
|
+
key
|
|
132
|
+
for key, entry in self._cache.items()
|
|
133
|
+
if entry.get("method_name") == method_name
|
|
134
|
+
]
|
|
135
|
+
for key in keys_to_remove:
|
|
136
|
+
del self._cache[key]
|
|
137
|
+
return len(keys_to_remove)
|
|
138
|
+
|
|
139
|
+
def _cleanup_expired(self) -> None:
|
|
140
|
+
"""
|
|
141
|
+
Remove all expired entries from the cache.
|
|
142
|
+
|
|
143
|
+
Note: This method assumes the lock is already acquired by the caller.
|
|
144
|
+
"""
|
|
145
|
+
now = datetime.now()
|
|
146
|
+
expired_keys = [
|
|
147
|
+
key for key, entry in self._cache.items() if now > entry["expires_at"]
|
|
148
|
+
]
|
|
149
|
+
for key in expired_keys:
|
|
150
|
+
del self._cache[key]
|