@superdurable/dex-agents 0.4.0 → 0.6.0

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.
Files changed (144) hide show
  1. package/README.md +616 -55
  2. package/dist/src/agent-approval-display.d.ts +135 -0
  3. package/dist/src/agent-approval-display.js +536 -0
  4. package/dist/src/agent-approval-display.js.map +1 -0
  5. package/dist/src/agent-context-compaction.d.ts +1 -1
  6. package/dist/src/agent-framework-runner.d.ts +160 -12
  7. package/dist/src/agent-framework-runner.js +4 -0
  8. package/dist/src/agent-framework-runner.js.map +1 -1
  9. package/dist/src/agent-local-directory-media-store.d.ts +111 -0
  10. package/dist/src/agent-local-directory-media-store.js +417 -0
  11. package/dist/src/agent-local-directory-media-store.js.map +1 -0
  12. package/dist/src/agent-media.d.ts +279 -0
  13. package/dist/src/agent-media.js +457 -0
  14. package/dist/src/agent-media.js.map +1 -0
  15. package/dist/src/agent-session-codecs.d.ts +5 -1
  16. package/dist/src/agent-session-codecs.js +76 -4
  17. package/dist/src/agent-session-codecs.js.map +1 -1
  18. package/dist/src/agent-session-failure.d.ts +4 -2
  19. package/dist/src/agent-session-failure.js +6 -2
  20. package/dist/src/agent-session-failure.js.map +1 -1
  21. package/dist/src/agent-session-flow-graph.d.ts +46 -0
  22. package/dist/src/agent-session-flow-graph.js +51 -0
  23. package/dist/src/agent-session-flow-graph.js.map +1 -1
  24. package/dist/src/agent-session-flow.d.ts +28 -3
  25. package/dist/src/agent-session-flow.js +21 -1
  26. package/dist/src/agent-session-flow.js.map +1 -1
  27. package/dist/src/agent-session-persistence.d.ts +33 -0
  28. package/dist/src/agent-session-persistence.js +22 -1
  29. package/dist/src/agent-session-persistence.js.map +1 -1
  30. package/dist/src/agent-session-start.d.ts +1 -1
  31. package/dist/src/agent-session-start.js +2 -2
  32. package/dist/src/agent-session-start.js.map +1 -1
  33. package/dist/src/agent-session-steps.d.ts +2 -0
  34. package/dist/src/agent-session-steps.js +74 -5
  35. package/dist/src/agent-session-steps.js.map +1 -1
  36. package/dist/src/agent-session-summary.d.ts +138 -0
  37. package/dist/src/agent-session-summary.js +151 -0
  38. package/dist/src/agent-session-summary.js.map +1 -0
  39. package/dist/src/agent-session-tracer.js +1 -1
  40. package/dist/src/agent-session-tracer.js.map +1 -1
  41. package/dist/src/agent-session-transitions.d.ts +11 -3
  42. package/dist/src/agent-session-transitions.js +58 -6
  43. package/dist/src/agent-session-transitions.js.map +1 -1
  44. package/dist/src/agent-session-values.d.ts +179 -2
  45. package/dist/src/agent-session-values.js.map +1 -1
  46. package/dist/src/agent-session-wait-steps.js +14 -2
  47. package/dist/src/agent-session-wait-steps.js.map +1 -1
  48. package/dist/src/ai-sdk/ai-sdk-model-client.d.ts +15 -3
  49. package/dist/src/ai-sdk/ai-sdk-model-client.js +36 -7
  50. package/dist/src/ai-sdk/ai-sdk-model-client.js.map +1 -1
  51. package/dist/src/ai-sdk/index.d.ts +1 -1
  52. package/dist/src/ai-sdk/index.js +1 -1
  53. package/dist/src/ai-sdk/index.js.map +1 -1
  54. package/dist/src/{stepwise → builtin-loop}/agent-definition.d.ts +120 -5
  55. package/dist/src/builtin-loop/agent-definition.js.map +1 -0
  56. package/dist/src/builtin-loop/builtin-agent-session-flow.d.ts +77 -0
  57. package/dist/src/{stepwise/stepwise-agent-session-flow.js → builtin-loop/builtin-agent-session-flow.js} +19 -9
  58. package/dist/src/builtin-loop/builtin-agent-session-flow.js.map +1 -0
  59. package/dist/src/{stepwise/stepwise-agent-runner.d.ts → builtin-loop/builtin-loop-agent-runner.d.ts} +72 -14
  60. package/dist/src/{stepwise/stepwise-agent-runner.js → builtin-loop/builtin-loop-agent-runner.js} +284 -41
  61. package/dist/src/builtin-loop/builtin-loop-agent-runner.js.map +1 -0
  62. package/dist/src/{stepwise/stepwise-input-items.d.ts → builtin-loop/builtin-loop-input-items.d.ts} +7 -3
  63. package/dist/src/{stepwise/stepwise-input-items.js → builtin-loop/builtin-loop-input-items.js} +57 -10
  64. package/dist/src/builtin-loop/builtin-loop-input-items.js.map +1 -0
  65. package/dist/src/builtin-loop/function-tool.d.ts +282 -0
  66. package/dist/src/{stepwise → builtin-loop}/function-tool.js +63 -3
  67. package/dist/src/builtin-loop/function-tool.js.map +1 -0
  68. package/dist/src/builtin-loop/index.d.ts +8 -0
  69. package/dist/src/builtin-loop/index.js +13 -0
  70. package/dist/src/builtin-loop/index.js.map +1 -0
  71. package/dist/src/builtin-loop/json-schema-validation.js.map +1 -0
  72. package/dist/src/{stepwise → builtin-loop}/model-client.d.ts +36 -7
  73. package/dist/src/builtin-loop/model-client.js.map +1 -0
  74. package/dist/src/{stepwise → builtin-loop}/scripted-model-client.d.ts +8 -5
  75. package/dist/src/{stepwise → builtin-loop}/scripted-model-client.js +8 -5
  76. package/dist/src/builtin-loop/scripted-model-client.js.map +1 -0
  77. package/dist/src/{stepwise → builtin-loop}/tool-source.d.ts +2 -2
  78. package/dist/src/builtin-loop/tool-source.js.map +1 -0
  79. package/dist/src/connectors/connector-input-schema.js +1 -1
  80. package/dist/src/connectors/connector-input-schema.js.map +1 -1
  81. package/dist/src/connectors/connector-step-context.d.ts +19 -2
  82. package/dist/src/connectors/connector-step-context.js +61 -5
  83. package/dist/src/connectors/connector-step-context.js.map +1 -1
  84. package/dist/src/connectors/connector-tool-source.d.ts +63 -14
  85. package/dist/src/connectors/connector-tool-source.js +124 -25
  86. package/dist/src/connectors/connector-tool-source.js.map +1 -1
  87. package/dist/src/index.d.ts +8 -4
  88. package/dist/src/index.js +5 -1
  89. package/dist/src/index.js.map +1 -1
  90. package/dist/src/mcp/index.d.ts +1 -0
  91. package/dist/src/mcp/index.js +1 -0
  92. package/dist/src/mcp/index.js.map +1 -1
  93. package/dist/src/mcp/mcp-dex-conventions.d.ts +57 -0
  94. package/dist/src/mcp/mcp-dex-conventions.js +90 -0
  95. package/dist/src/mcp/mcp-dex-conventions.js.map +1 -0
  96. package/dist/src/mcp/mcp-image-content.d.ts +20 -0
  97. package/dist/src/mcp/mcp-image-content.js +82 -0
  98. package/dist/src/mcp/mcp-image-content.js.map +1 -0
  99. package/dist/src/mcp/mcp-tool-source.d.ts +205 -18
  100. package/dist/src/mcp/mcp-tool-source.js +289 -47
  101. package/dist/src/mcp/mcp-tool-source.js.map +1 -1
  102. package/dist/src/s3/index.d.ts +1 -0
  103. package/dist/src/s3/index.js +9 -0
  104. package/dist/src/s3/index.js.map +1 -0
  105. package/dist/src/s3/s3-media-store.d.ts +138 -0
  106. package/dist/src/s3/s3-media-store.js +255 -0
  107. package/dist/src/s3/s3-media-store.js.map +1 -0
  108. package/dist/src/stepwise/index.d.ts +41 -8
  109. package/dist/src/stepwise/index.js +35 -5
  110. package/dist/src/stepwise/index.js.map +1 -1
  111. package/dist/src/testing/agent-session-test-client.d.ts +6 -3
  112. package/dist/src/testing/agent-session-test-client.js +10 -3
  113. package/dist/src/testing/agent-session-test-client.js.map +1 -1
  114. package/dist/src/testing/private-dex-engine.d.ts +8 -0
  115. package/dist/src/testing/private-dex-engine.js +17 -1
  116. package/dist/src/testing/private-dex-engine.js.map +1 -1
  117. package/dist/src/testing/scripted-model-client.d.ts +1 -1
  118. package/dist/src/testing/scripted-model-client.js +2 -2
  119. package/dist/src/testing/scripted-model-client.js.map +1 -1
  120. package/dist/src/tool-source-router.d.ts +3 -3
  121. package/dist/src/tool-source-router.js +2 -2
  122. package/dist/src/ui-stream/agent-event-json.d.ts +2 -1
  123. package/dist/src/ui-stream/agent-event-json.js +3 -1
  124. package/dist/src/ui-stream/agent-event-json.js.map +1 -1
  125. package/dist/src/ui-stream/agent-ui-messages.d.ts +11 -3
  126. package/dist/src/ui-stream/agent-ui-messages.js +29 -5
  127. package/dist/src/ui-stream/agent-ui-messages.js.map +1 -1
  128. package/package.json +17 -4
  129. package/dist/src/stepwise/agent-definition.js.map +0 -1
  130. package/dist/src/stepwise/function-tool.d.ts +0 -130
  131. package/dist/src/stepwise/function-tool.js.map +0 -1
  132. package/dist/src/stepwise/json-schema-validation.js.map +0 -1
  133. package/dist/src/stepwise/model-client.js.map +0 -1
  134. package/dist/src/stepwise/scripted-model-client.js.map +0 -1
  135. package/dist/src/stepwise/stepwise-agent-runner.js.map +0 -1
  136. package/dist/src/stepwise/stepwise-agent-session-flow.d.ts +0 -35
  137. package/dist/src/stepwise/stepwise-agent-session-flow.js.map +0 -1
  138. package/dist/src/stepwise/stepwise-input-items.js.map +0 -1
  139. package/dist/src/stepwise/tool-source.js.map +0 -1
  140. /package/dist/src/{stepwise → builtin-loop}/agent-definition.js +0 -0
  141. /package/dist/src/{stepwise → builtin-loop}/json-schema-validation.d.ts +0 -0
  142. /package/dist/src/{stepwise → builtin-loop}/json-schema-validation.js +0 -0
  143. /package/dist/src/{stepwise → builtin-loop}/model-client.js +0 -0
  144. /package/dist/src/{stepwise → builtin-loop}/tool-source.js +0 -0
