@deepseek-ai/dsh-attachment 0.1.0-rc.6 → 0.1.0-rc.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/attachment/attachment/README.md
5
- README.md: baeeca0cf939f1a3d4608769b362d532507b90f5
6
- README.zh.md: 238b90794c510e71fffe34d62b044a5c2ece8a6e
5
+ README.md: 19232bd4bb86ed33e56fcdca93999967822422ab
6
+ README.zh.md: e5e7aab7c1af30b2b101bdcd218044cd1095ae0d
package/README.md CHANGED
@@ -2,9 +2,11 @@
2
2
 
3
3
  English | [中文](README.zh.md)
4
4
 
5
- The durable attachment seam. `ctx.attachments` validates and atomically commits immutable image bytes, then returns a serializable `ImageAttachmentRef`; consumers never persist browser paths, object URLs, provider URLs, or base64 in session events.
5
+ The durable attachment seam. `ctx.attachments` validates and durably commits immutable image bytes, then returns a serializable `ImageAttachmentRef`; consumers never persist browser paths, object URLs, provider URLs, or base64 in session events.
6
6
 
7
- Unsent composer images remain browser-owned temporary drafts. `validateImage` runs the same admission policy without persisting; batch writers validate every member first so a malformed member cannot strand earlier members as unreferenced objects. `saveImage` commits each accepted image before any model-visible session event is published, and `readImage` verifies the content-addressed object against its logged metadata. Callers may cancel `readImage`; implementations observe cancellation around backend and verification work and preserve it instead of translating it into a storage failure.
7
+ Unsent composer images remain browser-owned temporary drafts. `validateImage` runs the same admission policy without persisting. `saveImages` owns batch count and aggregate-byte limits, validates every member before writing any member, then commits in order and returns references only after the complete batch succeeds. A later storage failure returns no partial references, although an earlier immutable content-addressed object may remain unreachable until reference-aware garbage collection exists. `AttachmentError.code` uses the closed `AttachmentErrorCode` string union. Its `ImageAdmissionErrorCode` subset marks caller-correctable image-input failures; `isImageAdmissionError` recognizes that subset at runtime so each protocol adapter can map its own error vocabulary. `saveImage` commits one accepted image before any model-visible session event is published, and `readImage` verifies the content-addressed object against its logged metadata. Callers may cancel `readImage`; implementations observe cancellation around backend and verification work and preserve it instead of translating it into a storage failure.
8
+
9
+ `admitEncodedImages(attachments, images)` is the shared wire entry used by every RPC endpoint that accepts browser uploads (the session prompt endpoint and the command executor): it enforces canonical base64 on every member, then delegates batch admission — limits, validation, ordered commit — to `saveImages`. The base64 upload form is `EncodedImageAttachment`, exported from `@deepseek-ai/dsh-attachment/types` so wire contracts can reference it.
8
10
 
9
11
  ## Model Experience
10
12
 
package/README.zh.md CHANGED
@@ -2,9 +2,11 @@
2
2
 
3
3
  [English](README.md) | 中文
4
4
 
5
- 持久附件服务边界。`ctx.attachments` 校验并以原子方式提交不可变图片字节,随后返回可序列化的 `ImageAttachmentRef`;消费方绝不会在会话事件中持久保存浏览器路径、对象 URL、提供方 URL 或 base64。
5
+ 持久附件服务边界。`ctx.attachments` 校验并持久提交不可变图片字节,随后返回可序列化的 `ImageAttachmentRef`;消费方绝不会在会话事件中持久保存浏览器路径、对象 URL、提供方 URL 或 base64。
6
6
 
