/** * Turns an `AttachmentFailure` into the one error every action surface * (agent tool, HTTP action route, A2A) throws. The decision "does this end the * run?" is made here from the typed status, never from message text: * * - `notFound`, `forbiddenScope`, `expired`, `malformed` are definitive: the * same ref can never succeed, so they stop the turn as `permanent_precondition` * with a message that names the real cause and tells the user to attach again. * - `storageUnavailable` is the only retryable outcome. It is an ordinary * action error (never a stop) and tells the model the ref is still valid. */ import { type AttachmentFailure, type AttachmentFile, type AttachmentResolution } from "./attachment-ref.js"; export declare const ATTACHMENT_ERROR_CODES: { readonly notFound: "attachment_not_found"; readonly forbiddenScope: "attachment_forbidden_scope"; readonly expired: "attachment_expired"; readonly malformed: "attachment_malformed"; readonly storageUnavailable: "attachment_storage_unavailable"; }; export type AttachmentErrorCode = (typeof ATTACHMENT_ERROR_CODES)[AttachmentFailure["status"]]; /** What the caller reads off `error.details` instead of parsing the message. */ export interface AttachmentFailureDetails extends Record { attachmentStatus: AttachmentFailure["status"]; attachmentErrorCode: AttachmentErrorCode; reason: string; retryable: boolean; whoCanFix?: "workspace_admin" | "operator" | "self_resolving"; } export interface AttachmentFailureDescription { /** User-facing: says what is wrong and what to do. */ message: string; /** Model-facing: the same cause plus whether to retry. */ toolResult: string; } /** Whether the caller was saving a new file or opening a stored one. */ export type AttachmentOperation = "save" | "open"; export declare function describeAttachmentFailure(failure: AttachmentFailure, operation?: AttachmentOperation): AttachmentFailureDescription; export declare function attachmentFailureDetails(failure: AttachmentFailure): AttachmentFailureDetails; /** * A definitive attachment failure. It is a stop for the agent * (`permanent_precondition`) and carries a real HTTP status so the action * route answers 404/403/410/400 rather than an opaque 500. */ export declare class AttachmentUnavailableError extends Error { readonly agentNativeStop = true; readonly errorCode = "permanent_precondition"; readonly details: AttachmentFailureDetails; readonly toolResult: string | undefined; readonly statusCode: number; readonly failure: AttachmentFailure; constructor(failure: AttachmentFailure); } /** The retryable outcome: an ordinary typed action error, never a stop. */ export declare class AttachmentStorageUnavailableError extends Error { readonly actionContractError = true; readonly errorCode: string; readonly details: AttachmentFailureDetails; readonly statusCode: number; readonly failure: Extract; constructor(failure: Extract, operation?: AttachmentOperation); } export declare function attachmentFailureToError(failure: AttachmentFailure, operation?: AttachmentOperation): AttachmentUnavailableError | AttachmentStorageUnavailableError; /** Returns the file, or throws the typed error for the failure. */ export declare function unwrapAttachment(resolution: AttachmentResolution): AttachmentFile; /** True when `error` is one of the attachment errors above, by shape. */ export declare function isAttachmentError(error: unknown): error is AttachmentUnavailableError | AttachmentStorageUnavailableError;