needware-cli 1.7.3 → 1.7.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "needware-cli",
3
- "version": "1.7.3",
3
+ "version": "1.7.7",
4
4
  "description": "一个功能强大的 Node.js 命令行工具",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -361,14 +361,6 @@ export async function streamChat({
361
361
 
362
362
  if (!resp.ok) {
363
363
  const errorData = await resp.json().catch(() => ({}));
364
- if (resp.status === 429) {
365
- onError(errorData.error || "Request rate too high, please try again later");
366
- return;
367
- }
368
- if (resp.status === 402) {
369
- onError(errorData.error || "Insufficient quota, please recharge to continue");
370
- return;
371
- }
372
364
  onError(errorData.error || "Connection failed, please retry");
373
365
  return;
374
366
  }
@@ -590,107 +582,39 @@ Requirements:
590
582
  }),
591
583
  });
592
584
 
593
- if (!response.ok) {
594
- const errorText = await response.text();
595
- console.error("AI service error:", response.status, errorText);
596
-
597
- if (response.status === 429) {
598
- return new Response(
599
- JSON.stringify({ error: "Request rate too high, please try again later" }),
600
- { status: 429, headers: { "Content-Type": "application/json", ...corsHeaders } }
601
- );
602
- }
585
+ // 非流式响应
586
+ const result = await response.json();
603
587
 
604
- if (response.status === 402) {
605
- return new Response(
606
- JSON.stringify({ error: "AI service quota exhausted" }),
607
- { status: 402, headers: { "Content-Type": "application/json", ...corsHeaders } }
608
- );
609
- }
610
588
 
611
- let errorMessage = "AI service temporarily unavailable";
612
- try {
613
- const errorJson = JSON.parse(errorText);
614
- errorMessage = errorJson.error?.message || errorJson.message || errorMessage;
615
- } catch {
616
- if (errorText) errorMessage = errorText.slice(0, 200);
617
- }
618
-
619
- return new Response(
620
- JSON.stringify({ error: errorMessage }),
621
- { status: 500, headers: { "Content-Type": "application/json", ...corsHeaders } }
622
- );
623
- }
624
-
625
- const data = await response.json();
626
- console.log("AI response:", JSON.stringify(data, null, 2));
627
-
628
- // ⚠️ IMPORTANT: Parse image from multiple possible response formats
629
- let generatedImage: string | null = null;
630
- const message = data.choices?.[0]?.message;
631
-
632
- // Format 1: content_parts (Gemini native format)
633
- if (message?.content_parts && Array.isArray(message.content_parts)) {
634
- for (const part of message.content_parts) {
635
- if (part.inline_data?.data) {
636
- const mimeType = part.inline_data.mime_type || "image/png";
637
- generatedImage = `data:${mimeType};base64,${part.inline_data.data}`;
638
- break;
639
- }
640
- }
641
- }
642
-
643
- // Format 2: content array with various structures
644
- if (!generatedImage && Array.isArray(message?.content)) {
645
- for (const item of message.content) {
646
- if (item.type === "image_url" && item.image_url?.url) {
647
- generatedImage = item.image_url.url;
648
- break;
649
- }
650
- if (item.type === "image" && item.data) {
651
- generatedImage = `data:image/png;base64,${item.data}`;
652
- break;
653
- }
654
- if (item.inline_data?.data) {
655
- const mimeType = item.inline_data.mime_type || "image/png";
656
- generatedImage = `data:${mimeType};base64,${item.inline_data.data}`;
657
- break;
658
- }
659
- }
660
- }
589
+ // 解析响应,提取生成的图片
590
+ let generatedImageUrl: string | null = null;
591
+ let textContent: string | null = null;
661
592
 