7
- 未发送的输入区图片仍是由浏览器持有的临时草稿。`validateImage` 运行相同的准入策略,但不执行持久化;批量写入方会先校验每个成员,避免某个格式错误的成员使较早的成员成为无引用对象。`saveImage` 会在发布任何模型可见的会话事件前提交每张已接受的图片,`readImage` 则根据已记录的元数据校验内容寻址对象。调用方可以取消 `readImage`;实现会在后端读取与校验工作的边界观察取消,并保留取消语义,而不会将其转换为存储失败。
7
+ 未发送的输入区图片仍是由浏览器持有的临时草稿。`validateImage` 运行相同的准入策略,但不执行持久化。`saveImages` 负责批次图片数量和总字节限制,先校验全部成员,再按顺序提交,并且只在完整批次成功后返回引用。后续存储失败不会返回部分引用,但较早写入的不可变内容寻址对象可能保持不可达,直至具备按引用感知的垃圾回收。`AttachmentError.code` 使用封闭的 `AttachmentErrorCode` 字符串联合类型。其 `ImageAdmissionErrorCode` 子集标记可由调用方修正的图片输入失败;`isImageAdmissionError` 在运行时识别该子集,使每个协议适配器可以映射自己的错误词汇。`saveImage` 会在发布任何模型可见的会话事件前提交一张已接受的图片,`readImage` 则根据已记录的元数据校验内容寻址对象。调用方可以取消 `readImage`;实现会在后端读取与校验工作的边界观察取消,并保留取消语义,而不会将其转换为存储失败。
8
+
9
+ `admitEncodedImages(attachments, images)` 是每个接受浏览器上传的 RPC 端点(会话 prompt 端点与命令执行器)共用的 wire 入口:它对每个成员强制执行规范 base64,随后把批量准入——限额、校验、有序提交——委托给 `saveImages`。base64 上传形式为 `EncodedImageAttachment`,从 `@deepseek-ai/dsh-attachment/types` 导出,供 wire 契约引用。
8
10
 
9
11
  ## 模型体验
10
12
 
package/lib/index.js CHANGED
@@ -1,17 +1,18 @@
1
1
  import { Service } from "@deepseek-ai/cordis";
2
- //#region lib/types/brand.js
3
- /** Attachment identifier brand. @module @deepseek-ai/dsh-attachment/brand */
4
- /**
5
- * Brand a validated storage identifier.
6
- * @param value - backend-produced opaque identifier.
7
- * @returns the branded identifier.
8
- */
9
- function AttachmentId(value) {
10
- return value;
11
- }
12
- //#endregion
2
+ import { Buffer } from "node:buffer";
13
3
  //#region lib/types/error.js
14
- /** Attachment failure class. @module @deepseek-ai/dsh-attachment/error */
4
+ /** Runtime membership for structurally compatible errors crossing package boundaries. */
5
+ const IMAGE_ADMISSION_ERROR_CODE_SET = new Set([
6
+ "TOO_MANY_IMAGES",
7
+ "IMAGES_TOO_LARGE",
8
+ "UNSUPPORTED_IMAGE_TYPE",
9
+ "INVALID_IMAGE_BASE64",
10
+ "INVALID_IMAGE",
11
+ "IMAGE_TYPE_MISMATCH",
12
+ "IMAGE_TOO_LARGE",
13
+ "IMAGE_TOO_MANY_PIXELS",
14
+ "IMAGE_DIMENSION_TOO_LARGE"
15
+ ]);
15
16
  /**
16
17
  * Stable failures suitable for host RPC error mapping.
17
18
  *
@@ -35,6 +36,55 @@ var AttachmentError = class extends Error {
35
36
  this.code = code;
36
37
  }
37
38
  };
39
+ /**
40
+ * Distinguish caller-correctable image admission failures from storage faults.
41
+ * @param error - failure raised while validating or persisting an image batch.
42
+ * @returns whether the caller can correct the proposed image content or batch.
43
+ */
44
+ function isImageAdmissionError(error) {
45
+ return error instanceof Error && "code" in error && typeof error.code === "string" && IMAGE_ADMISSION_ERROR_CODE_SET.has(error.code);
46
+ }
47
+ //#endregion
48
+ //#region lib/types/brand.js
49
+ /** Attachment identifier brand. @module @deepseek-ai/dsh-attachment/brand */
50
+ /**
51
+ * Brand a validated storage identifier.
52
+ * @param value - backend-produced opaque identifier.
53
+ * @returns the branded identifier.
54
+ */
55
+ function AttachmentId(value) {
56
+ return value;
57
+ }
58
+ //#endregion
59
+ //#region lib/types/admission.js
60
+ /** Wire-form admission of base64-encoded image uploads. @module @deepseek-ai/dsh-attachment/admission */
61
+ /** Decode one upload payload while rejecting non-canonical base64 forms. */
62
+ function decodeBase64(data) {
63
+ const decoded = Buffer.from(data, "base64");
64
+ if (data.length === 0 || decoded.toString("base64") !== data) throw new AttachmentError("Image upload is not canonical base64.", "INVALID_IMAGE_BASE64");
65
+ return new Uint8Array(decoded);
66
+ }
67
+ /** Store input for one decoded upload. */
68
+ function saveInput(image) {
69
+ return {
70
+ data: decodeBase64(image.data),
71
+ mediaType: image.mediaType,
72
+ ...image.name === void 0 ? {} : { name: image.name }
73
+ };
74
+ }
75
+ /**
76
+ * Admit one wire image batch: enforce canonical base64 on every member, then
77
+ * delegate batch admission — count and aggregate-byte limits, media-type and
78
+ * per-image validation, ordered commit — to {@link AttachmentStore.saveImages}.
79
+ * The shared entry for every RPC endpoint accepting browser uploads.
80
+ * @param attachments - the deployment attachment store owning batch policy.
81
+ * @param images - base64-encoded uploads in caller order.
82
+ * @returns durable references in the same order as `images`.
83
+ * @throws AttachmentError on a non-canonical payload or a refused batch.
84
+ */
85
+ async function admitEncodedImages(attachments, images) {
86
+ return attachments.saveImages(images.map(saveInput));
87
+ }
38
88
  //#endregion