@@ -0,0 +1,457 @@
1
+ // Copyright (c) 2026 Super Durable, Inc.
2
+ //
3
+ // Licensed under the Sustainable Use License 1.0.
4
+ // You may not use this file except in compliance with the License.
5
+ // See the LICENSE file in the repository root.
6
+ //
7
+ // SPDX-License-Identifier: LicenseRef-Sustainable-Use-1.0
8
+ import { createHash } from "node:crypto";
9
+ /**
10
+ * Largest image a media store accepts, in bytes. Its base64 text is 5,000,000 bytes, which fits the per-image limits
11
+ * of Amazon Bedrock (5 MB of base64) and the Claude API (10 MB of base64).
12
+ * @since 0.5.0
13
+ */
14
+ export const maxImageBytes = 3_750_000;
15
+ /**
16
+ * Most images one user message or one tool result may carry.
17
+ * @since 0.5.0
18
+ */
19
+ export const maxImagesPerMessage = 20;
20
+ /**
21
+ * Image types a media store accepts, detected from the bytes.
22
+ * @since 0.5.0
23
+ */
24
+ export const supportedImageMimeTypes = ["image/png", "image/jpeg", "image/gif", "image/webp"];
25
+ /**
26
+ * Longest {@link AgentImageReference.uri} in bytes as UTF-8, the same unit in every core; S3 object keys are at most
27
+ * 1024 bytes.
28
+ * @since 0.5.0
29
+ */
30
+ export const maxImageUriLength = 1024;
31
+ const sha256Pattern = /^[0-9a-f]{64}$/;
32
+ const imageUriPattern = /^[a-z][a-z0-9+.-]*:\/\/\S+\/sha256\/[0-9a-f]{64}$/;
33
+ const pngSignature = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];
34
+ const pngHeaderChunk = [0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52];
35
+ const webpChunkTypes = ["VP8 ", "VP8L", "VP8X"];
36
+ const formatNames = {
37
+ "image/png": "PNG",
38
+ "image/jpeg": "JPEG",
39
+ "image/gif": "GIF",
40
+ "image/webp": "WebP",
41
+ };
42
+ /**
43
+ * Image bytes or an image reference that Dex agents refuse.
44
+ *
45
+ * `putImage` throws it for bytes that are empty, larger than {@link maxImageBytes}, or not PNG, JPEG, GIF, or WebP.
46
+ * {@link validateImageReference} and {@link validateImageReferences} throw it for a reference whose fields are
47
+ * invalid. The message says what is wrong.
48
+ * @since 0.5.0
49
+ */
50
+ export class ImageValidationError extends Error {
51
+ /**
52
+ * @param message - What is wrong with the image or reference.
53
+ */
54
+ constructor(message) {
55
+ super(message);
56
+ this.name = "ImageValidationError";
57
+ }
58
+ }
59
+ /**
60
+ * A media store cannot return the bytes of a valid reference.
61
+ *
62
+ * `getImage` throws it when the reference belongs to another store, when the store has no object for it, or when the
63
+ * stored bytes do not match the reference's SHA-256, size, and type.
64
+ * @since 0.5.0
65
+ */
66
+ export class MediaStoreError extends Error {
67
+ /**
68
+ * @param message - Which image could not be read, and why.
69
+ * @param options - Standard error options, such as the `cause` from the storage service.
70
+ */
71
+ constructor(message, options) {
72
+ super(message, options);
73
+ this.name = "MediaStoreError";
74
+ }
75
+ }
76
+ /**
77
+ * Keeps images in this process, for tests and single-process tools.
78
+ *
79
+ * References use the `memory://<name>` location. Two stores with the same name accept each other's references, but
80
+ * each holds only what was put into it, so a Worker in another process cannot read them.
81
+ *
82
+ * @example
83
+ * ```ts
84
+ * const store = new InMemoryMediaStore();
85
+ * const reference = await store.putImage(pngBytes);
86
+ * assert.deepEqual(await store.getImage(reference), pngBytes);
87
+ * ```
88
+ * @since 0.5.0
89
+ */
90
+ export class InMemoryMediaStore {
91
+ /** The location that every reference of this store starts with: `"memory://<name>"`. */
92
+ storeUri;
93
+ images = new Map();
94
+ /**
95
+ * Creates an empty store.
96
+ *
97
+ * @param name - The location name in `memory://<name>`, `"default"` when omitted. It must be non-empty and contain
98
+ * no `/` or whitespace.
99
+ * @throws {TypeError} When `name` is empty or contains `/` or whitespace.
100
+ * @throws {RangeError} When `name` makes image URIs longer than {@link maxImageUriLength}.
101
+ */
102
+ constructor(name = "default") {
103
+ if (name === "" || name.includes("/") || /\s/.test(name)) {
104
+ throw new TypeError("InMemoryMediaStore name must be non-empty, without / or whitespace");
105
+ }
106
+ this.storeUri = `memory://${name}`;
107
+ requireShortImageUris(this.storeUri);
108
+ }
109
+ /** How many distinct images the store holds; uploading the same bytes twice counts once. */
110
+ get imageCount() {
111
+ return this.images.size;
112
+ }
113
+ /**
114
+ * Stores one image and returns its reference. See {@link MediaStore.putImage}.
115
+ *
116
+ * @param data - PNG, JPEG, GIF, or WebP bytes, at most {@link maxImageBytes}.
117
+ * @returns The reference.
118
+ * @throws {ImageValidationError} When the bytes are empty, too large, or of another type.
119
+ */
120
+ async putImage(data) {
121
+ const reference = buildImageReference(data, this.storeUri);
122
+ if (!this.images.has(reference.sha256)) {
123
+ this.images.set(reference.sha256, Uint8Array.from(data));
124
+ }
125
+ return reference;
126
+ }
127
+ /**
128
+ * Returns the bytes of one image. See {@link MediaStore.getImage}.
129
+ *
130
+ * @param reference - A reference that this store's `putImage` returned.
131
+ * @returns A copy of the exact bytes; changing it leaves the stored image as it was.
132
+ * @throws {ImageValidationError} When the reference's fields are invalid.
133
+ * @throws {MediaStoreError} When the reference belongs to another store, the store does not hold the image, or its
134
+ * bytes do not match.
135
+ */
136
+ async getImage(reference) {
137
+ requireStoreImageReference(reference, this.storeUri);
138
+ const data = this.images.get(reference.sha256);
139
+ if (data === undefined) {
140
+ throw new MediaStoreError(`image ${reference.uri} is not in the media store`);
141
+ }
142
+ return verifyImageBytes(reference, Uint8Array.from(data));
143
+ }
144
+ }
145
+ /**
146
+ * Returns the MIME type of image bytes, read from their structure.
147
+ *
148
+ * The signature picks the type, then a cheap structural check must hold; it does not decode the image. PNG needs its
149
+ * signature followed by the `IHDR` chunk. JPEG needs SOI, a marker right after it, and EOI as the last two bytes. GIF
150
+ * needs a `GIF87a` or `GIF89a` header and the logical screen descriptor. WebP needs a RIFF size equal to the byte count
151
+ * minus 8 and a first chunk of `VP8 `, `VP8L`, or `VP8X`.
152
+ *
153
+ * @param data - Image bytes.
154
+ * @returns `"image/png"`, `"image/jpeg"`, `"image/gif"`, or `"image/webp"`.
155
+ * @throws {ImageValidationError} When the bytes are empty, start with no supported signature, or fail the structural
156
+ * check of their type.
157
+ * @since 0.5.0
158
+ */
159
+ export function detectImageMimeType(data) {
160
+ if (data.length === 0) {
161
+ throw new ImageValidationError("image is empty");
162
+ }
163
+ const mimeType = signatureMimeType(data);
164
+ if (mimeType === undefined) {
165
+ throw new ImageValidationError("image is not PNG, JPEG, GIF, or WebP");
166
+ }
167
+ if (!isWellFormed(mimeType, data)) {
168
+ throw new ImageValidationError(`image is not a well-formed ${formatNames[mimeType]}`);
169
+ }
170
+ return mimeType;
171
+ }
172
+ function signatureMimeType(data) {
173
+ if (startsWithBytes(data, pngSignature)) {
174
+ return "image/png";
175
+ }
176
+ if (startsWithBytes(data, [0xff, 0xd8, 0xff])) {
177
+ return "image/jpeg";
178
+ }
179
+ if (startsWithText(data, 0, "GIF87a") || startsWithText(data, 0, "GIF89a")) {
180
+ return "image/gif";
181
+ }
182
+ if (startsWithText(data, 0, "RIFF") && startsWithText(data, 8, "WEBP")) {
183
+ return "image/webp";
184
+ }
185
+ return undefined;
186
+ }
187
+ function isWellFormed(mimeType, data) {
188
+ switch (mimeType) {
189
+ case "image/png":
190
+ return data.length >= 33 && startsWithBytes(data.subarray(8), pngHeaderChunk);
191
+ case "image/jpeg": {
192
+ const marker = data[3] ?? 0;
193
+ return data.length >= 6 && marker >= 0xc0 && marker <= 0xfe && data.at(-2) === 0xff && data.at(-1) === 0xd9;
194
+ }
195
+ case "image/gif":
196
+ return data.length >= 13;
197
+ default: {
198
+ if (data.length < 20) {
199
+ return false;
200
+ }
201
+ const riffSize = new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(4, true);
202
+ const chunkType = String.fromCharCode(...data.subarray(12, 16));
203
+ return riffSize + 8 === data.length && webpChunkTypes.includes(chunkType);
204
+ }
205
+ }
206
+ }
207
+ /**
208
+ * Checks image bytes and returns the reference a store keeps them under.
209
+ *
210
+ * A {@link MediaStore} implementation calls it before it uploads: the reference names the object,
211
+ * `imageUri(storeUri, sha256)`.
212
+ *
213
+ * @param data - Image bytes.
214
+ * @param storeUri - The store's location, such as `"s3://media/agents"`.
215
+ * @returns The reference, with the detected MIME type, SHA-256, and size.
216
+ * @throws {ImageValidationError} When the bytes are empty, larger than {@link maxImageBytes}, or not a well-formed
217
+ * PNG, JPEG, GIF, or WebP, or when {@link validateImageReference} refuses the reference, such as for a URI longer than
218
+ * {@link maxImageUriLength}.
219
+ * @since 0.5.0
220
+ */
221
+ export function buildImageReference(data, storeUri) {
222
+ if (data.length > maxImageBytes) {
223
+ throw new ImageValidationError(`image is ${data.length} bytes; the limit is ${maxImageBytes} bytes`);
224
+ }
225
+ const mimeType = detectImageMimeType(data);
226
+ const sha256 = createHash("sha256").update(data).digest("hex");
227
+ const reference = {
228
+ type: "image",
229
+ uri: imageUri(storeUri, sha256),
230
+ mimeType,
231
+ sha256,
232
+ sizeBytes: data.length,
233
+ };
234
+ validateImageReference(reference);
235
+ return reference;
236
+ }
237
+ /**
238
+ * Returns the URI of the image with this SHA-256 in a store.
239
+ *
240
+ * @param storeUri - The store's location; trailing `/` characters are dropped.
241
+ * @param sha256 - SHA-256 of the bytes as 64 lowercase hex digits.
242
+ * @returns `"<storeUri>/sha256/<sha256>"`.
243
+ * @since 0.5.0
244
+ */
245
+ export function imageUri(storeUri, sha256) {
246
+ return `${storeUri.replace(/\/+$/, "")}/sha256/${sha256}`;
247
+ }
248
+ /**
249
+ * Checks that every image URI of a store fits {@link maxImageUriLength}.
250
+ *
251
+ * A {@link MediaStore} implementation calls it in its constructor, so a long location fails at once instead of on the
252
+ * first upload.
253
+ *
254
+ * @param storeUri - The store's location.
255
+ * @throws {RangeError} When `imageUri(storeUri, sha256)` is longer than {@link maxImageUriLength} bytes as UTF-8.
256
+ * @since 0.5.0
257
+ */
258
+ export function requireShortImageUris(storeUri) {
259
+ if (Buffer.byteLength(imageUri(storeUri, "0".repeat(64)), "utf8") > maxImageUriLength) {
260
+ throw new RangeError(`media store location ${storeUri} makes image URIs longer than ${maxImageUriLength} bytes as UTF-8`);
261
+ }
262
+ }
263
+ /**
264
+ * Checks the fields of one image reference.
265
+ *
266
+ * The checks run in order, and the first failure is thrown: `type` is `"image"`; `mimeType` is supported; `sha256` is
267
+ * 64 lowercase hex digits; `sizeBytes` is from 1 to {@link maxImageBytes}; `uri` is at most
268
+ * {@link maxImageUriLength} bytes as UTF-8, looks like `<scheme>://<location>/sha256/<sha256>`, and ends with the
269
+ * reference's own `sha256`. It does not read the store.
270
+ *
271
+ * @param reference - The reference, such as one decoded from a request.
272
+ * @throws {ImageValidationError} When a field is invalid.
273
+ * @since 0.5.0
274
+ */
275
+ export function validateImageReference(reference) {
276
+ if (reference.type !== "image") {
277
+ throw new ImageValidationError('image reference type must be "image"');
278
+ }
279
+ if (!supportedImageMimeTypes.includes(reference.mimeType)) {
280
+ throw new ImageValidationError(`image reference mime_type must be one of ${supportedImageMimeTypes.join(", ")}`);
281
+ }
282
+ if (typeof reference.sha256 !== "string" || !sha256Pattern.test(reference.sha256)) {
283
+ throw new ImageValidationError("image reference sha256 must be 64 lowercase hex digits");
284
+ }
285
+ const size = reference.sizeBytes;
286
+ if (!Number.isSafeInteger(size) || size < 1 || size > maxImageBytes) {
287
+ throw new ImageValidationError(`image reference size_bytes must be from 1 to ${maxImageBytes}`);
288
+ }
289
+ const uri = reference.uri;
290
+ if (typeof uri !== "string" || Buffer.byteLength(uri, "utf8") > maxImageUriLength) {
291
+ throw new ImageValidationError(`image reference uri must be at most ${maxImageUriLength} bytes as UTF-8`);
292
+ }
293
+ if (!imageUriPattern.test(uri)) {
294
+ throw new ImageValidationError("image reference uri must look like <scheme>://<location>/sha256/<sha256>");
295
+ }
296
+ if (!uri.endsWith(`/${reference.sha256}`)) {
297
+ throw new ImageValidationError("image reference uri must end with its own sha256");
298
+ }
299
+ }
300
+ /**
301
+ * Checks the images of one user message or one tool result.
302
+ *
303
+ * @param references - The images, at most {@link maxImagesPerMessage}.
304
+ * @throws {ImageValidationError} When there are too many images, or with `"images[<index>]: "` before the reason
305
+ * when one is invalid.
306
+ * @since 0.5.0
307
+ */
308
+ export function validateImageReferences(references) {
309
+ if (references.length > maxImagesPerMessage) {
310
+ throw new ImageValidationError(`a message may carry at most ${maxImagesPerMessage} images, got ${references.length}`);
311
+ }
312
+ references.forEach((reference, index) => {
313
+ try {
314
+ validateImageReference(reference);
315
+ }
316
+ catch (error) {
317
+ if (error instanceof ImageValidationError) {
318
+ throw new ImageValidationError(`images[${index}]: ${error.message}`);
319
+ }
320
+ throw error;
321
+ }
322
+ });
323
+ }
324
+ /**
325
+ * Checks that a valid reference names an image of the store at `storeUri`.
326
+ *
327
+ * A {@link MediaStore} implementation calls it first in `getImage`, so a request cannot make the Worker read outside
328
+ * the store's location.
329
+ *
330
+ * @param reference - The reference to read.
331
+ * @param storeUri - The store's location.
332
+ * @throws {ImageValidationError} When the reference's fields are invalid.
333
+ * @throws {MediaStoreError} When its `uri` is not `imageUri(storeUri, sha256)`.
334
+ * @since 0.5.0
335
+ */
336
+ export function requireStoreImageReference(reference, storeUri) {
337
+ validateImageReference(reference);
338
+ if (reference.uri !== imageUri(storeUri, reference.sha256)) {
339
+ throw new MediaStoreError(`image ${reference.uri} is not in the media store ${storeUri}`);
340
+ }
341
+ }
342
+ /**
343
+ * Checks bytes read from a store against their reference.
344
+ *
345
+ * The SHA-256 binds the bytes, and {@link detectImageMimeType} must find the reference's `mimeType` in them, so a
346
+ * reference whose type was changed after upload fails here.
347
+ *
348
+ * @param reference - The reference that was read.
349
+ * @param data - The bytes the store returned.
350
+ * @returns `data`, unchanged.
351
+ * @throws {MediaStoreError} When the size or the SHA-256 differs, or when the bytes are not a well-formed image of
352
+ * `mimeType`.
353
+ * @since 0.5.0
354
+ */
355
+ export function verifyImageBytes(reference, data) {
356
+ if (data.length !== reference.sizeBytes || createHash("sha256").update(data).digest("hex") !== reference.sha256) {
357
+ throw new MediaStoreError(`image ${reference.uri} does not match its sha256 and size`);
358
+ }
359
+ let detected;
360
+ try {
361
+ detected = detectImageMimeType(data);
362
+ }
363
+ catch (error) {
364
+ if (!(error instanceof ImageValidationError)) {
365
+ throw error;
366
+ }
367
+ }
368
+ if (detected !== reference.mimeType) {
369
+ throw new MediaStoreError(`image ${reference.uri} does not hold a well-formed ${reference.mimeType}`);
370
+ }
371
+ return data;
372
+ }
373
+ /**
374
+ * Reads the bytes of several images, each distinct image once.
375
+ *
376
+ * A runner calls it while building model input, with the references it chose from {@link collectTurnImages} or from
377
+ * its own replayed items. The reads run concurrently.
378
+ *
379
+ * @example
380
+ * ```ts
381
+ * const images = await loadImages(store, collectTurnImages(turn));
382
+ * const parts = (message.images ?? []).map((reference) => imagePart(reference.mimeType, images.get(reference.sha256)!));
383
+ * ```
384
+ * @param store - The store that holds the images.
385
+ * @param references - The images to read, in any order, with repeats allowed.
386
+ * @returns The bytes of each image, keyed by {@link AgentImageReference.sha256}.
387
+ * @throws {ImageValidationError} When a reference's fields are invalid.
388
+ * @throws {MediaStoreError} When the store cannot return an image's exact bytes.
389
+ * @throws The store's own error when a read fails.
390
+ * @since 0.5.0
391
+ */
392
+ export async function loadImages(store, references) {
393
+ const distinct = new Map();
394
+ for (const reference of references) {
395
+ distinct.set(reference.sha256, reference);
396
+ }
397
+ const contents = await Promise.all([...distinct.values()].map((reference) => store.getImage(reference)));
398
+ return new Map([...distinct.keys()].map((sha256, index) => [sha256, contents[index]]));
399
+ }
400
+ /**
401
+ * Returns every image a model call of this turn may show, each once.
402
+ *
403
+ * It collects `AgentMessage.images` of `turn.messages` in sequence order, then `AgentToolCall.images` of the turn's
404
+ * records in deferral order, keeping the first reference to each SHA-256. Whether a model call shows earlier turns'
405
+ * images is the runner's choice; pass only the references it needs to {@link loadImages}.
406
+ *
407
+ * @param turn - The context of one `runModelStep` call.
408
+ * @returns The references, without repeats.
409
+ * @since 0.5.0
410
+ */
411
+ export function collectTurnImages(turn) {
412
+ const collected = new Map();
413
+ const keepFirst = (reference) => {
414
+ if (!collected.has(reference.sha256)) {
415
+ collected.set(reference.sha256, reference);
416
+ }
417
+ };
418
+ for (const message of turn.messages) {
419
+ (message.images ?? []).forEach(keepFirst);
420
+ }
421
+ const records = [...turn.toolCalls].sort((left, right) => left.deferralOrder - right.deferralOrder);
422
+ for (const record of records) {
423
+ (record.images ?? []).forEach(keepFirst);
424
+ }
425
+ return [...collected.values()];
426
+ }
427
+ /** Reports whether {@link validateImageReferences} accepts the images; the RPCs answer `false` instead of throwing. */
428
+ export function areValidImageReferences(references) {
429
+ try {
430
+ validateImageReferences(references);
431
+ return true;
432
+ }
433
+ catch (error) {
434
+ if (error instanceof ImageValidationError) {
435
+ return false;
436
+ }
437
+ throw error;
438
+ }
439
+ }
440
+ /**
441
+ * Returns the `images` field of a succeeded record from a tool's result. An invalid reference throws
442
+ * {@link ImageValidationError}, which fails the tool Step attempt.
443
+ */
444
+ export function toolResultImages(references) {
445
+ if (references === undefined || references.length === 0) {
446
+ return {};
447
+ }
448
+ validateImageReferences(references);
449
+ return { images: [...references] };
450
+ }
451
+ function startsWithBytes(data, signature) {
452
+ return data.length >= signature.length && signature.every((byte, index) => data[index] === byte);
453
+ }
454
+ function startsWithText(data, offset, text) {
455
+ return startsWithBytes(data.subarray(offset), [...text].map((character) => character.charCodeAt(0)));
456
+ }
457
+ //# sourceMappingURL=agent-media.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-media.js","sourceRoot":"","sources":["../../src/agent-media.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { type Codec } from "@superdurable/dex";
2
- import type { AgentEvent, AgentInterrupt, AgentInterruptResolution, AgentMessage, AgentMessageChunk, AgentMessageChunkRange, AgentMessageIndex, AgentMessagesPage, AgentPlan, AgentPlanTask, AgentSessionStartInput, AgentSnapshot, AgentState, AgentToolCallRecord, AgentUsage, AgentUserMessage, AnswerQuestionRequest, CancelTurnRequest, DeleteQueuedMessageRequest, ExecutePlanRequest, CompactContextInput, ContextSummary, ListAgentMessagesInput, PendingUserMessage, PlanExecutionRequest, QuestionAnswer, ResolveInterruptInput, SteerUserMessageRequest, ToolCallCancellation, ToolCallCompleted, TurnCancellationRequest, TurnControlRequest, SessionSettings, TurnReplySequence, TurnSessionSettings, UpdateSessionSettingsRequest } from "./agent-session-values.js";
2
+ import type { AgentEvent, AgentImageReference, AgentInterrupt, AgentInterruptDisplay, AgentInterruptResolution, AgentMessage, AgentMessageChunk, AgentMessageChunkRange, AgentMessageIndex, AgentMessagesPage, AgentPlan, AgentPlanTask, AgentSessionStartInput, AgentSnapshot, AgentState, AgentToolCallRecord, AgentUsage, AgentUserMessage, AnswerQuestionRequest, CancelTurnRequest, DeleteQueuedMessageRequest, ExecutePlanRequest, CompactContextInput, ContextSummary, ListAgentMessagesInput, PendingUserMessage, PlanExecutionRequest, QuestionAnswer, ResolveInterruptInput, SteerUserMessageRequest, ToolCallCancellation, ToolCallCompleted, TurnCancellationRequest, TurnControlRequest, SessionSettings, TurnReplySequence, TurnSessionSettings, UpdateSessionSettingsRequest } from "./agent-session-values.js";
3
3
  export declare function encodeAgentSessionStartInput(value: AgentSessionStartInput): unknown;
