Response-consumer cancellation already stopped lineage reads, persistence reads, and ZIP production, but the final attachment phase called readImage without the producer signal. A slow or stalled attachment backend could therefore keep working after the browser abandoned the download and prevent the producer from settling.\n\nExtend the attachment read seam with optional cancellation, forward it through the local backend into Node's filesystem read, and preserve the abort reason rather than wrapping it as a storage failure. The exporter now passes its combined request/consumer signal to every attachment read.\n\nCover both ownership boundaries: the local-store test proves filesystem forwarding and cancellation identity, while the assembled export test cancels a reader during a pending attachment provider call. Regenerate the Cordis API catalog and paired documentation so implementers can rely on the new contract.
63 lines
2.2 KiB
TypeScript
63 lines
2.2 KiB
TypeScript
/** Durable attachment storage seam (`ctx.attachments`). @module @deepseek-ai/dsh-attachment */
|
|
|
|
import { Context, Service } from '@deepseek-ai/cordis'
|
|
import type {
|
|
ImageAttachmentLimits,
|
|
ImageAttachmentRef,
|
|
SaveImageAttachment,
|
|
StoredImageAttachment,
|
|
} from './types.ts'
|
|
|
|
export { AttachmentId } from './brand.ts'
|
|
export { AttachmentError } from './error.ts'
|
|
export type {
|
|
AttachmentId as AttachmentIdType,
|
|
ImageAttachmentLimits,
|
|
ImageAttachmentRef,
|
|
ImageMediaType,
|
|
SaveImageAttachment,
|
|
StoredImageAttachment,
|
|
} from './types.ts'
|
|
|
|
declare module '@deepseek-ai/cordis' {
|
|
interface Context {
|
|
attachments: AttachmentStore
|
|
}
|
|
}
|
|
|
|
/** Immutable binary attachment service. Implementations validate bytes before publishing a reference. */
|
|
export abstract class AttachmentStore extends Service {
|
|
constructor(ctx: Context) {
|
|
super(ctx, 'attachments')
|
|
}
|
|
|
|
/** Deployment-resolved image policy used by authoritative and fast-path validation. */
|
|
abstract readonly imageLimits: ImageAttachmentLimits
|
|
|
|
/**
|
|
* Validate one image without persisting it.
|
|
* Batch callers validate every member before saving any member.
|
|
* @param input - encoded bytes, declared media type, and optional display name.
|
|
* @returns completion after the encoded raster has been fully decoded.
|
|
*/
|
|
abstract validateImage(input: SaveImageAttachment): Promise<void>
|
|
|
|
/**
|
|
* Validate and durably commit one image before its owning session event is appended.
|
|
* @param input - encoded bytes, declared media type, and optional display name.
|
|
* @returns a durable content-addressed reference.
|
|
*/
|
|
abstract saveImage(input: SaveImageAttachment): Promise<ImageAttachmentRef>
|
|
|
|
/**
|
|
* Read one image and verify that bytes still match the recorded reference.
|
|
* @param ref - durable reference from the session log.
|
|
* @param signal - optional cancellation for backend read and verification work.
|
|
* @returns the verified bytes and canonical reference.
|
|
* @throws the signal reason when aborted, or a storage error when verification fails.
|
|
*/
|
|
abstract readImage(ref: ImageAttachmentRef, signal?: AbortSignal): Promise<StoredImageAttachment>
|
|
}
|
|
|
|
export default AttachmentStore
|