39
89
  //#region lib/types/index.js
40
90
  /** Durable attachment storage seam (`ctx.attachments`). @module @deepseek-ai/dsh-attachment */
@@ -43,6 +93,24 @@ var AttachmentStore = class extends Service {
43
93
  constructor(ctx) {
44
94
  super(ctx, "attachments");
45
95
  }
96
+ /**
97
+ * Validate one ordered image batch before committing any member.
98
+ * Validation failures start no writes; storage failures return no partial
99
+ * references, although already published content-addressed objects may stay
100
+ * unreachable until a future retention policy collects them.
101
+ * @param inputs - encoded images in their owning message order.
102
+ * @returns durable references in the exact input order.
103
+ */
104
+ async saveImages(inputs) {
105
+ const { maxImagesPerMessage, maxMessageImageBytes, mediaTypes } = this.imageLimits;
106
+ if (inputs.length > maxImagesPerMessage) throw new AttachmentError("Image batch exceeds the configured image-count limit.", "TOO_MANY_IMAGES");
107
+ if (inputs.reduce((sum, input) => sum + input.data.byteLength, 0) > maxMessageImageBytes) throw new AttachmentError("Image batch exceeds the configured aggregate image-byte limit.", "IMAGES_TOO_LARGE");
108
+ for (const input of inputs) if (!mediaTypes.includes(input.mediaType)) throw new AttachmentError(`Image type ${input.mediaType} is not accepted by this deployment.`, "UNSUPPORTED_IMAGE_TYPE");
109
+ for (const input of inputs) await this.validateImage(input);
110
+ const refs = [];
111
+ for (const input of inputs) refs.push(await this.saveImage(input));
112
+ return refs;
113
+ }
46
114
  };
47
115
  //#endregion