4
4
  export declare function decodeAgentSessionStartInput(value: unknown): AgentSessionStartInput;
5
5
  export declare function encodeSessionSettings(value: SessionSettings): unknown;
@@ -10,6 +10,10 @@ export declare function encodeTurnSessionSettings(value: TurnSessionSettings): u
10
10
  export declare function decodeTurnSessionSettings(value: unknown): TurnSessionSettings;
11
11
  export declare function encodeAgentState(value: AgentState): unknown;
12
12
  export declare function decodeAgentState(value: unknown): AgentState;
13
+ export declare function encodeAgentImageReference(value: AgentImageReference): unknown;
14
+ export declare function decodeAgentImageReference(value: unknown): AgentImageReference;
15
+ export declare function encodeAgentInterruptDisplay(value: AgentInterruptDisplay | null | undefined): unknown;
16
+ export declare function decodeAgentInterruptDisplay(value: unknown): AgentInterruptDisplay | null;
13
17
  export declare function encodeAgentMessage(value: AgentMessage): unknown;
14
18
  export declare function decodeAgentMessage(value: unknown): AgentMessage;
15
19
  export declare function encodeAgentToolCall(value: AgentToolCallRecord): unknown;
@@ -136,18 +136,25 @@ class WireRecordReader {
136
136
  }
