@aigne/doubao 1.0.39 → 1.1.0-beta

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/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.1.0-beta](https://github.com/AIGNE-io/aigne-framework/compare/doubao-v1.0.40...doubao-v1.1.0-beta) (2025-09-22)
4
+
5
+
6
+ ### Features
7
+
8
+ * improve image model architecture and file handling ([#527](https://github.com/AIGNE-io/aigne-framework/issues/527)) ([4db50aa](https://github.com/AIGNE-io/aigne-framework/commit/4db50aa0387a1a0f045ca11aaa61613e36ca7597))
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * The following workspace dependencies were updated
14
+ * dependencies
15
+ * @aigne/openai bumped to 0.16.0-beta
16
+ * devDependencies
17
+ * @aigne/core bumped to 1.61.0-beta
18
+ * @aigne/test-utils bumped to 0.5.53-beta
19
+
20
+ ## [1.0.40](https://github.com/AIGNE-io/aigne-framework/compare/doubao-v1.0.39...doubao-v1.0.40) (2025-09-18)
21
+
22
+
23
+ ### Bug Fixes
24
+
25
+ * support the correct 3.0 model ([#514](https://github.com/AIGNE-io/aigne-framework/issues/514)) ([98e0d44](https://github.com/AIGNE-io/aigne-framework/commit/98e0d44ce2c4c7b043d5fc934c6e312ffa821521))
26
+
27
+
28
+ ### Dependencies
29
+
30
+ * The following workspace dependencies were updated
31
+ * dependencies
32
+ * @aigne/openai bumped to 0.15.4
33
+ * devDependencies
34
+ * @aigne/core bumped to 1.60.3
35
+ * @aigne/test-utils bumped to 0.5.52
36
+
3
37
  ## [1.0.39](https://github.com/AIGNE-io/aigne-framework/compare/doubao-v1.0.38...doubao-v1.0.39) (2025-09-16)
4
38
 
5
39
 
@@ -1,4 +1,4 @@
1
- import { ImageModel, type ImageModelInput, type ImageModelOptions, type ImageModelOutput } from "@aigne/core";
1
+ import { type AgentInvokeOptions, ImageModel, type ImageModelInput, type ImageModelOptions, type ImageModelOutput } from "@aigne/core";
2
2
  export interface DoubaoImageModelInput extends ImageModelInput {
3
3
  size?: string;
4
4
  seed?: number;
@@ -30,5 +30,5 @@ export declare class DoubaoImageModel extends ImageModel<DoubaoImageModelInput,
30
30
  };
31
31
  get modelOptions(): Omit<Partial<DoubaoImageModelInput>, "model"> | undefined;
32
32
  private extractDataObjects;
33
- process(input: DoubaoImageModelInput): Promise<ImageModelOutput>;
33
+ process(input: DoubaoImageModelInput, options: AgentInvokeOptions): Promise<ImageModelOutput>;
34
34
  }
@@ -8,6 +8,7 @@ const ufo_1 = require("ufo");
8
8
  const zod_1 = require("zod");
9
9
  const DOUBAO_DEFAULT_IMAGE_MODEL = "doubao-seedream-4-0-250828";
10
10
  const DOUBAO_BASE_URL = "https://ark.cn-beijing.volces.com/api/v3";
11
+ const OUTPUT_MIME_TYPE = "image/jpeg";
11
12
  const doubaoImageModelInputSchema = core_1.imageModelInputSchema.extend({});
12
13
  const doubaoImageModelOptionsSchema = zod_1.z.object({
13
14
  apiKey: zod_1.z.string().optional(),
@@ -59,7 +60,7 @@ class DoubaoImageModel extends core_1.ImageModel {
59
60
  }
60
61
  return dataObjects;
61
62
  }
62
- async process(input) {
63
+ async process(input, options) {
63
64
  const model = input.model || this.credential.model;
64
65
  const { url, apiKey } = this.credential;
65
66
  if (!apiKey) {
@@ -69,7 +70,6 @@ class DoubaoImageModel extends core_1.ImageModel {
69
70
  "doubao-seedream-4": [
70
71
  "model",
71
72
  "prompt",
72
- "image",
73
73
  "size",
74
74
  "sequentialImageGeneration",
75
75
  "sequentialImageGenerationOptions",
@@ -77,7 +77,7 @@ class DoubaoImageModel extends core_1.ImageModel {
77
77
  "responseFormat",
78
78
  "watermark",
79
79
  ],
80
- "doubao-seedream-3.0-t2i": [
80
+ "doubao-seedream-3-0-t2i": [
81
81
  "model",
82
82
  "prompt",
83
83
  "size",
@@ -86,10 +86,9 @@ class DoubaoImageModel extends core_1.ImageModel {
86
86
  "responseFormat",
87
87
  "watermark",
88
88
  ],
89
- "doubao-seededit-3.0-i2i": [
89
+ "doubao-seededit-3-0-i2i": [
90
90
  "model",
91
91
  "prompt",
92
- "image",
93
92
  "size",
94
93
  "seed",
95
94
  "guidanceScale",
@@ -105,9 +104,14 @@ class DoubaoImageModel extends core_1.ImageModel {
105
104
  throw new Error(`${this.name} only support ${Object.keys(map).join(", ")}`);
106
105
  }
107
106
  const mergeInput = { ...this.modelOptions, ...input };
108
- const body = { ...(0, camelize_js_1.snakelize)((0, type_utils_js_1.pick)(mergeInput, map[key])), model };
109
- body.response_format =
110
- mergeInput.responseFormat === "base64" ? "b64_json" : mergeInput.responseFormat || "url";
107
+ const image = await Promise.all((0, type_utils_js_1.flat)(input.image).map((image) => this.transformFileOutput(core_1.FileOutputType.file, image, options).then((file) => `data:${file.mimeType || "image/png"};base64,${file.data}`)));
108
+ const body = {
109
+ ...(0, camelize_js_1.snakelize)((0, type_utils_js_1.pick)(mergeInput, map[key])),
110
+ model,
111
+ response_format: "b64_json",
112
+ watermark: mergeInput.watermark ?? false,
113
+ image: image.length ? image : undefined,
114
+ };
111
115
  const response = await fetch((0, ufo_1.joinURL)(url, `/images/generations`), {
112
116
  method: "POST",
113
117
  headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
@@ -141,10 +145,11 @@ class DoubaoImageModel extends core_1.ImageModel {
141
145
  images: dataObjects
142
146
  .filter((i) => i.type === "image_generation.partial_succeeded")
143
147
  .map((i) => {
144
- return {
145
- url: i.url,
146
- base64: i.b64_json,
147
- };
148
+ if (typeof i.url === "string")
149
+ return { type: "url", url: i.url, mimeType: OUTPUT_MIME_TYPE };
150
+ if (typeof i.b64_json === "string")
151
+ return { type: "file", data: i.b64_json, mimeType: OUTPUT_MIME_TYPE };
152
+ throw new Error("Image response does not contain a valid URL or base64 data");
148
153
  }),
149
154
  usage: { inputTokens: 0, outputTokens: completed?.usage.output_tokens || 0 },
150
155
  model: model,
@@ -155,10 +160,13 @@ class DoubaoImageModel extends core_1.ImageModel {
155
160
  throw new Error(`Doubao API error: ${data.error.message}`);
156
161
  }
157
162
  return {
158
- images: data.data.map((item) => ({
159
- url: item.url,
160
- base64: item.b64_json,
161
- })),
163
+ images: data.data.map((item) => {
164
+ if (item.url)
165
+ return { type: "url", url: item.url, mimeType: OUTPUT_MIME_TYPE };
166
+ if (item.b64_json)
167
+ return { type: "file", data: item.b64_json, mimeType: OUTPUT_MIME_TYPE };
168
+ throw new Error("Image response does not contain a valid URL or base64 data");
169
+ }),
162
170
  usage: {
163
171
  inputTokens: 0,
164
172
  outputTokens: data?.usage?.output_tokens || 0,
@@ -1,4 +1,4 @@
1
- import { ImageModel, type ImageModelInput, type ImageModelOptions, type ImageModelOutput } from "@aigne/core";
1
+ import { type AgentInvokeOptions, ImageModel, type ImageModelInput, type ImageModelOptions, type ImageModelOutput } from "@aigne/core";
2
2
  export interface DoubaoImageModelInput extends ImageModelInput {
3
3
  size?: string;
4
4
  seed?: number;
@@ -30,5 +30,5 @@ export declare class DoubaoImageModel extends ImageModel<DoubaoImageModelInput,
30
30
  };
31
31
  get modelOptions(): Omit<Partial<DoubaoImageModelInput>, "model"> | undefined;
32
32
  private extractDataObjects;
33
- process(input: DoubaoImageModelInput): Promise<ImageModelOutput>;
33
+ process(input: DoubaoImageModelInput, options: AgentInvokeOptions): Promise<ImageModelOutput>;
34
34
  }
@@ -1,4 +1,4 @@
1
- import { ImageModel, type ImageModelInput, type ImageModelOptions, type ImageModelOutput } from "@aigne/core";
1
+ import { type AgentInvokeOptions, ImageModel, type ImageModelInput, type ImageModelOptions, type ImageModelOutput } from "@aigne/core";
2
2
  export interface DoubaoImageModelInput extends ImageModelInput {
3
3
  size?: string;
4
4
  seed?: number;
@@ -30,5 +30,5 @@ export declare class DoubaoImageModel extends ImageModel<DoubaoImageModelInput,
30
30
  };
31
31
  get modelOptions(): Omit<Partial<DoubaoImageModelInput>, "model"> | undefined;
32
32
  private extractDataObjects;
33
- process(input: DoubaoImageModelInput): Promise<ImageModelOutput>;
33
+ process(input: DoubaoImageModelInput, options: AgentInvokeOptions): Promise<ImageModelOutput>;
34
34
  }
@@ -1,10 +1,11 @@
1
- import { ImageModel, imageModelInputSchema, } from "@aigne/core";
1
+ import { FileOutputType, ImageModel, imageModelInputSchema, } from "@aigne/core";
2
2
  import { snakelize } from "@aigne/core/utils/camelize.js";
3
- import { checkArguments, pick } from "@aigne/core/utils/type-utils.js";
3
+ import { checkArguments, flat, pick } from "@aigne/core/utils/type-utils.js";
4
4
  import { joinURL } from "ufo";
5
5
  import { z } from "zod";
6
6
  const DOUBAO_DEFAULT_IMAGE_MODEL = "doubao-seedream-4-0-250828";
7
7
  const DOUBAO_BASE_URL = "https://ark.cn-beijing.volces.com/api/v3";
8
+ const OUTPUT_MIME_TYPE = "image/jpeg";
8
9
  const doubaoImageModelInputSchema = imageModelInputSchema.extend({});
9
10
  const doubaoImageModelOptionsSchema = z.object({
10
11
  apiKey: z.string().optional(),
@@ -56,7 +57,7 @@ export class DoubaoImageModel extends ImageModel {
56
57
  }
57
58
  return dataObjects;
58
59
  }
59
- async process(input) {
60
+ async process(input, options) {
60
61
  const model = input.model || this.credential.model;
61
62
  const { url, apiKey } = this.credential;
62
63
  if (!apiKey) {
@@ -66,7 +67,6 @@ export class DoubaoImageModel extends ImageModel {
66
67
  "doubao-seedream-4": [
67
68
  "model",
68
69
  "prompt",
69
- "image",
70
70
  "size",
71
71
  "sequentialImageGeneration",
72
72
  "sequentialImageGenerationOptions",
@@ -74,7 +74,7 @@ export class DoubaoImageModel extends ImageModel {
74
74
  "responseFormat",
75
75
  "watermark",
76
76
  ],
77
- "doubao-seedream-3.0-t2i": [
77
+ "doubao-seedream-3-0-t2i": [
78
78
  "model",
79
79
  "prompt",
80
80
  "size",
@@ -83,10 +83,9 @@ export class DoubaoImageModel extends ImageModel {
83
83
  "responseFormat",
84
84
  "watermark",
85
85
  ],
86
- "doubao-seededit-3.0-i2i": [
86
+ "doubao-seededit-3-0-i2i": [
87
87
  "model",
88
88
  "prompt",
89
- "image",
90
89
  "size",
91
90
  "seed",
92
91
  "guidanceScale",
@@ -102,9 +101,14 @@ export class DoubaoImageModel extends ImageModel {
102
101
  throw new Error(`${this.name} only support ${Object.keys(map).join(", ")}`);
103
102
  }
104
103
  const mergeInput = { ...this.modelOptions, ...input };
105
- const body = { ...snakelize(pick(mergeInput, map[key])), model };
106
- body.response_format =
107
- mergeInput.responseFormat === "base64" ? "b64_json" : mergeInput.responseFormat || "url";
104
+ const image = await Promise.all(flat(input.image).map((image) => this.transformFileOutput(FileOutputType.file, image, options).then((file) => `data:${file.mimeType || "image/png"};base64,${file.data}`)));
105
+ const body = {
106
+ ...snakelize(pick(mergeInput, map[key])),
107
+ model,
108
+ response_format: "b64_json",
109
+ watermark: mergeInput.watermark ?? false,
110
+ image: image.length ? image : undefined,
111
+ };
108
112
  const response = await fetch(joinURL(url, `/images/generations`), {
109
113
  method: "POST",
110
114
  headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
@@ -138,10 +142,11 @@ export class DoubaoImageModel extends ImageModel {
138
142
  images: dataObjects
139
143
  .filter((i) => i.type === "image_generation.partial_succeeded")
140
144
  .map((i) => {
141
- return {
142
- url: i.url,
143
- base64: i.b64_json,
144
- };
145
+ if (typeof i.url === "string")
146
+ return { type: "url", url: i.url, mimeType: OUTPUT_MIME_TYPE };
147
+ if (typeof i.b64_json === "string")
148
+ return { type: "file", data: i.b64_json, mimeType: OUTPUT_MIME_TYPE };
149
+ throw new Error("Image response does not contain a valid URL or base64 data");
145
150
  }),
146
151
  usage: { inputTokens: 0, outputTokens: completed?.usage.output_tokens || 0 },
147
152
  model: model,
@@ -152,10 +157,13 @@ export class DoubaoImageModel extends ImageModel {
152
157
  throw new Error(`Doubao API error: ${data.error.message}`);
153
158
  }
154
159
  return {
155
- images: data.data.map((item) => ({
156
- url: item.url,
157
- base64: item.b64_json,
158
- })),
160
+ images: data.data.map((item) => {
161
+ if (item.url)
162
+ return { type: "url", url: item.url, mimeType: OUTPUT_MIME_TYPE };
163
+ if (item.b64_json)
164
+ return { type: "file", data: item.b64_json, mimeType: OUTPUT_MIME_TYPE };
165
+ throw new Error("Image response does not contain a valid URL or base64 data");
166
+ }),
159
167
  usage: {
160
168
  inputTokens: 0,
161
169
  outputTokens: data?.usage?.output_tokens || 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/doubao",
3
- "version": "1.0.39",
3
+ "version": "1.1.0-beta",
4
4
  "description": "AIGNE doubao SDK for integrating with doubao AI models",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -37,18 +37,18 @@
37
37
  "dependencies": {
38
38
  "ufo": "^1.6.1",
39
39
  "zod": "^3.25.67",
40
- "@aigne/openai": "^0.15.3"
40
+ "@aigne/openai": "^0.16.0-beta"
41
41
  },
42
42
  "devDependencies": {
43
- "@types/bun": "^1.2.18",
44
- "@types/node": "^24.0.12",
43
+ "@types/bun": "^1.2.22",
44
+ "@types/node": "^24.5.1",
45
45
  "detect-port": "^2.1.0",
46
46
  "hono": "^4.9.7",
47
47
  "npm-run-all": "^4.1.5",
48
48
  "rimraf": "^6.0.1",
49
- "typescript": "^5.8.3",
50
- "@aigne/core": "^1.60.2",
51
- "@aigne/test-utils": "^0.5.51"
49
+ "typescript": "^5.9.2",
50
+ "@aigne/core": "^1.61.0-beta",
51
+ "@aigne/test-utils": "^0.5.53-beta"
52
52
  },
53
53
  "scripts": {
54
54
  "lint": "tsc --noEmit",