48
- export { AttachmentError, AttachmentId, AttachmentStore, AttachmentStore as default };
116
+ export { AttachmentError, AttachmentId, AttachmentStore, AttachmentStore as default, admitEncodedImages, isImageAdmissionError };
@@ -0,0 +1,15 @@
1
+ /** Wire-form admission of base64-encoded image uploads. @module @deepseek-ai/dsh-attachment/admission */
2
+ import type { AttachmentStore } from './index.ts';
3
+ import type { EncodedImageAttachment, ImageAttachmentRef } from './types.ts';
4
+ /**
5
+ * Admit one wire image batch: enforce canonical base64 on every member, then
6
+ * delegate batch admission — count and aggregate-byte limits, media-type and
7
+ * per-image validation, ordered commit — to {@link AttachmentStore.saveImages}.
8
+ * The shared entry for every RPC endpoint accepting browser uploads.
9
+ * @param attachments - the deployment attachment store owning batch policy.
10
+ * @param images - base64-encoded uploads in caller order.
11
+ * @returns durable references in the same order as `images`.
12
+ * @throws AttachmentError on a non-canonical payload or a refused batch.
13
+ */
14
+ export declare function admitEncodedImages(attachments: AttachmentStore, images: readonly EncodedImageAttachment[]): Promise<readonly ImageAttachmentRef[]>;
15
+ //# sourceMappingURL=admission.d.ts.map
@@ -0,0 +1,33 @@
1
+ /** Wire-form admission of base64-encoded image uploads. @module @deepseek-ai/dsh-attachment/admission */
2
+ import { Buffer } from 'node:buffer';
3
+ import { AttachmentError } from "./error.js";
4
+ /** Decode one upload payload while rejecting non-canonical base64 forms. */
5
+ function decodeBase64(data) {
6
+ const decoded = Buffer.from(data, 'base64');
7
+ if (data.length === 0 || decoded.toString('base64') !== data) {
8
+ throw new AttachmentError('Image upload is not canonical base64.', 'INVALID_IMAGE_BASE64');
9
+ }
10
+ return new Uint8Array(decoded);
11
+ }
12
+ /** Store input for one decoded upload. */
13
+ function saveInput(image) {
14
+ return {
15
+ data: decodeBase64(image.data),
16
+ mediaType: image.mediaType,
17
+ ...image.name === undefined ? {} : { name: image.name },
18
+ };
19
+ }
20
+ /**
21
+ * Admit one wire image batch: enforce canonical base64 on every member, then
22
+ * delegate batch admission — count and aggregate-byte limits, media-type and
23
+ * per-image validation, ordered commit — to {@link AttachmentStore.saveImages}.
24
+ * The shared entry for every RPC endpoint accepting browser uploads.
25
+ * @param attachments - the deployment attachment store owning batch policy.
26
+ * @param images - base64-encoded uploads in caller order.
27
+ * @returns durable references in the same order as `images`.
28
+ * @throws AttachmentError on a non-canonical payload or a refused batch.
29
+ */
30
+ export async function admitEncodedImages(attachments, images) {
31
+ return attachments.saveImages(images.map(saveInput));
32
+ }
33
+ //# sourceMappingURL=admission.js.map
@@ -0,0 +1,10 @@
1
+ /** Attachment identifier brand. @module @deepseek-ai/dsh-attachment/brand */
2
+ /**
3
+ * Brand a validated storage identifier.
4
+ * @param value - backend-produced opaque identifier.
5
+ * @returns the branded identifier.
6
+ */
7
+ export function AttachmentId(value) {
8
+ return value;
9
+ }
10
+ //# sourceMappingURL=brand.js.map
@@ -1,4 +1,9 @@
1
1
  /** Attachment failure class. @module @deepseek-ai/dsh-attachment/error */
2
+ declare const IMAGE_ADMISSION_ERROR_CODES: readonly ["TOO_MANY_IMAGES", "IMAGES_TOO_LARGE", "UNSUPPORTED_IMAGE_TYPE", "INVALID_IMAGE_BASE64", "INVALID_IMAGE", "IMAGE_TYPE_MISMATCH", "IMAGE_TOO_LARGE", "IMAGE_TOO_MANY_PIXELS", "IMAGE_DIMENSION_TOO_LARGE"];
3
+ /** Caller-correctable attachment failure codes raised while admitting image input. */
4
+ export type ImageAdmissionErrorCode = typeof IMAGE_ADMISSION_ERROR_CODES[number];
5
+ /** Stable attachment failure codes used for protocol error routing. */
6
+ export type AttachmentErrorCode = ImageAdmissionErrorCode | 'INVALID_ATTACHMENT_REF' | 'ATTACHMENT_CORRUPT' | 'ATTACHMENT_WRITE_FAILED' | 'ATTACHMENT_NOT_FOUND' | 'ATTACHMENT_READ_FAILED';
2
7
  /**
3
8
  * Stable failures suitable for host RPC error mapping.
4
9
  *
@@ -10,12 +15,21 @@
10
15
  */