137
137
  }
138
138
  export function encodeAgentSessionStartInput(value) {
139
- return { initial_message: value.initialMessage, session_settings: value.sessionSettings ?? null };
139
+ return {
140
+ initial_message: value.initialMessage,
141
+ session_settings: value.sessionSettings ?? null,
142
+ start_environment: value.startEnvironment ?? null,
143
+ };
140
144
  }
141
145
  export function decodeAgentSessionStartInput(value) {
142
146
  if (value === null || value === undefined) {
143
- return { initialMessage: null, sessionSettings: null };
147
+ return { initialMessage: null, sessionSettings: null, startEnvironment: null };
144
148
  }
145
149
  const reader = new WireRecordReader(value, "AgentSessionStartInput");
146
150
  const sessionSettings = reader.readObject("session_settings");
151
+ const startEnvironment = reader.readObject("start_environment");
147
152
  return {
148
153
  initialMessage: reader.readNullableString("initial_message"),
149
154
  // Kept as sent: StartAgentSession refuses a value that is not an object, failing the session at once.
150
155
  sessionSettings: sessionSettings == null ? null : sessionSettings,
156
+ // Kept as sent: the session never reads it.
157
+ startEnvironment: startEnvironment == null ? null : startEnvironment,
151
158
  };
152
159
  }
