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,373 @@
|
|
|
1
|
+
"""User playbook management commands (list, search, add, delete, regenerate)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Annotated
|
|
6
|
+
|
|
7
|
+
import typer
|
|
8
|
+
|
|
9
|
+
from reflexio.cli.errors import (
|
|
10
|
+
EXIT_VALIDATION,
|
|
11
|
+
CliError,
|
|
12
|
+
handle_errors,
|
|
13
|
+
raise_if_failed,
|
|
14
|
+
)
|
|
15
|
+
from reflexio.cli.output import (
|
|
16
|
+
pagination_meta,
|
|
17
|
+
print_info,
|
|
18
|
+
print_user_playbooks,
|
|
19
|
+
render,
|
|
20
|
+
)
|
|
21
|
+
from reflexio.cli.state import get_client, require_agent_version
|
|
22
|
+
|
|
23
|
+
app = typer.Typer(help="Manage user playbooks.")
|
|
24
|
+
|
|
25
|
+
_STATUS_MAP = {
|
|
26
|
+
"current": "current",
|
|
27
|
+
"pending": "pending",
|
|
28
|
+
"archived": "archived",
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@app.command(name="list")
|
|
33
|
+
@handle_errors
|
|
34
|
+
def list_user_playbooks(
|
|
35
|
+
ctx: typer.Context,
|
|
36
|
+
user_id: Annotated[
|
|
37
|
+
str | None,
|
|
38
|
+
typer.Option("--user-id", help="Filter by user ID"),
|
|
39
|
+
] = None,
|
|
40
|
+
limit: Annotated[
|
|
41
|
+
int,
|
|
42
|
+
typer.Option("--limit", help="Maximum number of playbooks to return"),
|
|
43
|
+
] = 20,
|
|
44
|
+
playbook_name: Annotated[
|
|
45
|
+
str | None,
|
|
46
|
+
typer.Option("--playbook-name", help="Filter by playbook name"),
|
|
47
|
+
] = None,
|
|
48
|
+
agent_version: Annotated[
|
|
49
|
+
str | None,
|
|
50
|
+
typer.Option("--agent-version", help="Filter by agent version"),
|
|
51
|
+
] = None,
|
|
52
|
+
status: Annotated[
|
|
53
|
+
str | None,
|
|
54
|
+
typer.Option("--status", help="Status filter (current/pending/archived)"),
|
|
55
|
+
] = None,
|
|
56
|
+
) -> None:
|
|
57
|
+
"""List user playbooks.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
ctx: Typer context with CliState in ctx.obj
|
|
61
|
+
user_id: Optional user ID filter
|
|
62
|
+
limit: Maximum number of playbooks to return
|
|
63
|
+
playbook_name: Optional playbook name filter
|
|
64
|
+
agent_version: Optional agent version filter
|
|
65
|
+
status: Optional status filter (current, pending, archived)
|
|
66
|
+
"""
|
|
67
|
+
from reflexio.models.api_schema.service_schemas import Status
|
|
68
|
+
|
|
69
|
+
if status and status not in _STATUS_MAP:
|
|
70
|
+
raise CliError(
|
|
71
|
+
error_type="validation",
|
|
72
|
+
message=f"Invalid status: {status}. Must be current, pending, or archived.",
|
|
73
|
+
exit_code=EXIT_VALIDATION,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
status_filter: list[Status | None] | None = None
|
|
77
|
+
if status == "current":
|
|
78
|
+
status_filter = [Status.CURRENT]
|
|
79
|
+
elif status == "pending":
|
|
80
|
+
status_filter = [Status.PENDING]
|
|
81
|
+
elif status == "archived":
|
|
82
|
+
status_filter = [Status.ARCHIVED]
|
|
83
|
+
|
|
84
|
+
client = get_client(ctx)
|
|
85
|
+
resp = client.get_user_playbooks(
|
|
86
|
+
limit=limit,
|
|
87
|
+
user_id=user_id,
|
|
88
|
+
playbook_name=playbook_name,
|
|
89
|
+
agent_version=agent_version,
|
|
90
|
+
status_filter=status_filter,
|
|
91
|
+
)
|
|
92
|
+
playbooks = resp.user_playbooks or []
|
|
93
|
+
|
|
94
|
+
json_mode: bool = ctx.obj.json_mode
|
|
95
|
+
if json_mode:
|
|
96
|
+
render(playbooks, json_mode=True, meta=pagination_meta(playbooks, limit))
|
|
97
|
+
else:
|
|
98
|
+
print_info(f"Found {len(playbooks)} user playbook(s)")
|
|
99
|
+
if playbooks:
|
|
100
|
+
print_user_playbooks(playbooks)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@app.command()
|
|
104
|
+
@handle_errors
|
|
105
|
+
def search(
|
|
106
|
+
ctx: typer.Context,
|
|
107
|
+
query: Annotated[
|
|
108
|
+
str,
|
|
109
|
+
typer.Argument(help="Semantic search query for user playbooks"),
|
|
110
|
+
],
|
|
111
|
+
limit: Annotated[
|
|
112
|
+
int,
|
|
113
|
+
typer.Option("--limit", help="Maximum number of results"),
|
|
114
|
+
] = 10,
|
|
115
|
+
agent_version: Annotated[
|
|
116
|
+
str | None,
|
|
117
|
+
typer.Option("--agent-version", help="Agent version to filter by"),
|
|
118
|
+
] = None,
|
|
119
|
+
) -> None:
|
|
120
|
+
"""Search user playbooks by semantic query.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
ctx: Typer context with CliState in ctx.obj
|
|
124
|
+
query: Search query string
|
|
125
|
+
limit: Maximum number of results
|
|
126
|
+
agent_version: Optional agent version filter
|
|
127
|
+
"""
|
|
128
|
+
client = get_client(ctx)
|
|
129
|
+
|
|
130
|
+
resp = client.search_user_playbooks(
|
|
131
|
+
query=query,
|
|
132
|
+
agent_version=agent_version,
|
|
133
|
+
top_k=limit,
|
|
134
|
+
)
|
|
135
|
+
playbooks = resp.user_playbooks or []
|
|
136
|
+
|
|
137
|
+
json_mode: bool = ctx.obj.json_mode
|
|
138
|
+
if json_mode:
|
|
139
|
+
render(playbooks, json_mode=True, meta=pagination_meta(playbooks, limit))
|
|
140
|
+
else:
|
|
141
|
+
print_info(f"Found {len(playbooks)} user playbook(s)")
|
|
142
|
+
if playbooks:
|
|
143
|
+
print_user_playbooks(playbooks)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
@app.command()
|
|
147
|
+
@handle_errors
|
|
148
|
+
def add(
|
|
149
|
+
ctx: typer.Context,
|
|
150
|
+
content: Annotated[
|
|
151
|
+
str,
|
|
152
|
+
typer.Option("--content", help="Playbook content text"),
|
|
153
|
+
],
|
|
154
|
+
playbook_name: Annotated[
|
|
155
|
+
str,
|
|
156
|
+
typer.Option("--playbook-name", help="Playbook category name"),
|
|
157
|
+
] = "agent_corrections",
|
|
158
|
+
trigger: Annotated[
|
|
159
|
+
str | None,
|
|
160
|
+
typer.Option("--trigger", help="When this playbook applies"),
|
|
161
|
+
] = None,
|
|
162
|
+
rationale: Annotated[
|
|
163
|
+
str | None,
|
|
164
|
+
typer.Option("--rationale", help="Why this playbook matters"),
|
|
165
|
+
] = None,
|
|
166
|
+
agent_version: Annotated[
|
|
167
|
+
str | None,
|
|
168
|
+
typer.Option(
|
|
169
|
+
"--agent-version",
|
|
170
|
+
help="Agent version to tag this playbook with (defaults to 'cli')",
|
|
171
|
+
),
|
|
172
|
+
] = None,
|
|
173
|
+
) -> None:
|
|
174
|
+
"""Add a manual user playbook entry.
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
ctx: Typer context with CliState in ctx.obj
|
|
178
|
+
content: Playbook content text
|
|
179
|
+
playbook_name: Playbook category name
|
|
180
|
+
trigger: When this playbook applies
|
|
181
|
+
rationale: Why this playbook matters
|
|
182
|
+
agent_version: Agent version label to scope the playbook to;
|
|
183
|
+
defaults to "cli" so CLI-authored entries stay isolated from
|
|
184
|
+
integration-authored ones (e.g. ``openclaw-agent``).
|
|
185
|
+
"""
|
|
186
|
+
from reflexio.models.api_schema.service_schemas import UserPlaybook
|
|
187
|
+
|
|
188
|
+
playbook = UserPlaybook(
|
|
189
|
+
agent_version=agent_version or "cli",
|
|
190
|
+
request_id="cli-manual",
|
|
191
|
+
playbook_name=playbook_name,
|
|
192
|
+
content=content,
|
|
193
|
+
trigger=trigger,
|
|
194
|
+
rationale=rationale,
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
client = get_client(ctx)
|
|
198
|
+
resp = client.add_user_playbook([playbook])
|
|
199
|
+
|
|
200
|
+
json_mode: bool = ctx.obj.json_mode
|
|
201
|
+
if json_mode:
|
|
202
|
+
render(resp, json_mode=True)
|
|
203
|
+
else:
|
|
204
|
+
raise_if_failed(resp, default="Failed to add user playbook")
|
|
205
|
+
print_info(f"User playbook added: {content[:80]}")
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
@app.command()
|
|
209
|
+
@handle_errors
|
|
210
|
+
def update(
|
|
211
|
+
ctx: typer.Context,
|
|
212
|
+
playbook_id: Annotated[
|
|
213
|
+
int,
|
|
214
|
+
typer.Option("--playbook-id", help="User playbook ID to update"),
|
|
215
|
+
],
|
|
216
|
+
content: Annotated[
|
|
217
|
+
str | None,
|
|
218
|
+
typer.Option("--content", help="New content text"),
|
|
219
|
+
] = None,
|
|
220
|
+
playbook_name: Annotated[
|
|
221
|
+
str | None,
|
|
222
|
+
typer.Option("--playbook-name", help="New playbook category name"),
|
|
223
|
+
] = None,
|
|
224
|
+
) -> None:
|
|
225
|
+
"""Update editable fields of a user playbook.
|
|
226
|
+
|
|
227
|
+
Pass only the fields you want to change. Currently supports
|
|
228
|
+
``--content`` and ``--playbook-name``.
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
ctx: Typer context with CliState in ctx.obj
|
|
232
|
+
playbook_id: User playbook ID to update
|
|
233
|
+
content: New content text
|
|
234
|
+
playbook_name: New playbook category name
|
|
235
|
+
"""
|
|
236
|
+
if content is None and playbook_name is None:
|
|
237
|
+
raise CliError(
|
|
238
|
+
error_type="validation",
|
|
239
|
+
message=("Pass at least one of --content/--playbook-name to update."),
|
|
240
|
+
exit_code=EXIT_VALIDATION,
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
client = get_client(ctx)
|
|
244
|
+
resp = client.update_user_playbook(
|
|
245
|
+
user_playbook_id=playbook_id,
|
|
246
|
+
content=content,
|
|
247
|
+
playbook_name=playbook_name,
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
json_mode: bool = ctx.obj.json_mode
|
|
251
|
+
if json_mode:
|
|
252
|
+
render(resp, json_mode=True)
|
|
253
|
+
else:
|
|
254
|
+
raise_if_failed(resp, default="Failed to update user playbook")
|
|
255
|
+
print_info(f"User playbook {playbook_id} updated")
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
@app.command()
|
|
259
|
+
@handle_errors
|
|
260
|
+
def delete(
|
|
261
|
+
ctx: typer.Context,
|
|
262
|
+
playbook_id: Annotated[
|
|
263
|
+
str,
|
|
264
|
+
typer.Option("--playbook-id", help="User playbook ID"),
|
|
265
|
+
],
|
|
266
|
+
) -> None:
|
|
267
|
+
"""Delete a user playbook by ID.
|
|
268
|
+
|
|
269
|
+
Args:
|
|
270
|
+
ctx: Typer context with CliState in ctx.obj
|
|
271
|
+
playbook_id: User playbook ID to delete
|
|
272
|
+
"""
|
|
273
|
+
client = get_client(ctx)
|
|
274
|
+
resp = client.delete_user_playbook(
|
|
275
|
+
user_playbook_id=int(playbook_id),
|
|
276
|
+
wait_for_response=True,
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
json_mode: bool = ctx.obj.json_mode
|
|
280
|
+
if json_mode:
|
|
281
|
+
render(resp, json_mode=True)
|
|
282
|
+
else:
|
|
283
|
+
print_info(f"Deleted user playbook {playbook_id}")
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
@app.command(name="delete-all")
|
|
287
|
+
@handle_errors
|
|
288
|
+
def delete_all(
|
|
289
|
+
ctx: typer.Context,
|
|
290
|
+
yes: Annotated[
|
|
291
|
+
bool,
|
|
292
|
+
typer.Option("--yes", "-y", help="Skip confirmation prompt"),
|
|
293
|
+
] = False,
|
|
294
|
+
) -> None:
|
|
295
|
+
"""Delete all user playbooks (user only, not agent playbooks).
|
|
296
|
+
|
|
297
|
+
Uses the dedicated ``DELETE /api/delete_all_user_playbooks`` endpoint,
|
|
298
|
+
which is scoped strictly to user playbooks. To also wipe agent
|
|
299
|
+
playbooks, run ``reflexio agent-playbooks delete-all`` separately.
|
|
300
|
+
|
|
301
|
+
Args:
|
|
302
|
+
ctx: Typer context with CliState in ctx.obj
|
|
303
|
+
yes: If True, skip confirmation prompt
|
|
304
|
+
"""
|
|
305
|
+
if not yes:
|
|
306
|
+
confirmed = typer.confirm("Are you sure you want to delete all user playbooks?")
|
|
307
|
+
if not confirmed:
|
|
308
|
+
raise typer.Abort()
|
|
309
|
+
|
|
310
|
+
client = get_client(ctx)
|
|
311
|
+
resp = client.delete_all_user_playbooks()
|
|
312
|
+
|
|
313
|
+
json_mode: bool = ctx.obj.json_mode
|
|
314
|
+
if json_mode:
|
|
315
|
+
render(resp, json_mode=True)
|
|
316
|
+
else:
|
|
317
|
+
print_info("All user playbooks deleted")
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
@app.command()
|
|
321
|
+
@handle_errors
|
|
322
|
+
def regenerate(
|
|
323
|
+
ctx: typer.Context,
|
|
324
|
+
wait: Annotated[
|
|
325
|
+
bool,
|
|
326
|
+
typer.Option("--wait", help="Wait for regeneration to complete"),
|
|
327
|
+
] = False,
|
|
328
|
+
agent_version: Annotated[
|
|
329
|
+
str | None,
|
|
330
|
+
typer.Option(
|
|
331
|
+
"--agent-version", help="Agent version to regenerate playbooks for"
|
|
332
|
+
),
|
|
333
|
+
] = None,
|
|
334
|
+
) -> None:
|
|
335
|
+
"""Re-extract user playbooks from published interactions.
|
|
336
|
+
|
|
337
|
+
Re-runs the playbook extraction pipeline over all interactions for the
|
|
338
|
+
given agent version, producing fresh user playbooks.
|
|
339
|
+
|
|
340
|
+
Args:
|
|
341
|
+
ctx: Typer context with CliState in ctx.obj
|
|
342
|
+
wait: If True, wait for regeneration to complete
|
|
343
|
+
agent_version: Agent version to regenerate (required)
|
|
344
|
+
"""
|
|
345
|
+
client = get_client(ctx)
|
|
346
|
+
resolved_version = require_agent_version(
|
|
347
|
+
agent_version, command_hint="user-playbook regeneration"
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
resp = client.rerun_playbook_generation(
|
|
351
|
+
agent_version=resolved_version,
|
|
352
|
+
wait_for_response=wait,
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
# When waiting, auto-promote PENDING user playbooks to CURRENT so
|
|
356
|
+
# they're immediately visible in `list` output.
|
|
357
|
+
promoted = 0
|
|
358
|
+
if wait:
|
|
359
|
+
try:
|
|
360
|
+
upgrade_resp = client.upgrade_user_playbooks(
|
|
361
|
+
agent_version=resolved_version,
|
|
362
|
+
)
|
|
363
|
+
promoted = upgrade_resp.user_playbooks_promoted
|
|
364
|
+
except Exception:
|
|
365
|
+
print_info("Warning: promotion failed, but regeneration succeeded")
|
|
366
|
+
|
|
367
|
+
json_mode: bool = ctx.obj.json_mode
|
|
368
|
+
if json_mode:
|
|
369
|
+
render(resp, json_mode=True)
|
|
370
|
+
elif wait:
|
|
371
|
+
print_info(f"Playbook regeneration complete ({promoted} playbook(s) promoted)")
|
|
372
|
+
else:
|
|
373
|
+
print_info("Playbook regeneration started")
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
"""Shared .env discovery, loading, and mutation utility.
|
|
2
|
+
|
|
3
|
+
Searches for .env in multiple locations. On first run, auto-creates
|
|
4
|
+
~/.reflexio/.env from the bundled .env.example template.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import importlib.resources
|
|
10
|
+
import logging
|
|
11
|
+
import re
|
|
12
|
+
import secrets
|
|
13
|
+
import sys
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
_logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
from dotenv import load_dotenv
|
|
19
|
+
|
|
20
|
+
from .paths import reflexio_home
|
|
21
|
+
|
|
22
|
+
_USER_ENV_DIR = reflexio_home()
|
|
23
|
+
_USER_ENV_FILE = _USER_ENV_DIR / ".env"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# Path to the .env file that load_reflexio_env last resolved — None until
|
|
27
|
+
# load_reflexio_env runs for the first time. Exposed via get_loaded_env_path
|
|
28
|
+
# so the startup banner can show the operator exactly which dotenv was
|
|
29
|
+
# picked (./.env vs ~/.reflexio/.env vs auto-created).
|
|
30
|
+
_loaded_env_path: Path | None = None
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def get_env_path() -> Path:
|
|
34
|
+
"""Return the canonical path to the user-level .env file.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
Path: ``~/.reflexio/.env``
|
|
38
|
+
"""
|
|
39
|
+
return _USER_ENV_FILE
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def get_loaded_env_path() -> Path | None:
|
|
43
|
+
"""Return the .env path that the most recent ``load_reflexio_env`` call
|
|
44
|
+
resolved, or None if the loader hasn't run yet.
|
|
45
|
+
|
|
46
|
+
Used by the startup banner so operators can see at a glance which
|
|
47
|
+
dotenv file was actually consumed (``./.env`` wins over
|
|
48
|
+
``~/.reflexio/.env`` when both exist).
|
|
49
|
+
"""
|
|
50
|
+
return _loaded_env_path
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def set_env_var(env_path: Path, key: str, value: str) -> None:
|
|
54
|
+
"""Write or update an environment variable in a .env file.
|
|
55
|
+
|
|
56
|
+
If the key already exists (active or commented-out), the line is replaced
|
|
57
|
+
in-place. Active (uncommented) lines are prioritized over commented ones.
|
|
58
|
+
Values are always wrapped in double quotes for safe parsing.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
env_path (Path): Path to the .env file.
|
|
62
|
+
key (str): Environment variable name.
|
|
63
|
+
value (str): Environment variable value.
|
|
64
|
+
"""
|
|
65
|
+
content = env_path.read_text() if env_path.exists() else ""
|
|
66
|
+
lines = content.splitlines()
|
|
67
|
+
pattern = re.compile(rf"^#?\s*{re.escape(key)}=")
|
|
68
|
+
active_idx: int | None = None
|
|
69
|
+
commented_idx: int | None = None
|
|
70
|
+
for i, line in enumerate(lines):
|
|
71
|
+
if not pattern.match(line):
|
|
72
|
+
continue
|
|
73
|
+
if line.lstrip().startswith("#"):
|
|
74
|
+
if commented_idx is None:
|
|
75
|
+
commented_idx = i
|
|
76
|
+
else:
|
|
77
|
+
active_idx = i
|
|
78
|
+
break
|
|
79
|
+
escaped = value.replace("\\", "\\\\").replace('"', '\\"')
|
|
80
|
+
replacement = f'{key}="{escaped}"'
|
|
81
|
+
target = active_idx if active_idx is not None else commented_idx
|
|
82
|
+
if target is not None:
|
|
83
|
+
lines[target] = replacement
|
|
84
|
+
else:
|
|
85
|
+
lines.append(replacement)
|
|
86
|
+
env_path.write_text("\n".join(lines) + "\n")
|
|
87
|
+
env_path.chmod(0o600)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
_ENV_SEARCH_PATHS = [
|
|
91
|
+
Path(".env"), # 1. Current directory (local dev / project-level)
|
|
92
|
+
_USER_ENV_FILE, # 2. User home default (~/.reflexio/.env)
|
|
93
|
+
]
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def load_reflexio_env(
|
|
97
|
+
*,
|
|
98
|
+
package_data_module: str = "reflexio.data",
|
|
99
|
+
auto_generate_keys: list[str] | None = None,
|
|
100
|
+
) -> Path | None:
|
|
101
|
+
"""Load .env from the first location found, or auto-create on first run.
|
|
102
|
+
|
|
103
|
+
Search order:
|
|
104
|
+
1. ./.env (current directory)
|
|
105
|
+
2. ~/.reflexio/.env (user home)
|
|
106
|
+
3. Auto-create from bundled .env.example template
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
package_data_module: Module containing bundled .env.example
|
|
110
|
+
(for importlib.resources). The OS package passes "reflexio.data";
|
|
111
|
+
a downstream build may pass its own data module.
|
|
112
|
+
auto_generate_keys: Env var names to auto-generate as hex tokens
|
|
113
|
+
(e.g., ["JWT_SECRET_KEY"]).
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
Path to the loaded .env file, or None if no .env was found/created.
|
|
117
|
+
"""
|
|
118
|
+
global _loaded_env_path
|
|
119
|
+
for env_path in _ENV_SEARCH_PATHS:
|
|
120
|
+
if env_path.exists():
|
|
121
|
+
load_dotenv(dotenv_path=env_path)
|
|
122
|
+
resolved = env_path.resolve()
|
|
123
|
+
_logger.debug("Loaded env from: %s", resolved)
|
|
124
|
+
_loaded_env_path = resolved
|
|
125
|
+
# Auto-generate any missing secret keys into the existing .env
|
|
126
|
+
_backfill_missing_keys(env_path, auto_generate_keys or [])
|
|
127
|
+
return env_path
|
|
128
|
+
|
|
129
|
+
# No .env found — auto-create from bundled template
|
|
130
|
+
created = _create_default_env(package_data_module, auto_generate_keys or [])
|
|
131
|
+
if created is not None:
|
|
132
|
+
_loaded_env_path = created.resolve()
|
|
133
|
+
return created
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def ensure_user_env_for_setup(
|
|
137
|
+
*,
|
|
138
|
+
package_data_module: str = "reflexio.data",
|
|
139
|
+
auto_generate_keys: list[str] | None = None,
|
|
140
|
+
) -> Path | None:
|
|
141
|
+
"""Return ``~/.reflexio/.env``, creating it from the template if missing.
|
|
142
|
+
|
|
143
|
+
Distinct from :func:`load_reflexio_env`: that function honors a CWD-local
|
|
144
|
+
``./.env`` (intentional for ``services start``, where a project-level
|
|
145
|
+
override should take precedence). For ``setup init`` we never want to
|
|
146
|
+
write to whatever ``.env`` happens to be in the user's CWD — they may be
|
|
147
|
+
running from a worktree or a project root with an unrelated ``.env``,
|
|
148
|
+
and the resulting writes pollute that file and break the documented
|
|
149
|
+
``~/.reflexio/.env`` invariant.
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
package_data_module: Module containing the bundled ``.env.example``
|
|
153
|
+
template (for ``importlib.resources``). The OS package passes
|
|
154
|
+
``reflexio.data``; a downstream build may pass its own data module.
|
|
155
|
+
auto_generate_keys: Env var names to auto-fill with random hex
|
|
156
|
+
tokens when creating from the template.
|
|
157
|
+
|
|
158
|
+
Returns:
|
|
159
|
+
Path to ``~/.reflexio/.env`` (existing or newly created), or
|
|
160
|
+
``None`` if no template could be found.
|
|
161
|
+
"""
|
|
162
|
+
global _loaded_env_path
|
|
163
|
+
if _USER_ENV_FILE.exists():
|
|
164
|
+
load_dotenv(dotenv_path=_USER_ENV_FILE)
|
|
165
|
+
resolved = _USER_ENV_FILE.resolve()
|
|
166
|
+
_logger.debug("Loaded user env from: %s", resolved)
|
|
167
|
+
_loaded_env_path = resolved
|
|
168
|
+
_backfill_missing_keys(_USER_ENV_FILE, auto_generate_keys or [])
|
|
169
|
+
return _USER_ENV_FILE
|
|
170
|
+
created = _create_default_env(package_data_module, auto_generate_keys or [])
|
|
171
|
+
if created is not None:
|
|
172
|
+
_loaded_env_path = created.resolve()
|
|
173
|
+
return created
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def _backfill_missing_keys(env_path: Path, keys: list[str]) -> None:
|
|
177
|
+
"""Generate and write any missing secret keys into an existing .env file.
|
|
178
|
+
|
|
179
|
+
Called when ``load_reflexio_env`` finds a pre-existing .env (e.g. created
|
|
180
|
+
by ``setup init``) that may be missing keys that ``services start``
|
|
181
|
+
requires (like JWT_SECRET_KEY).
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
env_path: Path to the existing .env file.
|
|
185
|
+
keys: Env var names to check/generate.
|
|
186
|
+
"""
|
|
187
|
+
import os
|
|
188
|
+
|
|
189
|
+
generated: list[str] = []
|
|
190
|
+
for key in keys:
|
|
191
|
+
if os.environ.get(key):
|
|
192
|
+
continue
|
|
193
|
+
token = secrets.token_hex(32)
|
|
194
|
+
set_env_var(env_path, key, token)
|
|
195
|
+
os.environ[key] = token
|
|
196
|
+
generated.append(key)
|
|
197
|
+
if generated:
|
|
198
|
+
sys.stdout.write(f" Auto-generated missing keys: {', '.join(generated)}\n")
|
|
199
|
+
sys.stdout.flush()
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def _find_env_example(package_data_module: str) -> str | None:
|
|
203
|
+
"""Find .env.example content from CWD or package data.
|
|
204
|
+
|
|
205
|
+
Args:
|
|
206
|
+
package_data_module: Dotted module path for importlib.resources lookup.
|
|
207
|
+
|
|
208
|
+
Returns:
|
|
209
|
+
The template content as a string, or None if not found anywhere.
|
|
210
|
+
"""
|
|
211
|
+
# 1. Current directory (local dev checkout)
|
|
212
|
+
local = Path(".env.example")
|
|
213
|
+
if local.exists():
|
|
214
|
+
return local.read_text()
|
|
215
|
+
|
|
216
|
+
# 2. Package data (installed package)
|
|
217
|
+
try:
|
|
218
|
+
ref = importlib.resources.files(package_data_module).joinpath(".env.example")
|
|
219
|
+
return ref.read_text(encoding="utf-8")
|
|
220
|
+
except (ModuleNotFoundError, FileNotFoundError): # fmt: skip
|
|
221
|
+
pass
|
|
222
|
+
|
|
223
|
+
# 3. Editable install: .env.example lives at project root, two levels above reflexio/
|
|
224
|
+
try:
|
|
225
|
+
import reflexio as _pkg
|
|
226
|
+
|
|
227
|
+
project_root = Path(_pkg.__file__).resolve().parent.parent
|
|
228
|
+
candidate = project_root / ".env.example"
|
|
229
|
+
if candidate.is_file():
|
|
230
|
+
return candidate.read_text()
|
|
231
|
+
except Exception: # noqa: BLE001, S110
|
|
232
|
+
pass
|
|
233
|
+
|
|
234
|
+
return None
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def _create_default_env(
|
|
238
|
+
package_data_module: str,
|
|
239
|
+
auto_generate_keys: list[str],
|
|
240
|
+
) -> Path | None:
|
|
241
|
+
"""Create ~/.reflexio/.env from .env.example with auto-generated secrets.
|
|
242
|
+
|
|
243
|
+
Args:
|
|
244
|
+
package_data_module: Module path for finding the .env.example template.
|
|
245
|
+
auto_generate_keys: Env var names to auto-fill with random hex tokens.
|
|
246
|
+
|
|
247
|
+
Returns:
|
|
248
|
+
Path to the newly created .env file, or None if template not found.
|
|
249
|
+
"""
|
|
250
|
+
content = _find_env_example(package_data_module)
|
|
251
|
+
if content is None:
|
|
252
|
+
sys.stdout.write(
|
|
253
|
+
"Warning: no .env file found and no .env.example template available.\n"
|
|
254
|
+
" Set required environment variables manually.\n"
|
|
255
|
+
)
|
|
256
|
+
sys.stdout.flush()
|
|
257
|
+
return None
|
|
258
|
+
|
|
259
|
+
created_dir = not _USER_ENV_DIR.exists()
|
|
260
|
+
_USER_ENV_DIR.mkdir(parents=True, exist_ok=True)
|
|
261
|
+
if created_dir:
|
|
262
|
+
sys.stdout.write(f"Created directory: {_USER_ENV_DIR}\n")
|
|
263
|
+
|
|
264
|
+
# Auto-generate secret keys
|
|
265
|
+
for key in auto_generate_keys:
|
|
266
|
+
token = secrets.token_hex(32)
|
|
267
|
+
content = re.sub(
|
|
268
|
+
rf"^{re.escape(key)}=.*$",
|
|
269
|
+
f"{key}={token}",
|
|
270
|
+
content,
|
|
271
|
+
count=1,
|
|
272
|
+
flags=re.MULTILINE,
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
_USER_ENV_FILE.write_text(content)
|
|
276
|
+
_USER_ENV_FILE.chmod(0o600)
|
|
277
|
+
load_dotenv(dotenv_path=_USER_ENV_FILE)
|
|
278
|
+
|
|
279
|
+
sys.stdout.write(f"Created env file: {_USER_ENV_FILE}\n")
|
|
280
|
+
if auto_generate_keys:
|
|
281
|
+
sys.stdout.write(f" Auto-generated: {', '.join(auto_generate_keys)}\n")
|
|
282
|
+
sys.stdout.write(f" Edit {_USER_ENV_FILE} to add your API keys.\n\n")
|
|
283
|
+
sys.stdout.flush()
|
|
284
|
+
return _USER_ENV_FILE
|