Skip to content

Commit 059277f

Browse files
committed
docs: document provider error helpers
1 parent ae8b868 commit 059277f

4 files changed

Lines changed: 53 additions & 0 deletions

File tree

src/agents/live-model-errors.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
/**
2+
* Live-provider model error classifiers.
3+
*
4+
* Probe and fallback code uses these string checks to distinguish missing or
5+
* deprecated model ids from generic provider/runtime failures.
6+
*/
7+
/** Returns whether a provider error message indicates a missing or retired model id. */
18
export function isModelNotFoundErrorMessage(raw: string): boolean {
29
const msg = raw.trim();
310
if (!msg) {
@@ -45,6 +52,7 @@ export function isModelNotFoundErrorMessage(raw: string): boolean {
4552
return false;
4653
}
4754

55+
/** Returns whether a MiniMax HTML-style 404 body is a model-not-found signal. */
4856
export function isMiniMaxModelNotFoundErrorMessage(raw: string): boolean {
4957
const msg = raw.trim();
5058
if (!msg) {

src/agents/model-tool-support.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
/**
2+
* Model capability helper for tool-use support.
3+
*
4+
* Provider catalogs can opt a model out via `compat.supportsTools === false`;
5+
* absent metadata remains permissive for older catalog entries.
6+
*/
7+
/** Returns whether a catalog model should be offered tool calls. */
18
export function supportsModelTools(model: { compat?: unknown }): boolean {
29
const compat =
310
model.compat && typeof model.compat === "object"

src/agents/model-transport-debug.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
1+
/**
2+
* Environment-driven debug controls for model transport logging.
3+
*
4+
* Model adapters share these helpers so payload, SSE, and transport diagnostics
5+
* interpret OpenClaw debug environment variables consistently.
6+
*/
17
import type { createSubsystemLogger } from "../logging/subsystem.js";
28

39
type SubsystemLogger = ReturnType<typeof createSubsystemLogger>;
410

511
type ModelTransportDebugEnv = NodeJS.ProcessEnv;
612

13+
/** Payload debug detail levels accepted by `OPENCLAW_DEBUG_MODEL_PAYLOAD`. */
714
export type ModelPayloadDebugMode = "off" | "summary" | "tools" | "full-redacted";
15+
/** SSE debug detail levels accepted by `OPENCLAW_DEBUG_SSE`. */
816
export type ModelSseDebugMode = "off" | "events" | "peek";
917

1018
function normalizeEnv(value: unknown): string {
@@ -22,6 +30,7 @@ function isTruthyEnv(value: unknown): boolean {
2230
);
2331
}
2432

33+
/** Resolves model payload debug verbosity from `OPENCLAW_DEBUG_MODEL_PAYLOAD`. */
2534
export function resolveModelPayloadDebugMode(
2635
env: ModelTransportDebugEnv = process.env,
2736
): ModelPayloadDebugMode {
@@ -35,6 +44,7 @@ export function resolveModelPayloadDebugMode(
3544
return "off";
3645
}
3746

47+
/** Resolves SSE stream debug verbosity from `OPENCLAW_DEBUG_SSE`. */
3848
export function resolveModelSseDebugMode(
3949
env: ModelTransportDebugEnv = process.env,
4050
): ModelSseDebugMode {
@@ -48,6 +58,7 @@ export function resolveModelSseDebugMode(
4858
return "off";
4959
}
5060

61+
/** Returns whether any model transport debug channel is enabled. */
5162
export function isModelTransportDebugEnabled(env: ModelTransportDebugEnv = process.env): boolean {
5263
return (
5364
isTruthyEnv(env.OPENCLAW_DEBUG_MODEL_TRANSPORT) ||
@@ -57,6 +68,7 @@ export function isModelTransportDebugEnabled(env: ModelTransportDebugEnv = proce
5768
);
5869
}
5970

71+
/** Emits transport diagnostics at info level only when debug env explicitly enables them. */
6072
export function emitModelTransportDebug(log: SubsystemLogger, message: string): void {
6173
if (isModelTransportDebugEnabled()) {
6274
log.info(message);

src/agents/provider-http-errors.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
/**
2+
* Shared provider HTTP error normalization helpers.
3+
*
4+
* Transport adapters use this module to turn provider-specific response bodies,
5+
* request ids, and binary payload guardrails into stable OpenClaw error shapes.
6+
*/
17
export { asFiniteNumber } from "../../packages/normalization-core/src/number-coercion.js";
28
import { readResponseWithLimit } from "@openclaw/media-core/read-response-with-limit";
39
import { normalizeOptionalString as trimToUndefined } from "../../packages/normalization-core/src/string-coerce.js";
@@ -8,20 +14,24 @@ export { normalizeOptionalString as trimToUndefined } from "../../packages/norma
814
const ERROR_BODY_METADATA_LIMIT = 500;
915
const PROVIDER_BINARY_RESPONSE_MAX_BYTES = 16 * 1024 * 1024;
1016

17+
/** Returns a plain object view for provider JSON payloads when one exists. */
1118
export function asObject(value: unknown): Record<string, unknown> | undefined {
1219
return typeof value === "object" && value !== null && !Array.isArray(value)
1320
? (value as Record<string, unknown>)
1421
: undefined;
1522
}
1623

24+
/** Trims provider error details to a log- and prompt-safe preview length. */
1725
export function truncateErrorDetail(detail: string, limit = 220): string {
1826
return detail.length <= limit ? detail : `${detail.slice(0, limit - 1)}…`;
1927
}
2028

29+
/** Redacts secrets before preserving a bounded provider error body preview. */
2130
export function redactProviderErrorBody(body: string): string {
2231
return truncateErrorDetail(redactSensitiveText(body), ERROR_BODY_METADATA_LIMIT);
2332
}
2433

34+
/** Reads at most `limitBytes` from a response body without buffering provider-sized failures. */
2535
export async function readResponseTextLimited(
2636
response: Response,
2737
limitBytes = 16 * 1024,
@@ -64,13 +74,15 @@ export async function readResponseTextLimited(
6474
text += decoder.decode();
6575
} finally {
6676
if (reachedLimit) {
77+
// Stop the upstream body once the diagnostic budget is full.
6778
await reader.cancel().catch(() => {});
6879
}
6980
}
7081

7182
return text;
7283
}
7384

85+
/** Formats common provider JSON error payload shapes into one readable detail string. */
7486
export function formatProviderErrorPayload(payload: unknown): string | undefined {
7587
const root = asObject(payload);
7688
const detailObject = asObject(root?.detail);
@@ -132,6 +144,7 @@ function extractProviderErrorPayloadMetadata(payload: unknown): ProviderErrorPay
132144
};
133145
}
134146

147+
/** Metadata extracted from a non-2xx provider response body and headers. */
135148
export type ProviderHttpErrorInfo = {
136149
detail?: string;
137150
code?: string;
@@ -140,6 +153,7 @@ export type ProviderHttpErrorInfo = {
140153
requestId?: string;
141154
};
142155

156+
/** Extracts normalized provider error metadata while keeping the raw body bounded and redacted. */
143157
export async function extractProviderErrorInfo(response: Response): Promise<ProviderHttpErrorInfo> {
144158
const rawBody = trimToUndefined(await readResponseTextLimited(response).catch(() => ""));
145159
const requestId = extractProviderRequestId(response);
@@ -165,17 +179,20 @@ export async function extractProviderErrorInfo(response: Response): Promise<Prov
165179
}
166180
}
167181

182+
/** Returns only the normalized provider detail string for callers that do not need metadata. */
168183
export async function extractProviderErrorDetail(response: Response): Promise<string | undefined> {
169184
return (await extractProviderErrorInfo(response)).detail;
170185
}
171186

187+
/** Reads the provider request id header variants used across model and media APIs. */
172188
export function extractProviderRequestId(response: Response): string | undefined {
173189
return (
174190
trimToUndefined(response.headers.get("x-request-id")) ??
175191
trimToUndefined(response.headers.get("request-id"))
176192
);
177193
}
178194

195+
/** Error type carrying normalized provider status, request id, code, type, and body metadata. */
179196
export class ProviderHttpError extends Error {
180197
readonly status: number;
181198
readonly statusCode: number;
@@ -207,6 +224,7 @@ export class ProviderHttpError extends Error {
207224
}
208225
}
209226

227+
/** Builds the human-facing provider HTTP error message from normalized metadata. */
210228
export function formatProviderHttpErrorMessage(params: {
211229
label: string;
212230
status: number;
@@ -222,6 +240,7 @@ export function formatProviderHttpErrorMessage(params: {
222240
);
223241
}
224242

243+
/** Creates a normalized provider HTTP error from a failed response. */
225244
export async function createProviderHttpError(
226245
response: Response,
227246
label: string,
@@ -246,6 +265,7 @@ export async function createProviderHttpError(
246265
);
247266
}
248267

268+
/** Throws a normalized provider error when a fetch response is not OK. */
249269
export async function assertOkOrThrowProviderError(
250270
response: Response,
251271
label: string,
@@ -256,13 +276,15 @@ export async function assertOkOrThrowProviderError(
256276
throw await createProviderHttpError(response, label);
257277
}
258278

279+
/** Throws a normalized generic HTTP error when a fetch response is not OK. */
259280
export async function assertOkOrThrowHttpError(response: Response, label: string): Promise<void> {
260281
if (response.ok) {
261282
return;
262283
}
263284
throw await createProviderHttpError(response, label, { statusPrefix: "HTTP " });
264285
}
265286

287+
/** Parses a provider JSON response and wraps malformed JSON with the caller's label. */
266288
export async function readProviderJsonResponse<T>(response: Response, label: string): Promise<T> {
267289
try {
268290
return (await response.json()) as T;
@@ -271,6 +293,7 @@ export async function readProviderJsonResponse<T>(response: Response, label: str
271293
}
272294
}
273295

296+
/** Parses a provider JSON response that must be a top-level object. */
274297
export async function readProviderJsonObjectResponse(
275298
response: Response,
276299
label: string,
@@ -283,6 +306,7 @@ export async function readProviderJsonObjectResponse(
283306
return object;
284307
}
285308

309+
/** Parses a provider JSON object response and returns an array field. */
286310
export async function readProviderJsonArrayFieldResponse(
287311
response: Response,
288312
label: string,
@@ -301,6 +325,7 @@ function normalizeContentType(response: Response): string | undefined {
301325
return contentType || undefined;
302326
}
303327

328+
/** Rejects text or JSON responses on provider endpoints that should return binary bytes. */
304329
export function assertProviderBinaryResponseContent(
305330
response: Response,
306331
label: string,
@@ -319,6 +344,7 @@ export function assertProviderBinaryResponseContent(
319344
}
320345
}
321346

347+
/** Reads a bounded non-empty binary provider response after content-type validation. */
322348
export async function readProviderBinaryResponse(
323349
response: Response,
324350
label: string,

0 commit comments

Comments
 (0)