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,197 @@
|
|
|
1
|
+
"""Parse the NDJSON stream from ``claude -p --output-format stream-json``
|
|
2
|
+
and classify whether the call ended in a credit/auth stall.
|
|
3
|
+
|
|
4
|
+
Public surface:
|
|
5
|
+
- parse_stream_json(stdout, exit_code, stderr_text) -> ParseResult
|
|
6
|
+
- classify_stall(result) -> "billing_error" | "auth_error" | None
|
|
7
|
+
- parse_reset_estimate(text) -> datetime | None
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
import logging
|
|
14
|
+
import re
|
|
15
|
+
from dataclasses import dataclass, field
|
|
16
|
+
from datetime import UTC, datetime, time, timedelta
|
|
17
|
+
|
|
18
|
+
from reflexio.models.api_schema.stall_state_schema import StallReason
|
|
19
|
+
|
|
20
|
+
_LOGGER = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
_BILLING_CATEGORIES = {"billing_error"}
|
|
23
|
+
_AUTH_CATEGORIES = {"authentication_failed", "oauth_org_not_allowed"}
|
|
24
|
+
|
|
25
|
+
_TEXT_PATTERNS_BILLING = (
|
|
26
|
+
"hit your weekly limit",
|
|
27
|
+
"hit your session limit",
|
|
28
|
+
"credit balance is too low",
|
|
29
|
+
"billing_error",
|
|
30
|
+
)
|
|
31
|
+
_TEXT_PATTERNS_AUTH = (
|
|
32
|
+
"please run /login",
|
|
33
|
+
"oauth token revoked",
|
|
34
|
+
"oauth token has expired",
|
|
35
|
+
"not logged in",
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
_RESET_RE = re.compile(
|
|
39
|
+
r"resets\s+(?:(?P<weekday>mon|tue|wed|thu|fri|sat|sun)\w*\s+)?"
|
|
40
|
+
r"(?P<hour>\d{1,2}):(?P<minute>\d{2})\s*(?P<ampm>am|pm)",
|
|
41
|
+
re.IGNORECASE,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass
|
|
46
|
+
class ParseResult:
|
|
47
|
+
"""Aggregated state of one ``claude -p`` invocation.
|
|
48
|
+
|
|
49
|
+
Attributes:
|
|
50
|
+
success (bool): True iff exit_code==0 AND a terminal result event
|
|
51
|
+
with non-empty text appeared.
|
|
52
|
+
terminal_text (str): The ``result`` field from the terminal event.
|
|
53
|
+
retry_errors (list[str]): All ``error`` strings observed in
|
|
54
|
+
``api_retry`` events, in order.
|
|
55
|
+
stderr_text (str): Raw stderr text from the subprocess.
|
|
56
|
+
raw_lines_parsed (int): NDJSON lines parsed successfully.
|
|
57
|
+
raw_lines_failed (int): NDJSON lines that failed to parse.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
success: bool
|
|
61
|
+
terminal_text: str
|
|
62
|
+
retry_errors: list[str] = field(default_factory=list)
|
|
63
|
+
stderr_text: str = ""
|
|
64
|
+
raw_lines_parsed: int = 0
|
|
65
|
+
raw_lines_failed: int = 0
|
|
66
|
+
|
|
67
|
+
@property
|
|
68
|
+
def stall_candidate(self) -> str | None:
|
|
69
|
+
"""The last retry error string in a stall category, or None."""
|
|
70
|
+
for err in reversed(self.retry_errors):
|
|
71
|
+
if err in _BILLING_CATEGORIES or err in _AUTH_CATEGORIES:
|
|
72
|
+
return err
|
|
73
|
+
return None
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def parse_stream_json(
|
|
77
|
+
stdout: str,
|
|
78
|
+
*,
|
|
79
|
+
exit_code: int,
|
|
80
|
+
stderr_text: str = "",
|
|
81
|
+
) -> ParseResult:
|
|
82
|
+
"""Parse the full NDJSON stream from claude -p.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
stdout (str): Raw subprocess stdout — newline-delimited JSON events.
|
|
86
|
+
exit_code (int): Subprocess exit code.
|
|
87
|
+
stderr_text (str): Raw stderr — used by the text-fallback path.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
ParseResult: Aggregated state. ``success`` requires both a clean
|
|
91
|
+
exit and a parseable terminal ``result`` event.
|
|
92
|
+
"""
|
|
93
|
+
retry_errors: list[str] = []
|
|
94
|
+
terminal_text = ""
|
|
95
|
+
parsed = 0
|
|
96
|
+
failed = 0
|
|
97
|
+
saw_terminal = False
|
|
98
|
+
for line in stdout.splitlines():
|
|
99
|
+
if not line.strip():
|
|
100
|
+
continue
|
|
101
|
+
try:
|
|
102
|
+
event = json.loads(line)
|
|
103
|
+
except json.JSONDecodeError:
|
|
104
|
+
failed += 1
|
|
105
|
+
continue
|
|
106
|
+
parsed += 1
|
|
107
|
+
if not isinstance(event, dict):
|
|
108
|
+
continue
|
|
109
|
+
match event.get("type"), event.get("subtype"):
|
|
110
|
+
case ("system", "api_retry"):
|
|
111
|
+
err = event.get("error")
|
|
112
|
+
if isinstance(err, str):
|
|
113
|
+
retry_errors.append(err)
|
|
114
|
+
case ("result", _) | (_, "result"):
|
|
115
|
+
text = event.get("result")
|
|
116
|
+
if isinstance(text, str):
|
|
117
|
+
terminal_text = text
|
|
118
|
+
saw_terminal = True
|
|
119
|
+
return ParseResult(
|
|
120
|
+
success=(exit_code == 0 and saw_terminal and bool(terminal_text)),
|
|
121
|
+
terminal_text=terminal_text,
|
|
122
|
+
retry_errors=retry_errors,
|
|
123
|
+
stderr_text=stderr_text,
|
|
124
|
+
raw_lines_parsed=parsed,
|
|
125
|
+
raw_lines_failed=failed,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def classify_stall(result: ParseResult) -> StallReason | None:
|
|
130
|
+
"""Decide whether a finished ParseResult represents a stall.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
result (ParseResult): Output of :func:`parse_stream_json`.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
StallReason | None: ``"billing_error"`` or ``"auth_error"`` only
|
|
137
|
+
when the call terminated unsuccessfully AND a stall-class
|
|
138
|
+
signal was observed (event or text fallback).
|
|
139
|
+
"""
|
|
140
|
+
if result.success:
|
|
141
|
+
return None
|
|
142
|
+
candidate = result.stall_candidate
|
|
143
|
+
if candidate in _BILLING_CATEGORIES:
|
|
144
|
+
return "billing_error"
|
|
145
|
+
if candidate in _AUTH_CATEGORIES:
|
|
146
|
+
return "auth_error"
|
|
147
|
+
return _classify_from_text(result.stderr_text + " " + result.terminal_text)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def _classify_from_text(text: str) -> StallReason | None:
|
|
151
|
+
"""Belt-and-suspenders: regex the raw error text after NDJSON has been parsed."""
|
|
152
|
+
lower = text.lower()
|
|
153
|
+
if any(p in lower for p in _TEXT_PATTERNS_BILLING):
|
|
154
|
+
_LOGGER.warning("Stall classified via text fallback (billing): %r", text[:200])
|
|
155
|
+
return "billing_error"
|
|
156
|
+
if any(p in lower for p in _TEXT_PATTERNS_AUTH):
|
|
157
|
+
_LOGGER.warning("Stall classified via text fallback (auth): %r", text[:200])
|
|
158
|
+
return "auth_error"
|
|
159
|
+
return None
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def parse_reset_estimate(text: str) -> datetime | None:
|
|
163
|
+
"""Best-effort parse of a reset time from Claude Code error text.
|
|
164
|
+
|
|
165
|
+
The hour/minute extracted from the message text is treated as UTC, then
|
|
166
|
+
advanced one day if it has already passed. Claude Code's error messages
|
|
167
|
+
typically express reset times in the user's local timezone, so the
|
|
168
|
+
returned datetime may be off by the user's UTC offset (up to ±24h).
|
|
169
|
+
Callers should treat this as an approximation, not an authoritative
|
|
170
|
+
reset moment.
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
text (str): Error text — typically the terminal event message or stderr.
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
datetime | None: A UTC-naive-in-spirit but tz-aware datetime that
|
|
177
|
+
best approximates the next reset, or None when no recognizable
|
|
178
|
+
pattern is found.
|
|
179
|
+
"""
|
|
180
|
+
match = _RESET_RE.search(text or "")
|
|
181
|
+
if not match:
|
|
182
|
+
return None
|
|
183
|
+
hour_raw = int(match.group("hour"))
|
|
184
|
+
minute = int(match.group("minute"))
|
|
185
|
+
# The regex permits 1–2 digit hours and minutes; reject out-of-range
|
|
186
|
+
# values so "13:00pm" or "10:75am" parse as None instead of producing
|
|
187
|
+
# silently-wrong times via modulo arithmetic.
|
|
188
|
+
if not 1 <= hour_raw <= 12 or not 0 <= minute <= 59:
|
|
189
|
+
return None
|
|
190
|
+
hour = hour_raw % 12
|
|
191
|
+
if match.group("ampm").lower() == "pm":
|
|
192
|
+
hour += 12
|
|
193
|
+
today = datetime.now(UTC).date()
|
|
194
|
+
candidate = datetime.combine(today, time(hour, minute), tzinfo=UTC)
|
|
195
|
+
if candidate <= datetime.now(UTC):
|
|
196
|
+
candidate += timedelta(days=1)
|
|
197
|
+
return candidate
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
"""HTTP embedding service provider.
|
|
2
|
+
|
|
3
|
+
This module is the routing boundary between Reflexio's LLM client and an
|
|
4
|
+
OpenAI-compatible embedding service. It lets local Claude Smart installs keep
|
|
5
|
+
one model process alive across backend workers, Claude Code, and Codex, while
|
|
6
|
+
also supporting a horizontally-scaled internal service in cloud deployments.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
import logging
|
|
13
|
+
import os
|
|
14
|
+
import time
|
|
15
|
+
from typing import Any, Literal
|
|
16
|
+
|
|
17
|
+
import httpx
|
|
18
|
+
|
|
19
|
+
_LOGGER = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
EmbeddingProviderMode = Literal[
|
|
22
|
+
"cloud", "local_service", "internal_service", "inprocess", "off"
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
_ENV_PROVIDER = "REFLEXIO_EMBEDDING_PROVIDER"
|
|
26
|
+
_ENV_SERVICE_URL = "REFLEXIO_EMBEDDING_SERVICE_URL"
|
|
27
|
+
_ENV_TIMEOUT_MS = "REFLEXIO_EMBEDDING_SERVICE_TIMEOUT_MS"
|
|
28
|
+
_ENV_EMBEDDING_PORT = "EMBEDDING_PORT"
|
|
29
|
+
_ENV_DAEMON_HOST = "REFLEXIO_EMBEDDING_DAEMON_HOST"
|
|
30
|
+
_ENV_LOCAL_SERVICE_PROBE_TIMEOUT_MS = (
|
|
31
|
+
"REFLEXIO_EMBEDDING_LOCAL_SERVICE_PROBE_TIMEOUT_MS"
|
|
32
|
+
)
|
|
33
|
+
_ENV_CLAUDE_SMART_LOCAL = "CLAUDE_SMART_USE_LOCAL_EMBEDDING"
|
|
34
|
+
_ENV_MAX_TEXTS_PER_REQUEST = "REFLEXIO_EMBEDDING_SERVICE_MAX_TEXTS_PER_REQUEST"
|
|
35
|
+
_DEFAULT_LOCAL_PORT = 8072
|
|
36
|
+
_DEFAULT_INTERNAL_SERVICE_TIMEOUT_MS = 2_000
|
|
37
|
+
_DEFAULT_LOCAL_SERVICE_TIMEOUT_MS = 30_000
|
|
38
|
+
_DEFAULT_LOCAL_SERVICE_PROBE_TIMEOUT_MS = 200
|
|
39
|
+
# Each request embeds its whole ``input`` list in one ``model.encode()`` on the
|
|
40
|
+
# service, so an unbounded request can exceed the client read timeout on a CPU
|
|
41
|
+
# daemon. Cap texts per request and concatenate; encode batching is a separate
|
|
42
|
+
# server-side knob (REFLEXIO_EMBED_BATCH_SIZE).
|
|
43
|
+
_DEFAULT_MAX_TEXTS_PER_REQUEST = 32
|
|
44
|
+
_LOCAL_SERVICE_PROBE_CACHE_SECONDS = 5.0
|
|
45
|
+
_SERVICE_MODES = {"local_service", "internal_service"}
|
|
46
|
+
_VALID_MODES = {"cloud", *_SERVICE_MODES, "inprocess", "off"}
|
|
47
|
+
_local_service_probe_cache: tuple[float, bool, str | None] | None = None
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class EmbeddingUnavailableError(RuntimeError):
|
|
51
|
+
"""Raised when the configured embedding provider is unavailable."""
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _local_service_url() -> str:
|
|
55
|
+
host = os.environ.get(_ENV_DAEMON_HOST, "").strip() or "127.0.0.1"
|
|
56
|
+
port = os.environ.get(_ENV_EMBEDDING_PORT, str(_DEFAULT_LOCAL_PORT))
|
|
57
|
+
return f"http://{host}:{port}"
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _local_service_probe_timeout_seconds() -> float:
|
|
61
|
+
raw = os.environ.get(_ENV_LOCAL_SERVICE_PROBE_TIMEOUT_MS)
|
|
62
|
+
if raw is None:
|
|
63
|
+
return _DEFAULT_LOCAL_SERVICE_PROBE_TIMEOUT_MS / 1000
|
|
64
|
+
try:
|
|
65
|
+
timeout_ms = int(raw)
|
|
66
|
+
except ValueError:
|
|
67
|
+
_LOGGER.warning(
|
|
68
|
+
"%s must be an integer number of milliseconds; using %dms",
|
|
69
|
+
_ENV_LOCAL_SERVICE_PROBE_TIMEOUT_MS,
|
|
70
|
+
_DEFAULT_LOCAL_SERVICE_PROBE_TIMEOUT_MS,
|
|
71
|
+
)
|
|
72
|
+
return _DEFAULT_LOCAL_SERVICE_PROBE_TIMEOUT_MS / 1000
|
|
73
|
+
return max(timeout_ms, 1) / 1000
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def embedding_service_url(mode: EmbeddingProviderMode | None = None) -> str:
|
|
77
|
+
"""Return the configured embedding service URL.
|
|
78
|
+
|
|
79
|
+
``local_service`` defaults to ``127.0.0.1:$EMBEDDING_PORT`` so local
|
|
80
|
+
Claude Smart hosts can share a single machine daemon. ``internal_service``
|
|
81
|
+
requires an explicit URL because it is deployment-specific.
|
|
82
|
+
"""
|
|
83
|
+
resolved = mode or embedding_provider_mode()
|
|
84
|
+
configured = os.environ.get(_ENV_SERVICE_URL)
|
|
85
|
+
if configured:
|
|
86
|
+
return configured.rstrip("/")
|
|
87
|
+
if resolved == "local_service":
|
|
88
|
+
return _local_service_url()
|
|
89
|
+
raise EmbeddingUnavailableError(
|
|
90
|
+
f"{_ENV_SERVICE_URL} is required when {_ENV_PROVIDER}={resolved}"
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def embedding_service_timeout_seconds(
|
|
95
|
+
mode: EmbeddingProviderMode | None = None,
|
|
96
|
+
) -> float:
|
|
97
|
+
raw = os.environ.get(_ENV_TIMEOUT_MS)
|
|
98
|
+
if raw is None:
|
|
99
|
+
resolved = mode or embedding_provider_mode()
|
|
100
|
+
if resolved == "local_service":
|
|
101
|
+
return _DEFAULT_LOCAL_SERVICE_TIMEOUT_MS / 1000
|
|
102
|
+
return _DEFAULT_INTERNAL_SERVICE_TIMEOUT_MS / 1000
|
|
103
|
+
try:
|
|
104
|
+
timeout_ms = int(raw)
|
|
105
|
+
except ValueError as exc:
|
|
106
|
+
raise EmbeddingUnavailableError(
|
|
107
|
+
f"{_ENV_TIMEOUT_MS} must be an integer number of milliseconds"
|
|
108
|
+
) from exc
|
|
109
|
+
return max(timeout_ms, 1) / 1000
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _is_local_model(model: str | None) -> bool:
|
|
113
|
+
return bool(model and model.startswith("local/"))
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _local_service_status() -> tuple[bool, str | None]:
|
|
117
|
+
global _local_service_probe_cache
|
|
118
|
+
now = time.monotonic()
|
|
119
|
+
if (
|
|
120
|
+
_local_service_probe_cache is not None
|
|
121
|
+
and now - _local_service_probe_cache[0] < _LOCAL_SERVICE_PROBE_CACHE_SECONDS
|
|
122
|
+
):
|
|
123
|
+
return _local_service_probe_cache[1], _local_service_probe_cache[2]
|
|
124
|
+
|
|
125
|
+
try:
|
|
126
|
+
response = httpx.get(
|
|
127
|
+
f"{_local_service_url()}/health",
|
|
128
|
+
timeout=_local_service_probe_timeout_seconds(),
|
|
129
|
+
)
|
|
130
|
+
reachable = response.status_code < 500
|
|
131
|
+
active_model = response.json().get("active_model") if reachable else None
|
|
132
|
+
if not isinstance(active_model, str):
|
|
133
|
+
active_model = None
|
|
134
|
+
except httpx.HTTPError:
|
|
135
|
+
reachable = False
|
|
136
|
+
active_model = None
|
|
137
|
+
except ValueError:
|
|
138
|
+
reachable = False
|
|
139
|
+
active_model = None
|
|
140
|
+
_local_service_probe_cache = (now, reachable, active_model)
|
|
141
|
+
return reachable, active_model
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _local_service_supports_model(model: str | None) -> bool:
|
|
145
|
+
reachable, active_model = _local_service_status()
|
|
146
|
+
return reachable and (active_model is None or active_model == model)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def _ordered_embeddings_from_response(
|
|
150
|
+
data: Any, expected_count: int
|
|
151
|
+
) -> list[list[float]]:
|
|
152
|
+
if not isinstance(data, list):
|
|
153
|
+
raise ValueError("embedding service response is missing data[]")
|
|
154
|
+
if len(data) != expected_count:
|
|
155
|
+
raise ValueError(
|
|
156
|
+
"embedding service response cardinality mismatch: "
|
|
157
|
+
f"expected {expected_count}, got {len(data)}"
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
seen: set[int] = set()
|
|
161
|
+
indexed_embeddings: list[tuple[int, list[Any]]] = []
|
|
162
|
+
for item in data:
|
|
163
|
+
if not isinstance(item, dict):
|
|
164
|
+
raise ValueError("embedding service response data[] has invalid item")
|
|
165
|
+
|
|
166
|
+
index = item.get("index")
|
|
167
|
+
if type(index) is not int:
|
|
168
|
+
raise ValueError("embedding service response has invalid index")
|
|
169
|
+
if index in seen:
|
|
170
|
+
raise ValueError(f"embedding service response has duplicate index {index}")
|
|
171
|
+
seen.add(index)
|
|
172
|
+
|
|
173
|
+
embedding = item.get("embedding")
|
|
174
|
+
if not isinstance(embedding, list):
|
|
175
|
+
raise ValueError("embedding service response has invalid embeddings")
|
|
176
|
+
indexed_embeddings.append((index, embedding))
|
|
177
|
+
|
|
178
|
+
expected_indices = set(range(expected_count))
|
|
179
|
+
if seen != expected_indices:
|
|
180
|
+
raise ValueError(
|
|
181
|
+
"embedding service response indices mismatch: "
|
|
182
|
+
f"expected {sorted(expected_indices)}, got {sorted(seen)}"
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
return [
|
|
186
|
+
[float(value) for value in embedding]
|
|
187
|
+
for _, embedding in sorted(indexed_embeddings)
|
|
188
|
+
]
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def embedding_provider_mode(model: str | None = None) -> EmbeddingProviderMode:
|
|
192
|
+
"""Resolve the embedding provider mode for a model.
|
|
193
|
+
|
|
194
|
+
Explicit legacy env modes keep their historical behavior. With no explicit
|
|
195
|
+
env mode, routing is model-driven: ``local/*`` uses the local daemon when it
|
|
196
|
+
is reachable and otherwise falls back to the in-process embedder; cloud
|
|
197
|
+
models use their provider directly.
|
|
198
|
+
"""
|
|
199
|
+
configured = os.environ.get(_ENV_PROVIDER)
|
|
200
|
+
if configured:
|
|
201
|
+
mode = configured.strip().lower()
|
|
202
|
+
if mode not in _VALID_MODES:
|
|
203
|
+
raise EmbeddingUnavailableError(
|
|
204
|
+
f"Invalid {_ENV_PROVIDER}={configured!r}; expected one of "
|
|
205
|
+
f"{', '.join(sorted(_VALID_MODES))}"
|
|
206
|
+
)
|
|
207
|
+
return mode # type: ignore[return-value]
|
|
208
|
+
|
|
209
|
+
if os.environ.get(_ENV_CLAUDE_SMART_LOCAL) == "1":
|
|
210
|
+
return "local_service"
|
|
211
|
+
|
|
212
|
+
if os.environ.get(_ENV_SERVICE_URL):
|
|
213
|
+
return "internal_service"
|
|
214
|
+
|
|
215
|
+
if _is_local_model(model):
|
|
216
|
+
return "local_service" if _local_service_supports_model(model) else "inprocess"
|
|
217
|
+
return "cloud"
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def should_use_embedding_service(model: str) -> bool:
|
|
221
|
+
"""Return True when embedding requests should call the HTTP service."""
|
|
222
|
+
return embedding_provider_mode(model) in _SERVICE_MODES
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def get_service_embeddings(
|
|
226
|
+
texts: list[str],
|
|
227
|
+
*,
|
|
228
|
+
model: str,
|
|
229
|
+
dimensions: int | None = None,
|
|
230
|
+
) -> list[list[float]]:
|
|
231
|
+
"""Call the OpenAI-compatible embedding service.
|
|
232
|
+
|
|
233
|
+
Args:
|
|
234
|
+
texts: Inputs to embed.
|
|
235
|
+
model: Embedding model name.
|
|
236
|
+
dimensions: Optional embedding dimensions.
|
|
237
|
+
|
|
238
|
+
Returns:
|
|
239
|
+
Embeddings in input order.
|
|
240
|
+
|
|
241
|
+
Raises:
|
|
242
|
+
EmbeddingUnavailableError: If the service cannot be reached or returns
|
|
243
|
+
an invalid response.
|
|
244
|
+
"""
|
|
245
|
+
if not texts:
|
|
246
|
+
return []
|
|
247
|
+
|
|
248
|
+
mode = embedding_provider_mode(model)
|
|
249
|
+
if mode == "off":
|
|
250
|
+
raise EmbeddingUnavailableError("Embedding provider is disabled")
|
|
251
|
+
if mode not in _SERVICE_MODES:
|
|
252
|
+
raise EmbeddingUnavailableError(
|
|
253
|
+
f"Embedding service requested while {_ENV_PROVIDER}={mode}"
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
url = f"{embedding_service_url(mode)}/v1/embeddings"
|
|
257
|
+
timeout = embedding_service_timeout_seconds(mode)
|
|
258
|
+
|
|
259
|
+
# Bound each request so a single large publish cannot exceed the client read
|
|
260
|
+
# timeout: split into fixed-size chunks and concatenate the results in order.
|
|
261
|
+
chunk_size = _max_texts_per_request()
|
|
262
|
+
embeddings: list[list[float]] = []
|
|
263
|
+
for start in range(0, len(texts), chunk_size):
|
|
264
|
+
chunk = texts[start : start + chunk_size]
|
|
265
|
+
embeddings.extend(
|
|
266
|
+
_post_embedding_batch(
|
|
267
|
+
url, model=model, texts=chunk, dimensions=dimensions, timeout=timeout
|
|
268
|
+
)
|
|
269
|
+
)
|
|
270
|
+
return embeddings
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def _post_embedding_batch(
|
|
274
|
+
url: str,
|
|
275
|
+
*,
|
|
276
|
+
model: str,
|
|
277
|
+
texts: list[str],
|
|
278
|
+
dimensions: int | None,
|
|
279
|
+
timeout: float,
|
|
280
|
+
) -> list[list[float]]:
|
|
281
|
+
"""POST one bounded batch of texts to the embedding service."""
|
|
282
|
+
payload: dict[str, Any] = {"model": model, "input": texts}
|
|
283
|
+
if dimensions:
|
|
284
|
+
payload["dimensions"] = dimensions
|
|
285
|
+
|
|
286
|
+
last_error: Exception | None = None
|
|
287
|
+
for attempt in range(2):
|
|
288
|
+
try:
|
|
289
|
+
with httpx.Client(timeout=timeout) as client:
|
|
290
|
+
response = client.post(url, json=payload)
|
|
291
|
+
response.raise_for_status()
|
|
292
|
+
body = response.json()
|
|
293
|
+
return _ordered_embeddings_from_response(body.get("data"), len(texts))
|
|
294
|
+
except (httpx.ConnectError, httpx.ConnectTimeout) as exc:
|
|
295
|
+
# Connection never established — the request never reached the
|
|
296
|
+
# server, so a single retry is safe and cannot duplicate work.
|
|
297
|
+
last_error = exc
|
|
298
|
+
if attempt == 0:
|
|
299
|
+
time.sleep(0.1)
|
|
300
|
+
except (httpx.HTTPError, json.JSONDecodeError, ValueError) as exc:
|
|
301
|
+
# The server already received the request: a read timeout means it
|
|
302
|
+
# is still encoding, and retrying would queue a second identical
|
|
303
|
+
# encode behind the first and amplify load on an already-saturated
|
|
304
|
+
# daemon. HTTPStatusError (4xx/5xx) and malformed-payload errors
|
|
305
|
+
# (JSONDecodeError / the ValueError raised by
|
|
306
|
+
# _ordered_embeddings_from_response) will not change on retry
|
|
307
|
+
# either. Fail fast. Anything outside this set (AttributeError,
|
|
308
|
+
# TypeError, ...) is a programming bug and propagates raw.
|
|
309
|
+
last_error = exc
|
|
310
|
+
break
|
|
311
|
+
|
|
312
|
+
_LOGGER.warning("Embedding service unavailable at %s: %s", url, last_error)
|
|
313
|
+
raise EmbeddingUnavailableError(
|
|
314
|
+
f"Embedding service unavailable at {url}: {last_error}"
|
|
315
|
+
) from last_error
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
def _max_texts_per_request() -> int:
|
|
319
|
+
raw = os.environ.get(_ENV_MAX_TEXTS_PER_REQUEST)
|
|
320
|
+
if raw is None:
|
|
321
|
+
return _DEFAULT_MAX_TEXTS_PER_REQUEST
|
|
322
|
+
try:
|
|
323
|
+
value = int(raw)
|
|
324
|
+
except ValueError:
|
|
325
|
+
_LOGGER.warning(
|
|
326
|
+
"%s must be an integer; using %d",
|
|
327
|
+
_ENV_MAX_TEXTS_PER_REQUEST,
|
|
328
|
+
_DEFAULT_MAX_TEXTS_PER_REQUEST,
|
|
329
|
+
)
|
|
330
|
+
return _DEFAULT_MAX_TEXTS_PER_REQUEST
|
|
331
|
+
if value < 1:
|
|
332
|
+
_LOGGER.warning(
|
|
333
|
+
"%s must be >= 1; using %d",
|
|
334
|
+
_ENV_MAX_TEXTS_PER_REQUEST,
|
|
335
|
+
_DEFAULT_MAX_TEXTS_PER_REQUEST,
|
|
336
|
+
)
|
|
337
|
+
return _DEFAULT_MAX_TEXTS_PER_REQUEST
|
|
338
|
+
return value
|