11
16
  export declare class AttachmentError extends Error {
12
17
  /** Stable machine-routing failure code. */
13
- readonly code: string;
18
+ readonly code: AttachmentErrorCode;
14
19
  /**
15
20
  * @param message - human-readable failure description without raw bytes or host paths.
16
21
  * @param code - stable machine-routing code.
17
22
  * @param options - optional chained cause.
18
23
  */
19
- constructor(message: string, code: string, options?: ErrorOptions);
24
+ constructor(message: string, code: AttachmentErrorCode, options?: ErrorOptions);
20
25
  }
26
+ /**
27
+ * Distinguish caller-correctable image admission failures from storage faults.
28
+ * @param error - failure raised while validating or persisting an image batch.
29
+ * @returns whether the caller can correct the proposed image content or batch.
30
+ */
31
+ export declare function isImageAdmissionError(error: unknown): error is AttachmentError & {
32
+ readonly code: ImageAdmissionErrorCode;
33
+ };
34
+ export {};
21
35
  //# sourceMappingURL=error.d.ts.map
@@ -0,0 +1,49 @@
1
+ /** Attachment failure class. @module @deepseek-ai/dsh-attachment/error */
2
+ const IMAGE_ADMISSION_ERROR_CODES = [
3
+ 'TOO_MANY_IMAGES',
4
+ 'IMAGES_TOO_LARGE',
5
+ 'UNSUPPORTED_IMAGE_TYPE',
6
+ 'INVALID_IMAGE_BASE64',
7
+ 'INVALID_IMAGE',
8
+ 'IMAGE_TYPE_MISMATCH',
9
+ 'IMAGE_TOO_LARGE',
10
+ 'IMAGE_TOO_MANY_PIXELS',
11
+ 'IMAGE_DIMENSION_TOO_LARGE',
12
+ ];
13
+ /** Runtime membership for structurally compatible errors crossing package boundaries. */
14
+ const IMAGE_ADMISSION_ERROR_CODE_SET = new Set(IMAGE_ADMISSION_ERROR_CODES);
15
+ /**
16
+ * Stable failures suitable for host RPC error mapping.
17
+ *
18
+ * Deliberately re-implements the `HarnessError` shape instead of extending it:
19
+ * the base lives in `@deepseek-ai/dsh-llm`, which itself depends on this
20
+ * package (`ImageBlock` references `ImageAttachmentRef`), so sharing the base
21
+ * would create a dependency cycle. Consumers route on `code`, never on the
22
+ * prototype chain, so the shapes stay interchangeable at the wire boundary.
23
+ */
24
+ export class AttachmentError extends Error {
25
+ /** Stable machine-routing failure code. */
26
+ code;
27
+ /**
28
+ * @param message - human-readable failure description without raw bytes or host paths.
29
+ * @param code - stable machine-routing code.
30
+ * @param options - optional chained cause.
31
+ */
32
+ constructor(message, code, options) {
33
+ super(message, options);
34
+ this.name = 'AttachmentError';
35
+ this.code = code;
36
+ }
37
+ }
38
+ /**
39
+ * Distinguish caller-correctable image admission failures from storage faults.
40
+ * @param error - failure raised while validating or persisting an image batch.
41
+ * @returns whether the caller can correct the proposed image content or batch.
42
+ */
43
+ export function isImageAdmissionError(error) {
44
+ return error instanceof Error
45
+ && 'code' in error
46
+ && typeof error.code === 'string'
47
+ && IMAGE_ADMISSION_ERROR_CODE_SET.has(error.code);
48
+ }
49
+ //# sourceMappingURL=error.js.map
@@ -2,8 +2,10 @@
2
2
  import { Context, Service } from '@deepseek-ai/cordis';
