/** * Error classes thrown by the SDK 2.0 client surface. */ import type { ErrorEnvelope } from '../qar/envelopes.js'; import type { JsonObject } from '../qar/json.js'; import type { ToolApiErrorCode } from '../qar/tools.js'; /** * Thrown by API surfaces whose bodies haven't landed yet. Loud-but-typed — * the `ticket` field tells callers which work item fills this method's * body so they can wait for the right milestone. */ export declare class QodoNotImplementedError extends Error { /** Always `'QodoNotImplementedError'`. */ readonly name = "QodoNotImplementedError"; /** Human-readable name of the API surface that's not yet implemented. */ readonly api: string; /** Ticket ID that fills this stub. */ readonly ticket: string; constructor(api: string, ticket: string); } /** * Thrown when consumer code drives the client into an invalid state at * construction time (bad URL, missing required option). Distinct from * `QodoNotImplementedError` because this is a real validation failure. */ export declare class QodoClientOptionsError extends Error { readonly name = "QodoClientOptionsError"; constructor(message: string); } /** * Thrown by `tasks.cancel` when the consumer-supplied `AbortSignal` * short-circuits the cancel. Distinct from the generic "connection closed * before task.done arrived" failure shape so consumers can branch on * intentional abort vs. server-side cancel failure. * * `kind` distinguishes two scenarios with materially different wire * effects: * * - `'pre_aborted'`: signal was already aborted at the call site. * NO wire `task.cancel` was emitted (and nothing else). The * consumer can safely treat the task as untouched by this call. * Because `tasks.cancel` is async, this surfaces as a rejected * Promise — `try / catch` around `await tasks.cancel(...)` is * the consumer-side pattern, identical to the post-send-abort * case below. * * - `'aborted_after_send'`: the wire `task.cancel` was already on * the wire when the signal aborted. The server's terminal * `task.done` still arrives on the task's own subscription * (initiated by `tasks.start` / `tasks.continue`); only the * wait inside `tasks.cancel` was abandoned. * * Carries `taskId` so consumers can match the throw against their own * task-id state without parsing the message. */ export declare class QodoCancelAbortedError extends Error { readonly name = "QodoCancelAbortedError"; readonly taskId: string; readonly kind: 'pre_aborted' | 'aborted_after_send'; constructor(kind: 'pre_aborted' | 'aborted_after_send', taskId: string, reason?: unknown); } /** * Thrown synchronously by `tasks.cancel` / `tasks.continue` / * `tasks.resubscribe` / `tools.respond` when the SDK can't determine the * per-Task / per-ToolCall `session_id` locally AND the caller didn't pass * the explicit `sessionId` option. * * Surfaces locally before the wire write so the remediation lands in the * error message rather than in a wire round-trip's * `session_mismatch` rejection: * * - For cross-process recovery: hydrate `{ taskId, sessionId }` from * durable storage and pass `sessionId` in the cold-address options. * - For HITL respond after restart: same shape via * `client.tools.respond(node, response, { sessionId })`. * * `kind` is a stable discriminator (`'task'` for the three task ongoing * envelopes; `'tool_call'` for `tools.respond`) so consumer logging / * branching can pick the right hydration path without parsing the message. */ export declare class QodoColdAddressError extends Error { readonly name = "QodoColdAddressError"; readonly kind: 'task' | 'tool_call'; readonly addressId: string; constructor(kind: 'task' | 'tool_call', addressId: string); } /** * Client-side `idempotency_key` validation failure. * * Thrown synchronously by `tasks.start` / `tasks.startWithAgent` / * `tasks.startWithGraph` BEFORE the wire write when the consumer-supplied * `idempotencyKey` violates the wire contract (1–512 **Unicode code * points** — counted by `[...str].length`, not UTF-16 code units — and no * NUL byte). Mirrors QAR's Pydantic `Field(min_length=1, max_length=512, * pattern=r"^[^\x00]+$")` on `TaskStartPayload.idempotency_key` so a bad * value fails fast on the SDK side without waiting for the wire round-trip. * * The `reason` field is a stable discriminator (`'too_short'`, `'too_long'`, * `'contains_nul'`) so test assertions and downstream consumer error * handling can branch without parsing the human message. */ export declare class QodoIdempotencyKeyValidationError extends Error { readonly name = "QodoIdempotencyKeyValidationError"; readonly reason: 'too_short' | 'too_long' | 'contains_nul'; readonly codePoints: number; constructor(reason: 'too_short' | 'too_long' | 'contains_nul', codePoints: number); } /** * Multimodal `content` validation failure. * * Thrown synchronously by the content-part builders (`textPart` / `filePart` * / `imagePart`) and by `tasks.start` / `tasks.startWithAgent` / * `tasks.startWithGraph` / `tasks.continue` (and `tasks.continueOrStart` * transitively) BEFORE the wire write, when a `task.start.input` violates the * provider-neutral, schema-level invariants of QAR's `QodoTaskStartPayload`: * * - `user_query_and_content` — both `user_query` and `content` are set. * The wire contract is mutually exclusive: a turn is the plain string OR * the ordered parts, never both. * - `empty_content` — `content` is present but an empty array. A present * `content` key must carry at least one part (an empty turn is a * malformed multimodal message, not the deps-only path — omit the key * for that). * - `too_many_parts` — `content` exceeds the wire part-flood cap * ({@link MAX_CONTENT_PARTS}). * - `invalid_part` — a `content` entry is not a well-formed discriminated * part: not an object, a missing/unknown `type` (the wire models * `content` as a discriminated union on `type`), or a `text` part whose * `text` is not a string. * - `missing_media_type` — a file part was built without a non-empty * `mediaType`. * - `empty_file_data` — a file part decoded to zero bytes. * - `invalid_base64` — a string passed as file `data` is not valid base64. * * The SDK enforces only these invariants — it does NOT replicate the * operator-owned media-type allowlist or per-message size caps, which are * deliberately kept off the wire schema and out of the bindings (the runtime * applies them at dispatch). `reason` is a stable discriminator so consumers * can branch without parsing the message; `partIndex` locates the offending * part when the failure is part-specific. */ export declare class QodoContentValidationError extends Error { readonly name = "QodoContentValidationError"; readonly reason: 'user_query_and_content' | 'empty_content' | 'too_many_parts' | 'invalid_part' | 'missing_media_type' | 'empty_file_data' | 'invalid_base64'; /** Index into the `content` array of the offending part, when applicable. */ readonly partIndex?: number; constructor(reason: QodoContentValidationError['reason'], message: string, partIndex?: number); } /** * Thrown synchronously by {@link TaskClient.continueOrStart} when the * `graphSpec` argument is `undefined`. The helper requires a graphSpec * to handle the fresh-dispatch branch; consumers without one on hand * should reach for {@link TaskClient.continue} (if they already have a * `taskId`) or {@link TaskClient.forceResume} (if they only have the * `idempotencyKey` and want stuck-session recovery). * * Carries the rejected `idempotencyKey` so error-handling code can * surface which session-derivation key triggered the throw. */ export declare class RequiredGraphSpecError extends Error { readonly name = "RequiredGraphSpecError"; readonly idempotencyKey: string; constructor(idempotencyKey: string); } /** * Thrown at the transport seam for failures the underlying WebSocket * library can't surface in a typed way. Two cases live here: * * 1. **Pre-wire validation** — e.g. the RFC 6455 close-frame reason cap: * a caller synthesizing a reason longer than 123 UTF-8 bytes gets a * typed SDK error rather than an opaque `ws` crash. These are * programming errors and are NOT retryable (`isRetryable === false`, * no `statusCode`). * 2. **WS upgrade failure** — a non-auth HTTP response on the upgrade * (e.g. a `502`/`503` from the load balancer during a backend deploy). * These carry the HTTP `statusCode` and an `isRetryable` hint so a * consumer can branch on the type + status instead of string-matching * the message. `401`/`403` are auth failures and surface as * {@link QodoAuthError} instead — they never reach here. * * `isRetryable` is a transient-failure hint: `5xx` and `429` upgrade * responses (and a status-less transport drop before the upgrade * completed) are transient, so a retry of `connect()` is reasonable; a * `4xx` (other than 429) is a permanent client error. */ export declare class QodoTransportError extends Error { readonly name = "QodoTransportError"; /** * HTTP status from a failed WS upgrade response, when the failure was an * HTTP response (e.g. `502`). `undefined` for pre-wire validation * failures and status-less transport drops. */ readonly statusCode?: number; /** WebSocket close code for a socket that closed before opening. */ readonly closeCode?: number; /** * Whether the failure class is transient and retrying `connect()` is * reasonable. `true` for `5xx`/`429` upgrade responses and status-less * pre-upgrade drops; `false` for pre-wire validation errors and * permanent `4xx` responses. */ readonly isRetryable: boolean; constructor(message: string, options?: { readonly statusCode?: number; readonly closeCode?: number; readonly isRetryable?: boolean; /** * The underlying error this wraps (e.g. the raw `ws` socket error for a * pre-open DNS/TCP/TLS failure). Preserved so consumers can inspect the * original `code` / stack without string-matching the message. */ readonly cause?: unknown; }); } /** * Thrown when an outbound `task.start` / `task.continue` is rejected because * the connection is in `flow.pause` state and the paused queue has already * reached its cap. The matching wire-level taxonomy is * `sdk.error { code: 'flow_backlog_exceeded' }`. * * Pathological case: under healthy traffic only one or two envelopes ever * queue before `flow.resume` arrives. Hitting the cap means the consumer is * driving the client far above QAR's per-session in-flight ceiling — backing * off and waiting for `flow.resume` is the correct response. */ export declare class QodoBackpressureError extends Error { readonly name = "QodoBackpressureError"; /** Wire-aligned error code. */ readonly code = "flow_backlog_exceeded"; /** How many envelopes were already queued when this call was rejected. */ readonly queueSize: number; /** The configured cap. */ readonly queueCap: number; constructor(queueSize: number, queueCap: number); } /** * Thrown by `client.specs.validate` when the supplied spec is structurally * unfit to send — most commonly a missing or unknown `kind` discriminator. * * This is a *pre-wire* rejection: the spec never reached QAR. Per-rule * failures (D10-R*, D11-R*) come back from the endpoint in the * `SpecValidateResult.errors` array — those are not exceptions, they're a * normal `valid: false` result. */ export declare class QodoSpecValidationError extends Error { readonly name = "QodoSpecValidationError"; constructor(message: string); } /** * Thrown by `client.qar.registerAgent` / `client.qar.registerMcp` / * `client.qar.registerA2A` when a name conflicts with an existing * registration (and `replace: true` wasn't passed), or when the supplied * name / endpoint is empty. * * Carries `entity` (`'agent' | 'mcp' | 'a2a'`) and `entryName` so test code * and structured loggers can branch on the specific conflict shape without * parsing the message text. `name` (the standard Error field) is fixed at * `'QodoRegistryConflictError'`. * * **`entity` is open-ended by design.** New register-helpers (S9 added * `'a2a'`; future surfaces will add more) extend this union additively. * Consumers writing exhaustive `switch` / `assertNever` patterns on * `entity` should treat unknown values as "another registry the SDK * grew" — typically by routing through a default arm that surfaces the * raw `entryName` + message. The SDK is on the 2.x major; breaking the * union literally is allowed within the major per the SDK1→2 migration * posture, but each addition lands behind its own feature commit so * consumer code can pin if needed. */ export declare class QodoRegistryConflictError extends Error { readonly name = "QodoRegistryConflictError"; /** Which registry the conflict came from. */ readonly entity: 'agent' | 'mcp' | 'a2a'; /** The name the caller tried to register. */ readonly entryName: string; constructor(entity: 'agent' | 'mcp' | 'a2a', entryName: string, message: string); } /** * Wire-validation context attached to a `QodoWireValidationError`. Populated * on inbound failures so consumers routing the error into structured * logging / metrics can branch on the exact protocol drift without parsing * the `[@qodo/sdk]` console.error breadcrumb. */ export interface WireValidationContext { /** * `'outbound'` — thrown synchronously from `client.tools.respond(...)` * when the caller's input violates the wire shape. * `'inbound'` — surfaced (NOT thrown) via * `client.tools.onWireValidationError(...)` when the SDK drops a malformed * `tool.request` arriving from the runtime. */ readonly scope: 'outbound' | 'inbound'; /** `message_id` of the offending envelope (inbound only). */ readonly messageId?: string; /** * `node_name` from the offending envelope, if it was present and well-shaped * (inbound only). Absent for the "missing node_name" violation itself. */ readonly nodeName?: string; } /** * Surfaced when the SDK's tool-tunneling layer encounters an envelope * that violates the parallel-batched wire shape. Two scopes: * * - **`outbound`** — thrown synchronously from `client.tools.respond(...)` * when the caller's input is malformed (empty `node_name`, empty * `responses`). Catches consumer bugs at the call site instead of * letting them silently ship a malformed envelope onto the wire. * * - **`inbound`** — NOT thrown (throwing would fail the whole connection * across every subscription). Surfaced via * `client.tools.onWireValidationError(handler)` after the * `[@qodo/sdk]` console.error breadcrumb fires. The SDK has no * `tool_call_id` to respond against for these envelopes, so consumers * observe the failure but can't actively recover — QAR's per-task * tool-response timeout is the wire-side safety net. * * Handler-return shape violations (positional length mismatch from a * `ToolRequestHandler`, malformed `ToolResponseResult`) are NOT surfaced as * `QodoWireValidationError` — they're converted to per-call * `status: 'error'` items on the wire so the agent loop unblocks * deterministically. * * Distinct from `TypeError` because the failure is wire-shape specific; * consumers wanting a broader catch should `instanceof Error`. The * structured `context` field is the preferred branch surface — * `instanceof QodoWireValidationError` then switch on `err.context.scope`. */ export declare class QodoWireValidationError extends Error { readonly name: string; /** Structured drop metadata. Always populated. */ readonly context: WireValidationContext; constructor(message: string, context?: WireValidationContext); } /** * Thrown by `tasks.startWithAgent` / `tasks.startWithGraph` when the * consumer's `mcpTools` selector references an MCP name that isn't * registered on this client AND the selector opted into strict validation * via `mcpTools.onMissing: 'reject'`. Under the default `'drop'` policy the * unregistered reference is soft-dropped (with a `qodo.sdk.mcp.tool_dropped` * event) and this error is not raised. * * Surface remediation: call `client.qar.registerMcp('', ...)` * before the dispatch, or drop the entry from the `mcpTools` selector. */ export declare class QodoUnknownMcpError extends QodoWireValidationError { readonly name = "QodoUnknownMcpError"; /** Distinct MCP names referenced by `mcpTools` but not present in the registry. */ readonly mcpNames: readonly string[]; constructor(mcpNames: readonly string[]); } /** * Thrown by `tasks.startWithAgent` / `tasks.startWithGraph` when the * consumer's `mcpTools` selector — or the sibling `mcpToolOverrides` * map — references a `.` dotted name whose MCP IS registered * but whose live catalog doesn't expose the named tool, AND the selector * opted into strict validation via `mcpTools.onMissing: 'reject'`. Under * the default `'drop'` policy the unresolved reference is soft-dropped * (with a `qodo.sdk.mcp.tool_dropped` event) and this error is not raised. * * Catches version drift between consumer code and upstream MCP catalogs * at task.start, not at LLM-call time. Pair with * `client.qar.listMcpTools(name)` during development to see the live * surface. */ export declare class QodoUnknownMcpToolError extends QodoWireValidationError { readonly name = "QodoUnknownMcpToolError"; /** Distinct `.` dotted names that don't resolve to a discovered tool. */ readonly dottedNames: readonly string[]; constructor(dottedNames: readonly string[]); } /** * Thrown by `tasks.startWithAgent` / `tasks.startWithGraph` when a * registered MCP whose `unavailability` policy is `'fail'` (the default) * has no cached catalog at projection time — its cold-start * `Client.connect()` + `tools/list` cycle didn't complete inside the * SDK's settle window. * * Indicates a real config / startup bug for local sidecars (typical * fail-mode for `litegit`, `slack`, in-cluster MCPs). For third-party * remote MCPs that flake transiently, register with * `{ unavailability: 'warn' }` to ship without the MCP's tools instead * of failing the task. */ export declare class QodoMcpUnavailableError extends QodoWireValidationError { readonly name = "QodoMcpUnavailableError"; /** Distinct MCP names whose `unavailability` is `'fail'` and whose catalog hasn't populated. */ readonly mcpNames: readonly string[]; constructor(mcpNames: readonly string[]); } /** * One pre-wire validation failure on an inline `GraphSpec`. Mirrors QAR's * `SpecValidationError` envelope (rule_id + path + message) so consumers can * use the same branch logic for both client-side rejection (here) and * `client.specs.validate(...)` round-trips. */ export interface InlineGraphValidationFailure { /** Wire rule identifier (e.g. `'D11-R6'`, `'D11-R9'`, `'D11-R11'`, `'D11-R12'`). */ readonly rule_id: string; /** JSON Pointer (RFC 6901) into the offending spec. `""` denotes the root. */ readonly path: string; /** Human-readable explanation. */ readonly message: string; } /** * Thrown by `client.tasks.startWithGraph(...)` when the inline `GraphSpec` * fails one of the SDK's pre-wire structural checks against the * GraphSpec safe subset. * * Pre-wire rejection: the envelope never reaches QAR. Same `rule_id` / * `path` / `message` shape as `client.specs.validate(...)` per-rule failures, * so consumers can route both surfaces into the same error handler. * * The SDK enforces the rule subset that doesn't require server-side * state (no tenant lookup, no model-registry probe): * - `D11-R1..R3` — entry / agents present + named uniquely. * - `D11-R6..R8` — edges resolve to declared agents, entry resolves. * - `D11-R9` — `evaluate` edges only target evaluator-role nodes. * - `D11-R10` — graph depth ≤ configured maximum (default 4). * - `D11-R11` — evaluator nodes are leaves (no outbound edges). * - `D11-R12` — evaluator `output_schema` is shaped like `VerdictResult`. * - `D11-Rcycle` — acyclicity (the SDK rejects cycles unconditionally; QAR * surfaces the same rule via `D11-R9` numbering in its own response shape). * * Rules requiring server-side state (AgentSpec composition, alternate * operator-maximum depth) flow through the `client.specs.validate(...)` * opt-in pre-flight instead — see `preflight: true` on `TaskOptions`. */ export declare class QodoInlineGraphValidationError extends Error { readonly name = "QodoInlineGraphValidationError"; /** All failures the validator observed, in stable depth-first order. */ readonly failures: readonly InlineGraphValidationFailure[]; constructor(failures: readonly InlineGraphValidationFailure[]); } /** * Per-violation entry carried on `QodoInlineAgentValidationError` and * `QodoAgentSpecRejectedError`. Mirrors the QAR-side `agent_spec_rejected` * error envelope shape so consumers handling both paths can branch on the * same `(rule_id, path, message)` triple. * * `rule_id` is one of the `D10-R*` set (server-side wire validator) or a * `D10-SHAPE-*` synthetic id (SDK-side pre-wire shape check — distinct * prefix so SDK-only ids never collide with QAR's documented ruleset). * `path` is an RFC 6901 JSON Pointer into the spec — `""` denotes the * root. * * Shape parallels `InlineGraphValidationFailure` so consumers can write * one error handler that branches on `instanceof` and reads the same * fields off either error class. */ export interface InlineAgentSpecIssue { readonly rule_id: string; readonly path: string; readonly message: string; } /** * Thrown synchronously by `client.tasks.startWithAgent({ agent: spec, ... })` * when the supplied `InlineAgentSpec` violates the data-only safe subset * before the wire write. Carries the structured `issues` array so * structured-logging consumers can branch on `rule_id` / `path` without * parsing the message text. * * **Pre-wire only.** The mirror error for server-rejected specs (after * the wire write, when QAR's validator runs the full ruleset including * registry-dependent rules) is `QodoAgentSpecRejectedError`, surfaced * via the task iterator's `kind: 'error'` envelope. * * Distinct from `QodoSpecValidationError` (which is for * `client.specs.validate` — the pre-flight wrapper around * `POST /v1/specs/validate`); both exist because the pre-flight wrapper * accepts intentionally-invalid shapes (the whole point is to ask the * server "tell me which rule I broke"), while `startWithAgent` rejects * at intake to avoid kicking off server-side work the spec can't possibly * pass. */ export declare class QodoInlineAgentValidationError extends Error { readonly name = "QodoInlineAgentValidationError"; /** Per-violation breakdown — at least one entry. */ readonly issues: readonly InlineAgentSpecIssue[]; constructor(issues: readonly InlineAgentSpecIssue[]); } /** * Thrown / surfaced when QAR's `_handle_task_start` rejects the supplied * inline `agent: InlineAgentSpec` (Pattern B) at wire-validation time via * an `error { code: 'agent_spec_rejected' }` envelope. Mirror for the * server-static path doesn't exist — there's no inline-spec to reject for * Pattern A. * * Carries the full `issues` array so consumers can show per-rule messages * in IDE / Studio surfaces. The first issue's `rule_id` is also exposed * at `rule_id` / `path` for the common "just give me the primary failure" * branch. * * Surfaced via the iterator returned by `tasks.startWithAgent`: when the * first inbound envelope is an `error { code: 'agent_spec_rejected' }`, * the iterator rejects with this error (instead of yielding the envelope) * so consumers don't need to defensively type-narrow the error case out * of `TaskEvent.kind`. */ export declare class QodoAgentSpecRejectedError extends Error { readonly name = "QodoAgentSpecRejectedError"; /** Wire-aligned error code. */ readonly code = "agent_spec_rejected"; /** Per-violation breakdown — at least one entry. */ readonly issues: readonly InlineAgentSpecIssue[]; /** Convenience: first issue's `rule_id` (`'D10-R*'` or `'D10-UNSUPPORTED*'`). */ readonly rule_id: string; /** Convenience: first issue's `path` (RFC 6901 JSON Pointer; `""` = root). */ readonly path: string; constructor(issues: readonly InlineAgentSpecIssue[], message?: string); } /** * One per-rule entry on a server `error` envelope's `payload.errors`, when * the envelope carries the structured array (D15-R*, agent-spec-rejected * shape). Mirrors `InlineAgentSpecIssue` but is the canonical shape across * every typed server-error class — agent-spec rejection still ships its * own `InlineAgentSpecIssue` alias for back-compat with the existing * `QodoAgentSpecRejectedError` consumers. */ export interface ServerErrorEntry { /** D10/D11/D15 rule identifier or QAR-side code (`'cancel_routing_failed'`, …). */ readonly rule_id: string; /** JSON Pointer (RFC 6901) into the offending envelope/spec. `""` denotes the root. */ readonly path: string; /** Human-readable explanation. */ readonly message: string; } /** * Base class for every typed server-error class (cancel/resume/HITL/graph * codes). Each concrete subclass pins its `code` to the documented QAR * wire string so consumers can branch on * `instanceof QodoCancelRoutingFailedError` instead of * `err.code === 'cancel_routing_failed'`. * * `QodoAgentSpecRejectedError` predates this base and keeps its own * shape; new error codes here use the unified `QodoServerError` surface * for forward compatibility. */ export declare class QodoServerError extends Error { /** Wire-level QAR error code. Pinned per subclass. */ readonly code: string; /** * Structured per-rule breakdown, if QAR shipped one on the envelope. Empty * array when the envelope only carried top-level `code` + `message`. */ readonly errors: readonly ServerErrorEntry[]; /** `payload.offending_message_id` — useful for tracing the cause envelope. */ readonly offendingMessageId?: string; /** * @param name The concrete subclass name (matches `this.name`). * @param code Wire-level error code. * @param message Human-readable summary; mirrored to `Error.message`. * @param errors Structured breakdown when QAR emitted one. Default `[]`. * @param offendingMessageId `error.payload.offending_message_id` if present. */ constructor(name: string, code: string, message: string, errors?: readonly ServerErrorEntry[], offendingMessageId?: string); } /** Cancel routing lookup failed — see QAR `_handle_task_cancel`. */ export declare class QodoCancelRoutingFailedError extends QodoServerError { readonly name = "QodoCancelRoutingFailedError"; constructor(message: string, errors?: readonly ServerErrorEntry[], offendingMessageId?: string); } /** Cancel all-writes-fail — see QAR `_handle_task_cancel`. */ export declare class QodoCancelFailedError extends QodoServerError { readonly name = "QodoCancelFailedError"; constructor(message: string, errors?: readonly ServerErrorEntry[], offendingMessageId?: string); } /** Session lookup miss — `cancel`/`continue` against an unknown task. */ export declare class QodoTaskNotFoundError extends QodoServerError { readonly name = "QodoTaskNotFoundError"; constructor(message: string, errors?: readonly ServerErrorEntry[], offendingMessageId?: string); } /** Cancel-on-non-waiting-task — see QAR `_handle_task_cancel` precondition. */ export declare class QodoTaskNotWaitingError extends QodoServerError { readonly name = "QodoTaskNotWaitingError"; constructor(message: string, errors?: readonly ServerErrorEntry[], offendingMessageId?: string); } /** Pod failed to reconstruct the agent for a cross-pod task. */ export declare class QodoAgentReconstructionFailedError extends QodoServerError { readonly name = "QodoAgentReconstructionFailedError"; constructor(message: string, errors?: readonly ServerErrorEntry[], offendingMessageId?: string); } /** Cross-pod resume hook aborted before delivering control. */ export declare class QodoCrossPodResumeAbortedError extends QodoServerError { readonly name = "QodoCrossPodResumeAbortedError"; constructor(message: string, errors?: readonly ServerErrorEntry[], offendingMessageId?: string); } /** Deps construction failed during agent dispatch (Pattern A/B/C). */ export declare class QodoDepsConstructionFailedError extends QodoServerError { readonly name = "QodoDepsConstructionFailedError"; constructor(message: string, errors?: readonly ServerErrorEntry[], offendingMessageId?: string); } /** Message history load failed during resume / continue. */ export declare class QodoMessageHistoryLoadFailedError extends QodoServerError { readonly name = "QodoMessageHistoryLoadFailedError"; constructor(message: string, errors?: readonly ServerErrorEntry[], offendingMessageId?: string); } /** HITL persistence failure — substrate accepted but the row didn't durable. */ export declare class QodoHitlPersistFailedError extends QodoServerError { readonly name = "QodoHitlPersistFailedError"; constructor(message: string, errors?: readonly ServerErrorEntry[], offendingMessageId?: string); } /** HITL substrate unavailable — backing store offline / unconfigured. */ export declare class QodoHitlSubstrateUnavailableError extends QodoServerError { readonly name = "QodoHitlSubstrateUnavailableError"; constructor(message: string, errors?: readonly ServerErrorEntry[], offendingMessageId?: string); } /** Caller is not the authorized resolver for the HITL row. */ export declare class QodoUnauthorizedResolverError extends QodoServerError { readonly name = "QodoUnauthorizedResolverError"; constructor(message: string, errors?: readonly ServerErrorEntry[], offendingMessageId?: string); } /** HITL resolution payload failed validation against the prompt's schema. */ export declare class QodoInvalidResolutionError extends QodoServerError { readonly name = "QodoInvalidResolutionError"; constructor(message: string, errors?: readonly ServerErrorEntry[], offendingMessageId?: string); } /** * Pattern C (inline graph) validator rejection — GraphSpec rule failure * surfaced AFTER the wire. Mirror of `QodoAgentSpecRejectedError` for the * graph path; the `errors[]` array carries each `D11-R*` / `D13-R*` * failure with `rule_id` + `path` + `message`. */ export declare class QodoGraphSpecRejectedError extends QodoServerError { readonly name = "QodoGraphSpecRejectedError"; constructor(message: string, errors?: readonly ServerErrorEntry[], offendingMessageId?: string); } /** * Typed error for QAR's `session_mismatch` wire rejection. Surfaces when * an outbound ongoing envelope (`task.continue` / `task.cancel` / * `task.resubscribe` / `tool.response`) carries a `session_id` that * doesn't match the connection's bound session for the referenced task. * * The SDK no longer mints a zero-UUID sentinel for cold-address paths — * the missing-session case is caught locally and raised as * {@link QodoColdAddressError} before the wire write. This typed error * fires only when the consumer-supplied `sessionId` override on the * cold-address API doesn't actually match the server's bound session * (stale durable-storage row, deliberate mismatch test). */ export declare class QodoSessionMismatchError extends QodoServerError { readonly name = "QodoSessionMismatchError"; constructor(message: string, errors?: readonly ServerErrorEntry[], offendingMessageId?: string); } /** * QAR rejected a `task.start` admission because the derived session is * already running — another connection / pod holds the session lease. * Fires on the deterministic-`idempotencyKey` admission path when a * second `task.start` for the same session loses the lease race against * a still-active prior run. * * Recoverable, NOT a hard failure: the session exists and is * addressable. The carried `sessionId` (when present) is the derived * session UUID — a consumer can `task.resubscribe` against the in-flight * run to observe it, or retry the admission once the holding run reaches * a terminal state (the retry then re-dispatches the turn fresh). Branch * on `instanceof QodoSessionAlreadyRunningError` (or `err.code === * 'session_already_running'`) rather than message-matching. * * The wire envelope carries the derived `session_id`, exposed here as * `sessionId` so consumers don't have to dig through the envelope. * `undefined` only on synthetic envelopes that omit the field. */ export declare class QodoSessionAlreadyRunningError extends QodoServerError { readonly name = "QodoSessionAlreadyRunningError"; /** * Derived `session_id` from the inbound `session_already_running` * envelope. Populated by {@link attachSessionId} (called by * `errorFromServerErrorEnvelope` when it has the inherited envelope * field in hand). The constructor matches the unified server-error * factory signature so the typed-error dispatcher * (`classForServerErrorCode`) can build instances uniformly. */ sessionId?: string; constructor(message: string, errors?: readonly ServerErrorEntry[], offendingMessageId?: string); /** Internal — set by the envelope-to-error helper. Read-once-after-construct. */ attachSessionId(sessionId: string): void; } /** * Admission has been pending past the operator timeout * (`PENDING_ADMISSION_TIMEOUT`, server default 5 min). Terminal, * non-retryable. Scoped to the derived `session_id` so the consumer can * `task.resubscribe` if a recovery path exists, but the typical handling * is to surface the failure to the operator — the server's sweeper will * compensate the orphan row on its next sweep cycle. * * The wire envelope carries the derived `session_id` — exposed here as * `sessionId` so consumers don't need to dig through the envelope to * find it. `undefined` only on synthetic / spec-violating envelopes * that omit the field. */ export declare class QodoAdmissionStalledError extends QodoServerError { readonly name = "QodoAdmissionStalledError"; /** * Derived `session_id` from the inbound `admission_stalled` envelope. * Populated by {@link attachSessionId} (called by * `errorFromServerErrorEnvelope` when it has the inherited envelope * field in hand) — the constructor matches the unified server-error * factory signature so the typed-error dispatcher (`classForServerErrorCode`) * can build instances uniformly. `undefined` only on synthetic envelopes * that omit the session_id field. */ sessionId?: string; constructor(message: string, errors?: readonly ServerErrorEntry[], offendingMessageId?: string); /** Internal — set by the envelope-to-error helper. Read-once-after-construct. */ attachSessionId(sessionId: string): void; } /** * Client-side terminal when the consumer breaks the `TaskStartIterable` * (via `iter.return()`, `break` inside a `for await`, or `iter.throw()`) * BEFORE the server's `task.started` admission ack arrives. * * Surfaces on `await stream.sessionId` / `await stream.admittedTaskId` so * the caller's pending awaits don't hang forever after they've abandoned * the stream. * * Distinct from `QodoAdmissionTimeoutError` (SDK-side budget exhaustion) * and `QodoAdmissionStalledError` (server-emitted terminal) so consumer * code can branch on the reason — voluntary abort vs. genuine admission * failure. */ export declare class QodoStreamAbortedError extends Error { readonly name = "QodoStreamAbortedError"; constructor(message?: string); } /** * Client-side terminal after the SDK's `admission_in_progress` retry * loop exhausts its budget without ever seeing a `task.started` ack. * * The SDK honours the server's `retry_after_ms` hint when present and * falls back to exponential backoff with jitter (initial 100 ms, doubling, * capped at `PENDING_ADMISSION_TIMEOUT = 5 min`). Reaching the cap means * the deterministic-key admission contended for the full timeout window * without resolving. * * `sessionId` carries the derived session UUID extracted from the final * `admission_in_progress` envelope so a consumer that wants to * `task.resubscribe` has the address; `undefined` only when no * admission_in_progress envelope was ever observed (transport drop * mid-retry). */ export declare class QodoAdmissionTimeoutError extends Error { readonly name = "QodoAdmissionTimeoutError"; /** Total wall-clock milliseconds spent retrying before giving up. */ readonly elapsedMs: number; /** Number of `admission_in_progress` envelopes observed before timing out. */ readonly attempts: number; /** Derived `session_id` from the final envelope, if observed. */ readonly sessionId?: string; constructor(elapsedMs: number, attempts: number, sessionId?: string); } /** * Fallback for any unrecognized `error.code` value arriving from QAR. * * The SDK's typed-error catalog tracks the codes QAR's documented contract * surfaces; a new code that hasn't landed in the SDK yet still surfaces * as a typed throw (via this class) so consumers' `catch * (err: QodoServerError)` blocks see structure rather than a yielded * `kind: 'error'` event their type narrows can't account for. Branch on * `err.code` (the raw wire string) until the SDK adds a typed subclass. */ export declare class QodoUnknownServerError extends QodoServerError { readonly name = "QodoUnknownServerError"; constructor(code: string, message: string, errors?: readonly ServerErrorEntry[], offendingMessageId?: string); } /** * Map a wire `error.code` to its typed `QodoServerError` subclass. Returns * `undefined` for the SDK-side `agent_spec_rejected` code — that case is * intentionally handled by `QodoAgentSpecRejectedError`'s own * `errorFromAgentSpecRejection` parser (it carries an * `InlineAgentSpecIssue[]` shape that predates the unified * `ServerErrorEntry`). All other documented codes route through here. * * Callers needing to wrap an arbitrary error envelope: prefer the * higher-level `errorFromServerErrorEnvelope` helper in `TaskClient.ts` — * it handles the parse-`errors[]` step, the `agent_spec_rejected` carve- * out, and the `QodoUnknownServerError` fallback uniformly. */ export declare function classForServerErrorCode(code: string): (new (message: string, errors?: readonly ServerErrorEntry[], offendingMessageId?: string) => QodoServerError) | undefined; /** * Thrown when the SDK's MCP client pool fails to connect to a registered * remote / stdio MCP server. * * Carries the registered MCP `name` so callers can branch / log without * parsing the message text. `cause` is the underlying transport / protocol * error from `@modelcontextprotocol/sdk` (`McpError`, `StreamableHTTPError`, * `SseError`, plain `Error` from `Client.connect`) — preserved on * `Error.cause` per the standard idiom. * * Distinct from `QodoMcpToolError` so consumer code can branch on * "connection failed" vs. "tool invocation failed" without inspecting * the underlying cause. */ export declare class QodoMcpClientError extends Error { readonly name = "QodoMcpClientError"; /** Registered MCP name (the `name` argument passed to `qar.registerMcp`). */ readonly mcpName: string; /** Transport discriminator from the failing config. */ readonly transport: string; constructor(mcpName: string, transport: string, message: string, cause?: unknown); } /** * Thrown when a tool invocation against a registered remote / stdio MCP * fails. Distinct from `QodoMcpClientError` (which is a connection * failure) — this one fires AFTER the MCP `Client` is connected and is * reporting an error from a `callTool` round-trip. * * Two failure shapes both route through this class: * - **Transport error** — the wire layer (HTTP request, SSE stream, stdio * pipe) failed during the call. `cause` is the underlying error. * - **Tool-reported error** — the call succeeded at the transport level * but the tool result has `isError: true`. The MCP envelope is preserved * in `mcpResult` so consumers can inspect the per-tool content array. * * `mcpName` and `toolName` are populated so structured logging / metrics * can branch on the exact dispatch coordinates without parsing the message. */ export declare class QodoMcpToolError extends Error { readonly name = "QodoMcpToolError"; /** Registered MCP name (the `name` argument passed to `qar.registerMcp`). */ readonly mcpName: string; /** MCP tool name that failed (the `name` field of the `callTool` request). */ readonly toolName: string; /** * MCP envelope when the tool returned `isError: true`. Absent for pure * transport failures (those carry the underlying error on `cause`). */ readonly mcpResult?: { readonly content: readonly unknown[]; readonly isError?: boolean; }; constructor(mcpName: string, toolName: string, message: string, opts?: { readonly cause?: unknown; readonly mcpResult?: { readonly content: readonly unknown[]; readonly isError?: boolean; }; }); } /** * Thrown when a server-side managed-tool invocation fails — the typed * `{ ok: false, error: { code, message, metadata } }` body QAR returns on a * non-2xx from `POST /v1/tools/{name}:invoke` or a `failed` operation poll. * * Distinct from `QodoMcpToolError` (consumer-registered MCP tools, tunneled * over the WebSocket) — this one reports a failure from QAR's HTTP managed-tool * catalog, reached via `client.managedTools.invoke(...)`. * * `code` is the closed `ToolApiErrorCode` union (the `MT-*` family, * `TOOL-PREVIEW-GATED`, and endpoint-protocol codes), so consumers branch exhaustively on * `instanceof QodoToolError` + `.code` instead of matching message text. * `metadata` carries the server's stage-dependent context (empty object when * the error omits it). `retryAfter` is the parsed `Retry-After` (seconds) when * the failure was a rate-limit (`MT-RATE-LIMITED`); absent otherwise. */ export declare class QodoToolError extends Error { readonly name = "QodoToolError"; /** Closed error-code union, including tool, preview, and endpoint-protocol failures. */ readonly code: ToolApiErrorCode; /** Managed-tool name passed to `client.managedTools.invoke(name, ...)`. */ readonly toolName: string; /** Server-supplied, stage-dependent context. `{}` when the error omits it. */ readonly metadata: JsonObject; /** Parsed `Retry-After` in seconds — present on rate-limit failures. */ readonly retryAfter?: number; constructor(toolName: string, code: ToolApiErrorCode, message: string, opts?: { readonly metadata?: JsonObject; readonly retryAfter?: number; }); } /** * Typed escape path for a tool handler that wants to reject a `tool.request`. * * Throwing `new ToolDeniedError("not allowed")` from a handler registered via * `client.tools.onRequest` maps to a `tool.response { outcome: "denied" }` * envelope on the wire. The reason string is forwarded to QAR (truncated to * keep error payloads bounded) so the model and observability traces see why * the call was rejected. * * Plain `throw new Error(...)` from a handler still works — the SDK maps any * other thrown value to `outcome: "error"`. Use `ToolDeniedError` only when * the rejection is a deliberate policy decision (approval flow rejected the * call, capability lookup denied the tool) rather than an unexpected failure. */ export declare class ToolDeniedError extends Error { readonly name = "ToolDeniedError"; constructor(reason: string); } /** * Tell the pre-bind zero-UUID (`00000000-0000-0000-0000-000000000000`) * apart from a real derived session_id. The wire emits the zero-UUID on * pre-derivation errors (envelope parse, auth rejection, invalid * `idempotency_key`); post-derivation errors (`admission_stalled`, * `admission_in_progress`, `session_already_running`, etc.) carry the real * derived UUID. Don't surface the zero-UUID through typed errors — it's not * a routable address. */ export declare function isZeroUuid(value: string): boolean; /** * Parse a server `error` envelope into the appropriate typed error class: * * - `agent_spec_rejected` → `QodoAgentSpecRejectedError` (carries * `issues: InlineAgentSpecIssue[]`). * - Any code recognized by `classForServerErrorCode` → * the matching `QodoServerError` subclass. * - Anything else → `QodoUnknownServerError` so consumers' `catch * (err: QodoServerError)` blocks still see structured fields. * * The wire `payload.errors` array is duck-typed (codegen still narrows * to the base `ErrorPayload` shape without the `errors` extension), so * absent/malformed entries default to an empty array and the typed * error class carries just `code` + `message`. * * Codes whose typed class carries a derived `sessionId` (admission * stalled, session-already-running) get the envelope's inherited * `session_id` attached when it's a real (non-zero) UUID, so consumers * can address the in-flight session for recovery without dipping into * the raw envelope. */ export declare function errorFromServerErrorEnvelope(envelope: ErrorEnvelope): QodoServerError | QodoAgentSpecRejectedError; /** * Parse QAR's `agent_spec_rejected` envelope into a typed * `QodoAgentSpecRejectedError`. The envelope's `payload` carries the * structured `errors: [{ rule_id, path, message }]` array; codegen * types the payload as the base `ErrorPayload` (`{ code, message, * offending_message_id? }`) without the `errors` extension, so the * parse here is duck-typed: we read `errors` if present, otherwise * fall back to a single-entry list with the envelope's `code` as * `rule_id`. */ export declare function errorFromAgentSpecRejection(envelope: ErrorEnvelope): QodoAgentSpecRejectedError; /** * Whether the SDK has a typed `QodoServerError` subclass (or * `QodoAgentSpecRejectedError`) for this wire code. Used by the * iterator wrappers to decide whether to throw vs yield the * `kind: 'error'` event — codes without a typed class flow through * unchanged so existing consumer narrowing keeps working. */ export declare function isTypedErrorCode(code: string): boolean; //# sourceMappingURL=errors.d.ts.map