662
- // Format 3: Direct base64 string in content
663
- if (!generatedImage && typeof message?.content === "string" && message.content) {
664
- if (message.content.startsWith("data:image")) {
665
- generatedImage = message.content;
666
- } else if (message.content.length > 1000 && /^[A-Za-z0-9+/=\s]+$/.test(message.content)) {
667
- // Looks like raw base64 data
668
- generatedImage = `data:image/png;base64,${message.content.replace(/\s/g, '')}`;
669
- }
593
+ // 从正确的路径获取图片 URL
594
+ const images = result.choices?.[0]?.message?.images;
595
+ if (images && images.length > 0 && images[0].image_url?.url) {
596
+ generatedImageUrl = images[0].image_url.url;
670
597
  }
671
-
672
- if (!generatedImage) {
673
- const reasoning = message?.reasoning;
674
- console.error("No image in response. Full response:", JSON.stringify(data));
675
-
676
- return new Response(
677
- JSON.stringify({
678
- error: "AI failed to generate try-on image, please retry or use a different photo",
679
- debug: reasoning ? reasoning.slice(0, 100) : "Unable to extract image"
680
- }),
681
- { status: 500, headers: { "Content-Type": "application/json", ...corsHeaders } }
682
- );
598
+
599
+ // 获取文本内容
600
+ const messageContent = result.choices?.[0]?.message?.content;
601
+ if (typeof messageContent === 'string') {
602
+ textContent = messageContent;
683
603
  }
684
604
 
685
- console.log("Virtual try-on completed successfully");
605
+ // 包装响应 - 返回简洁的格式
606
+ const virtualTryOnResponse = {
607
+ resultImage: generatedImageUrl,
608
+ message: generatedImageUrl ? "换装效果生成成功" : "未能生成图片,请重试",
609
+ };
686
610
 
687
- return new Response(
688
- JSON.stringify({
689
- success: true,
690
- image: generatedImage
691
- }),
692
- { status: 200, headers: { "Content-Type": "application/json", ...corsHeaders } }
693
- );
611
+ return new Response(JSON.stringify(virtualTryOnResponse), {
612
+ status: response.ok ? 200 : response.status,
613
+ headers: {
614
+ "Content-Type": "application/json",
615
+ ...corsHeaders
616
+ },
617
+ });
694
618
 
695
619
  } catch (error: any) {
696
620
  console.error("Virtual try-on error:", error);
@@ -945,30 +869,6 @@ pnpm add @supabase/supabase-js
945
869
  - ✅ Implement usage monitoring and alerts
946
870
  - ✅ Consider using batch processing to reduce costs
947
871
 
948
- ## Error Handling Checklist
949
-
950
- ```typescript
951
- // Standard error handling pattern
952
- const handleAIError = (error: any, statusCode: number) => {
953
- const errorMap: Record<number, string> = {
954
- 400: "Invalid request parameters",
955
- 401: "Authentication failed",
956
- 402: "Insufficient account balance or quota exhausted",
957
- 403: "No permission to access this API",
958
- 404: "API endpoint does not exist",
959
- 429: "Too many requests, please try again later",
960
- 500: "AI service internal error",
961
- 503: "AI service temporarily unavailable",
962
- };
963
-
964
- return {
965
- error: errorMap[statusCode] || "Unknown error",
966
- statusCode,
967
- originalError: error?.message,
968
- timestamp: new Date().toISOString(),
969
- };
970
- };
971
- ```
972
872
 
973
873
  ## When NOT to Use This Skill
974
874
 
@@ -977,15 +877,3 @@ const handleAIError = (error: any, statusCode: number) => {
977
877
  - Pure data processing logic (no AI inference needed)
978
878
  - Static content display
979
879
  - User is just asking about AI concepts (just provide explanation)
980
-
981
- ## Final Reminders
982
-
983
- **After completing AI integration, must:**
984
- 1. ✅ Test all error scenarios
985
- 2. ✅ Check response format correctness
986
- 3. ✅ Test edge cases (extra-long input, special characters, etc.)
987
- 4. ✅ Confirm smooth user experience
988
- 5. ✅ Add usage documentation and examples
989
-
990
- **Remember: AI integration is not "set it and forget it", requires continuous monitoring and optimization.**
991
-
File without changes