@x1a0f3n9/dsh-attachment 0.1.5-rc.4 → 0.1.7-rc.2

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
@@ -1,6 +1,67 @@
1
- # Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
2
- # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
- # after editing either side, bring the other along and re-record with:
1
+ # Bilingual-pair consistency record for README.md (docs/i18n/README.md): per heading
2
+ # section, a hash of its English and Chinese blocks outside code blocks and generated regions.
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: 35fde71833fa13b26662244cfa68cec17b90b663
6
- README.zh.md: b0e98d1e4a0c35082a8eef23f69659f47916d3f7
5
+ /:
6
+ en: c8448ea82a8ce005
7
+ zh: 24444a57de8c007c
8
+ /x1a0f3n9-dsh-attachment:
9
+ en: e48eef5a4815564b
10
+ zh: b7682dc87f678d3e
11
+ /x1a0f3n9-dsh-attachment/summary:
12
+ en: ecfee6cc000f679e
13
+ zh: fadcee31cbd4becb
14
+ /x1a0f3n9-dsh-attachment/table-of-contents:
15
+ en: d152484eb41ac6b4
16
+ zh: 09388d293f9be9cb
17
+ /x1a0f3n9-dsh-attachment/use-this-package:
18
+ en: f51a5528232ac43b
19
+ zh: 931041df996b39d2
20
+ /x1a0f3n9-dsh-attachment/use-this-package/attach-images-to-a-prompt:
21
+ en: b440422892839de9
22
+ zh: 0290b366b5a4ef88
23
+ /x1a0f3n9-dsh-attachment/use-this-package/attach-any-other-file-to-a-prompt:
24
+ en: d5019c6ae76c0bcf
25
+ zh: b7aeaf7e6920ff10
26
+ /x1a0f3n9-dsh-attachment/use-this-package/pass-attachments-to-commands:
27
+ en: 8a0fa64e84aa4450
28
+ zh: ed2ac44ef20250d4
29
+ /x1a0f3n9-dsh-attachment/use-this-package/reuse-images-across-the-session:
30
+ en: c99e4e088be92c4f
31
+ zh: 34997ecb9a420d08
32
+ /x1a0f3n9-dsh-attachment/use-this-package/what-can-go-wrong:
33
+ en: b35e2f7f17269ae1
34
+ zh: 57cf0ef9fee6c7e1
35
+ /x1a0f3n9-dsh-attachment/understand-the-implementation:
36
+ en: 25d9c7d6c0899d23
37
+ zh: ad8380d14810ff1c
38
+ /x1a0f3n9-dsh-attachment/understand-the-implementation/design-decisions:
39
+ en: af7deef72fd2fa93
40
+ zh: f217d52ce3971135
41
+ /x1a0f3n9-dsh-attachment/understand-the-implementation/service-operations:
42
+ en: 4a35cdba790c3b8b
43
+ zh: 08d4a18bbad4b182
44
+ /x1a0f3n9-dsh-attachment/understand-the-implementation/source-map:
45
+ en: a196e1f4cf9895ae
46
+ zh: 39b430b53d30297e
47
+ /x1a0f3n9-dsh-attachment/further-exploration:
48
+ en: 0f179d9ab84a962a
49
+ zh: 4a1d0722a3309f4a
50
+ /x1a0f3n9-dsh-attachment/model-experience:
51
+ en: 3a9fc2cc8896a2db
52
+ zh: 256ffa52315cb597
53
+ /x1a0f3n9-dsh-attachment/model-experience/kv-cache-effect:
54
+ en: 2fcaf6d01d42da7c
55
+ zh: 81e61690b955dd18
56
+ /x1a0f3n9-dsh-attachment/known-limitations-and-deferred-work:
57
+ en: d1ee04ac73471377
58
+ zh: 1abf40510951d5c2
59
+ /x1a0f3n9-dsh-attachment/known-limitations-and-deferred-work/dev-note:
60
+ en: d56846da29ad869c
61
+ zh: 41e655e01351fd1d
62
+ /x1a0f3n9-dsh-attachment/known-limitations-and-deferred-work/dev-note/future-reference-aware-garbage-collection:
63
+ en: 20c22bbf4263d41e
64
+ zh: f85699e18a0e5f43
65
+ /x1a0f3n9-dsh-attachment/known-limitations-and-deferred-work/dev-note/future-audio-video-and-assistant-side-output:
66
+ en: 85353325b14af5a8
67
+ zh: c03fb041c2daee7e
package/README.md CHANGED
@@ -66,13 +66,13 @@ This section explains the design decisions behind the seam and the service opera
66
66
  - **Normalize and persist before event.** Every source is prepared and verified before the batch publishes in order, so the session log never references a partial or failed normalization.
