@aigne/openai 0.16.3 → 0.16.4-beta.1

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,37 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.16.4-beta.1](https://github.com/AIGNE-io/aigne-framework/compare/openai-v0.16.4-beta...openai-v0.16.4-beta.1) (2025-10-24)
4
+
5
+
6
+ ### Features
7
+
8
+ * **model:** support video model ([#647](https://github.com/AIGNE-io/aigne-framework/issues/647)) ([de81742](https://github.com/AIGNE-io/aigne-framework/commit/de817421ef1dd3246d0d8c51ff12f0a855658f9f))
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **model:** updated default video duration settings for AI video models ([#663](https://github.com/AIGNE-io/aigne-framework/issues/663)) ([1203941](https://github.com/AIGNE-io/aigne-framework/commit/12039411aaef77ba665e8edfb0fe6f8097c43e39))
14
+
15
+
16
+ ### Dependencies
17
+
18
+ * The following workspace dependencies were updated
19
+ * dependencies
20
+ * @aigne/core bumped to 1.65.0-beta
21
+ * devDependencies
22
+ * @aigne/test-utils bumped to 0.5.57-beta.1
23
+
24
+ ## [0.16.4-beta](https://github.com/AIGNE-io/aigne-framework/compare/openai-v0.16.3...openai-v0.16.4-beta) (2025-10-23)
25
+
26
+
27
+ ### Dependencies
28
+
29
+ * The following workspace dependencies were updated
30
+ * dependencies
31
+ * @aigne/core bumped to 1.64.1-beta
32
+ * devDependencies
33
+ * @aigne/test-utils bumped to 0.5.57-beta
34
+
3
35
  ## [0.16.3](https://github.com/AIGNE-io/aigne-framework/compare/openai-v0.16.3-beta.1...openai-v0.16.3) (2025-10-22)
4
36
 
5
37
 
@@ -1,2 +1,3 @@
1
1
  export * from "./openai-chat-model.js";
2
2
  export * from "./openai-image-model.js";
3
+ export * from "./openai-video-model.js";
package/lib/cjs/index.js CHANGED
@@ -16,3 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./openai-chat-model.js"), exports);
18
18
  __exportStar(require("./openai-image-model.js"), exports);
19
+ __exportStar(require("./openai-video-model.js"), exports);
@@ -0,0 +1,72 @@
1
+ import { VideoModel, type VideoModelInput, type VideoModelOptions, type VideoModelOutput } from "@aigne/core";
2
+ import type OpenAI from "openai";
3
+ import type { ClientOptions } from "openai";
4
+ /**
5
+ * Input options for OpenAI Video Model
6
+ */
7
+ export interface OpenAIVideoModelInput extends VideoModelInput {
8
+ /**
9
+ * Optional image reference that guides generation (file path or URL)
10
+ */
11
+ inputReference?: string;
12
+ }
13
+ /**
14
+ * Output from OpenAI Video Model
15
+ */
16
+ export interface OpenAIVideoModelOutput extends VideoModelOutput {
17
+ }
18
+ /**
19
+ * Configuration options for OpenAI Video Model
20
+ */
21
+ export interface OpenAIVideoModelOptions extends VideoModelOptions<OpenAIVideoModelInput, OpenAIVideoModelOutput> {
22
+ /**
23
+ * API key for OpenAI API
24
+ *
25
+ * If not provided, will look for OPENAI_API_KEY in environment variables
26
+ */
27
+ apiKey?: string;
28
+ /**
29
+ * Base URL for OpenAI API
30
+ *
31
+ * Useful for proxies or alternate endpoints
32
+ */
33
+ baseURL?: string;
34
+ /**
35
+ * OpenAI model to use
36
+ *
37
+ * Defaults to 'sora-2'
38
+ */
39
+ model?: string;
40
+ /**
41
+ * Additional model options to control behavior
42
+ */
43
+ modelOptions?: Omit<Partial<OpenAIVideoModelInput>, "model">;
44
+ /**
45
+ * Client options for OpenAI API
46
+ */
47
+ clientOptions?: Partial<ClientOptions>;
48
+ /**
49
+ * Polling interval in milliseconds for checking video generation status
50
+ *
51
+ * Defaults to 2000ms (2 seconds)
52
+ */
53
+ pollingInterval?: number;
54
+ }
55
+ export declare class OpenAIVideoModel extends VideoModel<OpenAIVideoModelInput, OpenAIVideoModelOutput> {
56
+ options?: OpenAIVideoModelOptions | undefined;
57
+ constructor(options?: OpenAIVideoModelOptions | undefined);
58
+ /**
59
+ * @hidden
60
+ */
61
+ protected _client?: OpenAI;
62
+ protected apiKeyEnvName: string;
63
+ get client(): OpenAI;
64
+ get credential(): {
65
+ url: string | undefined;
66
+ apiKey: string | undefined;
67
+ model: string;
68
+ };
69
+ get modelOptions(): Omit<Partial<OpenAIVideoModelInput>, "model"> | undefined;
70
+ downloadToFile(videoId: string): Promise<string>;
71
+ process(input: OpenAIVideoModelInput): Promise<OpenAIVideoModelOutput>;
72
+ }
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OpenAIVideoModel = void 0;
4
+ const core_1 = require("@aigne/core");
5
+ const logger_js_1 = require("@aigne/core/utils/logger.js");
6
+ const type_utils_js_1 = require("@aigne/core/utils/type-utils.js");
7
+ const zod_1 = require("zod");
8
+ const openai_js_1 = require("./openai.js");
9
+ const DEFAULT_MODEL = "sora-2";
10
+ const DEFAULT_SECONDS = 4;
11
+ const openAIVideoModelInputSchema = core_1.videoModelInputSchema.extend({
12
+ inputReference: zod_1.z.string().optional(),
13
+ });
14
+ const openAIVideoModelOptionsSchema = zod_1.z.object({
15
+ apiKey: zod_1.z.string().optional(),
16
+ baseURL: zod_1.z.string().optional(),
17
+ model: zod_1.z.string().optional(),
18
+ modelOptions: zod_1.z.object({}).optional(),
19
+ clientOptions: zod_1.z.object({}).optional(),
20
+ pollingInterval: zod_1.z.number().optional(),
21
+ });
22
+ class OpenAIVideoModel extends core_1.VideoModel {
23
+ options;
24
+ constructor(options) {
25
+ super({
26
+ ...options,
27
+ description: options?.description ?? "Generate videos using OpenAI Sora models",
28
+ inputSchema: openAIVideoModelInputSchema,
29
+ });
30
+ this.options = options;
31
+ if (options)
32
+ (0, type_utils_js_1.checkArguments)(this.name, openAIVideoModelOptionsSchema, options);
33
+ }
34
+ /**
35
+ * @hidden
36
+ */
37
+ _client;
38
+ apiKeyEnvName = "OPENAI_API_KEY";
39
+ get client() {
40
+ const { apiKey, url } = this.credential;
41
+ if (!apiKey)
42
+ throw new Error(`${this.name} requires an API key. Please provide it via \`options.apiKey\`, or set the \`${this.apiKeyEnvName}\` environment variable`);
43
+ this._client ??= new openai_js_1.CustomOpenAI({
44
+ baseURL: url,
45
+ apiKey,
46
+ ...this.options?.clientOptions,
47
+ });
48
+ return this._client;
49
+ }
50
+ get credential() {
51
+ return {
52
+ url: this.options?.baseURL || process.env.OPENAI_BASE_URL,
53
+ apiKey: this.options?.apiKey || process.env[this.apiKeyEnvName],
54
+ model: this.options?.model || DEFAULT_MODEL,
55
+ };
56
+ }
57
+ get modelOptions() {
58
+ return this.options?.modelOptions;
59
+ }
60
+ async downloadToFile(videoId) {
61
+ logger_js_1.logger.debug("Downloading video content...");
62
+ const content = await this.client.videos.downloadContent(videoId);
63
+ const arrayBuffer = await content.arrayBuffer();
64
+ const buffer = Buffer.from(arrayBuffer);
65
+ const base64 = buffer.toString("base64");
66
+ const dataUrl = `data:video/mp4;base64,${base64}`;
67
+ return dataUrl;
68
+ }
69
+ async process(input) {
70
+ const model = input.model ?? this.credential.model;
71
+ const createParams = {
72
+ model: model,
73
+ prompt: input.prompt,
74
+ };
75
+ if (input.seconds)
76
+ createParams.seconds = input.seconds;
77
+ if (input.size)
78
+ createParams.size = input.size;
79
+ if (input.inputReference) {
80
+ createParams.input_reference =
81
+ input.inputReference;
82
+ }
83
+ let video = await this.client.videos.create(createParams);
84
+ logger_js_1.logger.debug(`Video generation started: ${video.id}`);
85
+ const pollingInterval = this.options?.pollingInterval ?? 2000;
86
+ while (video.status === "in_progress" || video.status === "queued") {
87
+ await new Promise((resolve) => setTimeout(resolve, pollingInterval));
88
+ video = await this.client.videos.retrieve(video.id);
89
+ const progress = video.progress ?? 0;
90
+ const statusText = video.status === "queued" ? "Queued" : "Processing";
91
+ logger_js_1.logger.debug(`${statusText}: ${progress.toFixed(1)}%`);
92
+ }
93
+ if (video.status === "failed") {
94
+ throw new Error(`Video generation failed: ${video.error?.message || "Unknown error"}`);
95
+ }
96
+ if (video.status !== "completed") {
97
+ throw new Error(`Unexpected video status: ${video.status}`);
98
+ }
99
+ return {
100
+ videos: [
101
+ {
102
+ type: "file",
103
+ data: await this.downloadToFile(video.id),
104
+ },
105
+ ],
106
+ usage: {
107
+ inputTokens: 0,
108
+ outputTokens: 0,
109
+ },
110
+ model,
111
+ seconds: input.seconds ? parseInt(input.seconds, 10) : DEFAULT_SECONDS,
112
+ };
113
+ }
114
+ }
115
+ exports.OpenAIVideoModel = OpenAIVideoModel;
@@ -1,2 +1,3 @@
1
1
  export * from "./openai-chat-model.js";
2
2
  export * from "./openai-image-model.js";
3
+ export * from "./openai-video-model.js";
@@ -0,0 +1,72 @@
1
+ import { VideoModel, type VideoModelInput, type VideoModelOptions, type VideoModelOutput } from "@aigne/core";
2
+ import type OpenAI from "openai";
3
+ import type { ClientOptions } from "openai";
4
+ /**
5
+ * Input options for OpenAI Video Model
6
+ */
7
+ export interface OpenAIVideoModelInput extends VideoModelInput {
8
+ /**
9
+ * Optional image reference that guides generation (file path or URL)
10
+ */
11
+ inputReference?: string;
12
+ }
13
+ /**
14
+ * Output from OpenAI Video Model
15
+ */
16
+ export interface OpenAIVideoModelOutput extends VideoModelOutput {
17
+ }
18
+ /**
19
+ * Configuration options for OpenAI Video Model
20
+ */
21
+ export interface OpenAIVideoModelOptions extends VideoModelOptions<OpenAIVideoModelInput, OpenAIVideoModelOutput> {
22
+ /**
23
+ * API key for OpenAI API
24
+ *
25
+ * If not provided, will look for OPENAI_API_KEY in environment variables
26
+ */
27
+ apiKey?: string;
28
+ /**
29
+ * Base URL for OpenAI API
30
+ *
31
+ * Useful for proxies or alternate endpoints
32
+ */
33
+ baseURL?: string;
34
+ /**
35
+ * OpenAI model to use
36
+ *
37
+ * Defaults to 'sora-2'
38
+ */
39
+ model?: string;
40
+ /**
41
+ * Additional model options to control behavior
42
+ */
43
+ modelOptions?: Omit<Partial<OpenAIVideoModelInput>, "model">;
44
+ /**
45
+ * Client options for OpenAI API
46
+ */
47
+ clientOptions?: Partial<ClientOptions>;
48
+ /**
49
+ * Polling interval in milliseconds for checking video generation status
50
+ *
51
+ * Defaults to 2000ms (2 seconds)
52
+ */
53
+ pollingInterval?: number;
54
+ }
55
+ export declare class OpenAIVideoModel extends VideoModel<OpenAIVideoModelInput, OpenAIVideoModelOutput> {
56
+ options?: OpenAIVideoModelOptions | undefined;
57
+ constructor(options?: OpenAIVideoModelOptions | undefined);
58
+ /**
59
+ * @hidden
60
+ */
61
+ protected _client?: OpenAI;
62
+ protected apiKeyEnvName: string;
63
+ get client(): OpenAI;
64
+ get credential(): {
65
+ url: string | undefined;
66
+ apiKey: string | undefined;
67
+ model: string;
68
+ };
69
+ get modelOptions(): Omit<Partial<OpenAIVideoModelInput>, "model"> | undefined;
70
+ downloadToFile(videoId: string): Promise<string>;
71
+ process(input: OpenAIVideoModelInput): Promise<OpenAIVideoModelOutput>;
72
+ }
@@ -1,2 +1,3 @@
1
1
  export * from "./openai-chat-model.js";
2
2
  export * from "./openai-image-model.js";
3
+ export * from "./openai-video-model.js";
package/lib/esm/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from "./openai-chat-model.js";
2
2
  export * from "./openai-image-model.js";
3
+ export * from "./openai-video-model.js";
@@ -0,0 +1,72 @@
1
+ import { VideoModel, type VideoModelInput, type VideoModelOptions, type VideoModelOutput } from "@aigne/core";
2
+ import type OpenAI from "openai";
3
+ import type { ClientOptions } from "openai";
4
+ /**
5
+ * Input options for OpenAI Video Model
6
+ */
7
+ export interface OpenAIVideoModelInput extends VideoModelInput {
8
+ /**
9
+ * Optional image reference that guides generation (file path or URL)
10
+ */
11
+ inputReference?: string;
12
+ }
13
+ /**
14
+ * Output from OpenAI Video Model
15
+ */
16
+ export interface OpenAIVideoModelOutput extends VideoModelOutput {
17
+ }
18
+ /**
19
+ * Configuration options for OpenAI Video Model
20
+ */
21
+ export interface OpenAIVideoModelOptions extends VideoModelOptions<OpenAIVideoModelInput, OpenAIVideoModelOutput> {
22
+ /**
23
+ * API key for OpenAI API
24
+ *
25
+ * If not provided, will look for OPENAI_API_KEY in environment variables
26
+ */
27
+ apiKey?: string;
28
+ /**
29
+ * Base URL for OpenAI API
30
+ *
31
+ * Useful for proxies or alternate endpoints
32
+ */
33
+ baseURL?: string;
34
+ /**
35
+ * OpenAI model to use
36
+ *
37
+ * Defaults to 'sora-2'
38
+ */
39
+ model?: string;
40
+ /**
41
+ * Additional model options to control behavior
42
+ */
43
+ modelOptions?: Omit<Partial<OpenAIVideoModelInput>, "model">;
44
+ /**
45
+ * Client options for OpenAI API
46
+ */
47
+ clientOptions?: Partial<ClientOptions>;
48
+ /**
49
+ * Polling interval in milliseconds for checking video generation status
50
+ *
51
+ * Defaults to 2000ms (2 seconds)
52
+ */
53
+ pollingInterval?: number;
54
+ }
55
+ export declare class OpenAIVideoModel extends VideoModel<OpenAIVideoModelInput, OpenAIVideoModelOutput> {
56
+ options?: OpenAIVideoModelOptions | undefined;
57
+ constructor(options?: OpenAIVideoModelOptions | undefined);
58
+ /**
59
+ * @hidden
60
+ */
61
+ protected _client?: OpenAI;
62
+ protected apiKeyEnvName: string;
63
+ get client(): OpenAI;
64
+ get credential(): {
65
+ url: string | undefined;
66
+ apiKey: string | undefined;
67
+ model: string;
68
+ };
69
+ get modelOptions(): Omit<Partial<OpenAIVideoModelInput>, "model"> | undefined;
70
+ downloadToFile(videoId: string): Promise<string>;
71
+ process(input: OpenAIVideoModelInput): Promise<OpenAIVideoModelOutput>;
72
+ }
@@ -0,0 +1,111 @@
1
+ import { VideoModel, videoModelInputSchema, } from "@aigne/core";
2
+ import { logger } from "@aigne/core/utils/logger.js";
3
+ import { checkArguments } from "@aigne/core/utils/type-utils.js";
4
+ import { z } from "zod";
5
+ import { CustomOpenAI } from "./openai.js";
6
+ const DEFAULT_MODEL = "sora-2";
7
+ const DEFAULT_SECONDS = 4;
8
+ const openAIVideoModelInputSchema = videoModelInputSchema.extend({
9
+ inputReference: z.string().optional(),
10
+ });
11
+ const openAIVideoModelOptionsSchema = z.object({
12
+ apiKey: z.string().optional(),
13
+ baseURL: z.string().optional(),
14
+ model: z.string().optional(),
15
+ modelOptions: z.object({}).optional(),
16
+ clientOptions: z.object({}).optional(),
17
+ pollingInterval: z.number().optional(),
18
+ });
19
+ export class OpenAIVideoModel extends VideoModel {
20
+ options;
21
+ constructor(options) {
22
+ super({
23
+ ...options,
24
+ description: options?.description ?? "Generate videos using OpenAI Sora models",
25
+ inputSchema: openAIVideoModelInputSchema,
26
+ });
27
+ this.options = options;
28
+ if (options)
29
+ checkArguments(this.name, openAIVideoModelOptionsSchema, options);
30
+ }
31
+ /**
32
+ * @hidden
33
+ */
34
+ _client;
35
+ apiKeyEnvName = "OPENAI_API_KEY";
36
+ get client() {
37
+ const { apiKey, url } = this.credential;
38
+ if (!apiKey)
39
+ throw new Error(`${this.name} requires an API key. Please provide it via \`options.apiKey\`, or set the \`${this.apiKeyEnvName}\` environment variable`);
40
+ this._client ??= new CustomOpenAI({
41
+ baseURL: url,
42
+ apiKey,
43
+ ...this.options?.clientOptions,
44
+ });
45
+ return this._client;
46
+ }
47
+ get credential() {
48
+ return {
49
+ url: this.options?.baseURL || process.env.OPENAI_BASE_URL,
50
+ apiKey: this.options?.apiKey || process.env[this.apiKeyEnvName],
51
+ model: this.options?.model || DEFAULT_MODEL,
52
+ };
53
+ }
54
+ get modelOptions() {
55
+ return this.options?.modelOptions;
56
+ }
57
+ async downloadToFile(videoId) {
58
+ logger.debug("Downloading video content...");
59
+ const content = await this.client.videos.downloadContent(videoId);
60
+ const arrayBuffer = await content.arrayBuffer();
61
+ const buffer = Buffer.from(arrayBuffer);
62
+ const base64 = buffer.toString("base64");
63
+ const dataUrl = `data:video/mp4;base64,${base64}`;
64
+ return dataUrl;
65
+ }
66
+ async process(input) {
67
+ const model = input.model ?? this.credential.model;
68
+ const createParams = {
69
+ model: model,
70
+ prompt: input.prompt,
71
+ };
72
+ if (input.seconds)
73
+ createParams.seconds = input.seconds;
74
+ if (input.size)
75
+ createParams.size = input.size;
76
+ if (input.inputReference) {
77
+ createParams.input_reference =
78
+ input.inputReference;
79
+ }
80
+ let video = await this.client.videos.create(createParams);
81
+ logger.debug(`Video generation started: ${video.id}`);
82
+ const pollingInterval = this.options?.pollingInterval ?? 2000;
83
+ while (video.status === "in_progress" || video.status === "queued") {
84
+ await new Promise((resolve) => setTimeout(resolve, pollingInterval));
85
+ video = await this.client.videos.retrieve(video.id);
86
+ const progress = video.progress ?? 0;
87
+ const statusText = video.status === "queued" ? "Queued" : "Processing";
88
+ logger.debug(`${statusText}: ${progress.toFixed(1)}%`);
89
+ }
90
+ if (video.status === "failed") {
91
+ throw new Error(`Video generation failed: ${video.error?.message || "Unknown error"}`);
92
+ }
93
+ if (video.status !== "completed") {
94
+ throw new Error(`Unexpected video status: ${video.status}`);
95
+ }
96
+ return {
97
+ videos: [
98
+ {
99
+ type: "file",
100
+ data: await this.downloadToFile(video.id),
101
+ },
102
+ ],
103
+ usage: {
104
+ inputTokens: 0,
105
+ outputTokens: 0,
106
+ },
107
+ model,
108
+ seconds: input.seconds ? parseInt(input.seconds, 10) : DEFAULT_SECONDS,
109
+ };
110
+ }
111
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/openai",
3
- "version": "0.16.3",
3
+ "version": "0.16.4-beta.1",
4
4
  "description": "AIGNE OpenAI SDK for integrating with OpenAI's GPT models and API services",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -36,9 +36,9 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "@aigne/uuid": "^13.0.1",
39
- "openai": "^5.20.3",
39
+ "openai": "^6.5.0",
40
40
  "zod": "^3.25.67",
41
- "@aigne/core": "^1.64.0",
41
+ "@aigne/core": "^1.65.0-beta",
42
42
  "@aigne/platform-helpers": "^0.6.3"
43
43
  },
44
44
  "devDependencies": {
@@ -47,7 +47,7 @@
47
47
  "npm-run-all": "^4.1.5",
48
48
  "rimraf": "^6.0.1",
49
49
  "typescript": "^5.9.2",
50
- "@aigne/test-utils": "^0.5.56"
50
+ "@aigne/test-utils": "^0.5.57-beta.1"
51
51
  },
52
52
  "scripts": {
53
53
  "lint": "tsc --noEmit",