@opencode/ai 0.0.0-dev-19544 → 0.0.0-dev-19545

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.
@@ -209,7 +209,7 @@ const lowerToolCall = (part) => ({
209
209
  input: removeEmptyToolInputKeys(part.input),
210
210
  },
211
211
  });
212
- const lowerToolResultContent = Effect.fn("BedrockConverse.lowerToolResultContent")(function* (part) {
212
+ const lowerToolResultContent = Effect.fn("BedrockConverse.lowerToolResultContent")(function* (part, documentNames) {
213
213
  if (part.result.type === "text" || part.result.type === "error")
214
214
  return [{ text: ProviderShared.toolResultText(part) }];
215
215
  if (part.result.type === "json")
@@ -225,22 +225,23 @@ const lowerToolResultContent = Effect.fn("BedrockConverse.lowerToolResultContent
225
225
  mediaType: item.mime,
226
226
  data: item.uri,
227
227
  filename: item.name,
228
- });
229
- content.push(media);
228
+ }, documentNames);
229
+ content.push(...media);
230
230
  }
231
231
  return content;
232
232
  });
233
- const lowerToolResult = Effect.fn("BedrockConverse.lowerToolResult")(function* (part) {
233
+ const lowerToolResult = Effect.fn("BedrockConverse.lowerToolResult")(function* (part, documentNames) {
234
234
  return {
235
235
  toolResult: {
236
236
  toolUseId: part.id,
237
- content: yield* lowerToolResultContent(part),
237
+ content: yield* lowerToolResultContent(part, documentNames),
238
238
  status: part.result.type === "error" ? "error" : "success",
239
239
  },
240
240
  };
241
241
  });
242
242
  const lowerMessages = Effect.fn("BedrockConverse.lowerMessages")(function* (request, breakpoints) {
243
243
  const messages = [];
244
+ const documentNames = new Set();
244
245
  const providerMetadataKey = request.model.route.providerMetadataKey ?? String(request.model.provider);
245
246
  for (const message of request.messages) {
246
247
  if (message.role === "system") {
@@ -263,7 +264,7 @@ const lowerMessages = Effect.fn("BedrockConverse.lowerMessages")(function* (requ
263
264
  continue;
264
265
  }
265
266
  if (part.type === "media") {
266
- content.push(yield* BedrockMedia.lower(part));
267
+ content.push(...(yield* BedrockMedia.lower(part, documentNames)));
267
268
  continue;
268
269
  }
269
270
  }
@@ -317,7 +318,7 @@ const lowerMessages = Effect.fn("BedrockConverse.lowerMessages")(function* (requ
317
318
  for (const part of message.content) {
318
319
  if (!ProviderShared.supportsContent(part, ["tool-result"]))
319
320
  return yield* ProviderShared.unsupportedContent("Bedrock Converse", "tool", ["tool-result"]);
320
- content.push(yield* lowerToolResult(part));
321
+ content.push(yield* lowerToolResult(part, documentNames));
321
322
  const cachePoint = BedrockCache.block(breakpoints, part.cache);
322
323
  if (cachePoint)
323
324
  content.push(cachePoint);
@@ -36,7 +36,14 @@ export declare const lower: (part: {
36
36
  };
37
37
  } | undefined;
38
38
  readonly filename?: string | undefined;
39
- }) => Effect.Effect<{
39
+ }, documentNames: Set<string>) => Effect.Effect<{
40
+ image: {
41
+ format: "png" | "jpeg" | "gif" | "webp";
42
+ source: {
43
+ bytes: string;
44
+ };
45
+ };
46
+ }[] | ({
40
47
  readonly document: {
41
48
  readonly format: "pdf" | "csv" | "doc" | "docx" | "xls" | "xlsx" | "html" | "txt" | "md";
42
49
  readonly name: string;
@@ -45,11 +52,6 @@ export declare const lower: (part: {
45
52
  };
46
53
  };
47
54
  } | {
48
- image: {
49
- format: "png" | "jpeg" | "gif" | "webp";
50
- source: {
51
- bytes: string;
52
- };
53
- };
54
- }, import("../../schema/errors.js").AIError, never>;
55
+ text: string;
56
+ })[], import("../../schema/errors.js").AIError, never>;
55
57
  export * as BedrockMedia from "./bedrock-media.js";
@@ -44,6 +44,23 @@ const documentBlock = (name, format, bytes) => ({
44
44
  source: { bytes },
45
45
  },
46
46
  });
47
+ function documentName(filename, names) {
48
+ const base = (filename ?? "")
49
+ .replace(/\.[^.]*$/, "")
50
+ .replace(/[^a-zA-Z0-9 ()[\]-]/g, " ")
51
+ .replace(/\s+/g, " ")
52
+ .trim()
53
+ .slice(0, 200)
54
+ .trim() || "document";
55
+ let name = base;
56
+ // Converse requires labels to be unique across the entire request, including tool results.
57
+ for (let index = 2; names.has(name); index++) {
58
+ const suffix = ` ${index}`;
59
+ name = `${base.slice(0, 200 - suffix.length).trimEnd()}${suffix}`;
60
+ }
61
+ names.add(name);
62
+ return name;
63
+ }
47
64
  const mediaBase64 = Effect.fn("BedrockMedia.mediaBase64")(function* (part) {
48
65
  const media = ProviderShared.normalizeMedia(part);
49
66
  const bytes = yield* Effect.fromResult(Encoding.decodeBase64(media.base64)).pipe(Effect.mapError((cause) => ProviderShared.invalidRequest("Bedrock Converse media data must be valid base64", cause)));
@@ -54,19 +71,26 @@ const mediaBase64 = Effect.fn("BedrockMedia.mediaBase64")(function* (part) {
54
71
  // document block. Image MIME types not in `IMAGE_FORMATS` (e.g. `image/svg+xml`)
55
72
  // get an image-specific error so the caller knows it's a format-support issue,
56
73
  // not a kind-detection issue.
57
- export const lower = Effect.fn("BedrockMedia.lower")(function* (part) {
74
+ export const lower = Effect.fn("BedrockMedia.lower")(function* (part, documentNames) {
58
75
  const mime = part.mediaType.toLowerCase();
59
76
  const imageFormat = IMAGE_FORMATS[mime];
60
77
  if (imageFormat) {
61
- return { image: { format: imageFormat, source: { bytes: yield* mediaBase64(part) } } };
78
+ return [{ image: { format: imageFormat, source: { bytes: yield* mediaBase64(part) } } }];
62
79
  }
63
80
  if (mime.startsWith("image/"))
64
81
  return yield* ProviderShared.invalidRequest(`Bedrock Converse does not support image media type ${part.mediaType}`);
65
82
  const documentFormat = DOCUMENT_FORMATS[mime];
66
83
  if (documentFormat) {
67
- if (!part.filename)
68
- return yield* ProviderShared.invalidRequest("Bedrock Converse document media requires a filename");
69
- return documentBlock(part.filename, documentFormat, yield* mediaBase64(part));
84
+ const name = documentName(part.filename, documentNames);
85
+ const block = documentBlock(name, documentFormat, yield* mediaBase64(part));
86
+ return part.filename !== undefined && part.filename !== name
87
+ ? [
88
+ {
89
+ text: `Attached file ${ProviderShared.encodeJson(part.filename)} has document label ${ProviderShared.encodeJson(name)}.`,
90
+ },
91
+ block,
92
+ ]
93
+ : [block];
70
94
  }
71
95
  return yield* ProviderShared.invalidRequest(`Bedrock Converse does not support media type ${part.mediaType}`);
72
96
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
- "version": "0.0.0-dev-19544",
3
+ "version": "0.0.0-dev-19545",
4
4
  "name": "@opencode/ai",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -30,7 +30,7 @@
30
30
  "devDependencies": {
31
31
  "@clack/prompts": "1.0.0-alpha.1",
32
32
  "@effect/platform-node": "4.0.0-rc.112",
33
- "@opencode/http-recorder": "0.0.0-dev-19544",
33
+ "@opencode/http-recorder": "0.0.0-dev-19545",
34
34
  "@tsconfig/bun": "1.0.9",
35
35
  "@types/bun": "1.4.0",
36
36
  "@typescript/native-preview": "7.0.0-dev.20251207.1",
@@ -40,7 +40,7 @@
40
40
  "@aws-sdk/credential-providers": "3.1057.0",
41
41
  "@smithy/eventstream-codec": "4.2.14",
42
42
  "@smithy/util-utf8": "4.2.2",
43
- "@opencode/schema": "0.0.0-dev-19544",
43
+ "@opencode/schema": "0.0.0-dev-19545",
44
44
  "aws4fetch": "1.0.20",
45
45
  "effect": "4.0.0-rc.112",
46
46
  "google-auth-library": "10.5.0"