feat(launch): startup-timing breakdown and faster AUTO backend-format detection#70
Conversation
WalkthroughChangesLaunch startup timing
Backend probe timeout handling
Estimated code review effort: 3 (Moderate) | ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
switchyard/lib/backends/backend_format_resolver.py (1)
89-114: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winUse the probe result instead of elapsed time to detect a timeout.
probe_openai_chat_completions_support_sync()collapses allhttpx.RequestErrorsubtypes intoFalse, sotime.perf_counter() - chat_started >= timeout_sis guessing. HTTPX applies connect/read/write/pool timeouts independently, so a slow but successful fast-negative can exceedtimeout_s, and a real timeout can still miss the threshold. Return a distinct timeout signal from the probe and branch on that instead.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@switchyard/lib/backends/backend_format_resolver.py` around lines 89 - 114, Update probe_openai_chat_completions_support_sync and the surrounding resolver flow to return a distinct timeout result instead of collapsing timeout RequestErrors into False. In the Chat Completions branch, remove the chat_started elapsed-time heuristic and branch directly on that timeout signal, while preserving successful probes and fast-negative fallthrough behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@switchyard/cli/launchers/claude_code_launcher.py`:
- Around line 393-394: Move the “child agent spawned” timing checkpoint from the
pre-invocation location into the actual child-process creation path used by
ShellTUI or _supervise_claude_plain, so the timestamp and dumped total include
process creation. Preserve the existing timing flow otherwise, and add a
regression test verifying the checkpoint occurs after the child is spawned.
---
Outside diff comments:
In `@switchyard/lib/backends/backend_format_resolver.py`:
- Around line 89-114: Update probe_openai_chat_completions_support_sync and the
surrounding resolver flow to return a distinct timeout result instead of
collapsing timeout RequestErrors into False. In the Chat Completions branch,
remove the chat_started elapsed-time heuristic and branch directly on that
timeout signal, while preserving successful probes and fast-negative fallthrough
behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: c6519c72-3901-427e-9a56-86703ec4c271
📒 Files selected for processing (6)
switchyard/cli/launch_command.pyswitchyard/cli/launchers/claude_code_launcher.pyswitchyard/cli/launchers/startup_timing.pyswitchyard/lib/backends/backend_format_resolver.pytests/test_backend_format_resolver.pytests/test_startup_timing.py
43614e1 to
40d8a6d
Compare
|
|
Thanks @coderabbitai — addressing both findings:
|
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -e
git log --oneline -15 origin/main..HEAD 2>/dev/null || git log --oneline -15
echo "---"
git log --all --oneline | grep -i "40d8a6d6" || true
echo "---search-file---"
fd backend_format_resolver.py
echo "---content---"
cat -n switchyard/lib/backends/backend_format_resolver.pyLength of output: 19817 Confirmed both points against the current HEAD.
(‑, ‑)ゞ |
d78d384 to
f6e3806
Compare
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
…ING) Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
…ng / env var Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
…ency Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
…ons first Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
5695bbc to
ba42368
Compare
What this adds
Tooling and a fix for slow
switchyard launch claudestartup, tied to SWITCH-872.TL;DR —
AUTObackend-format detection is the startup cost. Withformat: auto(the Claude Code / Codex launcher default), the resolver probes the upstream live before the agent starts to detect the wire format — Chat Completions first, then/v1/messages, then/v1/responses. Each probe is a round-trip, so a slow endpoint (e.g. a cold NVCF/Azure deployment on Inference Hub) adds real wall-clock latency to startup. This PR reduces the worst case and adds the tooling to see it.1. An opt-in, per-probe startup-timing breakdown. Enable it two ways — the
--startup-timingflag or theSWITCHYARD_STARTUP_TIMING=1env var; if neither is set it does nothing and a normal launch pays zero. When on, the launcher prints to stderr, right before it spawns the agent, how long each startup phase took — each backend-format probe on its own line:A slow line names the slow phase — three slow
probe:lines mean a slow upstream made AUTO stack timeouts. Works for both single-model (--model) and default classifier-routing launches.2. A fix for the phase that breakdown exposed. Before this change, if the Chat Completions probe timed out (reachable-but-slow endpoint), the resolver treated the timeout like a 404 and serially ran the
/v1/messagesand/v1/responsesprobes too, each stacking another timeout — one slow endpoint became several seconds (measured up to ~7 s). Now a probe timeout is detected via the raisedhttpx.TimeoutException(not a wall-clock heuristic) and falls back to Chat Completions immediately. A genuine fast 404 still falls through to the other probes, so detection is unchanged for Anthropic-native / Responses-only endpoints. Worst case drops from ~three stacked timeouts to one.3. Docs.
docs/architecture.mdnow states thatAUTOcosts startup latency (a live probe per format) and that settingformat:explicitly removes it — with a pointer to--startup-timingto measure it. Also corrected the AUTO decision-tree diagram, which showed/v1/messagesprobed first; the resolver actually probes/v1/chat/completionsfirst (with the timeout short-circuit).What stays the same
format:values still skip probing. Settingformat:is the real fix for slow startup.anthropic/andclaude…model prefixes still short-circuit to Anthropic with no probe./v1/messagesand/v1/responsesprobes. Only a probe timeout changes behavior.Tests
tests/test_backend_format_resolver.py:httpx.ReadTimeoutresolves to OPENAI without running the other two probes.AUTOrecords each probe as its own startup-timing mark.The existing probe-order tests are unchanged. The
--startup-timingoutput is debug-only diagnostic tooling, so it ships without its own test.Not included
switchyard launch claude --model X --dry-run. Trimming it is separate work.