@unityclaw/sdk 1.0.6 → 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.cjs CHANGED
@@ -33,12 +33,27 @@ __export(index_exports, {
33
33
  CONFIG_DIR: () => CONFIG_DIR,
34
34
  CONFIG_FILE: () => CONFIG_FILE,
35
35
  DEFAULT_TASKS_DIR: () => DEFAULT_TASKS_DIR,
36
+ DOC_CONVERT_INPUT_FORMATS: () => DOC_CONVERT_INPUT_FORMATS,
37
+ DOC_CONVERT_OUTPUT_FORMATS: () => DOC_CONVERT_OUTPUT_FORMATS,
38
+ DOC_TRANSLATE_LANGUAGE_CODES: () => DOC_TRANSLATE_LANGUAGE_CODES,
36
39
  DocumentAPI: () => DocumentAPI,
40
+ GEMINI_IMAGE_ASPECT_RATIOS: () => GEMINI_IMAGE_ASPECT_RATIOS,
41
+ GEMINI_IMAGE_SIZES: () => GEMINI_IMAGE_SIZES,
42
+ IDPAPI: () => IDPAPI,
43
+ IDP_TYPES: () => IDP_TYPES,
37
44
  ImageAPI: () => ImageAPI,
45
+ JIMENG_IMAGE_MODELS: () => JIMENG_IMAGE_MODELS,
46
+ JIMENG_IMAGE_SIZES: () => JIMENG_IMAGE_SIZES,
47
+ JIMENG_IMAGE_WEB_SEARCH_OPTIONS: () => JIMENG_IMAGE_WEB_SEARCH_OPTIONS,
48
+ KLING_ASPECT_RATIOS: () => KLING_ASPECT_RATIOS,
49
+ KLING_DURATIONS: () => KLING_DURATIONS,
50
+ KLING_MODELS: () => KLING_MODELS,
38
51
  MediaAPI: () => MediaAPI,
39
52
  TaskFolderManager: () => TaskFolderManager,
40
53
  UnityClawClient: () => UnityClawClient,
41
54
  VideoAPI: () => VideoAPI,
55
+ WAN_DEFAULT_MODELS: () => WAN_DEFAULT_MODELS,
56
+ WAN_SHOT_TYPES: () => WAN_SHOT_TYPES,
42
57
  getConfigPath: () => getConfigPath,
43
58
  getConfigValue: () => getConfigValue,
44
59
  loadConfig: () => loadConfig,
@@ -49,6 +64,8 @@ module.exports = __toCommonJS(index_exports);
49
64
 
50
65
  // src/client.ts
51
66
  var import_axios2 = __toESM(require("axios"), 1);
67
+ var import_path3 = require("path");
68
+ var import_promises2 = require("fs/promises");
52
69
 
53
70
  // src/task-folder.ts
54
71
  var import_promises = require("fs/promises");
@@ -309,7 +326,72 @@ function getConfigValue(key) {
309
326
  return value ? String(value) : void 0;
310
327
  }
311
328
 
329
+ // src/apis/normalize.ts
330
+ function toTextFieldItems(input) {
331
+ if (input == null) return void 0;
332
+ if (typeof input === "string") {
333
+ return [{ type: "text", text: input }];
334
+ }
335
+ return input;
336
+ }
337
+ function toLabelFieldItem(input) {
338
+ if (input == null) return void 0;
339
+ if (typeof input === "object" && "value" in input && "label" in input) {
340
+ return input;
341
+ }
342
+ return {
343
+ value: input,
344
+ label: String(input)
345
+ };
346
+ }
347
+
312
348
  // src/apis/image.ts
349
+ var JIMENG_3K_SIZES = /* @__PURE__ */ new Set([
350
+ "3072x3072",
351
+ "2592x3456",
352
+ "3456x2592",
353
+ "4096x2304",
354
+ "2304x4096",
355
+ "3744x2496",
356
+ "2496x3744",
357
+ "4704x2016"
358
+ ]);
359
+ var JIMENG_4K_SIZES = /* @__PURE__ */ new Set([
360
+ "4096x4096",
361
+ "3520x4704",
362
+ "4704x3520",
363
+ "5504x3040",
364
+ "3040x5504",
365
+ "4992x3328",
366
+ "3328x4992",
367
+ "6240x2656"
368
+ ]);
369
+ function getSelectRawValue(input) {
370
+ if (input == null) return "";
371
+ if (typeof input === "object" && "value" in input) {
372
+ return String(input.value ?? "");
373
+ }
374
+ return String(input);
375
+ }
376
+ function validateJimengImageParams(params) {
377
+ const sizeValue = getSelectRawValue(params.size);
378
+ const modelValue = getSelectRawValue(params.model_selector) || params.model || "doubao-seedream-5-0-260128";
379
+ const webSearchValue = getSelectRawValue(params.web_search);
380
+ if (!sizeValue || !sizeValue.includes("x")) {
381
+ throw new Error(
382
+ `Invalid jimeng size "${sizeValue}". /api/jimeng/image expects 2K/3K/4K size values like "2048x2048", "3072x3072", "4096x4096".`
383
+ );
384
+ }
385
+ if (modelValue === "doubao-seedream-5-0-260128" && JIMENG_4K_SIZES.has(sizeValue)) {
386
+ throw new Error('Invalid jimeng params: model "doubao-seedream-5-0-260128" does not support 4K sizes.');
387
+ }
388
+ if (modelValue === "doubao-seedream-4-5-251128" && JIMENG_3K_SIZES.has(sizeValue)) {
389
+ throw new Error('Invalid jimeng params: model "doubao-seedream-4-5-251128" does not support 3K sizes.');
390
+ }
391
+ if (webSearchValue === "true" && modelValue === "doubao-seedream-4-5-251128") {
392
+ throw new Error('Invalid jimeng params: web_search=true is only supported by model "doubao-seedream-5-0-260128".');
393
+ }
394
+ }
313
395
  var ImageAPI = class {
314
396
  constructor(client) {
315
397
  this.client = client;
@@ -364,12 +446,13 @@ var ImageAPI = class {
364
446
  * ```
365
447
  */
366
448
  async jimeng(params) {
449
+ validateJimengImageParams(params);
367
450
  return this.client.request("/api/jimeng/image", {
368
- prompt: params.prompt,
451
+ prompt: toTextFieldItems(params.prompt),
369
452
  attachment: params.attachment,
370
- size: params.size,
371
- model_selector: params.model_selector,
372
- web_search: params.web_search,
453
+ size: toLabelFieldItem(params.size),
454
+ model_selector: toLabelFieldItem(params.model_selector),
455
+ web_search: toLabelFieldItem(params.web_search),
373
456
  image_count: params.image_count,
374
457
  model: params.model
375
458
  });
@@ -380,11 +463,11 @@ var ImageAPI = class {
380
463
  */
381
464
  async jimengV3(params) {
382
465
  return this.client.request("/api/jimeng/image/v3", {
383
- prompt: params.prompt,
466
+ prompt: toTextFieldItems(params.prompt),
384
467
  attachment: params.attachment,
385
- size: params.size,
386
- model_selector: params.model_selector,
387
- web_search: params.web_search,
468
+ size: toLabelFieldItem(params.size),
469
+ model_selector: toLabelFieldItem(params.model_selector),
470
+ web_search: toLabelFieldItem(params.web_search),
388
471
  image_count: params.image_count,
389
472
  model: params.model
390
473
  });
@@ -402,6 +485,17 @@ var ImageAPI = class {
402
485
  };
403
486
 
404
487
  // src/apis/video.ts
488
+ function toNumericDurationLabelFieldItem(input) {
489
+ const item = toLabelFieldItem(input);
490
+ if (!item) return void 0;
491
+ if (typeof item.value === "string" && /^-?\d+(\.\d+)?$/.test(item.value)) {
492
+ return {
493
+ value: Number(item.value),
494
+ label: item.label
495
+ };
496
+ }
497
+ return item;
498
+ }
405
499
  var VideoAPI = class {
406
500
  constructor(client) {
407
501
  this.client = client;
@@ -422,8 +516,8 @@ var VideoAPI = class {
422
516
  async sora(params) {
423
517
  return this.client.request("/api/sora/video", {
424
518
  attachment: params.attachment,
425
- prompt: params.prompt,
426
- orientation: params.orientation
519
+ prompt: toTextFieldItems(params.prompt),
520
+ orientation: toLabelFieldItem(params.orientation)
427
521
  });
428
522
  }
429
523
  /**
@@ -433,9 +527,9 @@ var VideoAPI = class {
433
527
  async soraStable(params) {
434
528
  return this.client.request("/api/sora/video/stable", {
435
529
  attachment: params.attachment,
436
- prompt: params.prompt,
437
- size: params.size,
438
- seconds: params.seconds
530
+ prompt: toTextFieldItems(params.prompt),
531
+ size: toLabelFieldItem(params.size),
532
+ seconds: toLabelFieldItem(params.seconds)
439
533
  });
440
534
  }
441
535
  /**
@@ -453,13 +547,13 @@ var VideoAPI = class {
453
547
  */
454
548
  async veo(params) {
455
549
  return this.client.request("/api/veo/video", {
456
- prompt: params.prompt,
550
+ prompt: toTextFieldItems(params.prompt),
457
551
  attachment: params.attachment,
458
552
  first_frame: params.first_frame,
459
553
  last_frame: params.last_frame,
460
- aspect_ratio: params.aspect_ratio,
461
- resolution: params.resolution,
462
- duration: params.duration
554
+ aspect_ratio: toLabelFieldItem(params.aspect_ratio),
555
+ resolution: toLabelFieldItem(params.resolution),
556
+ duration: toLabelFieldItem(params.duration)
463
557
  });
464
558
  }
465
559
  /**
@@ -479,10 +573,10 @@ var VideoAPI = class {
479
573
  async kling(params) {
480
574
  return this.client.request("/api/kling/video", {
481
575
  attachment: params.attachment,
482
- prompt: params.prompt,
483
- aspect_ratio: params.aspect_ratio,
484
- duration: params.duration,
485
- model: params.model
576
+ prompt: toTextFieldItems(params.prompt),
577
+ aspect_ratio: toLabelFieldItem(params.aspect_ratio),
578
+ duration: toLabelFieldItem(params.duration),
579
+ model: toLabelFieldItem(params.model)
486
580
  });
487
581
  }
488
582
  /**
@@ -500,10 +594,10 @@ var VideoAPI = class {
500
594
  */
501
595
  async jimeng(params) {
502
596
  return this.client.request("/api/jimeng/video", {
503
- action: params.action,
597
+ action: toLabelFieldItem(params.action),
504
598
  attachment: params.attachment,
505
- prompt: params.prompt,
506
- aspect_ratio: params.aspect_ratio
599
+ prompt: toTextFieldItems(params.prompt),
600
+ aspect_ratio: toLabelFieldItem(params.aspect_ratio)
507
601
  });
508
602
  }
509
603
  /**
@@ -521,12 +615,12 @@ var VideoAPI = class {
521
615
  */
522
616
  async doubao(params) {
523
617
  return this.client.request("/api/doubao/video", {
524
- action: params.action,
618
+ action: toLabelFieldItem(params.action),
525
619
  attachment: params.attachment,
526
- prompt: params.prompt,
527
- resolution: params.resolution,
528
- ratio: params.ratio,
529
- duration: params.duration
620
+ prompt: toTextFieldItems(params.prompt),
621
+ resolution: toLabelFieldItem(params.resolution),
622
+ ratio: toLabelFieldItem(params.ratio),
623
+ duration: toNumericDurationLabelFieldItem(params.duration)
530
624
  });
531
625
  }
532
626
  /**
@@ -546,11 +640,11 @@ var VideoAPI = class {
546
640
  async wan(params) {
547
641
  return this.client.request("/api/wan/video", {
548
642
  attachment: params.attachment,
549
- prompt: params.prompt,
550
- size: params.size,
551
- duration: params.duration,
552
- model: params.model,
553
- shot_type: params.shot_type
643
+ prompt: toTextFieldItems(params.prompt),
644
+ size: toLabelFieldItem(params.size),
645
+ duration: toLabelFieldItem(params.duration),
646
+ model: toLabelFieldItem(params.model),
647
+ shot_type: toLabelFieldItem(params.shot_type)
554
648
  });
555
649
  }
556
650
  /**
@@ -569,10 +663,10 @@ var VideoAPI = class {
569
663
  async minimax(params) {
570
664
  return this.client.request("/api/minimax/video", {
571
665
  attachment: params.attachment,
572
- prompt: params.prompt,
573
- size: params.size,
574
- duration: params.duration,
575
- model: params.model
666
+ prompt: toTextFieldItems(params.prompt),
667
+ size: toLabelFieldItem(params.size),
668
+ duration: toLabelFieldItem(params.duration),
669
+ model: toLabelFieldItem(params.model)
576
670
  });
577
671
  }
578
672
  };
@@ -604,114 +698,73 @@ var DocumentAPI = class {
604
698
  });
605
699
  }
606
700
  /**
607
- * Convert image to Word document
608
- * @see /api/doc_convert/image2word
701
+ * Generic document conversion (recommended entrypoint).
702
+ * Uses /api/doc_convert/image or /api/doc_convert/pdf based on input_format.
703
+ */
704
+ async convertDocument(params) {
705
+ const isPdfInput = String(
706
+ typeof params.input_format === "object" && params.input_format !== null && "value" in params.input_format ? params.input_format.value : params.input_format ?? ""
707
+ ).toLowerCase() === "pdf";
708
+ const endpoint = isPdfInput ? "/api/doc_convert/pdf" : "/api/doc_convert/image";
709
+ return this.client.request(endpoint, {
710
+ attachment: params.attachment,
711
+ input_format: params.input_format,
712
+ output_format: params.output_format
713
+ });
714
+ }
715
+ /**
716
+ * @deprecated Use convertDocument({ input_format: 'image', output_format: 'docx' })
609
717
  */
610
718
  async image2Word(params) {
611
- return this.client.request(
612
- "/api/doc_convert/image2word",
613
- {
614
- attachment: params.attachment
615
- }
616
- );
719
+ return this.convertDocument({ attachment: params.attachment, input_format: "image", output_format: "docx" });
617
720
  }
618
721
  /**
619
- * Convert image to PowerPoint
620
- * @see /api/doc_convert/image2ppt
722
+ * @deprecated Use convertDocument({ input_format: 'image', output_format: 'pptx' })
621
723
  */
622
724
  async image2Ppt(params) {
623
- return this.client.request(
624
- "/api/doc_convert/image2ppt",
625
- {
626
- attachment: params.attachment
627
- }
628
- );
725
+ return this.convertDocument({ attachment: params.attachment, input_format: "image", output_format: "pptx" });
629
726
  }
630
727
  /**
631
- * Convert image to Excel
632
- * @see /api/doc_convert/image2excel
728
+ * @deprecated Use convertDocument({ input_format: 'image', output_format: 'xlsx' })
633
729
  */
634
730
  async image2Excel(params) {
635
- return this.client.request(
636
- "/api/doc_convert/image2excel",
637
- {
638
- attachment: params.attachment
639
- }
640
- );
731
+ return this.convertDocument({ attachment: params.attachment, input_format: "image", output_format: "xlsx" });
641
732
  }
642
733
  /**
643
- * Convert image to PDF
644
- * @see /api/doc_convert/image2pdf
734
+ * @deprecated Use convertDocument({ input_format: 'image', output_format: 'pdf' })
645
735
  */
646
736
  async image2Pdf(params) {
647
- return this.client.request(
648
- "/api/doc_convert/image2pdf",
649
- {
650
- attachment: params.attachment
651
- }
652
- );
737
+ return this.convertDocument({ attachment: params.attachment, input_format: "image", output_format: "pdf" });
653
738
  }
654
739
  /**
655
- * Convert PDF to Word document
656
- * @see /api/doc_convert/pdf2word
740
+ * @deprecated Use convertDocument({ input_format: 'pdf', output_format: 'docx' })
657
741
  */
658
742
  async pdf2Word(params) {
659
- return this.client.request(
660
- "/api/doc_convert/pdf2word",
661
- {
662
- attachment: params.attachment
663
- }
664
- );
743
+ return this.convertDocument({ attachment: params.attachment, input_format: "pdf", output_format: "docx" });
665
744
  }
666
745
  /**
667
- * Convert PDF to PowerPoint
668
- * @see /api/doc_convert/pdf2ppt
746
+ * @deprecated Use convertDocument({ input_format: 'pdf', output_format: 'pptx' })
669
747
  */
670
748
  async pdf2Ppt(params) {
671
- return this.client.request(
672
- "/api/doc_convert/pdf2ppt",
673
- {
674
- attachment: params.attachment
675
- }
676
- );
749
+ return this.convertDocument({ attachment: params.attachment, input_format: "pdf", output_format: "pptx" });
677
750
  }
678
751
  /**
679
- * Convert PDF to Excel
680
- * @see /api/doc_convert/pdf2excel
752
+ * @deprecated Use convertDocument({ input_format: 'pdf', output_format: 'xlsx' })
681
753
  */
682
754
  async pdf2Excel(params) {
683
- return this.client.request(
684
- "/api/doc_convert/pdf2excel",
685
- {
686
- attachment: params.attachment
687
- }
688
- );
755
+ return this.convertDocument({ attachment: params.attachment, input_format: "pdf", output_format: "xlsx" });
689
756
  }
690
757
  /**
691
- * Convert PDF to image
692
- * @see /api/doc_convert/pdf2image
758
+ * @deprecated Use convertDocument({ input_format: 'pdf', output_format: 'image' })
693
759
  */
694
760
  async pdf2Image(params) {
695
- return this.client.request(
696
- "/api/doc_convert/pdf2image",
697
- {
698
- attachment: params.attachment
699
- }
700
- );
761
+ return this.convertDocument({ attachment: params.attachment, input_format: "pdf", output_format: "image" });
701
762
  }
702
763
  /**
703
- * Generic document conversion
704
- * @see /api/doc_convert/image
705
- * @see /api/doc_convert/pdf
764
+ * Backward-compatible alias of convertDocument().
706
765
  */
707
766
  async convert(params) {
708
- const isImage = params.input_format === "image" || !params.input_format;
709
- const endpoint = isImage ? "/api/doc_convert/image" : "/api/doc_convert/pdf";
710
- return this.client.request(endpoint, {
711
- attachment: params.attachment,
712
- input_format: params.input_format,
713
- output_format: params.output_format
714
- });
767
+ return this.convertDocument(params);
715
768
  }
716
769
  };
717
770
 
@@ -785,13 +838,124 @@ var MediaAPI = class {
785
838
  url: [{ link: params.url, type: "url" }]
786
839
  });
787
840
  }
841
+ /**
842
+ * Fetch media stats from social video links.
843
+ * @see /api/media_stats
844
+ */
845
+ async stats(params) {
846
+ return this.client.request("/api/media_stats", {
847
+ link: params.link
848
+ });
849
+ }
850
+ /**
851
+ * Fetch media user profile information from homepage links.
852
+ * @see /api/media_user_info
853
+ */
854
+ async userInfo(params) {
855
+ return this.client.request("/api/media_user_info", {
856
+ link: params.link
857
+ });
858
+ }
859
+ /**
860
+ * Download Xiaohongshu media links.
861
+ * @see /api/xiaohongshu/download
862
+ */
863
+ async downloadXiaohongshu(params) {
864
+ return this.client.request("/api/xiaohongshu/download", {
865
+ url: params.url
866
+ });
867
+ }
868
+ /**
869
+ * Extract one frame from video attachment.
870
+ * @see /api/video/frame
871
+ */
872
+ async extractFrame(params) {
873
+ return this.client.request("/api/video/frame", {
874
+ attachment: params.attachment,
875
+ frame_option: toLabelFieldItem(params.frame_option),
876
+ frame: params.frame
877
+ });
878
+ }
879
+ };
880
+
881
+ // src/apis/idp.ts
882
+ var IDPAPI = class {
883
+ constructor(client) {
884
+ this.client = client;
885
+ }
886
+ /**
887
+ * Generic IDP extraction call.
888
+ * @see /api/idp/{type}
889
+ */
890
+ async extract(type, params) {
891
+ return this.client.request(`/api/idp/${type}`, {
892
+ attachments: params.attachments
893
+ });
894
+ }
895
+ async bankCard(params) {
896
+ return this.extract("bank_card", params);
897
+ }
898
+ async vehicleLicense(params) {
899
+ return this.extract("vehicle_license", params);
900
+ }
901
+ async trainInvoice(params) {
902
+ return this.extract("train_invoice", params);
903
+ }
904
+ async taxiInvoice(params) {
905
+ return this.extract("taxi_invoice", params);
906
+ }
907
+ async idCard(params) {
908
+ return this.extract("id_card", params);
909
+ }
910
+ async vatInvoice(params) {
911
+ return this.extract("vat_invoice", params);
912
+ }
913
+ async businessLicense(params) {
914
+ return this.extract("business_license", params);
915
+ }
916
+ async businessCard(params) {
917
+ return this.extract("business_card", params);
918
+ }
919
+ async contract(params) {
920
+ return this.extract("contract", params);
921
+ }
788
922
  };
789
923
 
790
924
  // src/client.ts
791
925
  var DEFAULT_BASE_URL = "https://unityclaw.com";
792
- var DEFAULT_TIMEOUT = 3e5;
926
+ var DEFAULT_TIMEOUT = 9e5;
793
927
  var OLD_DOMAINS = ["fieldshortcut.cn", "fieldshortcut.com"];
794
928
  var NEW_DOMAIN = "unityclaw.com";
929
+ var MIME_BY_EXT = {
930
+ ".jpg": "image/jpeg",
931
+ ".jpeg": "image/jpeg",
932
+ ".png": "image/png",
933
+ ".gif": "image/gif",
934
+ ".webp": "image/webp",
935
+ ".bmp": "image/bmp",
936
+ ".heic": "image/heic",
937
+ ".heif": "image/heif",
938
+ ".mp4": "video/mp4",
939
+ ".mov": "video/quicktime",
940
+ ".avi": "video/x-msvideo",
941
+ ".webm": "video/webm",
942
+ ".m4a": "audio/mp4",
943
+ ".mp3": "audio/mpeg",
944
+ ".wav": "audio/wav",
945
+ ".aac": "audio/aac",
946
+ ".flac": "audio/flac",
947
+ ".pdf": "application/pdf",
948
+ ".doc": "application/msword",
949
+ ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
950
+ ".xls": "application/vnd.ms-excel",
951
+ ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
952
+ ".ppt": "application/vnd.ms-powerpoint",
953
+ ".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
954
+ ".txt": "text/plain",
955
+ ".md": "text/markdown",
956
+ ".csv": "text/csv",
957
+ ".json": "application/json"
958
+ };
795
959
  function replaceOldDomains(text) {
796
960
  if (!text || typeof text !== "string") return text;
797
961
  let result = text;
@@ -800,6 +964,49 @@ function replaceOldDomains(text) {
800
964
  }
801
965
  return result;
802
966
  }
967
+ function isRecord(value) {
968
+ return !!value && typeof value === "object" && !Array.isArray(value);
969
+ }
970
+ function getLocalPathCandidate(value) {
971
+ const candidates = [value.path, value.localPath, value.filePath];
972
+ for (const candidate of candidates) {
973
+ if (typeof candidate === "string" && candidate.trim()) {
974
+ return candidate.trim();
975
+ }
976
+ }
977
+ return void 0;
978
+ }
979
+ function inferMimeType(filePath, provided) {
980
+ if (typeof provided === "string" && provided.trim()) {
981
+ return provided.trim();
982
+ }
983
+ const ext = (0, import_path3.extname)(filePath).toLowerCase();
984
+ return MIME_BY_EXT[ext] ?? "application/octet-stream";
985
+ }
986
+ function isDownloadableResponseItem(item) {
987
+ if (!item.content || typeof item.content !== "string") return false;
988
+ return /^https?:\/\//i.test(item.content);
989
+ }
990
+ function buildMultipartBody(fileBuffer, fieldName, filename, contentType) {
991
+ const boundary = `----UnityClawBoundary${Math.random().toString(16).slice(2)}`;
992
+ const chunks = [
993
+ Buffer.from(`--${boundary}\r
994
+ `),
995
+ Buffer.from(`Content-Disposition: form-data; name="${fieldName}"; filename="${filename}"\r
996
+ `),
997
+ Buffer.from(`Content-Type: ${contentType}\r
998
+ \r
999
+ `),
1000
+ fileBuffer,
1001
+ Buffer.from(`\r
1002
+ --${boundary}--\r
1003
+ `)
1004
+ ];
1005
+ return {
1006
+ body: Buffer.concat(chunks),
1007
+ contentType: `multipart/form-data; boundary=${boundary}`
1008
+ };
1009
+ }
803
1010
  var UnityClawClient = class {
804
1011
  config;
805
1012
  httpClient;
@@ -809,6 +1016,7 @@ var UnityClawClient = class {
809
1016
  video;
810
1017
  document;
811
1018
  media;
1019
+ idp;
812
1020
  constructor(config = {}) {
813
1021
  const fileConfig = loadConfig();
814
1022
  const apiKey = config.apiKey ?? process.env.UNITYCLAW_API_KEY ?? fileConfig.apiKey ?? "";
@@ -822,6 +1030,7 @@ var UnityClawClient = class {
822
1030
  taskDir: config.taskDir ?? fileConfig.taskDir ?? DEFAULT_TASKS_DIR,
823
1031
  timeout: config.timeout ?? DEFAULT_TIMEOUT,
824
1032
  downloadAttachments: config.downloadAttachments ?? true,
1033
+ autoUploadLocalFiles: config.autoUploadLocalFiles ?? true,
825
1034
  context: config.context ?? {}
826
1035
  };
827
1036
  this.httpClient = import_axios2.default.create({
@@ -841,6 +1050,7 @@ var UnityClawClient = class {
841
1050
  this.video = new VideoAPI(this);
842
1051
  this.document = new DocumentAPI(this);
843
1052
  this.media = new MediaAPI(this);
1053
+ this.idp = new IDPAPI(this);
844
1054
  }
845
1055
  /**
846
1056
  * Get the underlying HTTP client for custom requests
@@ -899,13 +1109,14 @@ var UnityClawClient = class {
899
1109
  const taskCtx = await this.taskFolderManager.createTaskFolder();
900
1110
  try {
901
1111
  await this.taskFolderManager.log(taskCtx, "info", `Starting request to ${endpoint}`);
1112
+ const normalizedParams = await this.normalizeParams(params, taskCtx);
902
1113
  const context = this.buildContext(contextOverrides);
903
1114
  const requestBody = {
904
- formItemParams: params,
1115
+ formItemParams: normalizedParams,
905
1116
  context
906
1117
  };
907
- await this.taskFolderManager.writeRequest(taskCtx, endpoint, params, context);
908
- await this.taskFolderManager.log(taskCtx, "info", "Request prepared", { endpoint, params });
1118
+ await this.taskFolderManager.writeRequest(taskCtx, endpoint, normalizedParams, context);
1119
+ await this.taskFolderManager.log(taskCtx, "info", "Request prepared", { endpoint, params: normalizedParams });
909
1120
  const response = await this.httpClient.post(endpoint, requestBody);
910
1121
  if (response.data.msg) {
911
1122
  response.data.msg = replaceOldDomains(response.data.msg);
@@ -919,7 +1130,7 @@ var UnityClawClient = class {
919
1130
  for (const item of response.data.data) {
920
1131
  if (item && typeof item === "object" && "content" in item && "contentType" in item) {
921
1132
  const attachmentItem = item;
922
- if (attachmentItem.contentType === "attachment/url" && attachmentItem.content) {
1133
+ if (isDownloadableResponseItem(attachmentItem)) {
923
1134
  const localPath = await this.taskFolderManager.downloadAttachment(taskCtx, {
924
1135
  tmp_url: attachmentItem.content,
925
1136
  name: attachmentItem.name
@@ -949,6 +1160,61 @@ var UnityClawClient = class {
949
1160
  return await this.taskFolderManager.finalizeTaskFolder(taskCtx, errorResponse, false);
950
1161
  }
951
1162
  }
1163
+ async uploadLocalFile(filePath, original) {
1164
+ const file = await (0, import_promises2.readFile)(filePath);
1165
+ const st = await (0, import_promises2.stat)(filePath);
1166
+ const filename = typeof original?.name === "string" && original.name.trim() ? original.name.trim() : (0, import_path3.basename)(filePath);
1167
+ const type = inferMimeType(filePath, original?.type);
1168
+ const { body, contentType } = buildMultipartBody(file, "file", filename, type);
1169
+ const uploadResponse = await this.httpClient.post("/api/upload", body, {
1170
+ headers: {
1171
+ "Content-Type": contentType,
1172
+ "Content-Length": body.length.toString()
1173
+ }
1174
+ });
1175
+ if (uploadResponse.data.code !== 0 || !uploadResponse.data.data) {
1176
+ const message = uploadResponse.data.msg || "upload failed";
1177
+ throw new Error(`Upload failed for ${filePath}: ${message}`);
1178
+ }
1179
+ return {
1180
+ tmp_url: uploadResponse.data.data,
1181
+ name: filename,
1182
+ type,
1183
+ size: Number.isFinite(st.size) ? st.size : void 0
1184
+ };
1185
+ }
1186
+ async normalizeParams(params, taskCtx) {
1187
+ if (!this.config.autoUploadLocalFiles) {
1188
+ return params;
1189
+ }
1190
+ const walk = async (value) => {
1191
+ if (Array.isArray(value)) {
1192
+ const output2 = [];
1193
+ for (const item of value) {
1194
+ output2.push(await walk(item));
1195
+ }
1196
+ return output2;
1197
+ }
1198
+ if (!isRecord(value)) {
1199
+ return value;
1200
+ }
1201
+ if (typeof value.tmp_url === "string" && value.tmp_url.trim()) {
1202
+ return value;
1203
+ }
1204
+ const localPath = getLocalPathCandidate(value);
1205
+ if (localPath) {
1206
+ await this.taskFolderManager.log(taskCtx, "info", "Uploading local attachment", { localPath });
1207
+ return this.uploadLocalFile(localPath, value);
1208
+ }
1209
+ const output = {};
1210
+ for (const [k, v] of Object.entries(value)) {
1211
+ output[k] = await walk(v);
1212
+ }
1213
+ return output;
1214
+ };
1215
+ const normalized = await walk(params);
1216
+ return isRecord(normalized) ? normalized : params;
1217
+ }
952
1218
  // ==================== Convenience Methods ====================
953
1219
  /**
954
1220
  * Generate image using Gemini API
@@ -1000,17 +1266,126 @@ var UnityClawClient = class {
1000
1266
  return this.media.analyze(params);
1001
1267
  }
1002
1268
  };
1269
+
1270
+ // src/types.ts
1271
+ var GEMINI_IMAGE_ASPECT_RATIOS = [
1272
+ "1:1",
1273
+ "9:16",
1274
+ "16:9",
1275
+ "4:3",
1276
+ "3:4",
1277
+ "3:2",
1278
+ "2:3",
1279
+ "5:4",
1280
+ "4:5",
1281
+ "21:9",
1282
+ "1:4",
1283
+ "1:8",
1284
+ "4:1",
1285
+ "8:1"
1286
+ ];
1287
+ var GEMINI_IMAGE_SIZES = ["1K", "2K", "4K", "1K_pro", "2K_pro", "4K_pro"];
1288
+ var JIMENG_IMAGE_MODELS = ["doubao-seedream-5-0-260128", "doubao-seedream-4-5-251128"];
1289
+ var JIMENG_IMAGE_SIZES = [
1290
+ "2048x2048",
1291
+ "1728x2304",
1292
+ "2304x1728",
1293
+ "2848x1600",
1294
+ "1600x2848",
1295
+ "2496x1664",
1296
+ "1664x2496",
1297
+ "3136x1344",
1298
+ "3072x3072",
1299
+ "2592x3456",
1300
+ "3456x2592",
1301
+ "4096x2304",
1302
+ "2304x4096",
1303
+ "3744x2496",
1304
+ "2496x3744",
1305
+ "4704x2016",
1306
+ "4096x4096",
1307
+ "3520x4704",
1308
+ "4704x3520",
1309
+ "5504x3040",
1310
+ "3040x5504",
1311
+ "4992x3328",
1312
+ "3328x4992",
1313
+ "6240x2656"
1314
+ ];
1315
+ var JIMENG_IMAGE_WEB_SEARCH_OPTIONS = ["true", "false"];
1316
+ var KLING_MODELS = [
1317
+ "kling-v1",
1318
+ "kling-v1-5",
1319
+ "kling-v1-6",
1320
+ "kling-v2-master",
1321
+ "kling-v2-1",
1322
+ "kling-v2-1-master",
1323
+ "kling-v2-5-turbo",
1324
+ "kling-v2-6"
1325
+ ];
1326
+ var KLING_ASPECT_RATIOS = ["16:9", "9:16", "1:1"];
1327
+ var KLING_DURATIONS = ["5", "10"];
1328
+ var WAN_DEFAULT_MODELS = ["wan2.6-t2v", "wan2.6-i2v", "wan2.6-i2v-flash", "wan2.6-r2v"];
1329
+ var WAN_SHOT_TYPES = ["single", "multi"];
1330
+ var DOC_CONVERT_INPUT_FORMATS = ["image", "pdf"];
1331
+ var DOC_CONVERT_OUTPUT_FORMATS = ["docx", "pptx", "xlsx", "pdf", "image"];
1332
+ var DOC_TRANSLATE_LANGUAGE_CODES = [
1333
+ "en",
1334
+ "zh",
1335
+ "zh-TW",
1336
+ "ja",
1337
+ "ko",
1338
+ "es",
1339
+ "fr",
1340
+ "de",
1341
+ "pt",
1342
+ "ru",
1343
+ "ar",
1344
+ "it",
1345
+ "nl",
1346
+ "pl",
1347
+ "tr",
1348
+ "vi",
1349
+ "th",
1350
+ "id"
1351
+ ];
1352
+ var IDP_TYPES = [
1353
+ "bank_card",
1354
+ "vehicle_license",
1355
+ "train_invoice",
1356
+ "taxi_invoice",
1357
+ "id_card",
1358
+ "vat_invoice",
1359
+ "business_license",
1360
+ "business_card",
1361
+ "contract"
1362
+ ];
1003
1363
  // Annotate the CommonJS export names for ESM import in node:
1004
1364
  0 && (module.exports = {
1005
1365
  CONFIG_DIR,
1006
1366
  CONFIG_FILE,
1007
1367
  DEFAULT_TASKS_DIR,
1368
+ DOC_CONVERT_INPUT_FORMATS,
1369
+ DOC_CONVERT_OUTPUT_FORMATS,
1370
+ DOC_TRANSLATE_LANGUAGE_CODES,
1008
1371
  DocumentAPI,
1372
+ GEMINI_IMAGE_ASPECT_RATIOS,
1373
+ GEMINI_IMAGE_SIZES,
1374
+ IDPAPI,
1375
+ IDP_TYPES,
1009
1376
  ImageAPI,
1377
+ JIMENG_IMAGE_MODELS,
1378
+ JIMENG_IMAGE_SIZES,
1379
+ JIMENG_IMAGE_WEB_SEARCH_OPTIONS,
1380
+ KLING_ASPECT_RATIOS,
1381
+ KLING_DURATIONS,
1382
+ KLING_MODELS,
1010
1383
  MediaAPI,
1011
1384
  TaskFolderManager,
1012
1385
  UnityClawClient,
1013
1386
  VideoAPI,
1387
+ WAN_DEFAULT_MODELS,
1388
+ WAN_SHOT_TYPES,
1014
1389
  getConfigPath,
1015
1390
  getConfigValue,
1016
1391
  loadConfig,