fix(sleep): address review — CLI choice, auth guard, provider-neutral kwargs, tests
Addresses maintainer review on the OpenAI-compatible endpoints PR: 1. CLI: accept --backend azure_openai in skillopt_sleep/__main__.py (the documented command was rejected by the argparse choices). 2. Example runner: exit with the child's return code so watchdog/supervisors see a failed sleep run as a failure. 3. Error state: clear last_call_error when a retry recovers; set an explicit "empty response on all N attempts" diagnostic when every attempt returns empty text. 4. Security guard: the managed-identity path now refuses to send an Azure AD bearer token to any endpoint outside *.openai.azure.com / *.cognitiveservices.azure.com — a custom endpoint requires explicit AZURE_OPENAI_AUTH_MODE=openai_compatible + API key. 5. Provider-neutral requests: compat mode sends only the standard contract (max_tokens, default 8192 via SKILLOPT_SLEEP_COMPAT_MAX_TOKENS); provider-specific body fields are opt-in via SKILLOPT_SLEEP_CHAT_EXTRA_BODY (JSON) — the deepseek model-name inference is removed. 6. Docs: removed the unimplemented OPTIMIZER_*/TARGET_* env-var claim; added a configuration reference matching the implementation exactly. 7. Tests: tests/test_azure_openai_compat.py — 17 deterministic no-network unittest cases covering CLI acceptance, compat-vs-Azure client selection, endpoint resolution, the credential guard, request kwargs (opt-in extra body / token cap), retry-success error clearing, empty-response diagnostics, and runner exit-code propagation. Re-verified live against DeepSeek (deepseek-v4-pro, openai_compatible mode) after the rework: client type OpenAI, completion returned, no error state.
This commit is contained in:
@@ -72,12 +72,14 @@ def main() -> None:
|
||||
# OpenAI-compatible path — see docs/sleep/openai-compatible-endpoints.md
|
||||
backend = "azure_openai"
|
||||
env["PYTHONIOENCODING"] = "utf-8"
|
||||
for prefix in ("", "OPTIMIZER_", "TARGET_"):
|
||||
env[f"{prefix}AZURE_OPENAI_AUTH_MODE"] = "openai_compatible"
|
||||
env[f"{prefix}AZURE_OPENAI_ENDPOINT"] = PROVIDER_ENDPOINT
|
||||
env[f"{prefix}AZURE_OPENAI_API_KEY"] = env["DEEPSEEK_API_KEY"]
|
||||
env["TARGET_DEPLOYMENT"] = PROVIDER_MODEL
|
||||
env["OPTIMIZER_DEPLOYMENT"] = PROVIDER_MODEL
|
||||
env["AZURE_OPENAI_AUTH_MODE"] = "openai_compatible"
|
||||
env["AZURE_OPENAI_ENDPOINT"] = PROVIDER_ENDPOINT
|
||||
env["AZURE_OPENAI_API_KEY"] = env["DEEPSEEK_API_KEY"]
|
||||
# Provider-specific request fields are opt-in, never inferred from the
|
||||
# model name. For DeepSeek reasoning models, enable the thinking channel:
|
||||
env.setdefault("SKILLOPT_SLEEP_CHAT_EXTRA_BODY",
|
||||
json.dumps({"thinking": {"type": "enabled"}}))
|
||||
env.setdefault("SKILLOPT_SLEEP_COMPAT_MAX_TOKENS", "8192")
|
||||
else:
|
||||
# OPTIONAL, UNVERIFIED fallback: route the `claude` CLI backend through a
|
||||
# local Anthropic-compatible proxy (e.g. LiteLLM) to reach Gemini. There
|
||||
@@ -93,7 +95,10 @@ def main() -> None:
|
||||
"--model", PROVIDER_MODEL, "--project", PROJECT_DIR]
|
||||
|
||||
print(f"Running: {' '.join(args)}")
|
||||
subprocess.run(args, env=env, check=False)
|
||||
# Propagate the child's exit code so supervisors (watchdog.py, systemd,
|
||||
# Task Scheduler) see a failed sleep run as a failure, not a success.
|
||||
proc = subprocess.run(args, env=env, check=False)
|
||||
sys.exit(proc.returncode)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user