Repository navigation
fix(cloud-agent-next): split assistant unavailability by gateway origin - #6802
Conversation
`assistant_unavailable` collapsed two different outcomes: a real upstream provider failure, and the gateway's own `temporarily_unavailable` (our over-limit guard or our managed-provider payment failure). The status code alone cannot tell them apart, so the code-review row said nothing about which component failed. The gateway already tags its own responses with a bounded `error_type`; read it from the client error body and map it to distinct reasons: `upstream_disconnect` -> `provider_disconnect`, `temporarily_unavailable` -> `gateway_unavailable`. `failure_family` is added to the disconnect body for the sub-cause. Both reasons stay on the model-serving path (`provider`), so this adds visibility without moving the platform share. The error body is provider-influenced on the passthrough path, so the read is length-bounded and only selects from a fixed set; nothing is retained or copied into a message.
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Executive SummaryThe incremental commit moves Files Reviewed (2 files)
Previous Review Summaries (2 snapshots, latest commit 50938b5)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit 50938b5)Status: 2 Issues Found | Recommendation: Address before merge Executive SummaryThe incremental commit reverted the gateway Overview
Issue Details (click to expand)WARNING
SUGGESTION
Files Reviewed (3 files)
Fix these issues in Kilo Cloud Previous review (commit d18eff7)Status: 1 Issue Found | Recommendation: Address before merge Executive SummaryThe gateway-origin branch that splits Overview
Issue Details (click to expand)WARNING
Files Reviewed (13 files)
Reviewed by deepseek-v4.1-flash · Input: 0 · Output: 0 · Cached: 0 Review guidance: REVIEW.md from base branch |
The classification split only needs the gateway's existing `error_type`; the extra `failure_family` field was optional observability, not a dependency. Drop it so the gateway response contract is untouched and the change is classifier-only.
The gateway APIError's data.message is built from the gateway's own response body, so an upstream_disconnect timeout body matched the text classifier's timeout pattern and never reached the error_type mapping. Read the structured error_type first so the gateway origin decides, and drop the stale failure_family mention from the classifier doc comment.
Summary
assistant_unavailableon the code-review page collapsed two different outcomes under one label: a real upstream provider failure, and the gateway's owntemporarily_unavailable(our over-limit guard or our managed-provider payment failure). The HTTP status code alone cannot tell them apart, so a failed review said nothing about which component actually failed.The gateway already tags its own non-2xx responses with a bounded
error_typein the JSON body. This change reads that tag in the single assistant-failure classifier and maps it to distinct reasons:upstream_disconnect→provider_disconnecttemporarily_unavailable→gateway_unavailableThe two reasons flow through the existing taxonomy (
packages/worker-utils, the sandbox control-protocol enum,packages/dbreason unions) to two new code-review terminal reasons, so "Assistant Unavailable" now splits into "Assistant Provider Disconnect" and "Assistant Gateway Unavailable" in the admin error analysis.The gateway response contract is unchanged — the
error_typethese mappings read already existed. This is a classifier-only change, with noapps/web/src/lib/ai-gatewayedits.Design notes for a reviewer:
providerresponsibility), matching the existing rule that the cloud agent treats the gateway and upstream as one origin. This adds visibility; it does not move the platform share. A comment marks the deliberate follow-up ifgateway_unavailableshould be attributed toplatform.terminal-reason-copyentries: these are transient infrastructure failures with no customer remedy, so the generic path applies.Verification
No manual tests were run — this affects failure classification on the cloud-agent callback path, which needs a running control plane plus a provider fault to exercise end to end, and the local stack was not started in this worktree. Verification was automated:
pnpm run testinservices/cloud-agent-next(7759 passed) andpackages/worker-utils(788 passed).apps/web jest for
src/lib/code-reviews,src/app/api/internal/code-review-status,src/app/admin/components/CloudAgentNextTelemetry,src/lib/ai-gateway,src/tests/openrouterApi.timeout.test.ts(all passing).tsgo --noEmitforapps/web,packages/worker-utils,packages/db,services/cloud-agent-next.oxlint and oxfmt clean on the changed files.
Manual end-to-end check of a gateway
503 upstream_disconnectproducingassistant_provider_disconnectKnown gap:
data.responseBodypresence on the client error was inferred from the ingest sanitizer and test fixtures, not captured from a live production error.Visual Changes
N/A
Reviewer Notes
.strict(), so an unknownassistantReasondiscards the whole failure object. Deploy apps/web before cloud-agent-next.temporarily_unavailablefrom an upstream disconnect. It does not split the upstream sub-cause (headers timeout vs connection reset): that would fragment the admin without a clear owner.rewriteModelResponse) is untouched.