@brotu/ai 0.7.0 → 0.8.0
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 +44 -0
- package/dist/adapters/kie.adapter.d.ts +62 -0
- package/dist/adapters/kie.adapter.d.ts.map +1 -0
- package/dist/catalog.cjs +9 -0
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +1 -1
- package/dist/{chunk-QQIHMDJC.js → chunk-OISTBZ64.js} +9 -0
- package/dist/client.d.ts +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/index.cjs +421 -61
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +410 -62
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -50,6 +50,7 @@ __export(index_exports, {
|
|
|
50
50
|
KLING_CAPABILITIES: () => KLING_CAPABILITIES,
|
|
51
51
|
KLING_CATALOG: () => KLING_CATALOG,
|
|
52
52
|
KLING_MODELS: () => KLING_MODELS,
|
|
53
|
+
KieAdapter: () => KieAdapter,
|
|
53
54
|
KlingAdapter: () => KlingAdapter,
|
|
54
55
|
OPENAI_CATALOG: () => OPENAI_CATALOG,
|
|
55
56
|
OPENAI_IMAGE_MODELS: () => OPENAI_IMAGE_MODELS,
|
|
@@ -78,7 +79,9 @@ __export(index_exports, {
|
|
|
78
79
|
getProviders: () => getProviders,
|
|
79
80
|
hasModel: () => hasModel,
|
|
80
81
|
isPendingJob: () => isPendingJob,
|
|
82
|
+
kieSnapshot: () => kieSnapshot,
|
|
81
83
|
ok: () => ok,
|
|
84
|
+
parseKieCallback: () => parseKieCallback,
|
|
82
85
|
persistOutputs: () => persistOutputs,
|
|
83
86
|
registerModels: () => registerModels,
|
|
84
87
|
resetCatalog: () => resetCatalog,
|
|
@@ -1349,6 +1352,7 @@ var PROVIDER_BASE_URLS = {
|
|
|
1349
1352
|
openai: "https://api.openai.com",
|
|
1350
1353
|
qwen: "https://dashscope-intl.aliyuncs.com",
|
|
1351
1354
|
topaz: "https://api.topazlabs.com",
|
|
1355
|
+
kie: "https://api.kie.ai/api/v1",
|
|
1352
1356
|
brotu: "https://api.brotu.app"
|
|
1353
1357
|
};
|
|
1354
1358
|
var DEFAULT_BROTU_API_URL = PROVIDER_BASE_URLS.brotu;
|
|
@@ -1424,6 +1428,14 @@ function resolveProvider(modelId, options) {
|
|
|
1424
1428
|
}
|
|
1425
1429
|
return { id, apiKey: configured.apiKey, baseUrl: baseUrl.replace(/\/$/, "") };
|
|
1426
1430
|
}
|
|
1431
|
+
const kie = vendorProviders(options).kie;
|
|
1432
|
+
if (kie && id !== "kie") {
|
|
1433
|
+
return {
|
|
1434
|
+
id: "kie",
|
|
1435
|
+
apiKey: kie.apiKey,
|
|
1436
|
+
baseUrl: (kie.baseUrl ?? PROVIDER_BASE_URLS.kie).replace(/\/$/, "")
|
|
1437
|
+
};
|
|
1438
|
+
}
|
|
1427
1439
|
const platformKey = brotuApiKey(options);
|
|
1428
1440
|
if (platformKey) {
|
|
1429
1441
|
return {
|
|
@@ -2827,10 +2839,383 @@ var GoogleAdapter = class {
|
|
|
2827
2839
|
}
|
|
2828
2840
|
};
|
|
2829
2841
|
|
|
2842
|
+
// src/lib/webhook.ts
|
|
2843
|
+
function resolveWebhook(value) {
|
|
2844
|
+
if (!value) return void 0;
|
|
2845
|
+
if (typeof value === "string") {
|
|
2846
|
+
return isHttpUrl(value) ? { url: value } : void 0;
|
|
2847
|
+
}
|
|
2848
|
+
if (!isHttpUrl(value.url)) return void 0;
|
|
2849
|
+
return {
|
|
2850
|
+
url: value.url,
|
|
2851
|
+
secret: value.secret,
|
|
2852
|
+
headers: value.headers
|
|
2853
|
+
};
|
|
2854
|
+
}
|
|
2855
|
+
function isHttpUrl(value) {
|
|
2856
|
+
try {
|
|
2857
|
+
const parsed = new URL(value);
|
|
2858
|
+
return parsed.protocol === "https:" || parsed.protocol === "http:";
|
|
2859
|
+
} catch {
|
|
2860
|
+
return false;
|
|
2861
|
+
}
|
|
2862
|
+
}
|
|
2863
|
+
async function deliverWebhook(config, payload) {
|
|
2864
|
+
try {
|
|
2865
|
+
await fetch(config.url, {
|
|
2866
|
+
method: "POST",
|
|
2867
|
+
headers: {
|
|
2868
|
+
"content-type": "application/json",
|
|
2869
|
+
"user-agent": "@brotu/ai",
|
|
2870
|
+
"x-brotu-event": payload.event,
|
|
2871
|
+
...config.secret ? { "x-brotu-webhook-secret": config.secret } : {},
|
|
2872
|
+
...config.headers
|
|
2873
|
+
},
|
|
2874
|
+
body: JSON.stringify(payload),
|
|
2875
|
+
signal: AbortSignal.timeout(1e4)
|
|
2876
|
+
});
|
|
2877
|
+
} catch {
|
|
2878
|
+
}
|
|
2879
|
+
}
|
|
2880
|
+
|
|
2881
|
+
// src/adapters/kie.adapter.ts
|
|
2882
|
+
var DEFAULT_BASE_URL4 = "https://api.kie.ai/api/v1";
|
|
2883
|
+
var POLL_INTERVAL_MS4 = 3e3;
|
|
2884
|
+
var DEFAULT_MAX_POLL_ATTEMPTS4 = 400;
|
|
2885
|
+
var KIE_MODEL_IDS = {
|
|
2886
|
+
"kling/v2-6": "kling-2.6/{mode}-to-video",
|
|
2887
|
+
"kling/v3": "kling-3.0/video",
|
|
2888
|
+
"dreamina-seedance-2-5-260628": "bytedance/seedance-2-5",
|
|
2889
|
+
"dreamina-seedance-2-0-260128": "bytedance/seedance-2",
|
|
2890
|
+
"dreamina-seedance-2-0-fast-260128": "bytedance/seedance-2-fast",
|
|
2891
|
+
"dreamina-seedance-2-0-mini-260615": "bytedance/seedance-2-mini",
|
|
2892
|
+
"wan2.6-t2v": "wan/2-6-text-to-video",
|
|
2893
|
+
"wan2.6-i2v": "wan/2-6-image-to-video",
|
|
2894
|
+
"wan2.7-t2v": "wan/2-7-text-to-video",
|
|
2895
|
+
"wan2.7-i2v": "wan/2-7-image-to-video",
|
|
2896
|
+
"gpt-image-1.5": "gpt-image/1.5-{mode}-to-image",
|
|
2897
|
+
"gpt-image-2": "gpt-image-2-{mode}-to-image",
|
|
2898
|
+
"topaz/video-upscale": "topaz/video-upscale"
|
|
2899
|
+
};
|
|
2900
|
+
var KieAdapter = class {
|
|
2901
|
+
constructor(opts) {
|
|
2902
|
+
this.opts = opts;
|
|
2903
|
+
}
|
|
2904
|
+
opts;
|
|
2905
|
+
providerName = "kie";
|
|
2906
|
+
supportedTypes = [
|
|
2907
|
+
"image",
|
|
2908
|
+
"video",
|
|
2909
|
+
"text",
|
|
2910
|
+
"audio"
|
|
2911
|
+
];
|
|
2912
|
+
get origin() {
|
|
2913
|
+
return (this.opts.baseUrl ?? DEFAULT_BASE_URL4).replace(/\/$/, "");
|
|
2914
|
+
}
|
|
2915
|
+
async request(path, init) {
|
|
2916
|
+
const response = await fetch(`${this.origin}${path}`, {
|
|
2917
|
+
...init,
|
|
2918
|
+
headers: {
|
|
2919
|
+
Authorization: `Bearer ${this.opts.apiKey}`,
|
|
2920
|
+
"Content-Type": "application/json",
|
|
2921
|
+
...init?.headers
|
|
2922
|
+
}
|
|
2923
|
+
});
|
|
2924
|
+
const text = await response.text();
|
|
2925
|
+
let body;
|
|
2926
|
+
try {
|
|
2927
|
+
body = text ? JSON.parse(text) : void 0;
|
|
2928
|
+
} catch {
|
|
2929
|
+
body = void 0;
|
|
2930
|
+
}
|
|
2931
|
+
const code = body?.code;
|
|
2932
|
+
if (!response.ok || typeof code === "number" && code !== 200) {
|
|
2933
|
+
const message = body?.msg || body?.message || text;
|
|
2934
|
+
throw new Error(message || `kie API ${response.status}`);
|
|
2935
|
+
}
|
|
2936
|
+
if (body?.data === void 0) {
|
|
2937
|
+
throw new Error("kie answered without a payload.");
|
|
2938
|
+
}
|
|
2939
|
+
return body.data;
|
|
2940
|
+
}
|
|
2941
|
+
/** Which market model serves this request. */
|
|
2942
|
+
marketModel(modelId, params) {
|
|
2943
|
+
const fromCatalog = getModel(modelId)?.endpoint?.replace(
|
|
2944
|
+
/^\/market\//,
|
|
2945
|
+
""
|
|
2946
|
+
);
|
|
2947
|
+
const mapped = fromCatalog || KIE_MODEL_IDS[modelId] || modelId;
|
|
2948
|
+
if (!mapped.includes("{mode}")) return mapped;
|
|
2949
|
+
return mapped.replace("{mode}", hasInputImage(params) ? "image" : "text");
|
|
2950
|
+
}
|
|
2951
|
+
callbackFor(params) {
|
|
2952
|
+
const perRequest = resolveWebhook(params.webhook);
|
|
2953
|
+
return perRequest?.url ?? this.opts.callbackUrl;
|
|
2954
|
+
}
|
|
2955
|
+
async createTask(kind, params) {
|
|
2956
|
+
const modelId = params.model ?? "";
|
|
2957
|
+
const body = {
|
|
2958
|
+
model: this.marketModel(modelId, params),
|
|
2959
|
+
input: buildInput(kind, params, modelId)
|
|
2960
|
+
};
|
|
2961
|
+
const callBackUrl = this.callbackFor(params);
|
|
2962
|
+
if (callBackUrl) body.callBackUrl = callBackUrl;
|
|
2963
|
+
const data = await this.request("/jobs/createTask", {
|
|
2964
|
+
method: "POST",
|
|
2965
|
+
body: JSON.stringify(body)
|
|
2966
|
+
});
|
|
2967
|
+
const taskId = data.taskId?.trim();
|
|
2968
|
+
if (!taskId) {
|
|
2969
|
+
throw new Error("kie accepted the task but returned no taskId.");
|
|
2970
|
+
}
|
|
2971
|
+
return taskId;
|
|
2972
|
+
}
|
|
2973
|
+
/** Ask kie about one task. The same shape a callback carries. */
|
|
2974
|
+
async task(taskId) {
|
|
2975
|
+
const record = await this.request(
|
|
2976
|
+
`/jobs/recordInfo?taskId=${encodeURIComponent(taskId)}`
|
|
2977
|
+
);
|
|
2978
|
+
return readTaskRecord(record, taskId);
|
|
2979
|
+
}
|
|
2980
|
+
async run(kind, params) {
|
|
2981
|
+
const startedAt = Date.now();
|
|
2982
|
+
const modelId = params.model ?? "(none)";
|
|
2983
|
+
const failure = (error) => ({
|
|
2984
|
+
success: false,
|
|
2985
|
+
outputs: [],
|
|
2986
|
+
creditsUsed: 0,
|
|
2987
|
+
provider: this.providerName,
|
|
2988
|
+
model: modelId,
|
|
2989
|
+
processingTimeMs: Date.now() - startedAt,
|
|
2990
|
+
error
|
|
2991
|
+
});
|
|
2992
|
+
let taskId;
|
|
2993
|
+
try {
|
|
2994
|
+
taskId = await this.createTask(kind, params);
|
|
2995
|
+
} catch (error) {
|
|
2996
|
+
return failure(error instanceof Error ? error.message : String(error));
|
|
2997
|
+
}
|
|
2998
|
+
const pollEndpoint = `/jobs/recordInfo?taskId=${encodeURIComponent(taskId)}`;
|
|
2999
|
+
if (isSubmitMode()) {
|
|
3000
|
+
throw new PendingJob(taskId, pollEndpoint);
|
|
3001
|
+
}
|
|
3002
|
+
const job = {
|
|
3003
|
+
id: taskId,
|
|
3004
|
+
provider: this.providerName,
|
|
3005
|
+
model: modelId,
|
|
3006
|
+
kind,
|
|
3007
|
+
pollEndpoint,
|
|
3008
|
+
params,
|
|
3009
|
+
submittedAt: new Date(startedAt).toISOString()
|
|
3010
|
+
};
|
|
3011
|
+
const maxAttempts = this.opts.maxPollAttempts ?? DEFAULT_MAX_POLL_ATTEMPTS4;
|
|
3012
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
3013
|
+
const snapshot = await this.completeJob(job);
|
|
3014
|
+
if (snapshot.status === "failed") {
|
|
3015
|
+
return failure(snapshot.error ?? "kie task failed.");
|
|
3016
|
+
}
|
|
3017
|
+
if (snapshot.status === "succeeded" && snapshot.result) {
|
|
3018
|
+
return { ...snapshot.result, processingTimeMs: Date.now() - startedAt };
|
|
3019
|
+
}
|
|
3020
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS4));
|
|
3021
|
+
}
|
|
3022
|
+
return failure(
|
|
3023
|
+
`kie task ${taskId} did not finish after ${maxAttempts} checks.`
|
|
3024
|
+
);
|
|
3025
|
+
}
|
|
3026
|
+
async completeJob(job) {
|
|
3027
|
+
const settled = await this.task(job.id);
|
|
3028
|
+
return snapshotFrom(settled, job.model);
|
|
3029
|
+
}
|
|
3030
|
+
generateImage(params) {
|
|
3031
|
+
return this.run("image", params);
|
|
3032
|
+
}
|
|
3033
|
+
generateVideo(params) {
|
|
3034
|
+
return this.run("video", params);
|
|
3035
|
+
}
|
|
3036
|
+
generateText(params) {
|
|
3037
|
+
return this.run("text", params);
|
|
3038
|
+
}
|
|
3039
|
+
generateAudio(params) {
|
|
3040
|
+
return this.run("audio", params);
|
|
3041
|
+
}
|
|
3042
|
+
async estimateCost(type, params) {
|
|
3043
|
+
return estimateFor(this.providerName, type, params);
|
|
3044
|
+
}
|
|
3045
|
+
supportsModel() {
|
|
3046
|
+
return true;
|
|
3047
|
+
}
|
|
3048
|
+
getAvailableModels() {
|
|
3049
|
+
return [];
|
|
3050
|
+
}
|
|
3051
|
+
};
|
|
3052
|
+
function parseKieCallback(body) {
|
|
3053
|
+
let parsed = body;
|
|
3054
|
+
if (typeof body === "string") {
|
|
3055
|
+
try {
|
|
3056
|
+
parsed = JSON.parse(body);
|
|
3057
|
+
} catch {
|
|
3058
|
+
throw new Error("kie callback body is not JSON.");
|
|
3059
|
+
}
|
|
3060
|
+
}
|
|
3061
|
+
const root = asRecord(parsed);
|
|
3062
|
+
const record = asRecord(root?.data) ?? root ?? {};
|
|
3063
|
+
const taskId = record.taskId?.trim();
|
|
3064
|
+
if (!taskId) {
|
|
3065
|
+
throw new Error("kie callback carries no taskId.");
|
|
3066
|
+
}
|
|
3067
|
+
return readTaskRecord(record, taskId);
|
|
3068
|
+
}
|
|
3069
|
+
function kieSnapshot(settled, model) {
|
|
3070
|
+
return snapshotFrom(settled, model ?? settled.model ?? "");
|
|
3071
|
+
}
|
|
3072
|
+
function snapshotFrom(settled, model) {
|
|
3073
|
+
if (settled.status === "failed") {
|
|
3074
|
+
return { status: "failed", error: settled.error ?? "kie task failed." };
|
|
3075
|
+
}
|
|
3076
|
+
if (settled.status === "pending") return { status: "pending" };
|
|
3077
|
+
return {
|
|
3078
|
+
status: "succeeded",
|
|
3079
|
+
result: {
|
|
3080
|
+
success: true,
|
|
3081
|
+
outputs: settled.outputs,
|
|
3082
|
+
creditsUsed: settled.creditsUsed,
|
|
3083
|
+
provider: "kie",
|
|
3084
|
+
model,
|
|
3085
|
+
processingTimeMs: 0
|
|
3086
|
+
}
|
|
3087
|
+
};
|
|
3088
|
+
}
|
|
3089
|
+
function readTaskRecord(record, taskId) {
|
|
3090
|
+
const state = (record.state ?? "").toLowerCase();
|
|
3091
|
+
const creditsUsed = record.creditsConsumed ?? 0;
|
|
3092
|
+
if (state === "fail") {
|
|
3093
|
+
return {
|
|
3094
|
+
taskId,
|
|
3095
|
+
model: record.model,
|
|
3096
|
+
status: "failed",
|
|
3097
|
+
outputs: [],
|
|
3098
|
+
creditsUsed,
|
|
3099
|
+
error: record.failMsg || (record.failCode ? `kie failCode ${record.failCode}` : void 0) || "kie task failed."
|
|
3100
|
+
};
|
|
3101
|
+
}
|
|
3102
|
+
if (state !== "success") {
|
|
3103
|
+
return {
|
|
3104
|
+
taskId,
|
|
3105
|
+
model: record.model,
|
|
3106
|
+
status: "pending",
|
|
3107
|
+
outputs: [],
|
|
3108
|
+
creditsUsed
|
|
3109
|
+
};
|
|
3110
|
+
}
|
|
3111
|
+
return {
|
|
3112
|
+
taskId,
|
|
3113
|
+
model: record.model,
|
|
3114
|
+
status: "succeeded",
|
|
3115
|
+
outputs: outputsFrom2(record.resultJson),
|
|
3116
|
+
creditsUsed
|
|
3117
|
+
};
|
|
3118
|
+
}
|
|
3119
|
+
function outputsFrom2(resultJson) {
|
|
3120
|
+
if (!resultJson) return [];
|
|
3121
|
+
let parsed;
|
|
3122
|
+
try {
|
|
3123
|
+
parsed = JSON.parse(resultJson);
|
|
3124
|
+
} catch {
|
|
3125
|
+
return [];
|
|
3126
|
+
}
|
|
3127
|
+
const record = asRecord(parsed);
|
|
3128
|
+
const urls = Array.isArray(record?.resultUrls) ? record.resultUrls.filter(
|
|
3129
|
+
(url) => typeof url === "string" && url.length > 0
|
|
3130
|
+
) : [];
|
|
3131
|
+
if (urls.length > 0) return urls.map((url) => ({ url, mimeType: mimeFor(url) }));
|
|
3132
|
+
const object = record?.resultObject;
|
|
3133
|
+
if (object !== void 0) {
|
|
3134
|
+
const text = typeof object === "string" ? object : JSON.stringify(object);
|
|
3135
|
+
return [
|
|
3136
|
+
{
|
|
3137
|
+
url: `data:text/plain;base64,${Buffer.from(text).toString("base64")}`,
|
|
3138
|
+
mimeType: "text/plain",
|
|
3139
|
+
raw: { text }
|
|
3140
|
+
}
|
|
3141
|
+
];
|
|
3142
|
+
}
|
|
3143
|
+
return [];
|
|
3144
|
+
}
|
|
3145
|
+
function mimeFor(url) {
|
|
3146
|
+
const path = url.split("?")[0]?.toLowerCase() ?? "";
|
|
3147
|
+
if (/\.(mp4|mov|webm|m4v)$/.test(path)) return "video/mp4";
|
|
3148
|
+
if (/\.(mp3|wav|m4a|aac)$/.test(path)) return "audio/mpeg";
|
|
3149
|
+
if (/\.jpe?g$/.test(path)) return "image/jpeg";
|
|
3150
|
+
if (/\.webp$/.test(path)) return "image/webp";
|
|
3151
|
+
return "image/png";
|
|
3152
|
+
}
|
|
3153
|
+
function asRecord(value) {
|
|
3154
|
+
return value && typeof value === "object" ? value : void 0;
|
|
3155
|
+
}
|
|
3156
|
+
function hasInputImage(params) {
|
|
3157
|
+
const p = params;
|
|
3158
|
+
return Boolean(
|
|
3159
|
+
p.imageUrl || p.imageUrls?.length || p.referenceImages?.length
|
|
3160
|
+
);
|
|
3161
|
+
}
|
|
3162
|
+
function buildInput(kind, params, modelId) {
|
|
3163
|
+
const raw = params.providerOptions?.kie ?? {};
|
|
3164
|
+
const base = modelId.startsWith("kling/") ? klingInput(params) : modelId.includes("seedance") ? seedanceInput(params) : commonInput(kind, params);
|
|
3165
|
+
return prune({ ...base, ...raw });
|
|
3166
|
+
}
|
|
3167
|
+
function klingInput(params) {
|
|
3168
|
+
const p = params;
|
|
3169
|
+
return {
|
|
3170
|
+
prompt: p.prompt,
|
|
3171
|
+
negative_prompt: p.negativePrompt,
|
|
3172
|
+
aspect_ratio: p.aspectRatio,
|
|
3173
|
+
// kie's kling enum is a string, unlike every other family.
|
|
3174
|
+
duration: p.duration === void 0 ? void 0 : String(p.duration),
|
|
3175
|
+
sound: p.withAudio,
|
|
3176
|
+
image_url: p.imageUrl ?? p.referenceImages?.[0]
|
|
3177
|
+
};
|
|
3178
|
+
}
|
|
3179
|
+
function seedanceInput(params) {
|
|
3180
|
+
const p = params;
|
|
3181
|
+
return {
|
|
3182
|
+
prompt: p.prompt,
|
|
3183
|
+
duration: p.duration,
|
|
3184
|
+
resolution: p.resolution,
|
|
3185
|
+
aspect_ratio: p.aspectRatio,
|
|
3186
|
+
first_frame_url: p.imageUrl ?? p.referenceImages?.[0],
|
|
3187
|
+
last_frame_url: p.referenceImages?.[1],
|
|
3188
|
+
reference_image_urls: p.imageUrls,
|
|
3189
|
+
reference_video_urls: p.videoUrls ?? (p.videoUrl ? [p.videoUrl] : void 0),
|
|
3190
|
+
generate_audio: p.withAudio
|
|
3191
|
+
};
|
|
3192
|
+
}
|
|
3193
|
+
function commonInput(kind, params) {
|
|
3194
|
+
const p = params;
|
|
3195
|
+
const images = p.imageUrls ?? p.referenceImages;
|
|
3196
|
+
return {
|
|
3197
|
+
prompt: p.prompt,
|
|
3198
|
+
negative_prompt: p.negativePrompt,
|
|
3199
|
+
aspect_ratio: p.aspectRatio,
|
|
3200
|
+
resolution: p.resolution,
|
|
3201
|
+
duration: kind === "video" ? p.duration : void 0,
|
|
3202
|
+
seed: p.seed,
|
|
3203
|
+
output_format: p.outputFormat,
|
|
3204
|
+
image_url: p.imageUrl ?? images?.[0],
|
|
3205
|
+
image_urls: images && images.length > 1 ? images : void 0,
|
|
3206
|
+
video_url: p.videoUrl
|
|
3207
|
+
};
|
|
3208
|
+
}
|
|
3209
|
+
function prune(input) {
|
|
3210
|
+
return Object.fromEntries(
|
|
3211
|
+
Object.entries(input).filter(([, value]) => value !== void 0)
|
|
3212
|
+
);
|
|
3213
|
+
}
|
|
3214
|
+
|
|
2830
3215
|
// src/adapters/kling.adapter.ts
|
|
2831
|
-
var
|
|
2832
|
-
var
|
|
2833
|
-
var
|
|
3216
|
+
var DEFAULT_BASE_URL5 = "https://api-singapore.klingai.com";
|
|
3217
|
+
var POLL_INTERVAL_MS5 = 5e3;
|
|
3218
|
+
var DEFAULT_MAX_POLL_ATTEMPTS5 = 240;
|
|
2834
3219
|
function stateOf(task) {
|
|
2835
3220
|
const raw = (task.status ?? task.task_status ?? "").toLowerCase();
|
|
2836
3221
|
if (raw === "failed") return "failed";
|
|
@@ -2845,7 +3230,7 @@ var KlingAdapter = class {
|
|
|
2845
3230
|
this.opts = opts;
|
|
2846
3231
|
}
|
|
2847
3232
|
get baseUrl() {
|
|
2848
|
-
return (this.opts.baseUrl ??
|
|
3233
|
+
return (this.opts.baseUrl ?? DEFAULT_BASE_URL5).replace(/\/$/, "");
|
|
2849
3234
|
}
|
|
2850
3235
|
async request(path, init) {
|
|
2851
3236
|
const response = await fetch(`${this.baseUrl}${path}`, {
|
|
@@ -3027,7 +3412,7 @@ var KlingAdapter = class {
|
|
|
3027
3412
|
params,
|
|
3028
3413
|
submittedAt: new Date(startedAt).toISOString()
|
|
3029
3414
|
};
|
|
3030
|
-
const maxAttempts = this.opts.maxPollAttempts ??
|
|
3415
|
+
const maxAttempts = this.opts.maxPollAttempts ?? DEFAULT_MAX_POLL_ATTEMPTS5;
|
|
3031
3416
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
3032
3417
|
const snapshot = await this.completeJob(job);
|
|
3033
3418
|
if (snapshot.status === "failed") {
|
|
@@ -3036,7 +3421,7 @@ var KlingAdapter = class {
|
|
|
3036
3421
|
if (snapshot.status === "succeeded" && snapshot.result) {
|
|
3037
3422
|
return { ...snapshot.result, processingTimeMs: Date.now() - startedAt };
|
|
3038
3423
|
}
|
|
3039
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
3424
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS5));
|
|
3040
3425
|
}
|
|
3041
3426
|
return failure(
|
|
3042
3427
|
`Kling task ${submitted.taskId} did not finish after ${maxAttempts} checks.`
|
|
@@ -3173,7 +3558,7 @@ var KlingAdapter = class {
|
|
|
3173
3558
|
};
|
|
3174
3559
|
|
|
3175
3560
|
// src/adapters/openai.adapter.ts
|
|
3176
|
-
var
|
|
3561
|
+
var DEFAULT_BASE_URL6 = "https://api.openai.com";
|
|
3177
3562
|
var IMAGES_PATH2 = "/v1/images/generations";
|
|
3178
3563
|
var OpenAIAdapter = class {
|
|
3179
3564
|
providerName = "openai";
|
|
@@ -3184,7 +3569,7 @@ var OpenAIAdapter = class {
|
|
|
3184
3569
|
this.opts = opts;
|
|
3185
3570
|
}
|
|
3186
3571
|
get baseUrl() {
|
|
3187
|
-
return (this.opts.baseUrl ??
|
|
3572
|
+
return (this.opts.baseUrl ?? DEFAULT_BASE_URL6).replace(/\/$/, "");
|
|
3188
3573
|
}
|
|
3189
3574
|
binding(modelId) {
|
|
3190
3575
|
const id = modelId ?? "";
|
|
@@ -3405,10 +3790,10 @@ var OpenAIAdapter = class {
|
|
|
3405
3790
|
};
|
|
3406
3791
|
|
|
3407
3792
|
// src/adapters/qwen.adapter.ts
|
|
3408
|
-
var
|
|
3793
|
+
var DEFAULT_BASE_URL7 = "https://dashscope-intl.aliyuncs.com";
|
|
3409
3794
|
var TASKS_PATH2 = "/api/v1/tasks";
|
|
3410
|
-
var
|
|
3411
|
-
var
|
|
3795
|
+
var POLL_INTERVAL_MS6 = 5e3;
|
|
3796
|
+
var DEFAULT_MAX_POLL_ATTEMPTS6 = 240;
|
|
3412
3797
|
var QwenAdapter = class {
|
|
3413
3798
|
providerName = "qwen";
|
|
3414
3799
|
supportedTypes = ["image", "video"];
|
|
@@ -3417,7 +3802,7 @@ var QwenAdapter = class {
|
|
|
3417
3802
|
this.opts = opts;
|
|
3418
3803
|
}
|
|
3419
3804
|
get baseUrl() {
|
|
3420
|
-
return (this.opts.baseUrl ??
|
|
3805
|
+
return (this.opts.baseUrl ?? DEFAULT_BASE_URL7).replace(/\/$/, "");
|
|
3421
3806
|
}
|
|
3422
3807
|
async request(path, init) {
|
|
3423
3808
|
const headers = {
|
|
@@ -3615,7 +4000,7 @@ var QwenAdapter = class {
|
|
|
3615
4000
|
params,
|
|
3616
4001
|
submittedAt: new Date(startedAt).toISOString()
|
|
3617
4002
|
};
|
|
3618
|
-
const maxAttempts = this.opts.maxPollAttempts ??
|
|
4003
|
+
const maxAttempts = this.opts.maxPollAttempts ?? DEFAULT_MAX_POLL_ATTEMPTS6;
|
|
3619
4004
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
3620
4005
|
const snapshot = await this.completeJob(job);
|
|
3621
4006
|
if (snapshot.status === "failed") {
|
|
@@ -3624,7 +4009,7 @@ var QwenAdapter = class {
|
|
|
3624
4009
|
if (snapshot.status === "succeeded" && snapshot.result) {
|
|
3625
4010
|
return { ...snapshot.result, processingTimeMs: Date.now() - startedAt };
|
|
3626
4011
|
}
|
|
3627
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
4012
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS6));
|
|
3628
4013
|
}
|
|
3629
4014
|
return failure(
|
|
3630
4015
|
`DashScope task ${taskId} did not finish after ${maxAttempts} checks.`
|
|
@@ -3869,9 +4254,9 @@ var QwenAdapter = class {
|
|
|
3869
4254
|
};
|
|
3870
4255
|
|
|
3871
4256
|
// src/adapters/topaz.adapter.ts
|
|
3872
|
-
var
|
|
3873
|
-
var
|
|
3874
|
-
var
|
|
4257
|
+
var DEFAULT_BASE_URL8 = "https://api.topazlabs.com";
|
|
4258
|
+
var POLL_INTERVAL_MS7 = 5e3;
|
|
4259
|
+
var DEFAULT_MAX_POLL_ATTEMPTS7 = 240;
|
|
3875
4260
|
var DEFAULT_FPS = 30;
|
|
3876
4261
|
var PIXELS2 = {
|
|
3877
4262
|
"720p": { width: 1280, height: 720 },
|
|
@@ -3891,7 +4276,7 @@ var TopazAdapter = class {
|
|
|
3891
4276
|
this.opts = opts;
|
|
3892
4277
|
}
|
|
3893
4278
|
get baseUrl() {
|
|
3894
|
-
return (this.opts.baseUrl ??
|
|
4279
|
+
return (this.opts.baseUrl ?? DEFAULT_BASE_URL8).replace(/\/$/, "");
|
|
3895
4280
|
}
|
|
3896
4281
|
get headers() {
|
|
3897
4282
|
return {
|
|
@@ -4104,7 +4489,7 @@ var TopazAdapter = class {
|
|
|
4104
4489
|
params,
|
|
4105
4490
|
submittedAt: new Date(startedAt).toISOString()
|
|
4106
4491
|
};
|
|
4107
|
-
const maxAttempts = this.opts.maxPollAttempts ??
|
|
4492
|
+
const maxAttempts = this.opts.maxPollAttempts ?? DEFAULT_MAX_POLL_ATTEMPTS7;
|
|
4108
4493
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
4109
4494
|
const snapshot = await this.completeJob(job);
|
|
4110
4495
|
if (snapshot.status === "failed") {
|
|
@@ -4113,7 +4498,7 @@ var TopazAdapter = class {
|
|
|
4113
4498
|
if (snapshot.status === "succeeded" && snapshot.result) {
|
|
4114
4499
|
return { ...snapshot.result, processingTimeMs: Date.now() - startedAt };
|
|
4115
4500
|
}
|
|
4116
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
4501
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS7));
|
|
4117
4502
|
}
|
|
4118
4503
|
return failure(
|
|
4119
4504
|
`Topaz request ${submitted.taskId} did not finish after ${maxAttempts} checks.`
|
|
@@ -4279,7 +4664,7 @@ var TopazAdapter = class {
|
|
|
4279
4664
|
params,
|
|
4280
4665
|
submittedAt: new Date(startedAt).toISOString()
|
|
4281
4666
|
};
|
|
4282
|
-
const maxAttempts = this.opts.maxPollAttempts ??
|
|
4667
|
+
const maxAttempts = this.opts.maxPollAttempts ?? DEFAULT_MAX_POLL_ATTEMPTS7;
|
|
4283
4668
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
4284
4669
|
const snapshot = await this.completeJob(job);
|
|
4285
4670
|
if (snapshot.status === "failed") {
|
|
@@ -4288,7 +4673,7 @@ var TopazAdapter = class {
|
|
|
4288
4673
|
if (snapshot.status === "succeeded" && snapshot.result) {
|
|
4289
4674
|
return { ...snapshot.result, processingTimeMs: Date.now() - startedAt };
|
|
4290
4675
|
}
|
|
4291
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
4676
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS7));
|
|
4292
4677
|
}
|
|
4293
4678
|
return failure(
|
|
4294
4679
|
`Topaz image ${submitted.taskId} did not finish after ${maxAttempts} checks.`
|
|
@@ -4491,50 +4876,12 @@ async function persistOutputs(storage, outputs) {
|
|
|
4491
4876
|
);
|
|
4492
4877
|
}
|
|
4493
4878
|
|
|
4494
|
-
// src/lib/webhook.ts
|
|
4495
|
-
function resolveWebhook(value) {
|
|
4496
|
-
if (!value) return void 0;
|
|
4497
|
-
if (typeof value === "string") {
|
|
4498
|
-
return isHttpUrl(value) ? { url: value } : void 0;
|
|
4499
|
-
}
|
|
4500
|
-
if (!isHttpUrl(value.url)) return void 0;
|
|
4501
|
-
return {
|
|
4502
|
-
url: value.url,
|
|
4503
|
-
secret: value.secret,
|
|
4504
|
-
headers: value.headers
|
|
4505
|
-
};
|
|
4506
|
-
}
|
|
4507
|
-
function isHttpUrl(value) {
|
|
4508
|
-
try {
|
|
4509
|
-
const parsed = new URL(value);
|
|
4510
|
-
return parsed.protocol === "https:" || parsed.protocol === "http:";
|
|
4511
|
-
} catch {
|
|
4512
|
-
return false;
|
|
4513
|
-
}
|
|
4514
|
-
}
|
|
4515
|
-
async function deliverWebhook(config, payload) {
|
|
4516
|
-
try {
|
|
4517
|
-
await fetch(config.url, {
|
|
4518
|
-
method: "POST",
|
|
4519
|
-
headers: {
|
|
4520
|
-
"content-type": "application/json",
|
|
4521
|
-
"user-agent": "@brotu/ai",
|
|
4522
|
-
"x-brotu-event": payload.event,
|
|
4523
|
-
...config.secret ? { "x-brotu-webhook-secret": config.secret } : {},
|
|
4524
|
-
...config.headers
|
|
4525
|
-
},
|
|
4526
|
-
body: JSON.stringify(payload),
|
|
4527
|
-
signal: AbortSignal.timeout(1e4)
|
|
4528
|
-
});
|
|
4529
|
-
} catch {
|
|
4530
|
-
}
|
|
4531
|
-
}
|
|
4532
|
-
|
|
4533
4879
|
// src/client.ts
|
|
4534
4880
|
var NATIVE_PROVIDERS = [
|
|
4535
4881
|
"byteplus",
|
|
4536
4882
|
"elevenlabs",
|
|
4537
4883
|
"google",
|
|
4884
|
+
"kie",
|
|
4538
4885
|
"kling",
|
|
4539
4886
|
"openai",
|
|
4540
4887
|
"qwen",
|
|
@@ -4600,6 +4947,16 @@ function brotu(options) {
|
|
|
4600
4947
|
workspaceId: optionsWithKey.workspaceId
|
|
4601
4948
|
});
|
|
4602
4949
|
}
|
|
4950
|
+
if (provider.id === "kie") {
|
|
4951
|
+
return new KieAdapter({
|
|
4952
|
+
apiKey: provider.apiKey,
|
|
4953
|
+
baseUrl: provider.baseUrl,
|
|
4954
|
+
// The client-level webhook doubles as kie's callback, so a submit
|
|
4955
|
+
// never has to be polled. kie posts its own payload there — read it
|
|
4956
|
+
// with `parseKieCallback`.
|
|
4957
|
+
callbackUrl: registeredWebhook?.url
|
|
4958
|
+
});
|
|
4959
|
+
}
|
|
4603
4960
|
if (provider.id === "kling") {
|
|
4604
4961
|
return new KlingAdapter({
|
|
4605
4962
|
apiKey: provider.apiKey,
|
|
@@ -5131,6 +5488,7 @@ function brotu(options) {
|
|
|
5131
5488
|
KLING_CAPABILITIES,
|
|
5132
5489
|
KLING_CATALOG,
|
|
5133
5490
|
KLING_MODELS,
|
|
5491
|
+
KieAdapter,
|
|
5134
5492
|
KlingAdapter,
|
|
5135
5493
|
OPENAI_CATALOG,
|
|
5136
5494
|
OPENAI_IMAGE_MODELS,
|
|
@@ -5159,7 +5517,9 @@ function brotu(options) {
|
|
|
5159
5517
|
getProviders,
|
|
5160
5518
|
hasModel,
|
|
5161
5519
|
isPendingJob,
|
|
5520
|
+
kieSnapshot,
|
|
5162
5521
|
ok,
|
|
5522
|
+
parseKieCallback,
|
|
5163
5523
|
persistOutputs,
|
|
5164
5524
|
registerModels,
|
|
5165
5525
|
resetCatalog,
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export type { ElevenLabsAdapterOptions, ElevenLabsVoice, } from "./adapters/elev
|
|
|
6
6
|
export { ElevenLabsAdapter } from "./adapters/elevenlabs.adapter";
|
|
7
7
|
export type { GoogleAdapterOptions } from "./adapters/google.adapter";
|
|
8
8
|
export { GoogleAdapter } from "./adapters/google.adapter";
|
|
9
|
+
export type { KieAdapterOptions, KieTaskResult } from "./adapters/kie.adapter";
|
|
10
|
+
export { KieAdapter, kieSnapshot, parseKieCallback } from "./adapters/kie.adapter";
|
|
9
11
|
export type { KlingAdapterOptions } from "./adapters/kling.adapter";
|
|
10
12
|
export { KlingAdapter } from "./adapters/kling.adapter";
|
|
11
13
|
export type { OpenAIAdapterOptions } from "./adapters/openai.adapter";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,YAAY,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,YAAY,EACX,wBAAwB,EACxB,eAAe,GACf,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,YAAY,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AACnF,YAAY,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,YAAY,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,YAAY,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,YAAY,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,YAAY,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EACN,0BAA0B,EAC1B,qBAAqB,EACrB,cAAc,EACd,kBAAkB,EAClB,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,eAAe,GACf,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,mBAAmB,yBAAyB,CAAC;AAC7C,OAAO,EACN,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,IAAI,EACJ,KAAK,UAAU,EACf,EAAE,EACF,KAAK,MAAM,GACX,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACX,SAAS,EACT,MAAM,EACN,KAAK,EACL,SAAS,GACT,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,YAAY,EACZ,KAAK,GAAG,EACR,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,UAAU,GACV,MAAM,YAAY,CAAC;AACpB,OAAO,EACN,eAAe,EACf,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,OAAO,GACZ,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,cAAc,EACd,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,gBAAgB,GACrB,MAAM,eAAe,CAAC;AACvB,mBAAmB,gCAAgC,CAAC;AACpD,OAAO,EACN,gBAAgB,EAChB,eAAe,EACf,KAAK,oBAAoB,GACzB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACN,kBAAkB,EAClB,iBAAiB,EACjB,yBAAyB,GACzB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACN,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,GACnB,MAAM,2BAA2B,CAAC;AACnC,YAAY,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EACN,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,gBAAgB,GACrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACN,cAAc,EACd,mBAAmB,EACnB,kBAAkB,GAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACN,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,GACrB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACN,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,YAAY,GACjB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACX,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,gBAAgB,GAChB,MAAM,SAAS,CAAC"}
|