@opencow-ai/opencow-agent-sdk 0.4.11 → 0.4.12

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/dist/client.js CHANGED
@@ -31267,6 +31267,27 @@ var init_types3 = __esm(() => {
31267
31267
  CanonicalUserAbortError = APIUserAbortError;
31268
31268
  });
31269
31269
 
31270
+ // src/session/canonical/imageSource.ts
31271
+ function normalizeCanonicalImageSource(source) {
31272
+ if (!source || typeof source !== "object")
31273
+ return null;
31274
+ const s = source;
31275
+ if (s.type === "base64" && typeof s.data === "string") {
31276
+ return {
31277
+ kind: "base64",
31278
+ mediaType: typeof s.media_type === "string" ? s.media_type : "image/png",
31279
+ data: s.data
31280
+ };
31281
+ }
31282
+ if (s.type === "url" && typeof s.url === "string") {
31283
+ return { kind: "url", url: s.url };
31284
+ }
31285
+ return null;
31286
+ }
31287
+ function imageSourceToDataUri(img) {
31288
+ return img.kind === "base64" ? `data:${img.mediaType};base64,${img.data}` : img.url;
31289
+ }
31290
+
31270
31291
  // src/session/canonical/index.ts
31271
31292
  var init_canonical = __esm(() => {
31272
31293
  init_types3();
@@ -95407,19 +95428,9 @@ function splitToolResultMedia(content) {
95407
95428
  continue;
95408
95429
  }
95409
95430
  if (block?.type === "image") {
95410
- const src = block.source;
95411
- if (src?.type === "base64" && typeof src.data === "string") {
95412
- images.push({
95413
- kind: "base64",
95414
- mediaType: src.media_type ?? "image/png",
95415
- data: src.data
95416
- });
95417
- continue;
95418
- }
95419
- if (src?.type === "url" && typeof src.url === "string") {
95420
- images.push({ kind: "url", url: src.url });
95421
- continue;
95422
- }
95431
+ const img = normalizeCanonicalImageSource(block.source);
95432
+ if (img)
95433
+ images.push(img);
95423
95434
  continue;
95424
95435
  }
95425
95436
  if (typeof block?.text === "string") {
@@ -95430,8 +95441,7 @@ function splitToolResultMedia(content) {
95430
95441
  `), images };
95431
95442
  }
95432
95443
  function toResponsesInputImagePart(img) {
95433
- const url3 = img.kind === "base64" ? `data:${img.mediaType};base64,${img.data}` : img.url;
95434
- return { type: "input_image", image_url: url3 };
95444
+ return { type: "input_image", image_url: imageSourceToDataUri(img) };
95435
95445
  }
95436
95446
  function convertContentBlocksToResponsesParts(content, role) {
95437
95447
  const textType = role === "assistant" ? "output_text" : "input_text";
@@ -95450,18 +95460,9 @@ function convertContentBlocksToResponsesParts(content, role) {
95450
95460
  case "image": {
95451
95461
  if (role === "assistant")
95452
95462
  break;
95453
- const source = block.source;
95454
- if (source?.type === "base64") {
95455
- parts.push({
95456
- type: "input_image",
95457
- image_url: `data:${source.media_type};base64,${source.data}`
95458
- });
95459
- } else if (source?.type === "url" && source.url) {
95460
- parts.push({
95461
- type: "input_image",
95462
- image_url: source.url
95463
- });
95464
- }
95463
+ const img = normalizeCanonicalImageSource(block.source);
95464
+ if (img)
95465
+ parts.push(toResponsesInputImagePart(img));
95465
95466
  break;
95466
95467
  }
95467
95468
  case "thinking":
@@ -96049,6 +96050,7 @@ var init_shim = __esm(() => {
96049
96050
  init_sdk();
96050
96051
  init_schema();
96051
96052
  init_capabilities2();
96053
+ init_canonical();
96052
96054
  });
96053
96055
 
96054
96056
  // src/providers/shared/providerRecommendation.ts
@@ -96191,19 +96193,9 @@ function splitToolResultMedia2(content) {
96191
96193
  continue;
96192
96194
  }
96193
96195
  if (block?.type === "image") {
96194
- const source = block.source;
96195
- if (source?.type === "base64" && typeof source.data === "string") {
96196
- images.push({
96197
- kind: "base64",
96198
- mediaType: source.media_type ?? "image/png",
96199
- data: source.data
96200
- });
96201
- continue;
96202
- }
96203
- if (source?.type === "url" && typeof source.url === "string") {
96204
- images.push({ kind: "url", url: source.url });
96205
- continue;
96206
- }
96196
+ const img = normalizeCanonicalImageSource(block.source);
96197
+ if (img)
96198
+ images.push(img);
96207
96199
  continue;
96208
96200
  }
96209
96201
  if (block?.type === "tool_reference" && typeof block.tool_name === "string") {
@@ -96218,8 +96210,7 @@ function splitToolResultMedia2(content) {
96218
96210
  `), images };
96219
96211
  }
96220
96212
  function toOpenAIImageUrl(img) {
96221
- const url3 = img.kind === "base64" ? `data:${img.mediaType};base64,${img.data}` : img.url;
96222
- return { type: "image_url", image_url: { url: url3 } };
96213
+ return { type: "image_url", image_url: { url: imageSourceToDataUri(img) } };
96223
96214
  }
96224
96215
  function convertContentBlocks(content) {
96225
96216
  if (typeof content === "string")
@@ -96233,17 +96224,9 @@ function convertContentBlocks(content) {
96233
96224
  parts.push({ type: "text", text: block.text ?? "" });
96234
96225
  break;
96235
96226
  case "image": {
96236
- const src = block.source;
96237
- if (src?.type === "base64") {
96238
- parts.push({
96239
- type: "image_url",
96240
- image_url: {
96241
- url: `data:${src.media_type};base64,${src.data}`
96242
- }
96243
- });
96244
- } else if (src?.type === "url") {
96245
- parts.push({ type: "image_url", image_url: { url: src.url } });
96246
- }
96227
+ const img = normalizeCanonicalImageSource(block.source);
96228
+ if (img)
96229
+ parts.push(toOpenAIImageUrl(img));
96247
96230
  break;
96248
96231
  }
96249
96232
  case "tool_use":
@@ -97120,6 +97103,7 @@ var init_shim2 = __esm(() => {
97120
97103
  init_schemaSanitizer();
97121
97104
  init_providerProfile();
97122
97105
  init_capabilities2();
97106
+ init_canonical();
97123
97107
  OpenAIShimStream = class OpenAIShimStream {
97124
97108
  generator;
97125
97109
  controller = new AbortController;
@@ -273622,9 +273606,21 @@ var init_mcpWebSocketTransport = __esm(() => {
273622
273606
  });
273623
273607
 
273624
273608
  // src/capabilities/adapters/callToolResultAdapter.ts
273609
+ async function buildImageBlock(bytes, mediaType, uploadMedia) {
273610
+ let url3 = null;
273611
+ if (uploadMedia) {
273612
+ try {
273613
+ url3 = await uploadMedia({ bytes, mediaType });
273614
+ } catch (e) {
273615
+ logError(e);
273616
+ }
273617
+ }
273618
+ const source = url3 ? { type: "url", url: url3 } : { type: "base64", media_type: mediaType, data: bytes.toString("base64") };
273619
+ return { type: "image", source };
273620
+ }
273625
273621
  async function translateMcpContentItem(input) {
273626
273622
  const { item, options: options2 } = input;
273627
- const { sourceName } = options2;
273623
+ const { sourceName, uploadMedia } = options2;
273628
273624
  switch (item.type) {
273629
273625
  case "text":
273630
273626
  return [{ type: "text", text: item.text }];
@@ -273642,14 +273638,7 @@ async function translateMcpContentItem(input) {
273642
273638
  const ext = item.mimeType?.split("/")[1] || "png";
273643
273639
  const resized = await maybeResizeAndDownsampleImageBuffer(imageBuffer, imageBuffer.length, ext);
273644
273640
  return [
273645
- {
273646
- type: "image",
273647
- source: {
273648
- data: resized.buffer.toString("base64"),
273649
- media_type: `image/${resized.mediaType}`,
273650
- type: "base64"
273651
- }
273652
- }
273641
+ await buildImageBlock(resized.buffer, `image/${resized.mediaType}`, uploadMedia)
273653
273642
  ];
273654
273643
  }
273655
273644
  case "resource": {
@@ -273666,14 +273655,7 @@ async function translateMcpContentItem(input) {
273666
273655
  const resized = await maybeResizeAndDownsampleImageBuffer(imageBuffer, imageBuffer.length, ext);
273667
273656
  return [
273668
273657
  { type: "text", text: prefix },
273669
- {
273670
- type: "image",
273671
- source: {
273672
- data: resized.buffer.toString("base64"),
273673
- media_type: `image/${resized.mediaType}`,
273674
- type: "base64"
273675
- }
273676
- }
273658
+ await buildImageBlock(resized.buffer, `image/${resized.mediaType}`, uploadMedia)
273677
273659
  ];
273678
273660
  }
273679
273661
  return await persistBlobToTextBlock({
@@ -273727,6 +273709,7 @@ var IMAGE_MIME_TYPES;
273727
273709
  var init_callToolResultAdapter = __esm(() => {
273728
273710
  init_imageResizer();
273729
273711
  init_mcpOutputStorage();
273712
+ init_log2();
273730
273713
  IMAGE_MIME_TYPES = new Set([
273731
273714
  "image/jpeg",
273732
273715
  "image/png",
@@ -282692,7 +282675,7 @@ function getAnthropicEnvMetadata() {
282692
282675
  function getBuildAgeMinutes() {
282693
282676
  if (false)
282694
282677
  ;
282695
- const buildTime = new Date("2026-06-24T03:20:56.844Z").getTime();
282678
+ const buildTime = new Date("2026-06-24T10:02:32.669Z").getTime();
282696
282679
  if (isNaN(buildTime))
282697
282680
  return;
282698
282681
  return Math.floor((Date.now() - buildTime) / 60000);
@@ -286016,6 +285999,16 @@ async function validateContentTokens(content, ext, maxTokens) {
286016
285999
  throw new MaxFileReadTokenExceededError(effectiveCount, effectiveMaxTokens);
286017
286000
  }
286018
286001
  }
286002
+ async function maybeUploadBytes(uploadMedia, bytes, mediaType) {
286003
+ if (!uploadMedia)
286004
+ return null;
286005
+ try {
286006
+ return await uploadMedia({ bytes, mediaType });
286007
+ } catch (e) {
286008
+ logError(e);
286009
+ return null;
286010
+ }
286011
+ }
286019
286012
  function createImageResponse(buffer, mediaType, originalSize, dimensions) {
286020
286013
  return {
286021
286014
  type: "image",
@@ -286063,6 +286056,10 @@ async function callInner(file_path, fullFilePath, resolvedFilePath, ext, offset,
286063
286056
  if (IMAGE_EXTENSIONS.has(ext)) {
286064
286057
  const data2 = await readImageWithTokenBudget(resolvedFilePath, maxTokens);
286065
286058
  context4.nestedMemoryAttachmentTriggers?.add(fullFilePath);
286059
+ const uploadedUrl = await maybeUploadBytes(context4.uploadMedia, Buffer.from(data2.file.base64, "base64"), data2.file.type);
286060
+ if (uploadedUrl) {
286061
+ data2.file.url = uploadedUrl;
286062
+ }
286066
286063
  logFileOperation({
286067
286064
  operation: "read",
286068
286065
  tool: "FileReadTool",
@@ -286104,14 +286101,14 @@ async function callInner(file_path, fullFilePath, resolvedFilePath, ext, offset,
286104
286101
  const imgPath = path11.join(extractResult.data.file.outputDir, f);
286105
286102
  const imgBuffer = await getFsImplementation().readFile(imgPath);
286106
286103
  const resized = await maybeResizeAndDownsampleImageBuffer(imgBuffer, imgBuffer.length, "jpeg");
286107
- return {
286108
- type: "image",
286109
- source: {
286110
- type: "base64",
286111
- media_type: `image/${resized.mediaType}`,
286112
- data: resized.buffer.toString("base64")
286113
- }
286104
+ const mediaType = `image/${resized.mediaType}`;
286105
+ const uploadedUrl2 = await maybeUploadBytes(context4.uploadMedia, resized.buffer, mediaType);
286106
+ const source = uploadedUrl2 ? { type: "url", url: uploadedUrl2 } : {
286107
+ type: "base64",
286108
+ media_type: mediaType,
286109
+ data: resized.buffer.toString("base64")
286114
286110
  };
286111
+ return { type: "image", source };
286115
286112
  }));
286116
286113
  return {
286117
286114
  data: extractResult.data,
@@ -286159,20 +286156,17 @@ async function callInner(file_path, fullFilePath, resolvedFilePath, ext, offset,
286159
286156
  filePath: fullFilePath,
286160
286157
  content: pdfData.file.base64
286161
286158
  });
286159
+ const uploadedUrl = await maybeUploadBytes(context4.uploadMedia, Buffer.from(pdfData.file.base64, "base64"), "application/pdf");
286160
+ const documentSource = uploadedUrl ? { type: "url", url: uploadedUrl } : {
286161
+ type: "base64",
286162
+ media_type: "application/pdf",
286163
+ data: pdfData.file.base64
286164
+ };
286162
286165
  return {
286163
286166
  data: pdfData,
286164
286167
  newMessages: [
286165
286168
  createUserMessage({
286166
- content: [
286167
- {
286168
- type: "document",
286169
- source: {
286170
- type: "base64",
286171
- media_type: "application/pdf",
286172
- data: pdfData.file.base64
286173
- }
286174
- }
286175
- ],
286169
+ content: [{ type: "document", source: documentSource }],
286176
286170
  isMeta: true
286177
286171
  })
286178
286172
  ]
@@ -286379,6 +286373,7 @@ var init_FileReadTool = __esm(() => {
286379
286373
  base64: exports_external2.string().describe("Base64-encoded image data"),
286380
286374
  type: imageMediaTypes.describe("The MIME type of the image"),
286381
286375
  originalSize: exports_external2.number().describe("Original file size in bytes"),
286376
+ url: exports_external2.string().optional().describe("Fetchable URL for the (compressed) image when a host uploader is configured; takes precedence over base64 for rendering"),
286382
286377
  dimensions: exports_external2.object({
286383
286378
  originalWidth: exports_external2.number().optional().describe("Original image width in pixels"),
286384
286379
  originalHeight: exports_external2.number().optional().describe("Original image height in pixels"),
@@ -286607,17 +286602,18 @@ var init_FileReadTool = __esm(() => {
286607
286602
  mapToolResultToToolResultBlockParam(data, toolUseID) {
286608
286603
  switch (data.type) {
286609
286604
  case "image": {
286605
+ const source = data.file.url ? { type: "url", url: data.file.url } : {
286606
+ type: "base64",
286607
+ data: data.file.base64,
286608
+ media_type: data.file.type
286609
+ };
286610
286610
  return {
286611
286611
  tool_use_id: toolUseID,
286612
286612
  type: "tool_result",
286613
286613
  content: [
286614
286614
  {
286615
286615
  type: "image",
286616
- source: {
286617
- type: "base64",
286618
- data: data.file.base64,
286619
- media_type: data.file.type
286620
- }
286616
+ source
286621
286617
  }
286622
286618
  ]
286623
286619
  };
@@ -300013,6 +300009,7 @@ class QueryEngine {
300013
300009
  agents = [],
300014
300010
  setSDKStatus,
300015
300011
  onToolInvoke,
300012
+ uploadMedia,
300016
300013
  orphanedPermission
300017
300014
  } = this.config;
300018
300015
  this.discoveredSkillNames.clear();
@@ -300116,7 +300113,8 @@ class QueryEngine {
300116
300113
  });
300117
300114
  },
300118
300115
  setSDKStatus,
300119
- onToolInvoke
300116
+ onToolInvoke,
300117
+ uploadMedia
300120
300118
  };
300121
300119
  if (orphanedPermission && !this.hasHandledOrphanedPermission) {
300122
300120
  this.hasHandledOrphanedPermission = true;
@@ -300205,7 +300203,8 @@ class QueryEngine {
300205
300203
  setResponseLength: () => {},
300206
300204
  updateFileHistoryState: processUserInputContext.updateFileHistoryState,
300207
300205
  updateAttributionState: processUserInputContext.updateAttributionState,
300208
- setSDKStatus
300206
+ setSDKStatus,
300207
+ uploadMedia
300209
300208
  };
300210
300209
  headlessProfilerCheckpoint("before_skills_plugins");
300211
300210
  const [skills, { enabled: enabledPlugins }] = await Promise.all([
@@ -300700,6 +300699,7 @@ async function* ask({
300700
300699
  agents = [],
300701
300700
  setSDKStatus,
300702
300701
  onToolInvoke,
300702
+ uploadMedia,
300703
300703
  orphanedPermission
300704
300704
  }) {
300705
300705
  const engine = new QueryEngine({
@@ -300732,6 +300732,7 @@ async function* ask({
300732
300732
  includePartialMessages,
300733
300733
  setSDKStatus,
300734
300734
  onToolInvoke,
300735
+ uploadMedia,
300735
300736
  abortController,
300736
300737
  orphanedPermission,
300737
300738
  ...{}
@@ -329479,7 +329480,7 @@ function toInternalTool(sdkTool) {
329479
329480
  });
329480
329481
  const content = await translateCallToolResultContent({
329481
329482
  content: result.content,
329482
- options: { sourceName: sdkTool.name }
329483
+ options: { sourceName: sdkTool.name, uploadMedia: context4.uploadMedia }
329483
329484
  });
329484
329485
  return { data: content };
329485
329486
  }
@@ -330002,6 +330003,7 @@ function runSdkQueryRuntime(params) {
330002
330003
  includePartialMessages: Boolean(options2.includePartialMessages),
330003
330004
  agents: mergedAgents,
330004
330005
  onToolInvoke: typeof options2.onToolInvoke === "function" ? options2.onToolInvoke : undefined,
330006
+ uploadMedia: typeof options2.uploadMedia === "function" ? options2.uploadMedia : undefined,
330005
330007
  setSDKStatus: (status) => {
330006
330008
  turnStatusStream.enqueue({
330007
330009
  type: "system",
@@ -336055,4 +336057,4 @@ export {
336055
336057
  AbortError2 as AbortError
336056
336058
  };
336057
336059
 
336058
- //# debugId=7376AE95E91B9BFD64756E2164756E21
336060
+ //# debugId=C79EE43EDCAB4CD864756E2164756E21
@@ -1,5 +1,6 @@
1
1
  import type { ChildProcessWithoutNullStreams } from 'node:child_process';
2
2
  import type { ModelProviders } from '../../providers/shared/routing.js';
3
+ import type { UploadMediaFn } from '../../types/toolRuntime.js';
3
4
  export type { ModelProviders, ModelProviderConfig } from '../../providers/shared/routing.js';
4
5
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
6
  import type { CallToolResult, ToolAnnotations } from '@modelcontextprotocol/sdk/types.js';
@@ -278,6 +279,21 @@ export type Options = {
278
279
  toolInput: Record<string, unknown>;
279
280
  toolUseId: string;
280
281
  }) => void | Promise<void>;
282
+ /**
283
+ * Host-injected media uploader. When supplied, media-producing built-in
284
+ * tools (FileReadTool reading an image) upload the **compressed** bytes
285
+ * (post token-budget) and emit `{type:'image', source:{type:'url', url}}`
286
+ * in the tool_result instead of inline base64 — keeping the bytes out of
287
+ * every subsequent turn's request and letting the host materialize them.
288
+ * Media-neutral: the same port serves image / PDF / page-image tool output,
289
+ * driven by `mediaType`.
290
+ *
291
+ * Returns a fetchable URL, or `null` when upload is unavailable; the SDK
292
+ * also treats a thrown error as "unavailable". Either way it falls back to
293
+ * inline base64, so standalone SDK/CLI runs (no uploader) are byte-for-byte
294
+ * unchanged.
295
+ */
296
+ uploadMedia?: UploadMediaFn;
281
297
  jsonSchema?: Record<string, unknown>;
282
298
  betas?: string[];
283
299
  settingSources?: SettingSource[];