@unityclaw/sdk 1.0.5 → 1.0.8

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.js CHANGED
@@ -11,6 +11,8 @@ import {
11
11
 
12
12
  // src/client.ts
13
13
  import axios2, { AxiosError } from "axios";
14
+ import { basename as basename2, extname } from "path";
15
+ import { readFile, stat } from "fs/promises";
14
16
 
15
17
  // src/task-folder.ts
16
18
  import { mkdir, writeFile, appendFile, readdir } from "fs/promises";
@@ -210,7 +212,72 @@ var TaskFolderManager = class {
210
212
  }
211
213
  };
212
214
 
215
+ // src/apis/normalize.ts
216
+ function toTextFieldItems(input) {
217
+ if (input == null) return void 0;
218
+ if (typeof input === "string") {
219
+ return [{ type: "text", text: input }];
220
+ }
221
+ return input;
222
+ }
223
+ function toLabelFieldItem(input) {
224
+ if (input == null) return void 0;
225
+ if (typeof input === "object" && "value" in input && "label" in input) {
226
+ return input;
227
+ }
228
+ return {
229
+ value: input,
230
+ label: String(input)
231
+ };
232
+ }
233
+
213
234
  // src/apis/image.ts
235
+ var JIMENG_3K_SIZES = /* @__PURE__ */ new Set([
236
+ "3072x3072",
237
+ "2592x3456",
238
+ "3456x2592",
239
+ "4096x2304",
240
+ "2304x4096",
241
+ "3744x2496",
242
+ "2496x3744",
243
+ "4704x2016"
244
+ ]);
245
+ var JIMENG_4K_SIZES = /* @__PURE__ */ new Set([
246
+ "4096x4096",
247
+ "3520x4704",
248
+ "4704x3520",
249
+ "5504x3040",
250
+ "3040x5504",
251
+ "4992x3328",
252
+ "3328x4992",
253
+ "6240x2656"
254
+ ]);
255
+ function getSelectRawValue(input) {
256
+ if (input == null) return "";
257
+ if (typeof input === "object" && "value" in input) {
258
+ return String(input.value ?? "");
259
+ }
260
+ return String(input);
261
+ }
262
+ function validateJimengImageParams(params) {
263
+ const sizeValue = getSelectRawValue(params.size);
264
+ const modelValue = getSelectRawValue(params.model_selector) || params.model || "doubao-seedream-5-0-260128";
265
+ const webSearchValue = getSelectRawValue(params.web_search);
266
+ if (!sizeValue || !sizeValue.includes("x")) {
267
+ throw new Error(
268
+ `Invalid jimeng size "${sizeValue}". /api/jimeng/image expects 2K/3K/4K size values like "2048x2048", "3072x3072", "4096x4096".`
269
+ );
270
+ }
271
+ if (modelValue === "doubao-seedream-5-0-260128" && JIMENG_4K_SIZES.has(sizeValue)) {
272
+ throw new Error('Invalid jimeng params: model "doubao-seedream-5-0-260128" does not support 4K sizes.');
273
+ }
274
+ if (modelValue === "doubao-seedream-4-5-251128" && JIMENG_3K_SIZES.has(sizeValue)) {
275
+ throw new Error('Invalid jimeng params: model "doubao-seedream-4-5-251128" does not support 3K sizes.');
276
+ }
277
+ if (webSearchValue === "true" && modelValue === "doubao-seedream-4-5-251128") {
278
+ throw new Error('Invalid jimeng params: web_search=true is only supported by model "doubao-seedream-5-0-260128".');
279
+ }
280
+ }
214
281
  var ImageAPI = class {
215
282
  constructor(client) {
216
283
  this.client = client;
@@ -265,12 +332,13 @@ var ImageAPI = class {
265
332
  * ```
266
333
  */
267
334
  async jimeng(params) {
335
+ validateJimengImageParams(params);
268
336
  return this.client.request("/api/jimeng/image", {
269
- prompt: params.prompt,
337
+ prompt: toTextFieldItems(params.prompt),
270
338
  attachment: params.attachment,
271
- size: params.size,
272
- model_selector: params.model_selector,
273
- web_search: params.web_search,
339
+ size: toLabelFieldItem(params.size),
340
+ model_selector: toLabelFieldItem(params.model_selector),
341
+ web_search: toLabelFieldItem(params.web_search),
274
342
  image_count: params.image_count,
275
343
  model: params.model
276
344
  });
@@ -281,11 +349,11 @@ var ImageAPI = class {
281
349
  */
282
350
  async jimengV3(params) {
283
351
  return this.client.request("/api/jimeng/image/v3", {
284
- prompt: params.prompt,
352
+ prompt: toTextFieldItems(params.prompt),
285
353
  attachment: params.attachment,
286
- size: params.size,
287
- model_selector: params.model_selector,
288
- web_search: params.web_search,
354
+ size: toLabelFieldItem(params.size),
355
+ model_selector: toLabelFieldItem(params.model_selector),
356
+ web_search: toLabelFieldItem(params.web_search),
289
357
  image_count: params.image_count,
290
358
  model: params.model
291
359
  });
@@ -303,6 +371,17 @@ var ImageAPI = class {
303
371
  };
304
372
 
305
373
  // src/apis/video.ts
374
+ function toNumericDurationLabelFieldItem(input) {
375
+ const item = toLabelFieldItem(input);
376
+ if (!item) return void 0;
377
+ if (typeof item.value === "string" && /^-?\d+(\.\d+)?$/.test(item.value)) {
378
+ return {
379
+ value: Number(item.value),
380
+ label: item.label
381
+ };
382
+ }
383
+ return item;
384
+ }
306
385
  var VideoAPI = class {
307
386
  constructor(client) {
308
387
  this.client = client;
@@ -323,8 +402,8 @@ var VideoAPI = class {
323
402
  async sora(params) {
324
403
  return this.client.request("/api/sora/video", {
325
404
  attachment: params.attachment,
326
- prompt: params.prompt,
327
- orientation: params.orientation
405
+ prompt: toTextFieldItems(params.prompt),
406
+ orientation: toLabelFieldItem(params.orientation)
328
407
  });
329
408
  }
330
409
  /**
@@ -334,9 +413,9 @@ var VideoAPI = class {
334
413
  async soraStable(params) {
335
414
  return this.client.request("/api/sora/video/stable", {
336
415
  attachment: params.attachment,
337
- prompt: params.prompt,
338
- size: params.size,
339
- seconds: params.seconds
416
+ prompt: toTextFieldItems(params.prompt),
417
+ size: toLabelFieldItem(params.size),
418
+ seconds: toLabelFieldItem(params.seconds)
340
419
  });
341
420
  }
342
421
  /**
@@ -354,13 +433,13 @@ var VideoAPI = class {
354
433
  */
355
434
  async veo(params) {
356
435
  return this.client.request("/api/veo/video", {
357
- prompt: params.prompt,
436
+ prompt: toTextFieldItems(params.prompt),
358
437
  attachment: params.attachment,
359
438
  first_frame: params.first_frame,
360
439
  last_frame: params.last_frame,
361
- aspect_ratio: params.aspect_ratio,
362
- resolution: params.resolution,
363
- duration: params.duration
440
+ aspect_ratio: toLabelFieldItem(params.aspect_ratio),
441
+ resolution: toLabelFieldItem(params.resolution),
442
+ duration: toLabelFieldItem(params.duration)
364
443
  });
365
444
  }
366
445
  /**
@@ -380,10 +459,10 @@ var VideoAPI = class {
380
459
  async kling(params) {
381
460
  return this.client.request("/api/kling/video", {
382
461
  attachment: params.attachment,
383
- prompt: params.prompt,
384
- aspect_ratio: params.aspect_ratio,
385
- duration: params.duration,
386
- model: params.model
462
+ prompt: toTextFieldItems(params.prompt),
463
+ aspect_ratio: toLabelFieldItem(params.aspect_ratio),
464
+ duration: toLabelFieldItem(params.duration),
465
+ model: toLabelFieldItem(params.model)
387
466
  });
388
467
  }
389
468
  /**
@@ -401,10 +480,10 @@ var VideoAPI = class {
401
480
  */
402
481
  async jimeng(params) {
403
482
  return this.client.request("/api/jimeng/video", {
404
- action: params.action,
483
+ action: toLabelFieldItem(params.action),
405
484
  attachment: params.attachment,
406
- prompt: params.prompt,
407
- aspect_ratio: params.aspect_ratio
485
+ prompt: toTextFieldItems(params.prompt),
486
+ aspect_ratio: toLabelFieldItem(params.aspect_ratio)
408
487
  });
409
488
  }
410
489
  /**
@@ -422,12 +501,12 @@ var VideoAPI = class {
422
501
  */
423
502
  async doubao(params) {
424
503
  return this.client.request("/api/doubao/video", {
425
- action: params.action,
504
+ action: toLabelFieldItem(params.action),
426
505
  attachment: params.attachment,
427
- prompt: params.prompt,
428
- resolution: params.resolution,
429
- ratio: params.ratio,
430
- duration: params.duration
506
+ prompt: toTextFieldItems(params.prompt),
507
+ resolution: toLabelFieldItem(params.resolution),
508
+ ratio: toLabelFieldItem(params.ratio),
509
+ duration: toNumericDurationLabelFieldItem(params.duration)
431
510
  });
432
511
  }
433
512
  /**
@@ -447,11 +526,11 @@ var VideoAPI = class {
447
526
  async wan(params) {
448
527
  return this.client.request("/api/wan/video", {
449
528
  attachment: params.attachment,
450
- prompt: params.prompt,
451
- size: params.size,
452
- duration: params.duration,
453
- model: params.model,
454
- shot_type: params.shot_type
529
+ prompt: toTextFieldItems(params.prompt),
530
+ size: toLabelFieldItem(params.size),
531
+ duration: toLabelFieldItem(params.duration),
532
+ model: toLabelFieldItem(params.model),
533
+ shot_type: toLabelFieldItem(params.shot_type)
455
534
  });
456
535
  }
457
536
  /**
@@ -470,10 +549,10 @@ var VideoAPI = class {
470
549
  async minimax(params) {
471
550
  return this.client.request("/api/minimax/video", {
472
551
  attachment: params.attachment,
473
- prompt: params.prompt,
474
- size: params.size,
475
- duration: params.duration,
476
- model: params.model
552
+ prompt: toTextFieldItems(params.prompt),
553
+ size: toLabelFieldItem(params.size),
554
+ duration: toLabelFieldItem(params.duration),
555
+ model: toLabelFieldItem(params.model)
477
556
  });
478
557
  }
479
558
  };
@@ -505,114 +584,73 @@ var DocumentAPI = class {
505
584
  });
506
585
  }
507
586
  /**
508
- * Convert image to Word document
509
- * @see /api/doc_convert/image2word
587
+ * Generic document conversion (recommended entrypoint).
588
+ * Uses /api/doc_convert/image or /api/doc_convert/pdf based on input_format.
589
+ */
590
+ async convertDocument(params) {
591
+ const isPdfInput = String(
592
+ typeof params.input_format === "object" && params.input_format !== null && "value" in params.input_format ? params.input_format.value : params.input_format ?? ""
593
+ ).toLowerCase() === "pdf";
594
+ const endpoint = isPdfInput ? "/api/doc_convert/pdf" : "/api/doc_convert/image";
595
+ return this.client.request(endpoint, {
596
+ attachment: params.attachment,
597
+ input_format: params.input_format,
598
+ output_format: params.output_format
599
+ });
600
+ }
601
+ /**
602
+ * @deprecated Use convertDocument({ input_format: 'image', output_format: 'docx' })
510
603
  */
511
604
  async image2Word(params) {
512
- return this.client.request(
513
- "/api/doc_convert/image2word",
514
- {
515
- attachment: params.attachment
516
- }
517
- );
605
+ return this.convertDocument({ attachment: params.attachment, input_format: "image", output_format: "docx" });
518
606
  }
519
607
  /**
520
- * Convert image to PowerPoint
521
- * @see /api/doc_convert/image2ppt
608
+ * @deprecated Use convertDocument({ input_format: 'image', output_format: 'pptx' })
522
609
  */
523
610
  async image2Ppt(params) {
524
- return this.client.request(
525
- "/api/doc_convert/image2ppt",
526
- {
527
- attachment: params.attachment
528
- }
529
- );
611
+ return this.convertDocument({ attachment: params.attachment, input_format: "image", output_format: "pptx" });
530
612
  }
531
613
  /**
532
- * Convert image to Excel
533
- * @see /api/doc_convert/image2excel
614
+ * @deprecated Use convertDocument({ input_format: 'image', output_format: 'xlsx' })
534
615
  */
535
616
  async image2Excel(params) {
536
- return this.client.request(
537
- "/api/doc_convert/image2excel",
538
- {
539
- attachment: params.attachment
540
- }
541
- );
617
+ return this.convertDocument({ attachment: params.attachment, input_format: "image", output_format: "xlsx" });
542
618
  }
543
619
  /**
544
- * Convert image to PDF
545
- * @see /api/doc_convert/image2pdf
620
+ * @deprecated Use convertDocument({ input_format: 'image', output_format: 'pdf' })
546
621
  */
547
622
  async image2Pdf(params) {
548
- return this.client.request(
549
- "/api/doc_convert/image2pdf",
550
- {
551
- attachment: params.attachment
552
- }
553
- );
623
+ return this.convertDocument({ attachment: params.attachment, input_format: "image", output_format: "pdf" });
554
624
  }
555
625
  /**
556
- * Convert PDF to Word document
557
- * @see /api/doc_convert/pdf2word
626
+ * @deprecated Use convertDocument({ input_format: 'pdf', output_format: 'docx' })
558
627
  */
559
628
  async pdf2Word(params) {
560
- return this.client.request(
561
- "/api/doc_convert/pdf2word",
562
- {
563
- attachment: params.attachment
564
- }
565
- );
629
+ return this.convertDocument({ attachment: params.attachment, input_format: "pdf", output_format: "docx" });
566
630
  }
567
631
  /**
568
- * Convert PDF to PowerPoint
569
- * @see /api/doc_convert/pdf2ppt
632
+ * @deprecated Use convertDocument({ input_format: 'pdf', output_format: 'pptx' })
570
633
  */
571
634
  async pdf2Ppt(params) {
572
- return this.client.request(
573
- "/api/doc_convert/pdf2ppt",
574
- {
575
- attachment: params.attachment
576
- }
577
- );
635
+ return this.convertDocument({ attachment: params.attachment, input_format: "pdf", output_format: "pptx" });
578
636
  }
579
637
  /**
580
- * Convert PDF to Excel
581
- * @see /api/doc_convert/pdf2excel
638
+ * @deprecated Use convertDocument({ input_format: 'pdf', output_format: 'xlsx' })
582
639
  */
583
640
  async pdf2Excel(params) {
584
- return this.client.request(
585
- "/api/doc_convert/pdf2excel",
586
- {
587
- attachment: params.attachment
588
- }
589
- );
641
+ return this.convertDocument({ attachment: params.attachment, input_format: "pdf", output_format: "xlsx" });
590
642
  }
591
643
  /**
592
- * Convert PDF to image
593
- * @see /api/doc_convert/pdf2image
644
+ * @deprecated Use convertDocument({ input_format: 'pdf', output_format: 'image' })
594
645
  */
595
646
  async pdf2Image(params) {
596
- return this.client.request(
597
- "/api/doc_convert/pdf2image",
598
- {
599
- attachment: params.attachment
600
- }
601
- );
647
+ return this.convertDocument({ attachment: params.attachment, input_format: "pdf", output_format: "image" });
602
648
  }
603
649
  /**
604
- * Generic document conversion
605
- * @see /api/doc_convert/image
606
- * @see /api/doc_convert/pdf
650
+ * Backward-compatible alias of convertDocument().
607
651
  */
608
652
  async convert(params) {
609
- const isImage = params.input_format === "image" || !params.input_format;
610
- const endpoint = isImage ? "/api/doc_convert/image" : "/api/doc_convert/pdf";
611
- return this.client.request(endpoint, {
612
- attachment: params.attachment,
613
- input_format: params.input_format,
614
- output_format: params.output_format
615
- });
653
+ return this.convertDocument(params);
616
654
  }
617
655
  };
618
656
 
@@ -686,13 +724,124 @@ var MediaAPI = class {
686
724
  url: [{ link: params.url, type: "url" }]
687
725
  });
688
726
  }
727
+ /**
728
+ * Fetch media stats from social video links.
729
+ * @see /api/media_stats
730
+ */
731
+ async stats(params) {
732
+ return this.client.request("/api/media_stats", {
733
+ link: params.link
734
+ });
735
+ }
736
+ /**
737
+ * Fetch media user profile information from homepage links.
738
+ * @see /api/media_user_info
739
+ */
740
+ async userInfo(params) {
741
+ return this.client.request("/api/media_user_info", {
742
+ link: params.link
743
+ });
744
+ }
745
+ /**
746
+ * Download Xiaohongshu media links.
747
+ * @see /api/xiaohongshu/download
748
+ */
749
+ async downloadXiaohongshu(params) {
750
+ return this.client.request("/api/xiaohongshu/download", {
751
+ url: params.url
752
+ });
753
+ }
754
+ /**
755
+ * Extract one frame from video attachment.
756
+ * @see /api/video/frame
757
+ */
758
+ async extractFrame(params) {
759
+ return this.client.request("/api/video/frame", {
760
+ attachment: params.attachment,
761
+ frame_option: toLabelFieldItem(params.frame_option),
762
+ frame: params.frame
763
+ });
764
+ }
765
+ };
766
+
767
+ // src/apis/idp.ts
768
+ var IDPAPI = class {
769
+ constructor(client) {
770
+ this.client = client;
771
+ }
772
+ /**
773
+ * Generic IDP extraction call.
774
+ * @see /api/idp/{type}
775
+ */
776
+ async extract(type, params) {
777
+ return this.client.request(`/api/idp/${type}`, {
778
+ attachments: params.attachments
779
+ });
780
+ }
781
+ async bankCard(params) {
782
+ return this.extract("bank_card", params);
783
+ }
784
+ async vehicleLicense(params) {
785
+ return this.extract("vehicle_license", params);
786
+ }
787
+ async trainInvoice(params) {
788
+ return this.extract("train_invoice", params);
789
+ }
790
+ async taxiInvoice(params) {
791
+ return this.extract("taxi_invoice", params);
792
+ }
793
+ async idCard(params) {
794
+ return this.extract("id_card", params);
795
+ }
796
+ async vatInvoice(params) {
797
+ return this.extract("vat_invoice", params);
798
+ }
799
+ async businessLicense(params) {
800
+ return this.extract("business_license", params);
801
+ }
802
+ async businessCard(params) {
803
+ return this.extract("business_card", params);
804
+ }
805
+ async contract(params) {
806
+ return this.extract("contract", params);
807
+ }
689
808
  };
690
809
 
691
810
  // src/client.ts
692
811
  var DEFAULT_BASE_URL = "https://unityclaw.com";
693
- var DEFAULT_TIMEOUT = 3e5;
812
+ var DEFAULT_TIMEOUT = 9e5;
694
813
  var OLD_DOMAINS = ["fieldshortcut.cn", "fieldshortcut.com"];
695
814
  var NEW_DOMAIN = "unityclaw.com";
815
+ var MIME_BY_EXT = {
816
+ ".jpg": "image/jpeg",
817
+ ".jpeg": "image/jpeg",
818
+ ".png": "image/png",
819
+ ".gif": "image/gif",
820
+ ".webp": "image/webp",
821
+ ".bmp": "image/bmp",
822
+ ".heic": "image/heic",
823
+ ".heif": "image/heif",
824
+ ".mp4": "video/mp4",
825
+ ".mov": "video/quicktime",
826
+ ".avi": "video/x-msvideo",
827
+ ".webm": "video/webm",
828
+ ".m4a": "audio/mp4",
829
+ ".mp3": "audio/mpeg",
830
+ ".wav": "audio/wav",
831
+ ".aac": "audio/aac",
832
+ ".flac": "audio/flac",
833
+ ".pdf": "application/pdf",
834
+ ".doc": "application/msword",
835
+ ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
836
+ ".xls": "application/vnd.ms-excel",
837
+ ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
838
+ ".ppt": "application/vnd.ms-powerpoint",
839
+ ".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
840
+ ".txt": "text/plain",
841
+ ".md": "text/markdown",
842
+ ".csv": "text/csv",
843
+ ".json": "application/json"
844
+ };
696
845
  function replaceOldDomains(text) {
697
846
  if (!text || typeof text !== "string") return text;
698
847
  let result = text;
@@ -701,6 +850,49 @@ function replaceOldDomains(text) {
701
850
  }
702
851
  return result;
703
852
  }
853
+ function isRecord(value) {
854
+ return !!value && typeof value === "object" && !Array.isArray(value);
855
+ }
856
+ function getLocalPathCandidate(value) {
857
+ const candidates = [value.path, value.localPath, value.filePath];
858
+ for (const candidate of candidates) {
859
+ if (typeof candidate === "string" && candidate.trim()) {
860
+ return candidate.trim();
861
+ }
862
+ }
863
+ return void 0;
864
+ }
865
+ function inferMimeType(filePath, provided) {
866
+ if (typeof provided === "string" && provided.trim()) {
867
+ return provided.trim();
868
+ }
869
+ const ext = extname(filePath).toLowerCase();
870
+ return MIME_BY_EXT[ext] ?? "application/octet-stream";
871
+ }
872
+ function isDownloadableResponseItem(item) {
873
+ if (!item.content || typeof item.content !== "string") return false;
874
+ return /^https?:\/\//i.test(item.content);
875
+ }
876
+ function buildMultipartBody(fileBuffer, fieldName, filename, contentType) {
877
+ const boundary = `----UnityClawBoundary${Math.random().toString(16).slice(2)}`;
878
+ const chunks = [
879
+ Buffer.from(`--${boundary}\r
880
+ `),
881
+ Buffer.from(`Content-Disposition: form-data; name="${fieldName}"; filename="${filename}"\r
882
+ `),
883
+ Buffer.from(`Content-Type: ${contentType}\r
884
+ \r
885
+ `),
886
+ fileBuffer,
887
+ Buffer.from(`\r
888
+ --${boundary}--\r
889
+ `)
890
+ ];
891
+ return {
892
+ body: Buffer.concat(chunks),
893
+ contentType: `multipart/form-data; boundary=${boundary}`
894
+ };
895
+ }
704
896
  var UnityClawClient = class {
705
897
  config;
706
898
  httpClient;
@@ -710,6 +902,7 @@ var UnityClawClient = class {
710
902
  video;
711
903
  document;
712
904
  media;
905
+ idp;
713
906
  constructor(config = {}) {
714
907
  const fileConfig = loadConfig();
715
908
  const apiKey = config.apiKey ?? process.env.UNITYCLAW_API_KEY ?? fileConfig.apiKey ?? "";
@@ -723,6 +916,7 @@ var UnityClawClient = class {
723
916
  taskDir: config.taskDir ?? fileConfig.taskDir ?? DEFAULT_TASKS_DIR,
724
917
  timeout: config.timeout ?? DEFAULT_TIMEOUT,
725
918
  downloadAttachments: config.downloadAttachments ?? true,
919
+ autoUploadLocalFiles: config.autoUploadLocalFiles ?? true,
726
920
  context: config.context ?? {}
727
921
  };
728
922
  this.httpClient = axios2.create({
@@ -730,7 +924,8 @@ var UnityClawClient = class {
730
924
  timeout: this.config.timeout,
731
925
  headers: {
732
926
  "Content-Type": "application/json",
733
- "X-Api-Key": this.config.apiKey
927
+ "X-Api-Key": this.config.apiKey,
928
+ "X-Source": "unityclaw"
734
929
  }
735
930
  });
736
931
  this.taskFolderManager = new TaskFolderManager({
@@ -741,6 +936,7 @@ var UnityClawClient = class {
741
936
  this.video = new VideoAPI(this);
742
937
  this.document = new DocumentAPI(this);
743
938
  this.media = new MediaAPI(this);
939
+ this.idp = new IDPAPI(this);
744
940
  }
745
941
  /**
746
942
  * Get the underlying HTTP client for custom requests
@@ -799,13 +995,14 @@ var UnityClawClient = class {
799
995
  const taskCtx = await this.taskFolderManager.createTaskFolder();
800
996
  try {
801
997
  await this.taskFolderManager.log(taskCtx, "info", `Starting request to ${endpoint}`);
998
+ const normalizedParams = await this.normalizeParams(params, taskCtx);
802
999
  const context = this.buildContext(contextOverrides);
803
1000
  const requestBody = {
804
- formItemParams: params,
1001
+ formItemParams: normalizedParams,
805
1002
  context
806
1003
  };
807
- await this.taskFolderManager.writeRequest(taskCtx, endpoint, params, context);
808
- await this.taskFolderManager.log(taskCtx, "info", "Request prepared", { endpoint, params });
1004
+ await this.taskFolderManager.writeRequest(taskCtx, endpoint, normalizedParams, context);
1005
+ await this.taskFolderManager.log(taskCtx, "info", "Request prepared", { endpoint, params: normalizedParams });
809
1006
  const response = await this.httpClient.post(endpoint, requestBody);
810
1007
  if (response.data.msg) {
811
1008
  response.data.msg = replaceOldDomains(response.data.msg);
@@ -819,7 +1016,7 @@ var UnityClawClient = class {
819
1016
  for (const item of response.data.data) {
820
1017
  if (item && typeof item === "object" && "content" in item && "contentType" in item) {
821
1018
  const attachmentItem = item;
822
- if (attachmentItem.contentType === "attachment/url" && attachmentItem.content) {
1019
+ if (isDownloadableResponseItem(attachmentItem)) {
823
1020
  const localPath = await this.taskFolderManager.downloadAttachment(taskCtx, {
824
1021
  tmp_url: attachmentItem.content,
825
1022
  name: attachmentItem.name
@@ -849,6 +1046,61 @@ var UnityClawClient = class {
849
1046
  return await this.taskFolderManager.finalizeTaskFolder(taskCtx, errorResponse, false);
850
1047
  }
851
1048
  }
1049
+ async uploadLocalFile(filePath, original) {
1050
+ const file = await readFile(filePath);
1051
+ const st = await stat(filePath);
1052
+ const filename = typeof original?.name === "string" && original.name.trim() ? original.name.trim() : basename2(filePath);
1053
+ const type = inferMimeType(filePath, original?.type);
1054
+ const { body, contentType } = buildMultipartBody(file, "file", filename, type);
1055
+ const uploadResponse = await this.httpClient.post("/api/upload", body, {
1056
+ headers: {
1057
+ "Content-Type": contentType,
1058
+ "Content-Length": body.length.toString()
1059
+ }
1060
+ });
1061
+ if (uploadResponse.data.code !== 0 || !uploadResponse.data.data) {
1062
+ const message = uploadResponse.data.msg || "upload failed";
1063
+ throw new Error(`Upload failed for ${filePath}: ${message}`);
1064
+ }
1065
+ return {
1066
+ tmp_url: uploadResponse.data.data,
1067
+ name: filename,
1068
+ type,
1069
+ size: Number.isFinite(st.size) ? st.size : void 0
1070
+ };
1071
+ }
1072
+ async normalizeParams(params, taskCtx) {
1073
+ if (!this.config.autoUploadLocalFiles) {
1074
+ return params;
1075
+ }
1076
+ const walk = async (value) => {
1077
+ if (Array.isArray(value)) {
1078
+ const output2 = [];
1079
+ for (const item of value) {
1080
+ output2.push(await walk(item));
1081
+ }
1082
+ return output2;
1083
+ }
1084
+ if (!isRecord(value)) {
1085
+ return value;
1086
+ }
1087
+ if (typeof value.tmp_url === "string" && value.tmp_url.trim()) {
1088
+ return value;
1089
+ }
1090
+ const localPath = getLocalPathCandidate(value);
1091
+ if (localPath) {
1092
+ await this.taskFolderManager.log(taskCtx, "info", "Uploading local attachment", { localPath });
1093
+ return this.uploadLocalFile(localPath, value);
1094
+ }
1095
+ const output = {};
1096
+ for (const [k, v] of Object.entries(value)) {
1097
+ output[k] = await walk(v);
1098
+ }
1099
+ return output;
1100
+ };
1101
+ const normalized = await walk(params);
1102
+ return isRecord(normalized) ? normalized : params;
1103
+ }
852
1104
  // ==================== Convenience Methods ====================
853
1105
  /**
854
1106
  * Generate image using Gemini API
@@ -900,16 +1152,125 @@ var UnityClawClient = class {
900
1152
  return this.media.analyze(params);
901
1153
  }
902
1154
  };
1155
+
1156
+ // src/types.ts
1157
+ var GEMINI_IMAGE_ASPECT_RATIOS = [
1158
+ "1:1",
1159
+ "9:16",
1160
+ "16:9",
1161
+ "4:3",
1162
+ "3:4",
1163
+ "3:2",
1164
+ "2:3",
1165
+ "5:4",
1166
+ "4:5",
1167
+ "21:9",
1168
+ "1:4",
1169
+ "1:8",
1170
+ "4:1",
1171
+ "8:1"
1172
+ ];
1173
+ var GEMINI_IMAGE_SIZES = ["1K", "2K", "4K", "1K_pro", "2K_pro", "4K_pro"];
1174
+ var JIMENG_IMAGE_MODELS = ["doubao-seedream-5-0-260128", "doubao-seedream-4-5-251128"];
1175
+ var JIMENG_IMAGE_SIZES = [
1176
+ "2048x2048",
1177
+ "1728x2304",
1178
+ "2304x1728",
1179
+ "2848x1600",
1180
+ "1600x2848",
1181
+ "2496x1664",
1182
+ "1664x2496",
1183
+ "3136x1344",
1184
+ "3072x3072",
1185
+ "2592x3456",
1186
+ "3456x2592",
1187
+ "4096x2304",
1188
+ "2304x4096",
1189
+ "3744x2496",
1190
+ "2496x3744",
1191
+ "4704x2016",
1192
+ "4096x4096",
1193
+ "3520x4704",
1194
+ "4704x3520",
1195
+ "5504x3040",
1196
+ "3040x5504",
1197
+ "4992x3328",
1198
+ "3328x4992",
1199
+ "6240x2656"
1200
+ ];
1201
+ var JIMENG_IMAGE_WEB_SEARCH_OPTIONS = ["true", "false"];
1202
+ var KLING_MODELS = [
1203
+ "kling-v1",
1204
+ "kling-v1-5",
1205
+ "kling-v1-6",
1206
+ "kling-v2-master",
1207
+ "kling-v2-1",
1208
+ "kling-v2-1-master",
1209
+ "kling-v2-5-turbo",
1210
+ "kling-v2-6"
1211
+ ];
1212
+ var KLING_ASPECT_RATIOS = ["16:9", "9:16", "1:1"];
1213
+ var KLING_DURATIONS = ["5", "10"];
1214
+ var WAN_DEFAULT_MODELS = ["wan2.6-t2v", "wan2.6-i2v", "wan2.6-i2v-flash", "wan2.6-r2v"];
1215
+ var WAN_SHOT_TYPES = ["single", "multi"];
1216
+ var DOC_CONVERT_INPUT_FORMATS = ["image", "pdf"];
1217
+ var DOC_CONVERT_OUTPUT_FORMATS = ["docx", "pptx", "xlsx", "pdf", "image"];
1218
+ var DOC_TRANSLATE_LANGUAGE_CODES = [
1219
+ "en",
1220
+ "zh",
1221
+ "zh-TW",
1222
+ "ja",
1223
+ "ko",
1224
+ "es",
1225
+ "fr",
1226
+ "de",
1227
+ "pt",
1228
+ "ru",
1229
+ "ar",
1230
+ "it",
1231
+ "nl",
1232
+ "pl",
1233
+ "tr",
1234
+ "vi",
1235
+ "th",
1236
+ "id"
1237
+ ];
1238
+ var IDP_TYPES = [
1239
+ "bank_card",
1240
+ "vehicle_license",
1241
+ "train_invoice",
1242
+ "taxi_invoice",
1243
+ "id_card",
1244
+ "vat_invoice",
1245
+ "business_license",
1246
+ "business_card",
1247
+ "contract"
1248
+ ];
903
1249
  export {
904
1250
  CONFIG_DIR,
905
1251
  CONFIG_FILE,
906
1252
  DEFAULT_TASKS_DIR,
1253
+ DOC_CONVERT_INPUT_FORMATS,
1254
+ DOC_CONVERT_OUTPUT_FORMATS,
1255
+ DOC_TRANSLATE_LANGUAGE_CODES,
907
1256
  DocumentAPI,
1257
+ GEMINI_IMAGE_ASPECT_RATIOS,
1258
+ GEMINI_IMAGE_SIZES,
1259
+ IDPAPI,
1260
+ IDP_TYPES,
908
1261
  ImageAPI,
1262
+ JIMENG_IMAGE_MODELS,
1263
+ JIMENG_IMAGE_SIZES,
1264
+ JIMENG_IMAGE_WEB_SEARCH_OPTIONS,
1265
+ KLING_ASPECT_RATIOS,
1266
+ KLING_DURATIONS,
1267
+ KLING_MODELS,
909
1268
  MediaAPI,
910
1269
  TaskFolderManager,
911
1270
  UnityClawClient,
912
1271
  VideoAPI,
1272
+ WAN_DEFAULT_MODELS,
1273
+ WAN_SHOT_TYPES,
913
1274
  getConfigPath,
914
1275
  getConfigValue,
915
1276
  loadConfig,