67
67
  - **Immutable and retention-neutral.** Objects are immutable once published; resumed and forked sessions may share them, so reference-aware garbage collection is deferred rather than tied to any one session's deletion.
68
68
  - **Verify on read.** Reads check bytes and metadata against the logged reference before returning them, and request projections fully decode cached bytes, so a missing, corrupted, or swapped object fails closed.
69
- - **Role-neutral image blocks.** The `ImageBlock` content block in `dsh-llm` carries an `ImageAttachmentRef`; provider adapters resolve it into deterministic request versions with explicit pixel and byte budgets, while execution filesystems may map the immutable host object to a model-readable process path.
69
+ - **Role-neutral image blocks.** The `ImageBlock` content block in `dsh-llm` carries an `ImageAttachmentRef`; provider adapters resolve it into deterministic request versions at an explicit route-chosen target size and byte target, while execution filesystems may map the immutable host object to a model-readable process path.
70
70
  - **Error routing by code.** `AttachmentError` re-implements the `HarnessError` shape instead of extending it because the base lives in `dsh-llm`, which depends on this package; consumers use `isAttachmentError` and route on `code`, never on the prototype chain.
71
71
  - **Files are verbatim, images are normalized.** `saveFile` commits an existing byte array, `saveFileStream` commits bounded chunks with backpressure and cancellation, `readFileStream` verifies and returns bounded chunks, and `fileHostPath` locates the stored object for read-on-demand projection; neither file write path applies admission limits. The image path keeps its separate normalization, limits, and request-version pipeline. The `FileBlock` content block in `dsh-llm` carries a `FileAttachmentRef`, and request assembly projects it to deterministic handle text for every route.
72
72
 
73
73
  ### Service operations
74
74
 
75
- The service family runs one admission-and-storage flow: every entry point enforces source batch limits and canonical base64, prepares provider-independent normalized attachments before publishing any member, and commits them durably in input order without partial results. Host prompt consumers pass ordered text, encoded images, and already resolved file references to `ctx.attachments.admitPromptContent()`; the method persists images and passes file references unchanged. Encoded protocol adapters call `ctx.attachments.admitEncodedFile()`, which checks canonical base64 before delegating to `saveFile`; adapters recognize attachment failures through `ctx.attachments.isAttachmentError()`. Generic-file callers choose `saveFile` for existing bytes or `saveFileStream` for a bounded asynchronous byte source; both return the same durable reference, while `readFileStream` verifies its digest and length during a bounded read. `readImageRequest` derives deterministic route-sized variants whose identity includes the attachment id, transform version, pixel and byte budgets, and encoder settings. The pure `requestImageDimensions` export computes each projection's aspect-preserving dimensions from a total-pixel budget, so providers and request pricing share one geometry. `imageHostPath` exposes an implementation-owned host location only to trusted same-process consumers that need execution-world mapping. Callers compose ordered batches while the implementation owns compression concurrency, caching, and singleflight. Reads, streamed writes, and projections preserve caller cancellation. Failures carry stable machine-readable codes, and the caller-correctable admission subset is recognizable at runtime so each protocol adapter maps its own vocabulary; the exact per-operation contracts live in [`src/index.ts`](src/index.ts) and [`src/error.ts`](src/error.ts).
75
+ The service family runs one admission-and-storage flow: every entry point enforces source batch limits and canonical base64, prepares provider-independent normalized attachments before publishing any member, and commits them durably in input order without partial results. Host prompt consumers pass ordered text, encoded images, and already resolved file references to `ctx.attachments.admitPromptContent()`; the method persists images and passes file references unchanged. Encoded protocol adapters call `ctx.attachments.admitEncodedFile()`, which checks canonical base64 before delegating to `saveFile`; adapters recognize attachment failures through `ctx.attachments.isAttachmentError()`. Generic-file callers choose `saveFile` for existing bytes or `saveFileStream` for a bounded asynchronous byte source; both return the same durable reference, while `readFileStream` verifies its digest and length during a bounded read. `readImageRequest` derives deterministic route-sized variants whose identity includes the attachment id, transform version, target dimensions, byte target, and encoder settings. The pure `requestImageDimensions` and `longEdgeDimensions` exports compute aspect-preserving dimensions from a total-pixel budget or an exact long edge, so routes and request pricing share one geometry. `imageHostPath` exposes an implementation-owned host location only to trusted same-process consumers that need execution-world mapping. Callers compose ordered batches while the implementation owns compression concurrency, caching, and singleflight. Reads, streamed writes, and projections preserve caller cancellation. Failures carry stable machine-readable codes, and the caller-correctable admission subset is recognizable at runtime so each protocol adapter maps its own vocabulary; the exact per-operation contracts live in [`src/index.ts`](src/index.ts) and [`src/error.ts`](src/error.ts).
76
76
 
