@openclaw/byteplus-provider 0.0.0 → 2026.8.1-beta.3
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/README.md +16 -2
- package/dist/api.js +2 -0
- package/dist/index.js +40 -0
- package/dist/models-DdB2dJk5.js +191 -0
- package/dist/models.js +2 -0
- package/dist/provider-discovery.js +8 -0
- package/dist/video-generation-provider.js +270 -0
- package/openclaw.plugin.json +178 -0
- package/package.json +43 -8
package/README.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
-
#
|
|
1
|
+
# OpenClaw BytePlus Provider
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Official OpenClaw provider plugin for BytePlus model inference and Seedance
|
|
4
|
+
video generation.
|
|
5
|
+
|
|
6
|
+
Install from OpenClaw:
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
openclaw plugins install @openclaw/byteplus-provider
|
|
10
|
+
openclaw gateway restart
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Set `BYTEPLUS_API_KEY`, then select a `byteplus/*` or `byteplus-plan/*` model.
|
|
14
|
+
|
|
15
|
+
See <https://docs.openclaw.ai/concepts/model-providers#byteplus-international>
|
|
16
|
+
for model setup and <https://docs.openclaw.ai/tools/video-generation> for
|
|
17
|
+
Seedance video generation.
|
package/dist/api.js
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { a as BYTEPLUS_PROVIDER_CATALOG, o as openclaw_plugin_default } from "./models-DdB2dJk5.js";
|
|
2
|
+
import { buildBytePlusVideoGenerationProvider } from "./video-generation-provider.js";
|
|
3
|
+
import { buildOpenAICompatibleProviderFamilyCatalog } from "openclaw/plugin-sdk/provider-catalog-live-runtime";
|
|
4
|
+
import { readManifestProviderDefaultModelRef } from "openclaw/plugin-sdk/provider-catalog-shared";
|
|
5
|
+
import { defineSingleProviderPluginEntry } from "openclaw/plugin-sdk/provider-entry";
|
|
6
|
+
import { ensureModelAllowlistEntry } from "openclaw/plugin-sdk/provider-onboard";
|
|
7
|
+
//#region extensions/byteplus/index.ts
|
|
8
|
+
/**
|
|
9
|
+
* BytePlus provider plugin entrypoint for model and video generation providers.
|
|
10
|
+
*/
|
|
11
|
+
const PROVIDER_ID = "byteplus";
|
|
12
|
+
const BYTEPLUS_DEFAULT_MODEL_REF = readManifestProviderDefaultModelRef(openclaw_plugin_default, "byteplus-plan");
|
|
13
|
+
var byteplus_default = defineSingleProviderPluginEntry({
|
|
14
|
+
id: PROVIDER_ID,
|
|
15
|
+
name: "BytePlus Provider",
|
|
16
|
+
description: "BytePlus provider plugin",
|
|
17
|
+
manifest: openclaw_plugin_default,
|
|
18
|
+
provider: {
|
|
19
|
+
label: "BytePlus",
|
|
20
|
+
docsPath: "/concepts/model-providers#byteplus-international",
|
|
21
|
+
manifestAuth: {
|
|
22
|
+
defaultModel: BYTEPLUS_DEFAULT_MODEL_REF,
|
|
23
|
+
applyConfig: (cfg) => ensureModelAllowlistEntry({
|
|
24
|
+
cfg,
|
|
25
|
+
modelRef: BYTEPLUS_DEFAULT_MODEL_REF
|
|
26
|
+
})
|
|
27
|
+
},
|
|
28
|
+
...buildOpenAICompatibleProviderFamilyCatalog({
|
|
29
|
+
credentialProviderId: PROVIDER_ID,
|
|
30
|
+
entries: BYTEPLUS_PROVIDER_CATALOG.entries,
|
|
31
|
+
staticCatalog: BYTEPLUS_PROVIDER_CATALOG.staticCatalog,
|
|
32
|
+
augmentModelCatalog: BYTEPLUS_PROVIDER_CATALOG.augmentModelCatalog
|
|
33
|
+
})
|
|
34
|
+
},
|
|
35
|
+
register(api) {
|
|
36
|
+
api.registerVideoGenerationProvider(buildBytePlusVideoGenerationProvider());
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
//#endregion
|
|
40
|
+
export { byteplus_default as default };
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { buildManifestProviderCatalogFamily } from "openclaw/plugin-sdk/provider-catalog-shared";
|
|
2
|
+
//#region extensions/byteplus/openclaw.plugin.json
|
|
3
|
+
var openclaw_plugin_default = {
|
|
4
|
+
id: "byteplus",
|
|
5
|
+
activation: { "onStartup": false },
|
|
6
|
+
enabledByDefault: true,
|
|
7
|
+
providerCatalogEntry: "./provider-discovery.ts",
|
|
8
|
+
providers: ["byteplus", "byteplus-plan"],
|
|
9
|
+
setup: { "providers": [{
|
|
10
|
+
"id": "byteplus",
|
|
11
|
+
"envVars": ["BYTEPLUS_API_KEY"]
|
|
12
|
+
}] },
|
|
13
|
+
providerAuthAliases: { "byteplus-plan": "byteplus" },
|
|
14
|
+
modelCatalog: {
|
|
15
|
+
"providers": {
|
|
16
|
+
"byteplus": {
|
|
17
|
+
"baseUrl": "https://ark.ap-southeast.bytepluses.com/api/v3",
|
|
18
|
+
"api": "openai-completions",
|
|
19
|
+
"models": [
|
|
20
|
+
{
|
|
21
|
+
"id": "dola-seed-2-1-turbo-260628",
|
|
22
|
+
"name": "Dola Seed 2.1 Turbo",
|
|
23
|
+
"reasoning": true,
|
|
24
|
+
"input": ["text", "image"],
|
|
25
|
+
"contextWindow": 256e3,
|
|
26
|
+
"maxTokens": 256e3,
|
|
27
|
+
"cost": {
|
|
28
|
+
"input": .5,
|
|
29
|
+
"output": 2.5,
|
|
30
|
+
"cacheRead": .1,
|
|
31
|
+
"cacheWrite": 0
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"id": "seed-2-0-code-preview-260328",
|
|
36
|
+
"name": "Seed 2.0 Code Preview",
|
|
37
|
+
"reasoning": true,
|
|
38
|
+
"input": ["text", "image"],
|
|
39
|
+
"contextWindow": 256e3,
|
|
40
|
+
"maxTokens": 128e3,
|
|
41
|
+
"cost": {
|
|
42
|
+
"input": .5,
|
|
43
|
+
"output": 3,
|
|
44
|
+
"cacheRead": .1,
|
|
45
|
+
"cacheWrite": 0
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"id": "glm-5-2-260617",
|
|
50
|
+
"name": "GLM 5.2",
|
|
51
|
+
"reasoning": true,
|
|
52
|
+
"input": ["text"],
|
|
53
|
+
"contextWindow": 1024e3,
|
|
54
|
+
"maxTokens": 128e3,
|
|
55
|
+
"cost": {
|
|
56
|
+
"input": 1.4,
|
|
57
|
+
"output": 4.4,
|
|
58
|
+
"cacheRead": .26,
|
|
59
|
+
"cacheWrite": 0
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"id": "deepseek-v4-pro-260425",
|
|
64
|
+
"name": "DeepSeek V4 Pro",
|
|
65
|
+
"reasoning": true,
|
|
66
|
+
"input": ["text"],
|
|
67
|
+
"contextWindow": 1024e3,
|
|
68
|
+
"maxTokens": 384e3,
|
|
69
|
+
"cost": {
|
|
70
|
+
"input": 1.74,
|
|
71
|
+
"output": 3.48,
|
|
72
|
+
"cacheRead": .145,
|
|
73
|
+
"cacheWrite": 0
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"id": "deepseek-v4-flash-260425",
|
|
78
|
+
"name": "DeepSeek V4 Flash",
|
|
79
|
+
"reasoning": true,
|
|
80
|
+
"input": ["text"],
|
|
81
|
+
"contextWindow": 1024e3,
|
|
82
|
+
"maxTokens": 384e3,
|
|
83
|
+
"cost": {
|
|
84
|
+
"input": .14,
|
|
85
|
+
"output": .28,
|
|
86
|
+
"cacheRead": .028,
|
|
87
|
+
"cacheWrite": 0
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"id": "glm-4-7-251222",
|
|
92
|
+
"name": "GLM 4.7",
|
|
93
|
+
"status": "deprecated",
|
|
94
|
+
"replacedBy": "glm-5-2-260617",
|
|
95
|
+
"reasoning": true,
|
|
96
|
+
"input": ["text"],
|
|
97
|
+
"contextWindow": 256e3,
|
|
98
|
+
"maxTokens": 128e3,
|
|
99
|
+
"cost": {
|
|
100
|
+
"input": .6,
|
|
101
|
+
"output": 2.2,
|
|
102
|
+
"cacheRead": .11,
|
|
103
|
+
"cacheWrite": 0
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
},
|
|
108
|
+
"byteplus-plan": {
|
|
109
|
+
"baseUrl": "https://ark.ap-southeast.bytepluses.com/api/coding/v3",
|
|
110
|
+
"api": "openai-completions",
|
|
111
|
+
"defaultModel": "ark-code-latest",
|
|
112
|
+
"models": [{
|
|
113
|
+
"id": "ark-code-latest",
|
|
114
|
+
"name": "Ark Coding Plan",
|
|
115
|
+
"input": ["text"],
|
|
116
|
+
"contextWindow": 256e3,
|
|
117
|
+
"maxTokens": 4096,
|
|
118
|
+
"cost": {
|
|
119
|
+
"input": 0,
|
|
120
|
+
"output": 0,
|
|
121
|
+
"cacheRead": 0,
|
|
122
|
+
"cacheWrite": 0
|
|
123
|
+
}
|
|
124
|
+
}, {
|
|
125
|
+
"id": "kimi-k2.5",
|
|
126
|
+
"name": "Kimi K2.5 Coding",
|
|
127
|
+
"reasoning": true,
|
|
128
|
+
"input": ["text", "image"],
|
|
129
|
+
"contextWindow": 256e3,
|
|
130
|
+
"maxTokens": 32768,
|
|
131
|
+
"cost": {
|
|
132
|
+
"input": 0,
|
|
133
|
+
"output": 0,
|
|
134
|
+
"cacheRead": 0,
|
|
135
|
+
"cacheWrite": 0
|
|
136
|
+
}
|
|
137
|
+
}]
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
"discovery": {
|
|
141
|
+
"byteplus": "refreshable",
|
|
142
|
+
"byteplus-plan": "refreshable"
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
providerAuthChoices: [{
|
|
146
|
+
"provider": "byteplus",
|
|
147
|
+
"method": "api-key",
|
|
148
|
+
"choiceId": "byteplus-api-key",
|
|
149
|
+
"appGuidedSecret": true,
|
|
150
|
+
"choiceLabel": "BytePlus API key",
|
|
151
|
+
"groupId": "byteplus",
|
|
152
|
+
"groupLabel": "BytePlus",
|
|
153
|
+
"groupHint": "API key",
|
|
154
|
+
"optionKey": "byteplusApiKey",
|
|
155
|
+
"cliFlag": "--byteplus-api-key",
|
|
156
|
+
"cliOption": "--byteplus-api-key <key>",
|
|
157
|
+
"cliDescription": "BytePlus API key"
|
|
158
|
+
}],
|
|
159
|
+
contracts: { "videoGenerationProviders": ["byteplus"] },
|
|
160
|
+
configSchema: {
|
|
161
|
+
"type": "object",
|
|
162
|
+
"additionalProperties": false,
|
|
163
|
+
"properties": {}
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
//#endregion
|
|
167
|
+
//#region extensions/byteplus/models.ts
|
|
168
|
+
/**
|
|
169
|
+
* BytePlus model catalog helpers derived from the plugin manifest.
|
|
170
|
+
*/
|
|
171
|
+
const BYTEPLUS_PROVIDER_CATALOG = buildManifestProviderCatalogFamily({ surfaces: [{
|
|
172
|
+
id: "byteplus",
|
|
173
|
+
label: "BytePlus",
|
|
174
|
+
catalog: openclaw_plugin_default.modelCatalog.providers.byteplus
|
|
175
|
+
}, {
|
|
176
|
+
id: "byteplus-plan",
|
|
177
|
+
label: "BytePlus Plan",
|
|
178
|
+
catalog: openclaw_plugin_default.modelCatalog.providers["byteplus-plan"]
|
|
179
|
+
}] });
|
|
180
|
+
const BYTEPLUS_PROVIDER = BYTEPLUS_PROVIDER_CATALOG.entries[0];
|
|
181
|
+
const BYTEPLUS_CODING_PROVIDER = BYTEPLUS_PROVIDER_CATALOG.entries[1];
|
|
182
|
+
/** Base URL for BytePlus chat/model APIs from the manifest catalog. */
|
|
183
|
+
const BYTEPLUS_BASE_URL = BYTEPLUS_PROVIDER.baseUrl;
|
|
184
|
+
/** Base URL for BytePlus Plan coding APIs from the manifest catalog. */
|
|
185
|
+
const BYTEPLUS_CODING_BASE_URL = BYTEPLUS_CODING_PROVIDER.baseUrl;
|
|
186
|
+
/** BytePlus general model catalog entries. */
|
|
187
|
+
const BYTEPLUS_MODEL_CATALOG = BYTEPLUS_PROVIDER.models;
|
|
188
|
+
/** BytePlus coding/planning model catalog entries. */
|
|
189
|
+
const BYTEPLUS_CODING_MODEL_CATALOG = BYTEPLUS_CODING_PROVIDER.models;
|
|
190
|
+
//#endregion
|
|
191
|
+
export { BYTEPLUS_PROVIDER_CATALOG as a, BYTEPLUS_MODEL_CATALOG as i, BYTEPLUS_CODING_BASE_URL as n, openclaw_plugin_default as o, BYTEPLUS_CODING_MODEL_CATALOG as r, BYTEPLUS_BASE_URL as t };
|
package/dist/models.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as BYTEPLUS_PROVIDER_CATALOG, i as BYTEPLUS_MODEL_CATALOG, n as BYTEPLUS_CODING_BASE_URL, r as BYTEPLUS_CODING_MODEL_CATALOG, t as BYTEPLUS_BASE_URL } from "./models-DdB2dJk5.js";
|
|
2
|
+
export { BYTEPLUS_BASE_URL, BYTEPLUS_CODING_BASE_URL, BYTEPLUS_CODING_MODEL_CATALOG, BYTEPLUS_MODEL_CATALOG, BYTEPLUS_PROVIDER_CATALOG };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { a as BYTEPLUS_PROVIDER_CATALOG } from "./models-DdB2dJk5.js";
|
|
2
|
+
//#region extensions/byteplus/provider-discovery.ts
|
|
3
|
+
/**
|
|
4
|
+
* Static provider discovery entries for BytePlus manifest-backed catalogs.
|
|
5
|
+
*/
|
|
6
|
+
var provider_discovery_default = BYTEPLUS_PROVIDER_CATALOG.staticDiscovery;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { provider_discovery_default as default };
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { t as BYTEPLUS_BASE_URL } from "./models-DdB2dJk5.js";
|
|
2
|
+
import { toImageDataUrl } from "openclaw/plugin-sdk/image-generation";
|
|
3
|
+
import { downloadGeneratedVideoAsset, resolveGeneratedMediaMaxBytes } from "openclaw/plugin-sdk/media-generation-runtime";
|
|
4
|
+
import { isProviderApiKeyConfigured } from "openclaw/plugin-sdk/provider-auth";
|
|
5
|
+
import { resolveApiKeyForProvider } from "openclaw/plugin-sdk/provider-auth-runtime";
|
|
6
|
+
import { assertOkOrThrowHttpError, createProviderOperationDeadline, createProviderOperationTimeoutResolver, fetchProviderDownloadResponse, pollProviderOperationJson, postJsonRequest, readProviderJsonResponse, resolveProviderHttpRequestConfig, resolveProviderOperationTimeoutMs } from "openclaw/plugin-sdk/provider-http";
|
|
7
|
+
import { asSafeIntegerInRange, isRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
8
|
+
//#region extensions/byteplus/video-generation-provider.ts
|
|
9
|
+
/**
|
|
10
|
+
* BytePlus Seedance video generation provider implementation.
|
|
11
|
+
*/
|
|
12
|
+
const DEFAULT_BYTEPLUS_VIDEO_MODEL = "seedance-1-0-pro-250528";
|
|
13
|
+
const DEFAULT_TIMEOUT_MS = 12e4;
|
|
14
|
+
const POLL_INTERVAL_MS = 5e3;
|
|
15
|
+
const MAX_POLL_ATTEMPTS = 120;
|
|
16
|
+
const BYTEPLUS_SEED_MAX = 2147483647;
|
|
17
|
+
const BYTEPLUS_MIN_DURATION_SECONDS = 2;
|
|
18
|
+
const BYTEPLUS_MAX_DURATION_SECONDS = 12;
|
|
19
|
+
async function readBytePlusJsonResponse(response, label) {
|
|
20
|
+
const payload = await readProviderJsonResponse(response, label);
|
|
21
|
+
if (!isRecord(payload)) throw new Error(`${label}: malformed JSON response`);
|
|
22
|
+
return payload;
|
|
23
|
+
}
|
|
24
|
+
function readBytePlusTaskStatus(payload) {
|
|
25
|
+
const status = normalizeOptionalString(payload.status);
|
|
26
|
+
switch (status) {
|
|
27
|
+
case "running":
|
|
28
|
+
case "failed":
|
|
29
|
+
case "queued":
|
|
30
|
+
case "succeeded":
|
|
31
|
+
case "cancelled": return status;
|
|
32
|
+
case void 0: throw new Error("BytePlus video status response missing task status");
|
|
33
|
+
default: throw new Error(`BytePlus video status response returned unknown task status: ${status}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function readBytePlusErrorMessage(error) {
|
|
37
|
+
return isRecord(error) ? normalizeOptionalString(error.message) : void 0;
|
|
38
|
+
}
|
|
39
|
+
function readBytePlusVideoUrl(payload) {
|
|
40
|
+
const content = payload.content;
|
|
41
|
+
if (content !== void 0 && !isRecord(content)) throw new Error("BytePlus video generation completed with malformed content");
|
|
42
|
+
const videoUrl = normalizeOptionalString(content?.video_url);
|
|
43
|
+
if (!videoUrl) throw new Error("BytePlus video generation completed without a video URL");
|
|
44
|
+
return videoUrl;
|
|
45
|
+
}
|
|
46
|
+
function resolveBytePlusVideoBaseUrl(req) {
|
|
47
|
+
return normalizeOptionalString(req.cfg?.models?.providers?.byteplus?.baseUrl) ?? BYTEPLUS_BASE_URL;
|
|
48
|
+
}
|
|
49
|
+
function resolveBytePlusImageUrl(req) {
|
|
50
|
+
const input = req.inputImages?.[0];
|
|
51
|
+
if (!input) return;
|
|
52
|
+
const inputUrl = normalizeOptionalString(input.url);
|
|
53
|
+
if (inputUrl) return inputUrl;
|
|
54
|
+
if (!input.buffer) throw new Error("BytePlus reference image is missing image data.");
|
|
55
|
+
return toImageDataUrl({
|
|
56
|
+
...input,
|
|
57
|
+
buffer: input.buffer,
|
|
58
|
+
defaultMimeType: "image/png"
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
function resolveBytePlusSeed(value) {
|
|
62
|
+
return asSafeIntegerInRange(value, {
|
|
63
|
+
min: -1,
|
|
64
|
+
max: BYTEPLUS_SEED_MAX
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
function resolveBytePlusDurationSeconds(value) {
|
|
68
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return;
|
|
69
|
+
return asSafeIntegerInRange(Math.round(value), {
|
|
70
|
+
min: BYTEPLUS_MIN_DURATION_SECONDS,
|
|
71
|
+
max: BYTEPLUS_MAX_DURATION_SECONDS
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function readBytePlusDurationSeconds(value) {
|
|
75
|
+
return asSafeIntegerInRange(value, {
|
|
76
|
+
min: BYTEPLUS_MIN_DURATION_SECONDS,
|
|
77
|
+
max: BYTEPLUS_MAX_DURATION_SECONDS
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
async function pollBytePlusTask(params) {
|
|
81
|
+
const deadline = createProviderOperationDeadline({
|
|
82
|
+
timeoutMs: params.timeoutMs,
|
|
83
|
+
label: `BytePlus video generation task ${params.taskId}`
|
|
84
|
+
});
|
|
85
|
+
return await pollProviderOperationJson({
|
|
86
|
+
url: `${params.baseUrl}/contents/generations/tasks/${params.taskId}`,
|
|
87
|
+
headers: params.headers,
|
|
88
|
+
deadline,
|
|
89
|
+
defaultTimeoutMs: DEFAULT_TIMEOUT_MS,
|
|
90
|
+
fetchFn: params.fetchFn,
|
|
91
|
+
maxAttempts: MAX_POLL_ATTEMPTS,
|
|
92
|
+
pollIntervalMs: POLL_INTERVAL_MS,
|
|
93
|
+
requestFailedMessage: "BytePlus video status request failed",
|
|
94
|
+
timeoutMessage: `BytePlus video generation task ${params.taskId} did not finish in time`,
|
|
95
|
+
isComplete: (payload) => readBytePlusTaskStatus(payload) === "succeeded",
|
|
96
|
+
getFailureMessage: (payload) => {
|
|
97
|
+
const status = readBytePlusTaskStatus(payload);
|
|
98
|
+
return status === "failed" || status === "cancelled" ? readBytePlusErrorMessage(payload.error) || "BytePlus video generation failed" : void 0;
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
async function downloadBytePlusVideo(params) {
|
|
103
|
+
return await downloadGeneratedVideoAsset({
|
|
104
|
+
url: params.url,
|
|
105
|
+
timeoutMs: params.timeoutMs ?? DEFAULT_TIMEOUT_MS,
|
|
106
|
+
defaultTimeoutMs: DEFAULT_TIMEOUT_MS,
|
|
107
|
+
fetchFn: params.fetchFn,
|
|
108
|
+
provider: "byteplus",
|
|
109
|
+
label: "BytePlus generated video download",
|
|
110
|
+
requestFailedMessage: "BytePlus generated video download failed",
|
|
111
|
+
maxBytes: params.maxBytes,
|
|
112
|
+
validateBinaryResponse: true,
|
|
113
|
+
fetchResponse: async ({ deadline }) => ({ response: await fetchProviderDownloadResponse({
|
|
114
|
+
url: params.url,
|
|
115
|
+
init: { method: "GET" },
|
|
116
|
+
deadline,
|
|
117
|
+
fetchFn: params.fetchFn,
|
|
118
|
+
provider: "byteplus",
|
|
119
|
+
requestFailedMessage: "BytePlus generated video download failed"
|
|
120
|
+
}) })
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/** Builds the BytePlus video generation provider registered by the plugin. */
|
|
124
|
+
function buildBytePlusVideoGenerationProvider() {
|
|
125
|
+
return {
|
|
126
|
+
id: "byteplus",
|
|
127
|
+
label: "BytePlus",
|
|
128
|
+
defaultModel: DEFAULT_BYTEPLUS_VIDEO_MODEL,
|
|
129
|
+
models: [DEFAULT_BYTEPLUS_VIDEO_MODEL, "seedance-1-5-pro-251215"],
|
|
130
|
+
isConfigured: (ctx) => isProviderApiKeyConfigured({
|
|
131
|
+
provider: "byteplus",
|
|
132
|
+
...ctx
|
|
133
|
+
}),
|
|
134
|
+
capabilities: {
|
|
135
|
+
providerOptions: {
|
|
136
|
+
seed: "number",
|
|
137
|
+
draft: "boolean",
|
|
138
|
+
camera_fixed: "boolean"
|
|
139
|
+
},
|
|
140
|
+
generate: {
|
|
141
|
+
maxVideos: 1,
|
|
142
|
+
maxDurationSeconds: 12,
|
|
143
|
+
supportsAspectRatio: true,
|
|
144
|
+
supportsResolution: true,
|
|
145
|
+
supportsAudio: true,
|
|
146
|
+
supportsWatermark: true
|
|
147
|
+
},
|
|
148
|
+
imageToVideo: {
|
|
149
|
+
enabled: true,
|
|
150
|
+
maxVideos: 1,
|
|
151
|
+
maxInputImages: 1,
|
|
152
|
+
maxDurationSeconds: 12,
|
|
153
|
+
supportsAspectRatio: true,
|
|
154
|
+
supportsResolution: true,
|
|
155
|
+
supportsAudio: true,
|
|
156
|
+
supportsWatermark: true
|
|
157
|
+
},
|
|
158
|
+
videoToVideo: { enabled: false }
|
|
159
|
+
},
|
|
160
|
+
async generateVideo(req) {
|
|
161
|
+
if ((req.inputVideos?.length ?? 0) > 0) throw new Error("BytePlus video generation does not support video reference inputs.");
|
|
162
|
+
const auth = await resolveApiKeyForProvider({
|
|
163
|
+
provider: "byteplus",
|
|
164
|
+
cfg: req.cfg,
|
|
165
|
+
agentDir: req.agentDir,
|
|
166
|
+
store: req.authStore
|
|
167
|
+
});
|
|
168
|
+
if (!auth.apiKey) throw new Error("BytePlus API key missing");
|
|
169
|
+
const fetchFn = fetch;
|
|
170
|
+
const deadline = createProviderOperationDeadline({
|
|
171
|
+
timeoutMs: req.timeoutMs,
|
|
172
|
+
label: "BytePlus video generation"
|
|
173
|
+
});
|
|
174
|
+
const { baseUrl, allowPrivateNetwork, headers, dispatcherPolicy } = resolveProviderHttpRequestConfig({
|
|
175
|
+
baseUrl: resolveBytePlusVideoBaseUrl(req),
|
|
176
|
+
defaultBaseUrl: BYTEPLUS_BASE_URL,
|
|
177
|
+
allowPrivateNetwork: false,
|
|
178
|
+
defaultHeaders: {
|
|
179
|
+
Authorization: `Bearer ${auth.apiKey}`,
|
|
180
|
+
"Content-Type": "application/json"
|
|
181
|
+
},
|
|
182
|
+
provider: "byteplus",
|
|
183
|
+
capability: "video",
|
|
184
|
+
transport: "http"
|
|
185
|
+
});
|
|
186
|
+
const resolvedModel = normalizeOptionalString(req.model) || DEFAULT_BYTEPLUS_VIDEO_MODEL;
|
|
187
|
+
const content = [{
|
|
188
|
+
type: "text",
|
|
189
|
+
text: req.prompt
|
|
190
|
+
}];
|
|
191
|
+
const imageUrl = resolveBytePlusImageUrl(req);
|
|
192
|
+
if (imageUrl) content.push({
|
|
193
|
+
type: "image_url",
|
|
194
|
+
image_url: { url: imageUrl },
|
|
195
|
+
role: "first_frame"
|
|
196
|
+
});
|
|
197
|
+
const body = {
|
|
198
|
+
model: resolvedModel,
|
|
199
|
+
content
|
|
200
|
+
};
|
|
201
|
+
const aspectRatio = normalizeOptionalString(req.aspectRatio);
|
|
202
|
+
if (aspectRatio) body.ratio = aspectRatio;
|
|
203
|
+
const resolution = normalizeOptionalString(req.resolution)?.toLowerCase();
|
|
204
|
+
if (resolution) body.resolution = resolution;
|
|
205
|
+
const duration = resolveBytePlusDurationSeconds(req.durationSeconds);
|
|
206
|
+
if (duration !== void 0) body.duration = duration;
|
|
207
|
+
if (typeof req.audio === "boolean") body.generate_audio = req.audio;
|
|
208
|
+
if (typeof req.watermark === "boolean") body.watermark = req.watermark;
|
|
209
|
+
const opts = req.providerOptions ?? {};
|
|
210
|
+
const seed = resolveBytePlusSeed(opts.seed);
|
|
211
|
+
const draft = opts.draft === true;
|
|
212
|
+
const cameraFixed = typeof opts.camera_fixed === "boolean" ? opts.camera_fixed : void 0;
|
|
213
|
+
if (seed != null) body.seed = seed;
|
|
214
|
+
if (draft && !body.resolution) body.resolution = "480p";
|
|
215
|
+
if (cameraFixed != null) body.camera_fixed = cameraFixed;
|
|
216
|
+
const { response, release } = await postJsonRequest({
|
|
217
|
+
url: `${baseUrl}/contents/generations/tasks`,
|
|
218
|
+
headers,
|
|
219
|
+
body,
|
|
220
|
+
timeoutMs: resolveProviderOperationTimeoutMs({
|
|
221
|
+
deadline,
|
|
222
|
+
defaultTimeoutMs: DEFAULT_TIMEOUT_MS
|
|
223
|
+
}),
|
|
224
|
+
fetchFn,
|
|
225
|
+
allowPrivateNetwork,
|
|
226
|
+
dispatcherPolicy
|
|
227
|
+
});
|
|
228
|
+
try {
|
|
229
|
+
await assertOkOrThrowHttpError(response, "BytePlus video generation failed");
|
|
230
|
+
const taskId = normalizeOptionalString((await readBytePlusJsonResponse(response, "BytePlus video generation failed")).id);
|
|
231
|
+
if (!taskId) throw new Error("BytePlus video generation response missing task id");
|
|
232
|
+
const completed = await pollBytePlusTask({
|
|
233
|
+
taskId,
|
|
234
|
+
headers,
|
|
235
|
+
timeoutMs: resolveProviderOperationTimeoutMs({
|
|
236
|
+
deadline,
|
|
237
|
+
defaultTimeoutMs: DEFAULT_TIMEOUT_MS
|
|
238
|
+
}),
|
|
239
|
+
baseUrl,
|
|
240
|
+
fetchFn
|
|
241
|
+
});
|
|
242
|
+
const videoUrl = readBytePlusVideoUrl(completed);
|
|
243
|
+
return {
|
|
244
|
+
videos: [await downloadBytePlusVideo({
|
|
245
|
+
url: videoUrl,
|
|
246
|
+
timeoutMs: createProviderOperationTimeoutResolver({
|
|
247
|
+
deadline,
|
|
248
|
+
defaultTimeoutMs: DEFAULT_TIMEOUT_MS
|
|
249
|
+
}),
|
|
250
|
+
fetchFn,
|
|
251
|
+
maxBytes: resolveGeneratedMediaMaxBytes(req.cfg, "video")
|
|
252
|
+
})],
|
|
253
|
+
model: normalizeOptionalString(completed.model) ?? resolvedModel,
|
|
254
|
+
metadata: {
|
|
255
|
+
taskId,
|
|
256
|
+
status: normalizeOptionalString(completed.status),
|
|
257
|
+
videoUrl,
|
|
258
|
+
ratio: normalizeOptionalString(completed.ratio),
|
|
259
|
+
resolution: normalizeOptionalString(completed.resolution),
|
|
260
|
+
duration: readBytePlusDurationSeconds(completed.duration)
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
} finally {
|
|
264
|
+
await release();
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
//#endregion
|
|
270
|
+
export { buildBytePlusVideoGenerationProvider };
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "byteplus",
|
|
3
|
+
"activation": {
|
|
4
|
+
"onStartup": false
|
|
5
|
+
},
|
|
6
|
+
"enabledByDefault": true,
|
|
7
|
+
"providerCatalogEntry": "./provider-discovery.ts",
|
|
8
|
+
"providers": ["byteplus", "byteplus-plan"],
|
|
9
|
+
"setup": {
|
|
10
|
+
"providers": [
|
|
11
|
+
{
|
|
12
|
+
"id": "byteplus",
|
|
13
|
+
"envVars": ["BYTEPLUS_API_KEY"]
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"providerAuthAliases": {
|
|
18
|
+
"byteplus-plan": "byteplus"
|
|
19
|
+
},
|
|
20
|
+
"modelCatalog": {
|
|
21
|
+
"providers": {
|
|
22
|
+
"byteplus": {
|
|
23
|
+
"baseUrl": "https://ark.ap-southeast.bytepluses.com/api/v3",
|
|
24
|
+
"api": "openai-completions",
|
|
25
|
+
"models": [
|
|
26
|
+
{
|
|
27
|
+
"id": "dola-seed-2-1-turbo-260628",
|
|
28
|
+
"name": "Dola Seed 2.1 Turbo",
|
|
29
|
+
"reasoning": true,
|
|
30
|
+
"input": ["text", "image"],
|
|
31
|
+
"contextWindow": 256000,
|
|
32
|
+
"maxTokens": 256000,
|
|
33
|
+
"cost": {
|
|
34
|
+
"input": 0.5,
|
|
35
|
+
"output": 2.5,
|
|
36
|
+
"cacheRead": 0.1,
|
|
37
|
+
"cacheWrite": 0
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"id": "seed-2-0-code-preview-260328",
|
|
42
|
+
"name": "Seed 2.0 Code Preview",
|
|
43
|
+
"reasoning": true,
|
|
44
|
+
"input": ["text", "image"],
|
|
45
|
+
"contextWindow": 256000,
|
|
46
|
+
"maxTokens": 128000,
|
|
47
|
+
"cost": {
|
|
48
|
+
"input": 0.5,
|
|
49
|
+
"output": 3,
|
|
50
|
+
"cacheRead": 0.1,
|
|
51
|
+
"cacheWrite": 0
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"id": "glm-5-2-260617",
|
|
56
|
+
"name": "GLM 5.2",
|
|
57
|
+
"reasoning": true,
|
|
58
|
+
"input": ["text"],
|
|
59
|
+
"contextWindow": 1024000,
|
|
60
|
+
"maxTokens": 128000,
|
|
61
|
+
"cost": {
|
|
62
|
+
"input": 1.4,
|
|
63
|
+
"output": 4.4,
|
|
64
|
+
"cacheRead": 0.26,
|
|
65
|
+
"cacheWrite": 0
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"id": "deepseek-v4-pro-260425",
|
|
70
|
+
"name": "DeepSeek V4 Pro",
|
|
71
|
+
"reasoning": true,
|
|
72
|
+
"input": ["text"],
|
|
73
|
+
"contextWindow": 1024000,
|
|
74
|
+
"maxTokens": 384000,
|
|
75
|
+
"cost": {
|
|
76
|
+
"input": 1.74,
|
|
77
|
+
"output": 3.48,
|
|
78
|
+
"cacheRead": 0.145,
|
|
79
|
+
"cacheWrite": 0
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"id": "deepseek-v4-flash-260425",
|
|
84
|
+
"name": "DeepSeek V4 Flash",
|
|
85
|
+
"reasoning": true,
|
|
86
|
+
"input": ["text"],
|
|
87
|
+
"contextWindow": 1024000,
|
|
88
|
+
"maxTokens": 384000,
|
|
89
|
+
"cost": {
|
|
90
|
+
"input": 0.14,
|
|
91
|
+
"output": 0.28,
|
|
92
|
+
"cacheRead": 0.028,
|
|
93
|
+
"cacheWrite": 0
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"id": "glm-4-7-251222",
|
|
98
|
+
"name": "GLM 4.7",
|
|
99
|
+
"status": "deprecated",
|
|
100
|
+
"replacedBy": "glm-5-2-260617",
|
|
101
|
+
"reasoning": true,
|
|
102
|
+
"input": ["text"],
|
|
103
|
+
"contextWindow": 256000,
|
|
104
|
+
"maxTokens": 128000,
|
|
105
|
+
"cost": {
|
|
106
|
+
"input": 0.6,
|
|
107
|
+
"output": 2.2,
|
|
108
|
+
"cacheRead": 0.11,
|
|
109
|
+
"cacheWrite": 0
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
},
|
|
114
|
+
"byteplus-plan": {
|
|
115
|
+
"baseUrl": "https://ark.ap-southeast.bytepluses.com/api/coding/v3",
|
|
116
|
+
"api": "openai-completions",
|
|
117
|
+
"defaultModel": "ark-code-latest",
|
|
118
|
+
"models": [
|
|
119
|
+
{
|
|
120
|
+
"id": "ark-code-latest",
|
|
121
|
+
"name": "Ark Coding Plan",
|
|
122
|
+
"input": ["text"],
|
|
123
|
+
"contextWindow": 256000,
|
|
124
|
+
"maxTokens": 4096,
|
|
125
|
+
"cost": {
|
|
126
|
+
"input": 0,
|
|
127
|
+
"output": 0,
|
|
128
|
+
"cacheRead": 0,
|
|
129
|
+
"cacheWrite": 0
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"id": "kimi-k2.5",
|
|
134
|
+
"name": "Kimi K2.5 Coding",
|
|
135
|
+
"reasoning": true,
|
|
136
|
+
"input": ["text", "image"],
|
|
137
|
+
"contextWindow": 256000,
|
|
138
|
+
"maxTokens": 32768,
|
|
139
|
+
"cost": {
|
|
140
|
+
"input": 0,
|
|
141
|
+
"output": 0,
|
|
142
|
+
"cacheRead": 0,
|
|
143
|
+
"cacheWrite": 0
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
]
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
"discovery": {
|
|
150
|
+
"byteplus": "refreshable",
|
|
151
|
+
"byteplus-plan": "refreshable"
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
"providerAuthChoices": [
|
|
155
|
+
{
|
|
156
|
+
"provider": "byteplus",
|
|
157
|
+
"method": "api-key",
|
|
158
|
+
"choiceId": "byteplus-api-key",
|
|
159
|
+
"appGuidedSecret": true,
|
|
160
|
+
"choiceLabel": "BytePlus API key",
|
|
161
|
+
"groupId": "byteplus",
|
|
162
|
+
"groupLabel": "BytePlus",
|
|
163
|
+
"groupHint": "API key",
|
|
164
|
+
"optionKey": "byteplusApiKey",
|
|
165
|
+
"cliFlag": "--byteplus-api-key",
|
|
166
|
+
"cliOption": "--byteplus-api-key <key>",
|
|
167
|
+
"cliDescription": "BytePlus API key"
|
|
168
|
+
}
|
|
169
|
+
],
|
|
170
|
+
"contracts": {
|
|
171
|
+
"videoGenerationProviders": ["byteplus"]
|
|
172
|
+
},
|
|
173
|
+
"configSchema": {
|
|
174
|
+
"type": "object",
|
|
175
|
+
"additionalProperties": false,
|
|
176
|
+
"properties": {}
|
|
177
|
+
}
|
|
178
|
+
}
|
package/package.json
CHANGED
|
@@ -1,14 +1,49 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/byteplus-provider",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
5
|
-
"license": "MIT",
|
|
3
|
+
"version": "2026.8.1-beta.3",
|
|
4
|
+
"description": "OpenClaw BytePlus provider plugin.",
|
|
6
5
|
"repository": {
|
|
7
6
|
"type": "git",
|
|
8
|
-
"url": "
|
|
7
|
+
"url": "https://github.com/openclaw/openclaw"
|
|
9
8
|
},
|
|
10
|
-
"
|
|
11
|
-
|
|
12
|
-
"
|
|
13
|
-
|
|
9
|
+
"type": "module",
|
|
10
|
+
"openclaw": {
|
|
11
|
+
"extensions": [
|
|
12
|
+
"./index.ts"
|
|
13
|
+
],
|
|
14
|
+
"install": {
|
|
15
|
+
"clawhubSpec": "clawhub:@openclaw/byteplus-provider",
|
|
16
|
+
"npmSpec": "@openclaw/byteplus-provider",
|
|
17
|
+
"defaultChoice": "npm",
|
|
18
|
+
"minHostVersion": ">=2026.7.2"
|
|
19
|
+
},
|
|
20
|
+
"compat": {
|
|
21
|
+
"pluginApi": ">=2026.8.1-beta.3"
|
|
22
|
+
},
|
|
23
|
+
"build": {
|
|
24
|
+
"openclawVersion": "2026.8.1-beta.3",
|
|
25
|
+
"bundledDist": false
|
|
26
|
+
},
|
|
27
|
+
"release": {
|
|
28
|
+
"publishToClawHub": true,
|
|
29
|
+
"publishToNpm": true
|
|
30
|
+
},
|
|
31
|
+
"runtimeExtensions": [
|
|
32
|
+
"./dist/index.js"
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"files": [
|
|
36
|
+
"dist/**",
|
|
37
|
+
"openclaw.plugin.json",
|
|
38
|
+
"README.md"
|
|
39
|
+
],
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"openclaw": ">=2026.8.1-beta.3"
|
|
42
|
+
},
|
|
43
|
+
"peerDependenciesMeta": {
|
|
44
|
+
"openclaw": {
|
|
45
|
+
"optional": true
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"bundledDependencies": []
|
|
14
49
|
}
|