@unityclaw/sdk 1.0.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/dist/index.cjs +937 -0
- package/dist/index.d.cts +799 -0
- package/dist/index.d.ts +799 -0
- package/dist/index.js +902 -0
- package/package.json +55 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,937 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
DocumentAPI: () => DocumentAPI,
|
|
34
|
+
ImageAPI: () => ImageAPI,
|
|
35
|
+
MediaAPI: () => MediaAPI,
|
|
36
|
+
TaskFolderManager: () => TaskFolderManager,
|
|
37
|
+
UnityClawClient: () => UnityClawClient,
|
|
38
|
+
VideoAPI: () => VideoAPI
|
|
39
|
+
});
|
|
40
|
+
module.exports = __toCommonJS(index_exports);
|
|
41
|
+
|
|
42
|
+
// src/client.ts
|
|
43
|
+
var import_axios2 = __toESM(require("axios"), 1);
|
|
44
|
+
|
|
45
|
+
// src/task-folder.ts
|
|
46
|
+
var import_promises = require("fs/promises");
|
|
47
|
+
var import_fs = require("fs");
|
|
48
|
+
var import_path = require("path");
|
|
49
|
+
var import_date_fns = require("date-fns");
|
|
50
|
+
var import_uuid = require("uuid");
|
|
51
|
+
var import_axios = __toESM(require("axios"), 1);
|
|
52
|
+
var TaskFolderManager = class {
|
|
53
|
+
options;
|
|
54
|
+
constructor(options) {
|
|
55
|
+
this.options = options;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Create a new task folder with timestamp and unique ID
|
|
59
|
+
*/
|
|
60
|
+
async createTaskFolder() {
|
|
61
|
+
const timestamp = (0, import_date_fns.format)(/* @__PURE__ */ new Date(), "yyyyMMdd_HHmmss");
|
|
62
|
+
const taskId = (0, import_uuid.v4)().slice(0, 8);
|
|
63
|
+
const folderName = `${timestamp}_${taskId}`;
|
|
64
|
+
const folderPath = (0, import_path.join)(this.options.taskDir, folderName);
|
|
65
|
+
const attachmentsPath = (0, import_path.join)(folderPath, "attachments");
|
|
66
|
+
const logsPath = (0, import_path.join)(folderPath, "logs");
|
|
67
|
+
await (0, import_promises.mkdir)(attachmentsPath, { recursive: true });
|
|
68
|
+
await (0, import_promises.mkdir)(logsPath, { recursive: true });
|
|
69
|
+
return {
|
|
70
|
+
taskId,
|
|
71
|
+
folderPath,
|
|
72
|
+
attachmentsPath,
|
|
73
|
+
logsPath,
|
|
74
|
+
startTime: Date.now(),
|
|
75
|
+
logs: [],
|
|
76
|
+
downloadedFiles: []
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Log a message to the task folder
|
|
81
|
+
*/
|
|
82
|
+
async log(ctx, level, message, data) {
|
|
83
|
+
const logEntry = {
|
|
84
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
85
|
+
level,
|
|
86
|
+
message,
|
|
87
|
+
data
|
|
88
|
+
};
|
|
89
|
+
ctx.logs.push(logEntry);
|
|
90
|
+
const logFile = (0, import_path.join)(ctx.logsPath, "execution.log");
|
|
91
|
+
const logLine = `${logEntry.timestamp} [${level.toUpperCase()}] ${message}${data ? "\n" + JSON.stringify(data, null, 2) : ""}
|
|
92
|
+
`;
|
|
93
|
+
await (0, import_promises.appendFile)(logFile, logLine, "utf-8");
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Download an attachment from URL to local folder
|
|
97
|
+
* Important: Downloads attachments to avoid tmp_url expiration
|
|
98
|
+
*/
|
|
99
|
+
async downloadAttachment(ctx, attachment) {
|
|
100
|
+
if (!this.options.downloadAttachments || !attachment.tmp_url) {
|
|
101
|
+
return attachment.tmp_url;
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
const url = attachment.tmp_url;
|
|
105
|
+
const urlPath = url.split("?")[0];
|
|
106
|
+
const baseName = urlPath ? (0, import_path.basename)(urlPath) : "";
|
|
107
|
+
const filename = attachment.name || baseName || `file_${Date.now()}`;
|
|
108
|
+
const localPath = (0, import_path.join)(ctx.attachmentsPath, filename);
|
|
109
|
+
const response = await import_axios.default.get(url, {
|
|
110
|
+
responseType: "arraybuffer",
|
|
111
|
+
timeout: 6e4
|
|
112
|
+
});
|
|
113
|
+
await (0, import_promises.writeFile)(localPath, Buffer.from(response.data));
|
|
114
|
+
ctx.downloadedFiles.push(localPath);
|
|
115
|
+
return localPath;
|
|
116
|
+
} catch (error) {
|
|
117
|
+
await this.log(ctx, "warn", `Failed to download attachment: ${attachment.name}`, {
|
|
118
|
+
error: error instanceof Error ? error.message : error
|
|
119
|
+
});
|
|
120
|
+
return attachment.tmp_url;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Download multiple attachments
|
|
125
|
+
*/
|
|
126
|
+
async downloadAttachments(ctx, attachments) {
|
|
127
|
+
const results = [];
|
|
128
|
+
for (const attachment of attachments) {
|
|
129
|
+
const localPath = await this.downloadAttachment(ctx, attachment);
|
|
130
|
+
if (localPath) {
|
|
131
|
+
results.push(localPath);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return results;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Write request details to task folder
|
|
138
|
+
*/
|
|
139
|
+
async writeRequest(ctx, endpoint, params, context) {
|
|
140
|
+
const requestFile = (0, import_path.join)(ctx.logsPath, "request.json");
|
|
141
|
+
await (0, import_promises.writeFile)(
|
|
142
|
+
requestFile,
|
|
143
|
+
JSON.stringify(
|
|
144
|
+
{
|
|
145
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
146
|
+
endpoint,
|
|
147
|
+
params,
|
|
148
|
+
context
|
|
149
|
+
},
|
|
150
|
+
null,
|
|
151
|
+
2
|
|
152
|
+
),
|
|
153
|
+
"utf-8"
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Write response details to task folder
|
|
158
|
+
*/
|
|
159
|
+
async writeResponse(ctx, response) {
|
|
160
|
+
const responseFile = (0, import_path.join)(ctx.logsPath, "response.json");
|
|
161
|
+
await (0, import_promises.writeFile)(responseFile, JSON.stringify(response, null, 2), "utf-8");
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Finalize task folder and return result
|
|
165
|
+
*/
|
|
166
|
+
async finalizeTaskFolder(ctx, response, success) {
|
|
167
|
+
const duration = Date.now() - ctx.startTime;
|
|
168
|
+
const summaryFile = (0, import_path.join)(ctx.logsPath, "summary.json");
|
|
169
|
+
await (0, import_promises.writeFile)(
|
|
170
|
+
summaryFile,
|
|
171
|
+
JSON.stringify(
|
|
172
|
+
{
|
|
173
|
+
taskId: ctx.taskId,
|
|
174
|
+
success,
|
|
175
|
+
duration,
|
|
176
|
+
startTime: new Date(ctx.startTime).toISOString(),
|
|
177
|
+
endTime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
178
|
+
logsCount: ctx.logs.length,
|
|
179
|
+
attachmentsCount: ctx.downloadedFiles.length
|
|
180
|
+
},
|
|
181
|
+
null,
|
|
182
|
+
2
|
|
183
|
+
),
|
|
184
|
+
"utf-8"
|
|
185
|
+
);
|
|
186
|
+
return {
|
|
187
|
+
taskId: ctx.taskId,
|
|
188
|
+
success,
|
|
189
|
+
response,
|
|
190
|
+
duration,
|
|
191
|
+
taskFolder: ctx.folderPath,
|
|
192
|
+
logs: ctx.logs,
|
|
193
|
+
attachments: ctx.downloadedFiles
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Clean up old task folders (optional utility)
|
|
198
|
+
*/
|
|
199
|
+
async cleanOldFolders(maxAge) {
|
|
200
|
+
if (!(0, import_fs.existsSync)(this.options.taskDir)) {
|
|
201
|
+
return 0;
|
|
202
|
+
}
|
|
203
|
+
const now = Date.now();
|
|
204
|
+
const folders = await (0, import_promises.readdir)(this.options.taskDir, { withFileTypes: true });
|
|
205
|
+
let deletedCount = 0;
|
|
206
|
+
for (const folder of folders) {
|
|
207
|
+
if (!folder.isDirectory()) continue;
|
|
208
|
+
const folderPath = (0, import_path.join)(this.options.taskDir, folder.name);
|
|
209
|
+
const { rm } = await import("fs/promises");
|
|
210
|
+
const match = folder.name.match(/^(\d{8}_\d{6})/);
|
|
211
|
+
if (match && match[1]) {
|
|
212
|
+
try {
|
|
213
|
+
const folderDate = new Date(
|
|
214
|
+
match[1].replace(/(\d{4})(\d{2})(\d{2})_(\d{2})(\d{2})(\d{2})/, "$1-$2-$3T$4:$5:$6")
|
|
215
|
+
);
|
|
216
|
+
if (now - folderDate.getTime() > maxAge) {
|
|
217
|
+
await rm(folderPath, { recursive: true });
|
|
218
|
+
deletedCount++;
|
|
219
|
+
}
|
|
220
|
+
} catch {
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return deletedCount;
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
// src/apis/image.ts
|
|
229
|
+
var ImageAPI = class {
|
|
230
|
+
constructor(client) {
|
|
231
|
+
this.client = client;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Generate image using Gemini API
|
|
235
|
+
* @see /api/gemini/image
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* ```typescript
|
|
239
|
+
* const result = await client.image.gemini({
|
|
240
|
+
* prompt: 'A beautiful sunset over mountains',
|
|
241
|
+
* size: { value: '2K', label: '2K' }
|
|
242
|
+
* });
|
|
243
|
+
* ```
|
|
244
|
+
*/
|
|
245
|
+
async gemini(params) {
|
|
246
|
+
const taskResult = await this.client.request("/api/gemini/image", {
|
|
247
|
+
prompt: params.prompt,
|
|
248
|
+
attachment: params.attachment,
|
|
249
|
+
model: params.model,
|
|
250
|
+
aspect_ratio: params.aspect_ratio,
|
|
251
|
+
size: params.size
|
|
252
|
+
});
|
|
253
|
+
return taskResult.response;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Generate image using Gemini API v2
|
|
257
|
+
* @see /api/gemini/image/v2
|
|
258
|
+
*/
|
|
259
|
+
async geminiV2(params) {
|
|
260
|
+
const taskResult = await this.client.request("/api/gemini/image/v2", {
|
|
261
|
+
prompt: params.prompt,
|
|
262
|
+
attachment: params.attachment,
|
|
263
|
+
model: params.model,
|
|
264
|
+
aspect_ratio: params.aspect_ratio,
|
|
265
|
+
size: params.size
|
|
266
|
+
});
|
|
267
|
+
return taskResult.response;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Generate image using JiMeng (Doubao) API
|
|
271
|
+
* @see /api/jimeng/image
|
|
272
|
+
*
|
|
273
|
+
* @example
|
|
274
|
+
* ```typescript
|
|
275
|
+
* const result = await client.image.jimeng({
|
|
276
|
+
* prompt: '一只可爱的猫咪',
|
|
277
|
+
* size: { value: '1024x1024', label: '1:1' }
|
|
278
|
+
* });
|
|
279
|
+
* ```
|
|
280
|
+
*/
|
|
281
|
+
async jimeng(params) {
|
|
282
|
+
const taskResult = await this.client.request("/api/jimeng/image", {
|
|
283
|
+
prompt: params.prompt,
|
|
284
|
+
attachment: params.attachment,
|
|
285
|
+
size: params.size,
|
|
286
|
+
model_selector: params.model_selector,
|
|
287
|
+
web_search: params.web_search,
|
|
288
|
+
image_count: params.image_count,
|
|
289
|
+
model: params.model
|
|
290
|
+
});
|
|
291
|
+
return taskResult.response;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Generate image using JiMeng V3 API
|
|
295
|
+
* @see /api/jimeng/image/v3
|
|
296
|
+
*/
|
|
297
|
+
async jimengV3(params) {
|
|
298
|
+
const taskResult = await this.client.request("/api/jimeng/image/v3", {
|
|
299
|
+
prompt: params.prompt,
|
|
300
|
+
attachment: params.attachment,
|
|
301
|
+
size: params.size,
|
|
302
|
+
model_selector: params.model_selector,
|
|
303
|
+
web_search: params.web_search,
|
|
304
|
+
image_count: params.image_count,
|
|
305
|
+
model: params.model
|
|
306
|
+
});
|
|
307
|
+
return taskResult.response;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Compress image
|
|
311
|
+
* @see /api/image/compress
|
|
312
|
+
*/
|
|
313
|
+
async compress(params) {
|
|
314
|
+
const taskResult = await this.client.request("/api/image/compress", {
|
|
315
|
+
attachment: params.attachment,
|
|
316
|
+
quality: params.quality
|
|
317
|
+
});
|
|
318
|
+
return taskResult.response;
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
// src/apis/video.ts
|
|
323
|
+
var VideoAPI = class {
|
|
324
|
+
constructor(client) {
|
|
325
|
+
this.client = client;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Generate video using Sora API
|
|
329
|
+
* @see /api/sora/video
|
|
330
|
+
*
|
|
331
|
+
* @example
|
|
332
|
+
* ```typescript
|
|
333
|
+
* const result = await client.video.sora({
|
|
334
|
+
* prompt: 'A cat playing piano',
|
|
335
|
+
* orientation: { value: 'landscape', label: 'Landscape' }
|
|
336
|
+
* });
|
|
337
|
+
* ```
|
|
338
|
+
*/
|
|
339
|
+
async sora(params) {
|
|
340
|
+
const taskResult = await this.client.request("/api/sora/video", {
|
|
341
|
+
attachment: params.attachment,
|
|
342
|
+
prompt: params.prompt,
|
|
343
|
+
orientation: params.orientation
|
|
344
|
+
});
|
|
345
|
+
return taskResult.response;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Generate video using Sora Stable API
|
|
349
|
+
* @see /api/sora/video/stable
|
|
350
|
+
*/
|
|
351
|
+
async soraStable(params) {
|
|
352
|
+
const taskResult = await this.client.request("/api/sora/video/stable", {
|
|
353
|
+
attachment: params.attachment,
|
|
354
|
+
prompt: params.prompt,
|
|
355
|
+
size: params.size,
|
|
356
|
+
seconds: params.seconds
|
|
357
|
+
});
|
|
358
|
+
return taskResult.response;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Generate video using Veo API
|
|
362
|
+
* @see /api/veo/video
|
|
363
|
+
*
|
|
364
|
+
* @example
|
|
365
|
+
* ```typescript
|
|
366
|
+
* const result = await client.video.veo({
|
|
367
|
+
* prompt: 'A beautiful sunset over the ocean',
|
|
368
|
+
* aspect_ratio: { value: '16:9', label: '16:9' },
|
|
369
|
+
* duration: { value: '8', label: '8s' }
|
|
370
|
+
* });
|
|
371
|
+
* ```
|
|
372
|
+
*/
|
|
373
|
+
async veo(params) {
|
|
374
|
+
const taskResult = await this.client.request("/api/veo/video", {
|
|
375
|
+
prompt: params.prompt,
|
|
376
|
+
attachment: params.attachment,
|
|
377
|
+
first_frame: params.first_frame,
|
|
378
|
+
last_frame: params.last_frame,
|
|
379
|
+
aspect_ratio: params.aspect_ratio,
|
|
380
|
+
resolution: params.resolution,
|
|
381
|
+
duration: params.duration
|
|
382
|
+
});
|
|
383
|
+
return taskResult.response;
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Generate video using Kling API
|
|
387
|
+
* @see /api/kling/video
|
|
388
|
+
*
|
|
389
|
+
* @example
|
|
390
|
+
* ```typescript
|
|
391
|
+
* const result = await client.video.kling({
|
|
392
|
+
* prompt: 'A dog running in the park',
|
|
393
|
+
* aspect_ratio: { value: '16:9', label: '16:9' },
|
|
394
|
+
* duration: { value: '5', label: '5s' },
|
|
395
|
+
* model: { value: 'kling-v1', label: 'V1' }
|
|
396
|
+
* });
|
|
397
|
+
* ```
|
|
398
|
+
*/
|
|
399
|
+
async kling(params) {
|
|
400
|
+
const taskResult = await this.client.request("/api/kling/video", {
|
|
401
|
+
attachment: params.attachment,
|
|
402
|
+
prompt: params.prompt,
|
|
403
|
+
aspect_ratio: params.aspect_ratio,
|
|
404
|
+
duration: params.duration,
|
|
405
|
+
model: params.model
|
|
406
|
+
});
|
|
407
|
+
return taskResult.response;
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Generate video using JiMeng API
|
|
411
|
+
* @see /api/jimeng/video
|
|
412
|
+
*
|
|
413
|
+
* @example
|
|
414
|
+
* ```typescript
|
|
415
|
+
* const result = await client.video.jimeng({
|
|
416
|
+
* action: { value: 't2v', label: 'Text to Video' },
|
|
417
|
+
* prompt: 'A beautiful landscape',
|
|
418
|
+
* aspect_ratio: { value: '16:9', label: '16:9' }
|
|
419
|
+
* });
|
|
420
|
+
* ```
|
|
421
|
+
*/
|
|
422
|
+
async jimeng(params) {
|
|
423
|
+
const taskResult = await this.client.request("/api/jimeng/video", {
|
|
424
|
+
action: params.action,
|
|
425
|
+
attachment: params.attachment,
|
|
426
|
+
prompt: params.prompt,
|
|
427
|
+
aspect_ratio: params.aspect_ratio
|
|
428
|
+
});
|
|
429
|
+
return taskResult.response;
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Generate video using Doubao API
|
|
433
|
+
* @see /api/doubao/video
|
|
434
|
+
*
|
|
435
|
+
* @example
|
|
436
|
+
* ```typescript
|
|
437
|
+
* const result = await client.video.doubao({
|
|
438
|
+
* prompt: 'A cinematic drone shot of mountains',
|
|
439
|
+
* resolution: { value: '1080p', label: '1080p' },
|
|
440
|
+
* ratio: { value: '16:9', label: '16:9' }
|
|
441
|
+
* });
|
|
442
|
+
* ```
|
|
443
|
+
*/
|
|
444
|
+
async doubao(params) {
|
|
445
|
+
const taskResult = await this.client.request("/api/doubao/video", {
|
|
446
|
+
action: params.action,
|
|
447
|
+
attachment: params.attachment,
|
|
448
|
+
prompt: params.prompt,
|
|
449
|
+
resolution: params.resolution,
|
|
450
|
+
ratio: params.ratio,
|
|
451
|
+
duration: params.duration
|
|
452
|
+
});
|
|
453
|
+
return taskResult.response;
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Generate video using Wan API (Alibaba)
|
|
457
|
+
* @see /api/wan/video
|
|
458
|
+
*
|
|
459
|
+
* @example
|
|
460
|
+
* ```typescript
|
|
461
|
+
* const result = await client.video.wan({
|
|
462
|
+
* prompt: 'A futuristic city at night',
|
|
463
|
+
* size: { value: '1280*720', label: '720p' },
|
|
464
|
+
* duration: { value: '5', label: '5s' },
|
|
465
|
+
* model: { value: 'wan2.6-t2v', label: 'Wan 2.6' }
|
|
466
|
+
* });
|
|
467
|
+
* ```
|
|
468
|
+
*/
|
|
469
|
+
async wan(params) {
|
|
470
|
+
const taskResult = await this.client.request("/api/wan/video", {
|
|
471
|
+
attachment: params.attachment,
|
|
472
|
+
prompt: params.prompt,
|
|
473
|
+
size: params.size,
|
|
474
|
+
duration: params.duration,
|
|
475
|
+
model: params.model,
|
|
476
|
+
shot_type: params.shot_type
|
|
477
|
+
});
|
|
478
|
+
return taskResult.response;
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Generate video using MiniMax API
|
|
482
|
+
* @see /api/minimax/video
|
|
483
|
+
*
|
|
484
|
+
* @example
|
|
485
|
+
* ```typescript
|
|
486
|
+
* const result = await client.video.minimax({
|
|
487
|
+
* prompt: 'A person walking through a forest',
|
|
488
|
+
* size: { value: '1360*768', label: '768p' },
|
|
489
|
+
* model: { value: 'MiniMax-Hailuo-2.3', label: 'Hailuo 2.3' }
|
|
490
|
+
* });
|
|
491
|
+
* ```
|
|
492
|
+
*/
|
|
493
|
+
async minimax(params) {
|
|
494
|
+
const taskResult = await this.client.request("/api/minimax/video", {
|
|
495
|
+
attachment: params.attachment,
|
|
496
|
+
prompt: params.prompt,
|
|
497
|
+
size: params.size,
|
|
498
|
+
duration: params.duration,
|
|
499
|
+
model: params.model
|
|
500
|
+
});
|
|
501
|
+
return taskResult.response;
|
|
502
|
+
}
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
// src/apis/document.ts
|
|
506
|
+
var DocumentAPI = class {
|
|
507
|
+
constructor(client) {
|
|
508
|
+
this.client = client;
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Translate document
|
|
512
|
+
* @see /api/doc/translate
|
|
513
|
+
*
|
|
514
|
+
* @example
|
|
515
|
+
* ```typescript
|
|
516
|
+
* const result = await client.document.translate({
|
|
517
|
+
* attachment: [{ tmp_url: 'https://...', name: 'document.pdf' }],
|
|
518
|
+
* source_language: { value: 'en', label: 'English' },
|
|
519
|
+
* target_language: { value: 'zh', label: 'Chinese' }
|
|
520
|
+
* });
|
|
521
|
+
* ```
|
|
522
|
+
*/
|
|
523
|
+
async translate(params) {
|
|
524
|
+
const taskResult = await this.client.request("/api/doc/translate", {
|
|
525
|
+
attachment: params.attachment,
|
|
526
|
+
source_language: params.source_language,
|
|
527
|
+
target_language: params.target_language
|
|
528
|
+
});
|
|
529
|
+
return taskResult.response;
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* Convert image to Word document
|
|
533
|
+
* @see /api/doc_convert/image2word
|
|
534
|
+
*/
|
|
535
|
+
async image2Word(params) {
|
|
536
|
+
const taskResult = await this.client.request(
|
|
537
|
+
"/api/doc_convert/image2word",
|
|
538
|
+
{
|
|
539
|
+
attachment: params.attachment
|
|
540
|
+
}
|
|
541
|
+
);
|
|
542
|
+
return taskResult.response;
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Convert image to PowerPoint
|
|
546
|
+
* @see /api/doc_convert/image2ppt
|
|
547
|
+
*/
|
|
548
|
+
async image2Ppt(params) {
|
|
549
|
+
const taskResult = await this.client.request(
|
|
550
|
+
"/api/doc_convert/image2ppt",
|
|
551
|
+
{
|
|
552
|
+
attachment: params.attachment
|
|
553
|
+
}
|
|
554
|
+
);
|
|
555
|
+
return taskResult.response;
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Convert image to Excel
|
|
559
|
+
* @see /api/doc_convert/image2excel
|
|
560
|
+
*/
|
|
561
|
+
async image2Excel(params) {
|
|
562
|
+
const taskResult = await this.client.request(
|
|
563
|
+
"/api/doc_convert/image2excel",
|
|
564
|
+
{
|
|
565
|
+
attachment: params.attachment
|
|
566
|
+
}
|
|
567
|
+
);
|
|
568
|
+
return taskResult.response;
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Convert image to PDF
|
|
572
|
+
* @see /api/doc_convert/image2pdf
|
|
573
|
+
*/
|
|
574
|
+
async image2Pdf(params) {
|
|
575
|
+
const taskResult = await this.client.request(
|
|
576
|
+
"/api/doc_convert/image2pdf",
|
|
577
|
+
{
|
|
578
|
+
attachment: params.attachment
|
|
579
|
+
}
|
|
580
|
+
);
|
|
581
|
+
return taskResult.response;
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* Convert PDF to Word document
|
|
585
|
+
* @see /api/doc_convert/pdf2word
|
|
586
|
+
*/
|
|
587
|
+
async pdf2Word(params) {
|
|
588
|
+
const taskResult = await this.client.request(
|
|
589
|
+
"/api/doc_convert/pdf2word",
|
|
590
|
+
{
|
|
591
|
+
attachment: params.attachment
|
|
592
|
+
}
|
|
593
|
+
);
|
|
594
|
+
return taskResult.response;
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* Convert PDF to PowerPoint
|
|
598
|
+
* @see /api/doc_convert/pdf2ppt
|
|
599
|
+
*/
|
|
600
|
+
async pdf2Ppt(params) {
|
|
601
|
+
const taskResult = await this.client.request(
|
|
602
|
+
"/api/doc_convert/pdf2ppt",
|
|
603
|
+
{
|
|
604
|
+
attachment: params.attachment
|
|
605
|
+
}
|
|
606
|
+
);
|
|
607
|
+
return taskResult.response;
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* Convert PDF to Excel
|
|
611
|
+
* @see /api/doc_convert/pdf2excel
|
|
612
|
+
*/
|
|
613
|
+
async pdf2Excel(params) {
|
|
614
|
+
const taskResult = await this.client.request(
|
|
615
|
+
"/api/doc_convert/pdf2excel",
|
|
616
|
+
{
|
|
617
|
+
attachment: params.attachment
|
|
618
|
+
}
|
|
619
|
+
);
|
|
620
|
+
return taskResult.response;
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Convert PDF to image
|
|
624
|
+
* @see /api/doc_convert/pdf2image
|
|
625
|
+
*/
|
|
626
|
+
async pdf2Image(params) {
|
|
627
|
+
const taskResult = await this.client.request(
|
|
628
|
+
"/api/doc_convert/pdf2image",
|
|
629
|
+
{
|
|
630
|
+
attachment: params.attachment
|
|
631
|
+
}
|
|
632
|
+
);
|
|
633
|
+
return taskResult.response;
|
|
634
|
+
}
|
|
635
|
+
/**
|
|
636
|
+
* Generic document conversion
|
|
637
|
+
* @see /api/doc_convert/image
|
|
638
|
+
* @see /api/doc_convert/pdf
|
|
639
|
+
*/
|
|
640
|
+
async convert(params) {
|
|
641
|
+
const isImage = params.input_format === "image" || !params.input_format;
|
|
642
|
+
const endpoint = isImage ? "/api/doc_convert/image" : "/api/doc_convert/pdf";
|
|
643
|
+
const taskResult = await this.client.request(endpoint, {
|
|
644
|
+
attachment: params.attachment,
|
|
645
|
+
input_format: params.input_format,
|
|
646
|
+
output_format: params.output_format
|
|
647
|
+
});
|
|
648
|
+
return taskResult.response;
|
|
649
|
+
}
|
|
650
|
+
};
|
|
651
|
+
|
|
652
|
+
// src/apis/media.ts
|
|
653
|
+
var MediaAPI = class {
|
|
654
|
+
constructor(client) {
|
|
655
|
+
this.client = client;
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* Analyze media (video/audio) from URL or file
|
|
659
|
+
* @see /api/media_analysis
|
|
660
|
+
*
|
|
661
|
+
* @example
|
|
662
|
+
* ```typescript
|
|
663
|
+
* // Analyze from URL
|
|
664
|
+
* const result = await client.media.analyze({
|
|
665
|
+
* url: [{ link: 'https://youtube.com/watch?v=...' }]
|
|
666
|
+
* });
|
|
667
|
+
*
|
|
668
|
+
* // Analyze from uploaded file
|
|
669
|
+
* const result = await client.media.analyze({
|
|
670
|
+
* url: [{ tmp_url: 'https://...', type: 'video/mp4', name: 'video.mp4' }]
|
|
671
|
+
* });
|
|
672
|
+
* ```
|
|
673
|
+
*/
|
|
674
|
+
async analyze(params) {
|
|
675
|
+
const taskResult = await this.client.request("/api/media_analysis", {
|
|
676
|
+
url: params.url
|
|
677
|
+
});
|
|
678
|
+
return taskResult.response;
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Analyze video file directly
|
|
682
|
+
* @see /api/video_analysis (internal)
|
|
683
|
+
*
|
|
684
|
+
* @example
|
|
685
|
+
* ```typescript
|
|
686
|
+
* const result = await client.media.analyzeVideo({
|
|
687
|
+
* file: { tmp_url: 'https://...', type: 'video/mp4', name: 'video.mp4' },
|
|
688
|
+
* prompt: 'Summarize this video'
|
|
689
|
+
* });
|
|
690
|
+
* ```
|
|
691
|
+
*/
|
|
692
|
+
async analyzeVideo(params) {
|
|
693
|
+
const taskResult = await this.client.request("/api/media_analysis", {
|
|
694
|
+
url: [
|
|
695
|
+
{
|
|
696
|
+
tmp_url: params.file.tmp_url,
|
|
697
|
+
type: params.file.type,
|
|
698
|
+
name: params.file.name,
|
|
699
|
+
size: params.file.size
|
|
700
|
+
}
|
|
701
|
+
]
|
|
702
|
+
});
|
|
703
|
+
return taskResult.response;
|
|
704
|
+
}
|
|
705
|
+
/**
|
|
706
|
+
* Analyze social media video (TikTok, YouTube, etc.)
|
|
707
|
+
* @see /api/media_analysis
|
|
708
|
+
*
|
|
709
|
+
* @example
|
|
710
|
+
* ```typescript
|
|
711
|
+
* const result = await client.media.analyzeSocialVideo({
|
|
712
|
+
* url: 'https://www.tiktok.com/@user/video/123456'
|
|
713
|
+
* });
|
|
714
|
+
* ```
|
|
715
|
+
*/
|
|
716
|
+
async analyzeSocialVideo(params) {
|
|
717
|
+
const taskResult = await this.client.request("/api/media_analysis", {
|
|
718
|
+
url: [{ link: params.url, type: "url" }]
|
|
719
|
+
});
|
|
720
|
+
return taskResult.response;
|
|
721
|
+
}
|
|
722
|
+
};
|
|
723
|
+
|
|
724
|
+
// src/client.ts
|
|
725
|
+
var DEFAULT_BASE_URL = "https://unityclaw.com";
|
|
726
|
+
var DEFAULT_TIMEOUT = 3e5;
|
|
727
|
+
var UnityClawClient = class {
|
|
728
|
+
config;
|
|
729
|
+
httpClient;
|
|
730
|
+
taskFolderManager;
|
|
731
|
+
// API modules
|
|
732
|
+
image;
|
|
733
|
+
video;
|
|
734
|
+
document;
|
|
735
|
+
media;
|
|
736
|
+
constructor(config = {}) {
|
|
737
|
+
const apiKey = config.apiKey ?? process.env.UNITYCLAW_API_KEY ?? "";
|
|
738
|
+
const baseUrl = config.baseUrl ?? process.env.UNITYCLAW_BASE_URL ?? DEFAULT_BASE_URL;
|
|
739
|
+
if (!apiKey) {
|
|
740
|
+
throw new Error("API key is required. Set UNITYCLAW_API_KEY environment variable or pass apiKey in config.");
|
|
741
|
+
}
|
|
742
|
+
this.config = {
|
|
743
|
+
apiKey,
|
|
744
|
+
baseUrl,
|
|
745
|
+
taskDir: config.taskDir ?? (() => {
|
|
746
|
+
const path = require("path");
|
|
747
|
+
const os = require("os");
|
|
748
|
+
try {
|
|
749
|
+
return path.join(process.cwd(), "tasks");
|
|
750
|
+
} catch {
|
|
751
|
+
return path.join(os.homedir(), "tasks");
|
|
752
|
+
}
|
|
753
|
+
})(),
|
|
754
|
+
timeout: config.timeout ?? DEFAULT_TIMEOUT,
|
|
755
|
+
downloadAttachments: config.downloadAttachments ?? true,
|
|
756
|
+
context: config.context ?? {}
|
|
757
|
+
};
|
|
758
|
+
this.httpClient = import_axios2.default.create({
|
|
759
|
+
baseURL: this.config.baseUrl,
|
|
760
|
+
timeout: this.config.timeout,
|
|
761
|
+
headers: {
|
|
762
|
+
"Content-Type": "application/json",
|
|
763
|
+
"X-Api-Key": this.config.apiKey
|
|
764
|
+
}
|
|
765
|
+
});
|
|
766
|
+
this.taskFolderManager = new TaskFolderManager({
|
|
767
|
+
taskDir: this.config.taskDir,
|
|
768
|
+
downloadAttachments: this.config.downloadAttachments
|
|
769
|
+
});
|
|
770
|
+
this.image = new ImageAPI(this);
|
|
771
|
+
this.video = new VideoAPI(this);
|
|
772
|
+
this.document = new DocumentAPI(this);
|
|
773
|
+
this.media = new MediaAPI(this);
|
|
774
|
+
}
|
|
775
|
+
/**
|
|
776
|
+
* Get the underlying HTTP client for custom requests
|
|
777
|
+
*/
|
|
778
|
+
getHttpClient() {
|
|
779
|
+
return this.httpClient;
|
|
780
|
+
}
|
|
781
|
+
/**
|
|
782
|
+
* Get the task folder manager
|
|
783
|
+
*/
|
|
784
|
+
getTaskFolderManager() {
|
|
785
|
+
return this.taskFolderManager;
|
|
786
|
+
}
|
|
787
|
+
/**
|
|
788
|
+
* Get current configuration
|
|
789
|
+
*/
|
|
790
|
+
getConfig() {
|
|
791
|
+
return this.config;
|
|
792
|
+
}
|
|
793
|
+
/**
|
|
794
|
+
* Build context object from config defaults
|
|
795
|
+
*/
|
|
796
|
+
buildContext(overrides) {
|
|
797
|
+
const now = Date.now();
|
|
798
|
+
const defaultContext = {
|
|
799
|
+
logID: `sdk_${now}_${Math.random().toString(36).slice(2, 10)}`,
|
|
800
|
+
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
801
|
+
baseID: "",
|
|
802
|
+
tableID: "",
|
|
803
|
+
bitable: {
|
|
804
|
+
logID: `sdk_${now}`,
|
|
805
|
+
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
806
|
+
baseID: "",
|
|
807
|
+
tableID: ""
|
|
808
|
+
},
|
|
809
|
+
tenantKey: "",
|
|
810
|
+
userID: this.config.context.userID ?? "",
|
|
811
|
+
packID: "",
|
|
812
|
+
extensionID: "sdk",
|
|
813
|
+
baseSignature: "",
|
|
814
|
+
baseOwnerID: this.config.context.userID ?? ""
|
|
815
|
+
};
|
|
816
|
+
if (this.config.context) {
|
|
817
|
+
Object.assign(defaultContext, this.config.context);
|
|
818
|
+
}
|
|
819
|
+
if (overrides) {
|
|
820
|
+
Object.assign(defaultContext, overrides);
|
|
821
|
+
}
|
|
822
|
+
return defaultContext;
|
|
823
|
+
}
|
|
824
|
+
/**
|
|
825
|
+
* Make a request to the UnityClaw API
|
|
826
|
+
* This is the core method that handles task folder creation, logging, and error handling
|
|
827
|
+
*/
|
|
828
|
+
async request(endpoint, params, contextOverrides) {
|
|
829
|
+
const taskCtx = await this.taskFolderManager.createTaskFolder();
|
|
830
|
+
try {
|
|
831
|
+
await this.taskFolderManager.log(taskCtx, "info", `Starting request to ${endpoint}`);
|
|
832
|
+
const context = this.buildContext(contextOverrides);
|
|
833
|
+
const requestBody = {
|
|
834
|
+
formItemParams: params,
|
|
835
|
+
context
|
|
836
|
+
};
|
|
837
|
+
await this.taskFolderManager.writeRequest(taskCtx, endpoint, params, context);
|
|
838
|
+
await this.taskFolderManager.log(taskCtx, "info", "Request prepared", { endpoint, params });
|
|
839
|
+
const response = await this.httpClient.post(endpoint, requestBody);
|
|
840
|
+
await this.taskFolderManager.writeResponse(taskCtx, response.data);
|
|
841
|
+
await this.taskFolderManager.log(taskCtx, "info", "Response received", {
|
|
842
|
+
code: response.data.code,
|
|
843
|
+
hasData: !!response.data.data
|
|
844
|
+
});
|
|
845
|
+
if (response.data.data && Array.isArray(response.data.data)) {
|
|
846
|
+
for (const item of response.data.data) {
|
|
847
|
+
if (item && typeof item === "object" && "content" in item && "contentType" in item) {
|
|
848
|
+
const attachmentItem = item;
|
|
849
|
+
if (attachmentItem.contentType === "attachment/url" && attachmentItem.content) {
|
|
850
|
+
const localPath = await this.taskFolderManager.downloadAttachment(taskCtx, {
|
|
851
|
+
tmp_url: attachmentItem.content,
|
|
852
|
+
name: attachmentItem.name
|
|
853
|
+
});
|
|
854
|
+
if (localPath) {
|
|
855
|
+
attachmentItem.localPath = localPath;
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
return await this.taskFolderManager.finalizeTaskFolder(
|
|
862
|
+
taskCtx,
|
|
863
|
+
response.data,
|
|
864
|
+
response.data.code === 0
|
|
865
|
+
);
|
|
866
|
+
} catch (error) {
|
|
867
|
+
const errorMessage = error instanceof import_axios2.AxiosError ? error.response?.data?.msg || error.message : error instanceof Error ? error.message : String(error);
|
|
868
|
+
await this.taskFolderManager.log(taskCtx, "error", `Request failed: ${errorMessage}`, {
|
|
869
|
+
error: error instanceof import_axios2.AxiosError ? { status: error.response?.status, data: error.response?.data } : error
|
|
870
|
+
});
|
|
871
|
+
const errorResponse = {
|
|
872
|
+
code: -1,
|
|
873
|
+
msg: errorMessage
|
|
874
|
+
};
|
|
875
|
+
return await this.taskFolderManager.finalizeTaskFolder(taskCtx, errorResponse, false);
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
// ==================== Convenience Methods ====================
|
|
879
|
+
/**
|
|
880
|
+
* Generate image using Gemini API
|
|
881
|
+
* @deprecated Use client.image.gemini() instead
|
|
882
|
+
*/
|
|
883
|
+
async generateImage(params) {
|
|
884
|
+
return this.image.gemini(params);
|
|
885
|
+
}
|
|
886
|
+
/**
|
|
887
|
+
* Generate image using JiMeng API
|
|
888
|
+
* @deprecated Use client.image.jimeng() instead
|
|
889
|
+
*/
|
|
890
|
+
async generateJiMengImage(params) {
|
|
891
|
+
return this.image.jimeng(params);
|
|
892
|
+
}
|
|
893
|
+
/**
|
|
894
|
+
* Generate video using Sora API
|
|
895
|
+
* @deprecated Use client.video.sora() instead
|
|
896
|
+
*/
|
|
897
|
+
async generateSoraVideo(params) {
|
|
898
|
+
return this.video.sora(params);
|
|
899
|
+
}
|
|
900
|
+
/**
|
|
901
|
+
* Generate video using Veo API
|
|
902
|
+
* @deprecated Use client.video.veo() instead
|
|
903
|
+
*/
|
|
904
|
+
async generateVeoVideo(params) {
|
|
905
|
+
return this.video.veo(params);
|
|
906
|
+
}
|
|
907
|
+
/**
|
|
908
|
+
* Generate video using Kling API
|
|
909
|
+
* @deprecated Use client.video.kling() instead
|
|
910
|
+
*/
|
|
911
|
+
async generateKlingVideo(params) {
|
|
912
|
+
return this.video.kling(params);
|
|
913
|
+
}
|
|
914
|
+
/**
|
|
915
|
+
* Translate document
|
|
916
|
+
* @deprecated Use client.document.translate() instead
|
|
917
|
+
*/
|
|
918
|
+
async translateDocument(params) {
|
|
919
|
+
return this.document.translate(params);
|
|
920
|
+
}
|
|
921
|
+
/**
|
|
922
|
+
* Analyze media (video/audio from URL)
|
|
923
|
+
* @deprecated Use client.media.analyze() instead
|
|
924
|
+
*/
|
|
925
|
+
async analyzeMedia(params) {
|
|
926
|
+
return this.media.analyze(params);
|
|
927
|
+
}
|
|
928
|
+
};
|
|
929
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
930
|
+
0 && (module.exports = {
|
|
931
|
+
DocumentAPI,
|
|
932
|
+
ImageAPI,
|
|
933
|
+
MediaAPI,
|
|
934
|
+
TaskFolderManager,
|
|
935
|
+
UnityClawClient,
|
|
936
|
+
VideoAPI
|
|
937
|
+
});
|