77
77
  ### Source map
78
78
 
package/README.zh.md CHANGED
@@ -66,13 +66,13 @@ kind: "package-reference"
66
66
  - **事件前完成规范化与持久化。** 每个源图都会在批次按序发布前完成准备与校验,因此会话日志绝不会引用部分完成或规范化失败的对象。
67
67
  - **不可变且保留策略中立。** 对象一经发布即不可变;恢复和 fork 后的会话可能共享它们,因此引用感知的垃圾回收被推迟,而不是与任何单个会话的删除绑定。
68
68
  - **读取时校验。** 读取在返回前把字节和元数据与记录的引用比对,请求投影还会完整解码缓存字节,因此缺失、损坏或被替换的对象不会通过校验。
69
- - **角色无关的图片块。** `dsh-llm` 中的 `ImageBlock` 内容块携带 `ImageAttachmentRef`;提供方适配器以显式像素与字节预算把引用解析为确定性请求版本,执行文件系统则可以把不可变宿主对象映射为模型可读的进程路径。
69
+ - **角色无关的图片块。** `dsh-llm` 中的 `ImageBlock` 内容块携带 `ImageAttachmentRef`;提供方适配器按路由显式选定的目标尺寸与字节目标把引用解析为确定性请求版本,执行文件系统则可以把不可变宿主对象映射为模型可读的进程路径。
70
70
  - **按错误码路由。** `AttachmentError` 重新实现 `HarnessError` 的结构而不是继承它,因为基类位于 `dsh-llm`,而后者依赖本包;消费方用 `isAttachmentError` 识别错误并按 `code` 路由,绝不依赖原型链。
71
71
  - **文件原样,图片规范化。**`saveFile` 提交已有字节数组,`saveFileStream` 以背压和取消语义提交有界分块,`readFileStream` 校验并返回有界分块,`fileHostPath` 定位存储对象供按需读取投影;两种文件写入路径都不设准入限制。图片路径保留其独立的规范化、限额与请求版本流水线。`dsh-llm` 中的 `FileBlock` 内容块承载 `FileAttachmentRef`,请求组装会为每条路由将其投影为确定性的句柄文本。
72
72
 
73
73
  ### 服务操作
74
74
 