153
160
  export function encodeSessionSettings(value) {
@@ -204,6 +211,54 @@ export function decodeAgentState(value) {
204
211
  ...(acceptsTurnControl ? { acceptsTurnControl } : {}),
205
212
  };
206
213
  }
214
+ export function encodeAgentImageReference(value) {
215
+ return {
216
+ type: value.type,
217
+ uri: value.uri,
218
+ mime_type: value.mimeType,
219
+ sha256: value.sha256,
220
+ size_bytes: value.sizeBytes,
221
+ };
222
+ }
223
+ export function decodeAgentImageReference(value) {
224
+ const reader = new WireRecordReader(value, "AgentImageReference");
225
+ return {
226
+ // Another type decodes as it is, so validateImageReference refuses it as Python does.
227
+ type: (reader.readNullableString("type") ?? "image"),
228
+ uri: reader.readString("uri"),
229
+ mimeType: reader.readString("mime_type"),
230
+ sha256: reader.readString("sha256"),
231
+ sizeBytes: reader.readInteger("size_bytes"),
232
+ };
233
+ }
234
+ function encodeImages(images) {
235
+ return (images ?? []).map(encodeAgentImageReference);
236
+ }
237
+ /** Decodes an `images` field; decoded values omit it when there are none, as they do `planMode`. */
238
+ function decodeImages(reader) {
239
+ const images = reader.readArrayOrEmpty("images").map(decodeAgentImageReference);
240
+ return images.length === 0 ? {} : { images };
241
+ }
242
+ export function encodeAgentInterruptDisplay(value) {
243
+ return value === null || value === undefined
244
+ ? null
245
+ : { target: value.target, summary: value.summary, preview: value.preview ?? null };
246
+ }
247
+ export function decodeAgentInterruptDisplay(value) {
248
+ if (value === null || value === undefined) {
249
+ return null;
250
+ }
251
+ const reader = new WireRecordReader(value, "AgentInterruptDisplay");
252
+ return {
253
+ target: reader.readString("target"),
254
+ summary: reader.readString("summary"),
255
+ preview: reader.readNullableString("preview"),
256
+ };
257
+ }
258
+ /** Decoded values omit a display field when there is none, as they do `images`. */
259
+ function omitNullDisplay(name, display) {
260
+ return (display === null ? {} : { [name]: display });
261
+ }
207
262
  export function encodeAgentMessage(value) {
208
263
  return {
209
264
  sequence: value.sequence,
@@ -216,6 +271,8 @@ export function encodeAgentMessage(value) {
216
271
  tool_output: value.toolOutput,
217
272
  framework_item: value.frameworkItem,
218
273
  created_at: value.createdAt,
274
+ images: encodeImages(value.images),
275
+ origin: value.origin ?? null,
219
276
  };
220
277
  }
221
278
  export function decodeAgentMessage(value) {
@@ -231,8 +288,15 @@ export function decodeAgentMessage(value) {
231
288
  toolOutput: reader.readNullableString("tool_output"),
232
289
  frameworkItem: reader.readString("framework_item"),
233
290
  createdAt: reader.readString("created_at"),
291
+ ...decodeImages(reader),
292
+ ...decodeAgentMessageOrigin(reader),
234
293
  };
235
294
  }
295
+ /** Keeps an origin this release does not know, so a client still tells the message apart from user text. */
296
+ function decodeAgentMessageOrigin(reader) {
297
+ const origin = reader.readNullableString("origin");
298
+ return origin === null ? {} : { origin };
299
+ }
236
300
  export function encodeAgentToolCall(value) {
237
301
  return {
238
302
  tool_call_id: value.toolCallId,
@@ -262,6 +326,9 @@ export function encodeAgentToolCall(value) {
262
326
  write_queued: value.writeQueued ?? false,
263
327
  skipped: value.skipped ?? false,
264
328
  truncated_output_bytes: value.truncatedOutputBytes ?? null,
329
+ images: encodeImages(value.images),
330
+ runner_tool_state: value.runnerToolState ?? null,
331
+ approval_display: encodeAgentInterruptDisplay(value.approvalDisplay),
265
332
  };
266
333
  }
267
334
  export function decodeAgentToolCall(value) {
@@ -293,7 +360,10 @@ export function decodeAgentToolCall(value) {
293
360
  writeQueued: reader.readBooleanOrDefault("write_queued", false),
294
361
  skipped: reader.readBooleanOrDefault("skipped", false),
295
362
  truncatedOutputBytes: reader.readNullableInteger("truncated_output_bytes"),
363
+ runnerToolState: reader.readNullableString("runner_tool_state"),
296
364
  ...(traceContext === null ? {} : { traceContext }),
365
+ ...decodeImages(reader),
366
+ ...omitNullDisplay("approvalDisplay", decodeAgentInterruptDisplay(reader.readObject("approval_display"))),
297
367
  };
298
368
  const toolSourceReference = reader.readNullableString("tool_source_reference");
299
369
  return toolSourceReference === null ? toolCall : { ...toolCall, toolSourceReference };
@@ -327,6 +397,7 @@ export function encodeAgentInterrupt(value) {
327
397
  question: value.question ?? null,
328
398
  choices: [...(value.choices ?? [])],
329
399
  allows_free_text: value.allowsFreeText ?? true,
400
+ display: encodeAgentInterruptDisplay(value.display),
330
401
  };
331
402
  }
332
403
  export function decodeAgentInterrupt(value) {
@@ -342,6 +413,7 @@ export function decodeAgentInterrupt(value) {
342
413
  question: reader.readNullableString("question"),
343
414
  choices: reader.readStringArrayOrEmpty("choices"),
344
415
  allowsFreeText: reader.readBooleanOrDefault("allows_free_text", true),
416
+ ...omitNullDisplay("display", decodeAgentInterruptDisplay(reader.readObject("display"))),
345
417
  };
346
418
  }
347
419
  export function encodeAgentInterruptResolution(value) {
@@ -382,12 +454,12 @@ export function decodeAgentUsage(value) {
382
454
  };
383
455
  }
384
456
  export function encodeAgentUserMessage(value) {
385
- return { text: value.text, plan_mode: value.planMode ?? false };
457
+ return { text: value.text, plan_mode: value.planMode ?? false, images: encodeImages(value.images) };
386
458
  }
387
459
  export function decodeAgentUserMessage(value) {
388
460
  const reader = new WireRecordReader(value, "AgentUserMessage");
389
461
  const planMode = reader.readBooleanOrDefault("plan_mode", false);
390
- return { text: reader.readString("text"), ...(planMode ? { planMode } : {}) };
462
+ return { text: reader.readString("text"), ...(planMode ? { planMode } : {}), ...decodeImages(reader) };
391
463
  }
392
464
  export function encodeAgentPlan(value) {
393
465
  return {