3
3
  import type { ImageAttachmentLimits, ImageAttachmentRef, SaveImageAttachment, StoredImageAttachment } from './types.ts';
4
4
  export { AttachmentId } from './brand.ts';
5
- export { AttachmentError } from './error.ts';
6
- export type { AttachmentId as AttachmentIdType, ImageAttachmentLimits, ImageAttachmentRef, ImageMediaType, SaveImageAttachment, StoredImageAttachment, } from './types.ts';
5
+ export { AttachmentError, isImageAdmissionError } from './error.ts';
6
+ export type { AttachmentErrorCode, ImageAdmissionErrorCode } from './error.ts';
7
+ export { admitEncodedImages } from './admission.ts';
8
+ export type { AttachmentId as AttachmentIdType, EncodedImageAttachment, ImageAttachmentLimits, ImageAttachmentRef, ImageMediaType, SaveImageAttachment, StoredImageAttachment, } from './types.ts';
7
9
  declare module '@deepseek-ai/cordis' {
8
10
  interface Context {
9
11
  attachments: AttachmentStore;
@@ -21,6 +23,15 @@ export declare abstract class AttachmentStore extends Service {
21
23
  * @returns completion after the encoded raster has been fully decoded.
22
24
  */
23
25
  abstract validateImage(input: SaveImageAttachment): Promise<void>;
26
+ /**
27
+ * Validate one ordered image batch before committing any member.
28
+ * Validation failures start no writes; storage failures return no partial
29
+ * references, although already published content-addressed objects may stay
30
+ * unreachable until a future retention policy collects them.
31
+ * @param inputs - encoded images in their owning message order.
32
+ * @returns durable references in the exact input order.
33
+ */
34
+ saveImages(inputs: readonly SaveImageAttachment[]): Promise<readonly ImageAttachmentRef[]>;
24
35
  /**
25
36
  * Validate and durably commit one image before its owning session event is appended.
26
37
  * @param input - encoded bytes, declared media type, and optional display name.
@@ -0,0 +1,43 @@
1
+ /** Durable attachment storage seam (`ctx.attachments`). @module @deepseek-ai/dsh-attachment */
2
+ import { Service } from '@deepseek-ai/cordis';
3
+ import { AttachmentError } from "./error.js";
4
+ export { AttachmentId } from "./brand.js";
5
+ export { AttachmentError, isImageAdmissionError } from "./error.js";
6
+ export { admitEncodedImages } from "./admission.js";
7
+ /** Immutable binary attachment service. Implementations validate bytes before publishing a reference. */
8
+ export class AttachmentStore extends Service {
9
+ constructor(ctx) {
10
+ super(ctx, 'attachments');
11
+ }
12
+ /**
13
+ * Validate one ordered image batch before committing any member.
14
+ * Validation failures start no writes; storage failures return no partial
15
+ * references, although already published content-addressed objects may stay
16
+ * unreachable until a future retention policy collects them.
17
+ * @param inputs - encoded images in their owning message order.
18
+ * @returns durable references in the exact input order.
19
+ */
20
+ async saveImages(inputs) {
21
+ const { maxImagesPerMessage, maxMessageImageBytes, mediaTypes } = this.imageLimits;
22
+ if (inputs.length > maxImagesPerMessage) {
23
+ throw new AttachmentError('Image batch exceeds the configured image-count limit.', 'TOO_MANY_IMAGES');
24
+ }
25
+ const totalBytes = inputs.reduce((sum, input) => sum + input.data.byteLength, 0);
26
+ if (totalBytes > maxMessageImageBytes) {
27
+ throw new AttachmentError('Image batch exceeds the configured aggregate image-byte limit.', 'IMAGES_TOO_LARGE');
28
+ }
29
+ for (const input of inputs) {
30
+ if (!mediaTypes.includes(input.mediaType)) {
31
+ throw new AttachmentError(`Image type ${input.mediaType} is not accepted by this deployment.`, 'UNSUPPORTED_IMAGE_TYPE');
32
+ }
33
+ }
34
+ for (const input of inputs)
35
+ await this.validateImage(input);
36
+ const refs = [];
37
+ for (const input of inputs)
38
+ refs.push(await this.saveImage(input));
39
+ return refs;
40
+ }
41
+ }
42
+ export default AttachmentStore;
43
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,16 @@
1
+ /** Package-owned invariant companion for `@deepseek-ai/dsh-attachment`. @module @deepseek-ai/dsh-attachment/invariant */
2
+ const PACKAGE_NAME = '@deepseek-ai/dsh-attachment';
3
+ /** Cordis companion plugin name. */
4
+ export const name = 'attachment-invariant';
5
+ /** Service required before package ownership can be reserved. */
6
+ export const inject = ['invariants'];
7
+ /** No runtime invariant: this stateless seam owns types while implementations enforce immutable-store checks. */
8
+ const install = () => { };
9
+ /**
10
+ * Register the package invariant companion.
11
+ * @param ctx - Cordis context carrying the invariant service.
12
+ * @returns the registration disposer.
13
+ */
14
+ export const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
15
+ /* jscpd:ignore-end */
16
+ //# sourceMappingURL=invariant.js.map
@@ -24,8 +24,19 @@ export interface ImageAttachmentLimits {
24
24
  maxImagesPerMessage: number;
25
25
  maxMessageImageBytes: number;
26
26
  maxImagePixels: number;
27
+ /** Maximum intrinsic width and maximum intrinsic height in pixels for one image. */
28
+ maxImageDimension: number;
27
29
  mediaTypes: readonly ImageMediaType[];
28
30
  }
31
+ /** Base64-encoded image upload accompanying one wire request. */
32
+ export interface EncodedImageAttachment {
33
+ /** Declared media type, verified against the decoded bytes during admission. */
34
+ mediaType: ImageMediaType;
35
+ /** Canonical base64 encoding of the image bytes. */
36
+ data: string;
37
+ /** Optional display name; it is never interpreted as a path. */
38
+ name?: string;
39
+ }
29
40
  /** Request to validate and durably commit one image. */
30
41
  export interface SaveImageAttachment {
31
42
  data: Uint8Array;
@@ -0,0 +1,3 @@
1
+ /** Durable attachment vocabulary. @module @deepseek-ai/dsh-attachment/types */
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-attachment",
3
3
  "description": "Durable immutable attachment storage seam for the DeepSeek Harness",
4
- "version": "0.1.0-rc.6",
4
+ "version": "0.1.0-rc.8",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -22,23 +22,28 @@
22
22
  "types": "./lib/types/invariant.d.ts",
23
23
  "default": "./lib/invariant.js"
24
24
  },
25
+ "./types": {
26
+ "types": "./lib/types/types.d.ts",
27
+ "default": "./lib/types/types.js"
28
+ },
25
29
  "./src/*": "./src/*",
26
30
  "./package.json": "./package.json"
27
31
  },
28
32
  "files": [
29
33
  "lib/index.js",
30
34
  "lib/invariant.js",
35
+ "lib/types/**/*.js",
31
36
  "lib/types/**/*.d.ts"
32
37
  ],
33
38
  "license": "MIT",
34
39
  "peerDependencies": {
35
- "@deepseek-ai/dsh-brand": "^0.1.0-rc.6",
36
- "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6",
40
+ "@deepseek-ai/dsh-brand": "^0.1.0-rc.8",
41
+ "@deepseek-ai/dsh-invariants": "^0.1.0-rc.8",
37
42
  "@deepseek-ai/cordis": "^4.0.1"
38
43
  },
39
44
  "devDependencies": {
40
- "@deepseek-ai/dsh-brand": "^0.1.0-rc.6",
41
- "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6",
42
- "@deepseek-ai/cordis": "^4.0.1"
45
+ "@deepseek-ai/dsh-brand": "^0.1.0-rc.8",
46
+ "@deepseek-ai/cordis": "^4.0.1",
47
+ "@deepseek-ai/dsh-invariants": "^0.1.0-rc.8"
43
48
  }
44
49
  }