75
- 服务族运行同一条准入与存储流程:每个入口都强制执行源批次限制与规范 base64,在发布任何成员前准备提供方无关的规范化附件,再按输入顺序持久提交而不产生部分结果。Host 提示词消费方把有序文本、编码图片和已经解析的文件引用交给 `ctx.attachments.admitPromptContent()`;该方法持久化图片,并让文件引用原样通过。编码协议适配器调用 `ctx.attachments.admitEncodedFile()`,由该方法检查规范 base64 后委托给 `saveFile`;适配器通过 `ctx.attachments.isAttachmentError()` 识别附件错误。通用文件调用方可以用 `saveFile` 提交已有字节,或用 `saveFileStream` 提交有界异步字节源;两者返回相同的持久引用,`readFileStream` 则在有界读取过程中校验摘要与长度。`readImageRequest` 派生确定性的路由尺寸变体,其身份包含附件 id、变换版本、像素与字节预算及编码参数。纯函数导出 `requestImageDimensions` 会按总像素预算计算每个投影保持宽高比的尺寸,使提供方与请求定价共享同一套几何计算。`imageHostPath` 只向需要把该位置映射到执行环境的受信任同进程消费方暴露实现拥有的宿主位置。调用方组合有序批次,而实现负责管理压缩并发、缓存与 singleflight。读取、流式写入和投影保留调用方的取消语义。失败带有稳定且机器可读的错误码,运行时即可识别可由调用方修正的准入子集,让每个协议适配器映射自己的词汇;各操作的确切约定见 [`src/index.ts`](src/index.ts) 与 [`src/error.ts`](src/error.ts)。
75
+ 服务族运行同一条准入与存储流程:每个入口都强制执行源批次限制与规范 base64,在发布任何成员前准备提供方无关的规范化附件,再按输入顺序持久提交而不产生部分结果。Host 提示词消费方把有序文本、编码图片和已经解析的文件引用交给 `ctx.attachments.admitPromptContent()`;该方法持久化图片,并让文件引用原样通过。编码协议适配器调用 `ctx.attachments.admitEncodedFile()`,由该方法检查规范 base64 后委托给 `saveFile`;适配器通过 `ctx.attachments.isAttachmentError()` 识别附件错误。通用文件调用方可以用 `saveFile` 提交已有字节,或用 `saveFileStream` 提交有界异步字节源;两者返回相同的持久引用,`readFileStream` 则在有界读取过程中校验摘要与长度。`readImageRequest` 派生确定性的路由尺寸变体,其身份包含附件 id、变换版本、目标尺寸、字节目标及编码参数。纯函数导出 `requestImageDimensions` 与 `longEdgeDimensions` 按总像素预算或精确长边计算保持宽高比的尺寸,使路由与请求定价共享同一套几何计算。`imageHostPath` 只向需要把该位置映射到执行环境的受信任同进程消费方暴露实现拥有的宿主位置。调用方组合有序批次,而实现负责管理压缩并发、缓存与 singleflight。读取、流式写入和投影保留调用方的取消语义。失败带有稳定且机器可读的错误码,运行时即可识别可由调用方修正的准入子集,让每个协议适配器映射自己的词汇;各操作的确切约定见 [`src/index.ts`](src/index.ts) 与 [`src/error.ts`](src/error.ts)。
76
76
 
77
77
  ### 源码地图
78
78
 
