@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 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
+ });