package/lib/index.js CHANGED
@@ -137,8 +137,8 @@ function ImageVariantId(value) {
137
137
  //#endregion
138
138
  //#region lib/types/request-projection.js
139
139
  /**
140
- * Pure request-projection geometry shared by attachment providers and
141
- * provider-side request pricing. @module @x1a0f3n9/dsh-attachment/request-projection
140
+ * Pure request-projection geometry shared by model routes and provider-side
141
+ * request pricing. @module @x1a0f3n9/dsh-attachment/request-projection
142
142
  */
143
143
  /**
144
144
  * Compute aspect-preserving integer dimensions within a hard total-pixel budget.
@@ -176,6 +176,28 @@ function requestImageDimensions(width, height, maxPixels) {
176
176
  height: projectedHeight
177
177
  };
178
178
  }
179
+ /**
180
+ * Compute aspect-preserving integer dimensions with an exact long edge; the
181
+ * short edge rounds to the nearest pixel, as an encoder resize by the
182
+ * long edge alone.
183
+ * @param width - positive source width.
184
+ * @param height - positive source height.
185
+ * @param longEdge - positive target for the longer source edge.
186
+ * @returns the target dimensions; a long edge at or above the source returns the source unchanged.
187
+ */
188
+ function longEdgeDimensions(width, height, longEdge) {
189
+ if (longEdge >= Math.max(width, height)) return {
190
+ width,
191
+ height
192
+ };
193
+ return width >= height ? {
194
+ width: longEdge,
195
+ height: Math.max(1, Math.round(longEdge * height / width))
196
+ } : {
197
+ width: Math.max(1, Math.round(longEdge * width / height)),
198
+ height: longEdge
199
+ };
200
+ }
179
201
  //#endregion
180
202
  //#region lib/types/index.js
181
203
  /** Durable attachment storage seam (`ctx.attachments`). @module @x1a0f3n9/dsh-attachment */
@@ -309,14 +331,14 @@ var AttachmentStore = class extends Service {
309
331
  /**
310
332
  * Generate or read one deterministic model-request version from the stored normalized image.
311
333
  * @param ref - durable provider-independent normalized attachment reference.
312
- * @param policy - exact route pixel budget and encoded-byte target; a target no ladder quality meets yields the smallest ladder output.
334
+ * @param target - route-chosen dimensions and byte target; an unmet byte target yields the smallest ladder output.
313
335
  * @param signal - optional cancellation.
314
336
  * @returns request bytes and the cache/upload identity covering every transform input.
315
337
  */
316
- readImageRequest(ref, policy, signal) {
338
+ readImageRequest(ref, target, signal) {
317
339
  signal?.throwIfAborted();
318
340
  return Promise.reject(new AttachmentError("The mounted attachment provider cannot derive model-request images.", "ATTACHMENT_PROJECTION_UNSUPPORTED"));
319
341
  }
320
342
  };
321
343
  //#endregion
322
- export { AttachmentError, AttachmentId, AttachmentStore, AttachmentStore as default, ImageVariantId, admitEncodedFile, admitEncodedImages, isAttachmentError, isImageAdmissionError, requestImageDimensions };
344
+ export { AttachmentError, AttachmentId, AttachmentStore, AttachmentStore as default, ImageVariantId, admitEncodedFile, admitEncodedImages, isAttachmentError, isImageAdmissionError, longEdgeDimensions, requestImageDimensions };
@@ -1,13 +1,14 @@
1
1
  /** Durable attachment storage seam (`ctx.attachments`). @module @x1a0f3n9/dsh-attachment */
2
2
  import { Context, Service } from '@deepseek-ai/cordis';
3
3
  import { AttachmentError } from './error.ts';
4
- import type { AdmittedPromptContentPart, AttachmentAdmissionPart, EncodedFileAttachment, FileAttachmentRef, ImageAttachmentLimits, ImageAttachmentRef, ImageRequestPolicy, RequestImageAttachment, SaveFileAttachment, SaveFileStreamAttachment, SaveImageAttachment, StoredImageAttachment } from './types.ts';
4
+ import type { AdmittedPromptContentPart, AttachmentAdmissionPart, EncodedFileAttachment, FileAttachmentRef, ImageAttachmentLimits, ImageAttachmentRef, ImageRequestTarget, RequestImageAttachment, SaveFileAttachment, SaveFileStreamAttachment, SaveImageAttachment, StoredImageAttachment } from './types.ts';
5
5
  export { AttachmentId, ImageVariantId } from './brand.ts';
6
6
  export { AttachmentError, isAttachmentError, isImageAdmissionError } from './error.ts';
7
7
  export type { AttachmentErrorCode, ImageAdmissionErrorCode } from './error.ts';
8
8
  export { admitEncodedFile, admitEncodedImages } from './admission.ts';
9
- export { requestImageDimensions } from './request-projection.ts';
10
- export type { AttachmentId as AttachmentIdType, AdmittedPromptContentPart, AttachmentAdmissionPart, EncodedFileAttachment, EncodedImageAttachment, FileAttachmentRef, ImageAttachmentLimits, ImageAttachmentRef, ImageRequestPolicy, ImageMediaType, PromptContentPart, RequestImageAttachment, SaveFileAttachment, SaveFileStreamAttachment, SaveImageAttachment, StoredImageAttachment, } from './types.ts';
9
+ export { longEdgeDimensions, requestImageDimensions } from './request-projection.ts';
10
+ export type { ProjectedDimensions } from './request-projection.ts';
11
+ export type { AttachmentId as AttachmentIdType, AdmittedPromptContentPart, AttachmentAdmissionPart, EncodedFileAttachment, EncodedImageAttachment, FileAttachmentRef, ImageAttachmentLimits, ImageAttachmentRef, ImageRequestTarget, ImageMediaType, PromptContentPart, RequestImageAttachment, SaveFileAttachment, SaveFileStreamAttachment, SaveImageAttachment, StoredImageAttachment, } from './types.ts';
11
12
  declare module '@deepseek-ai/cordis' {
12
13
  interface Context {
13
14
  attachments: AttachmentStore;
@@ -121,11 +122,11 @@ export declare abstract class AttachmentStore extends Service {
121
122
  /**
122
123
  * Generate or read one deterministic model-request version from the stored normalized image.
123
124
  * @param ref - durable provider-independent normalized attachment reference.
124
- * @param policy - exact route pixel budget and encoded-byte target; a target no ladder quality meets yields the smallest ladder output.
125
+ * @param target - route-chosen dimensions and byte target; an unmet byte target yields the smallest ladder output.
125
126
  * @param signal - optional cancellation.
126
127
  * @returns request bytes and the cache/upload identity covering every transform input.
127
128
  */
128
- readImageRequest(ref: ImageAttachmentRef, policy: ImageRequestPolicy, signal?: AbortSignal): Promise<RequestImageAttachment>;
129
+ readImageRequest(ref: ImageAttachmentRef, target: ImageRequestTarget, signal?: AbortSignal): Promise<RequestImageAttachment>;
129
130
  }
130
131
  export default AttachmentStore;
131
132
  //# sourceMappingURL=index.d.ts.map
@@ -5,7 +5,7 @@ import { AttachmentError, isAttachmentError as matchesAttachmentError } from "./
5
5
  export { AttachmentId, ImageVariantId } from "./brand.js";
6
6
  export { AttachmentError, isAttachmentError, isImageAdmissionError } from "./error.js";
7
7
  export { admitEncodedFile, admitEncodedImages } from "./admission.js";
8
- export { requestImageDimensions } from "./request-projection.js";
8
+ export { longEdgeDimensions, requestImageDimensions } from "./request-projection.js";
9
9
  /** Immutable binary attachment service. Implementations validate bytes before publishing a reference. */
10
10
  export class AttachmentStore extends Service {
11
11
  constructor(ctx) {
@@ -147,14 +147,14 @@ export class AttachmentStore extends Service {
147
147
  /**
148
148
  * Generate or read one deterministic model-request version from the stored normalized image.
149
149
  * @param ref - durable provider-independent normalized attachment reference.
150
- * @param policy - exact route pixel budget and encoded-byte target; a target no ladder quality meets yields the smallest ladder output.
150
+ * @param target - route-chosen dimensions and byte target; an unmet byte target yields the smallest ladder output.
151
151
  * @param signal - optional cancellation.
152
152
  * @returns request bytes and the cache/upload identity covering every transform input.
153
153
  */
154
- readImageRequest(ref, policy, signal) {
154
+ readImageRequest(ref, target, signal) {
155
155
  signal?.throwIfAborted();
156
156
  void ref;
157
- void policy;
157
+ void target;
158
158
  return Promise.reject(new AttachmentError('The mounted attachment provider cannot derive model-request images.', 'ATTACHMENT_PROJECTION_UNSUPPORTED'));
159
159
  }
160
160
  }
@@ -1,7 +1,12 @@
1
1
  /**
2
- * Pure request-projection geometry shared by attachment providers and
3
- * provider-side request pricing. @module @x1a0f3n9/dsh-attachment/request-projection
2
+ * Pure request-projection geometry shared by model routes and provider-side
3
+ * request pricing. @module @x1a0f3n9/dsh-attachment/request-projection
4
4
  */
5
+ /** Integer width and height of one projected image. */
6
+ export interface ProjectedDimensions {
7
+ width: number;
8
+ height: number;
9
+ }
5
10
  /**
6
11
  * Compute aspect-preserving integer dimensions within a hard total-pixel budget.
7
12
  * @param width - positive source width.
@@ -9,8 +14,15 @@
9
14
  * @param maxPixels - positive width-times-height cap.
10
15
  * @returns inward-rounded dimensions; small images are not enlarged.
11
16
  */
12
- export declare function requestImageDimensions(width: number, height: number, maxPixels: number): {
13
- width: number;
14
- height: number;
15
- };
17
+ export declare function requestImageDimensions(width: number, height: number, maxPixels: number): ProjectedDimensions;
18
+ /**
19
+ * Compute aspect-preserving integer dimensions with an exact long edge; the
20
+ * short edge rounds to the nearest pixel, as an encoder resize by the
21
+ * long edge alone.
22
+ * @param width - positive source width.
23
+ * @param height - positive source height.
24
+ * @param longEdge - positive target for the longer source edge.
25
+ * @returns the target dimensions; a long edge at or above the source returns the source unchanged.
26
+ */
27
+ export declare function longEdgeDimensions(width: number, height: number, longEdge: number): ProjectedDimensions;
16
28
  //# sourceMappingURL=request-projection.d.ts.map
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Pure request-projection geometry shared by attachment providers and
3
- * provider-side request pricing. @module @x1a0f3n9/dsh-attachment/request-projection
2
+ * Pure request-projection geometry shared by model routes and provider-side
3
+ * request pricing. @module @x1a0f3n9/dsh-attachment/request-projection
4
4
  */
5
5
  /**
6
6
  * Compute aspect-preserving integer dimensions within a hard total-pixel budget.
@@ -30,4 +30,20 @@ export function requestImageDimensions(width, height, maxPixels) {
30
30
  }
31
31
  return { width: projectedWidth, height: projectedHeight };
32
32
  }
33
+ /**
34
+ * Compute aspect-preserving integer dimensions with an exact long edge; the
35
+ * short edge rounds to the nearest pixel, as an encoder resize by the
36
+ * long edge alone.
37
+ * @param width - positive source width.
38
+ * @param height - positive source height.
39
+ * @param longEdge - positive target for the longer source edge.
40
+ * @returns the target dimensions; a long edge at or above the source returns the source unchanged.
41
+ */
42
+ export function longEdgeDimensions(width, height, longEdge) {
43
+ if (longEdge >= Math.max(width, height))
44
+ return { width, height };
45
+ return width >= height
46
+ ? { width: longEdge, height: Math.max(1, Math.round(longEdge * height / width)) }
47
+ : { width: Math.max(1, Math.round(longEdge * width / height)), height: longEdge };
48
+ }
33
49
  //# sourceMappingURL=request-projection.js.map
@@ -124,10 +124,12 @@ export interface StoredImageAttachment {
124
124
  ref: ImageAttachmentRef;
125
125
  data: Uint8Array;
126
126
  }
127
- /** Deterministic request-image policy selected by one exact model route. */
128
- export interface ImageRequestPolicy {
129
- /** Maximum width multiplied by height after aspect-preserving projection. */
130
- maxPixels: number;
127
+ /** Deterministic request-image target selected by one exact model route for one attachment. */
128
+ export interface ImageRequestTarget {
129
+ /** Target width in pixels; a target above the source keeps the source width. */
130
+ width: number;
131
+ /** Target height in pixels; a target above the source keeps the source height. */
132
+ height: number;
131
133
  /** Encoded-byte target before base64 expansion or Files API upload; the smallest quality-ladder output is kept when no quality fits. */
132
134
  maxBytes: number;
133
135
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@x1a0f3n9/dsh-attachment",
3
3
  "description": "Durable immutable attachment storage seam for the DeepSeek Harness",
4
- "version": "0.1.5-rc.4",
4
+ "version": "0.1.7-rc.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -32,11 +32,11 @@
32
32
  ],
33
33
  "license": "MIT",
34
34
  "peerDependencies": {
35
- "@x1a0f3n9/dsh-brand": "^0.1.5-rc.4",
36
- "@deepseek-ai/cordis": "^4.0.2"
35
+ "@x1a0f3n9/dsh-brand": "0.1.7-rc.2",
36
+ "@deepseek-ai/cordis": "~4.0.4"
37
37
  },
38
38
  "devDependencies": {
39
- "@x1a0f3n9/dsh-brand": "^0.1.5-rc.4",
40
- "@deepseek-ai/cordis": "^4.0.2"
39
+ "@x1a0f3n9/dsh-brand": "0.1.7-rc.2",
40
+ "@deepseek-ai/cordis": "~4.0.4"
41
41
  }
42
42
  }