needware-cli 1.6.11 → 1.6.15
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 +1 -1
- package/skills/ai-integration/SKILL.md +188 -116
package/package.json
CHANGED
|
@@ -9,24 +9,26 @@ description: Use this skill when the conversation requires integrating AI servic
|
|
|
9
9
|
|
|
10
10
|
**CRITICAL**: AI Integration requires Supabase as the backend (uses Supabase Edge Functions). Always check Supabase integration status before proceeding:
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
|
|
13
|
+
**Step 1: Check Supabase Integration**
|
|
13
14
|
|
|
14
15
|
Check if Supabase is already integrated:
|
|
15
16
|
- Look for `src/lib/supabase.ts` file
|
|
16
17
|
- Check `.env` file for Supabase environment variables:
|
|
17
18
|
- `VITE_SUPABASE_PROJECT_ID`
|
|
18
|
-
- `VITE_SUPABASE_PUBLISHABLE_KEY`
|
|
19
|
+
- `VITE_SUPABASE_PUBLISHABLE_KEY`
|
|
19
20
|
- `VITE_SUPABASE_URL`
|
|
20
21
|
|
|
21
22
|
**Step 2: Handle Based on Status**
|
|
22
23
|
|
|
23
24
|
**If Supabase is already integrated** (supabase.ts exists with valid configuration):
|
|
24
|
-
- ✓
|
|
25
|
-
-
|
|
25
|
+
- ✓ Proceed with Resend integration
|
|
26
|
+
- Inform user: "✓ Supabase is integrated. Proceeding with Resend setup."
|
|
26
27
|
|
|
27
|
-
**If Supabase is NOT integrated** (no supabase.ts):
|
|
28
|
-
-
|
|
29
|
-
-
|
|
28
|
+
**If Supabase is NOT integrated** (no supabase.ts or missing environment variables):
|
|
29
|
+
- ❌ Stop immediately
|
|
30
|
+
- Inform user: "⚠️ Supabase integration is required before setting up Resend. Resend email functions run on Supabase Edge Functions."
|
|
31
|
+
- Suggest: "Please enable Supabase first by saying 'Enable Cloud' or use the supabase-integration skill."
|
|
30
32
|
|
|
31
33
|
---
|
|
32
34
|
|
|
@@ -52,38 +54,20 @@ Trigger Conditions (use if any are met):
|
|
|
52
54
|
- Need to call large language model APIs (GPT, Claude, Gemini, etc.)
|
|
53
55
|
- Need visual AI capabilities (OCR, object recognition, image analysis)
|
|
54
56
|
- Need text AI capabilities (translation, summarization, sentiment analysis)
|
|
57
|
+
- Need image generation capabilities (text-to-image, AI art generation) 🎨
|
|
55
58
|
- User asks "how to integrate AI"
|
|
56
59
|
```
|
|
57
60
|
|
|
58
|
-
## Supabase Project Structure
|
|
59
61
|
|
|
60
|
-
|
|
62
|
+
## Model Selection Guide
|
|
61
63
|
|
|
62
|
-
|
|
63
|
-
project-root/
|
|
64
|
-
├── supabase/
|
|
65
|
-
│ ├── functions/
|
|
66
|
-
│ │ ├── <function-name-1>/
|
|
67
|
-
│ │ │ └── index.ts # AI Feature 1
|
|
68
|
-
│ │ ├── <function-name-2>/
|
|
69
|
-
│ │ │ └── index.ts # AI Feature 2
|
|
70
|
-
│ │ └── <function-name-3>/
|
|
71
|
-
│ │ └── index.ts # AI Feature 3
|
|
72
|
-
│ ├── .env.local # Functions environment variables
|
|
73
|
-
│ └── config.toml # Supabase configuration
|
|
74
|
-
├── src/
|
|
75
|
-
│ ├── lib/
|
|
76
|
-
│ │ └── supabase.ts # Supabase Client configuration
|
|
77
|
-
│ └── ...
|
|
78
|
-
└── .env # Frontend environment variables (VITE_SUPABASE_URL, etc.)
|
|
79
|
-
```
|
|
64
|
+
**IMPORTANT:** Use `gemini-3-pro-image-preview` model for image generation, and `google/gemini-2.5-flash` model for text/image analysis.
|
|
80
65
|
|
|
81
66
|
## AI Integration Architecture Patterns
|
|
82
67
|
|
|
83
68
|
### 1. Backend API Pattern (Recommended for Production)
|
|
84
69
|
|
|
85
70
|
**Use Cases:**
|
|
86
|
-
- Need to protect API keys
|
|
87
71
|
- Need rate limiting and usage control
|
|
88
72
|
- Need data preprocessing or postprocessing
|
|
89
73
|
- Need caching or logging
|
|
@@ -97,7 +81,6 @@ Frontend → Backend API → AI Gateway/Service → AI Provider
|
|
|
97
81
|
|
|
98
82
|
**Use Cases:**
|
|
99
83
|
- Prototyping or demos
|
|
100
|
-
- Using user's own API keys
|
|
101
84
|
- Scenarios requiring extremely high real-time performance
|
|
102
85
|
|
|
103
86
|
**Architecture:**
|
|
@@ -161,19 +144,12 @@ const handler = async (req: Request): Promise<Response> => {
|
|
|
161
144
|
);
|
|
162
145
|
}
|
|
163
146
|
|
|
164
|
-
// Get API key from environment variables
|
|
165
|
-
const AI_API_KEY = Deno.env.get("AI_API_KEY");
|
|
166
|
-
if (!AI_API_KEY) {
|
|
167
|
-
throw new Error("AI service not configured");
|
|
168
|
-
}
|
|
169
|
-
|
|
170
147
|
console.log("Processing AI request...");
|
|
171
148
|
|
|
172
149
|
// Call AI Gateway API
|
|
173
150
|
const response = await fetch("https://ai.gateway.needware.dev/v1/chat/completions", {
|
|
174
151
|
method: "POST",
|
|
175
152
|
headers: {
|
|
176
|
-
"Authorization": `Bearer ${AI_API_KEY}`,
|
|
177
153
|
"Content-Type": "application/json",
|
|
178
154
|
},
|
|
179
155
|
body: JSON.stringify({
|
|
@@ -515,6 +491,175 @@ export function ChatInterface() {
|
|
|
515
491
|
}
|
|
516
492
|
```
|
|
517
493
|
|
|
494
|
+
### Image Generation Specialized Template
|
|
495
|
+
|
|
496
|
+
**CRITICAL: Use `gemini-3-pro-image-preview` model for image generation tasks.**
|
|
497
|
+
|
|
498
|
+
Use this template when users need to generate images from text descriptions.
|
|
499
|
+
|
|
500
|
+
**File Location:** `supabase/functions/generate-image/index.ts`
|
|
501
|
+
|
|
502
|
+
```typescript
|
|
503
|
+
// supabase/functions/generate-image/index.ts
|
|
504
|
+
import { serve } from "https://deno.land/std@0.190.0/http/server.ts";
|
|
505
|
+
|
|
506
|
+
// CORS headers for cross-origin requests
|
|
507
|
+
const corsHeaders = {
|
|
508
|
+
"Access-Control-Allow-Origin": "*",
|
|
509
|
+
"Access-Control-Allow-Headers":
|
|
510
|
+
"authorization, x-client-info, apikey, content-type",
|
|
511
|
+
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
|
512
|
+
"Access-Control-Max-Age": "86400",
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
// Request interface
|
|
516
|
+
interface ImageGenerationRequest {
|
|
517
|
+
prompt: string;
|
|
518
|
+
options?: {
|
|
519
|
+
size?: string;
|
|
520
|
+
quality?: string;
|
|
521
|
+
style?: string;
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
const handler = async (req: Request): Promise<Response> => {
|
|
526
|
+
// Handle CORS preflight requests
|
|
527
|
+
if (req.method === "OPTIONS") {
|
|
528
|
+
return new Response(null, {
|
|
529
|
+
status: 200,
|
|
530
|
+
headers: corsHeaders
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
try {
|
|
535
|
+
const { prompt, options }: ImageGenerationRequest = await req.json();
|
|
536
|
+
|
|
537
|
+
// Validate input
|
|
538
|
+
if (!prompt) {
|
|
539
|
+
return new Response(
|
|
540
|
+
JSON.stringify({ error: "No prompt provided" }),
|
|
541
|
+
{
|
|
542
|
+
status: 400,
|
|
543
|
+
headers: { "Content-Type": "application/json", ...corsHeaders }
|
|
544
|
+
}
|
|
545
|
+
);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
console.log("Generating image with prompt:", prompt);
|
|
549
|
+
|
|
550
|
+
// Call AI Gateway API with image generation model
|
|
551
|
+
const response = await fetch("https://ai.gateway.needware.dev/v1/chat/completions", {
|
|
552
|
+
method: "POST",
|
|
553
|
+
headers: {
|
|
554
|
+
"Content-Type": "application/json",
|
|
555
|
+
},
|
|
556
|
+
body: JSON.stringify({
|
|
557
|
+
model: "gemini-3-pro-image-preview", // 🎨 Use image generation model
|
|
558
|
+
messages: [
|
|
559
|
+
{
|
|
560
|
+
role: "system",
|
|
561
|
+
content: "You are a professional image generation assistant. Generate high-quality images based on user descriptions."
|
|
562
|
+
},
|
|
563
|
+
{
|
|
564
|
+
role: "user",
|
|
565
|
+
content: prompt
|
|
566
|
+
}
|
|
567
|
+
],
|
|
568
|
+
temperature: 0.8,
|
|
569
|
+
max_tokens: 4000,
|
|
570
|
+
}),
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
if (!response.ok) {
|
|
574
|
+
const errorText = await response.text();
|
|
575
|
+
console.error("AI service error:", response.status, errorText);
|
|
576
|
+
throw new Error(`Image generation failed: ${errorText}`);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
const data = await response.json();
|
|
580
|
+
const result = data.choices?.[0]?.message?.content;
|
|
581
|
+
|
|
582
|
+
if (!result) {
|
|
583
|
+
throw new Error("No image generated");
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
console.log("Image generation completed");
|
|
587
|
+
|
|
588
|
+
return new Response(
|
|
589
|
+
JSON.stringify({
|
|
590
|
+
success: true,
|
|
591
|
+
imageUrl: result, // Image URL or base64 data
|
|
592
|
+
prompt: prompt,
|
|
593
|
+
model: "gemini-3-pro-image-preview"
|
|
594
|
+
}),
|
|
595
|
+
{
|
|
596
|
+
status: 200,
|
|
597
|
+
headers: { "Content-Type": "application/json", ...corsHeaders }
|
|
598
|
+
}
|
|
599
|
+
);
|
|
600
|
+
|
|
601
|
+
} catch (error: any) {
|
|
602
|
+
console.error("Image generation error:", error);
|
|
603
|
+
return new Response(
|
|
604
|
+
JSON.stringify({ error: error.message || "Unknown error" }),
|
|
605
|
+
{
|
|
606
|
+
status: 500,
|
|
607
|
+
headers: { "Content-Type": "application/json", ...corsHeaders }
|
|
608
|
+
}
|
|
609
|
+
);
|
|
610
|
+
}
|
|
611
|
+
};
|
|
612
|
+
|
|
613
|
+
serve(handler);
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
**Frontend Usage Example:**
|
|
617
|
+
|
|
618
|
+
```typescript
|
|
619
|
+
import { useState } from 'react';
|
|
620
|
+
import { supabase } from '@/lib/supabase';
|
|
621
|
+
import { toast } from 'sonner';
|
|
622
|
+
|
|
623
|
+
export function ImageGenerator() {
|
|
624
|
+
const [isGenerating, setIsGenerating] = useState(false);
|
|
625
|
+
const [generatedImage, setGeneratedImage] = useState<string | null>(null);
|
|
626
|
+
|
|
627
|
+
const handleGenerate = async (prompt: string) => {
|
|
628
|
+
setIsGenerating(true);
|
|
629
|
+
|
|
630
|
+
try {
|
|
631
|
+
const { data, error } = await supabase.functions.invoke('generate-image', {
|
|
632
|
+
body: {
|
|
633
|
+
prompt,
|
|
634
|
+
options: {
|
|
635
|
+
size: '1024x1024',
|
|
636
|
+
quality: 'high'
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
if (error) throw error;
|
|
642
|
+
if (data?.error) throw new Error(data.error);
|
|
643
|
+
|
|
644
|
+
setGeneratedImage(data.imageUrl);
|
|
645
|
+
toast.success("图片生成成功!");
|
|
646
|
+
} catch (error) {
|
|
647
|
+
console.error("Image generation error:", error);
|
|
648
|
+
toast.error(error instanceof Error ? error.message : "图片生成失败");
|
|
649
|
+
} finally {
|
|
650
|
+
setIsGenerating(false);
|
|
651
|
+
}
|
|
652
|
+
};
|
|
653
|
+
|
|
654
|
+
return (
|
|
655
|
+
<div>
|
|
656
|
+
{generatedImage && <img src={generatedImage} alt="Generated" />}
|
|
657
|
+
{/* UI components */}
|
|
658
|
+
</div>
|
|
659
|
+
);
|
|
660
|
+
}
|
|
661
|
+
```
|
|
662
|
+
|
|
518
663
|
### Image Analysis Specialized Template
|
|
519
664
|
|
|
520
665
|
Use this template when users need image analysis functionality.
|
|
@@ -563,19 +708,12 @@ const handler = async (req: Request): Promise<Response> => {
|
|
|
563
708
|
);
|
|
564
709
|
}
|
|
565
710
|
|
|
566
|
-
// Get AI API key from environment
|
|
567
|
-
const AI_API_KEY = Deno.env.get("AI_API_KEY");
|
|
568
|
-
if (!AI_API_KEY) {
|
|
569
|
-
throw new Error("AI service not configured");
|
|
570
|
-
}
|
|
571
|
-
|
|
572
711
|
console.log("Analyzing image...");
|
|
573
712
|
|
|
574
713
|
// Call AI Gateway API
|
|
575
714
|
const response = await fetch("https://ai.gateway.needware.dev/v1/chat/completions", {
|
|
576
715
|
method: "POST",
|
|
577
716
|
headers: {
|
|
578
|
-
"Authorization": `Bearer ${AI_API_KEY}`,
|
|
579
717
|
"Content-Type": "application/json",
|
|
580
718
|
},
|
|
581
719
|
body: JSON.stringify({
|
|
@@ -660,7 +798,8 @@ serve(handler);
|
|
|
660
798
|
When users request AI integration, follow these steps:
|
|
661
799
|
|
|
662
800
|
### Step 1: Requirements Analysis
|
|
663
|
-
- [ ] Confirm AI functionality type (image/text/speech/other)
|
|
801
|
+
- [ ] Confirm AI functionality type (image analysis/image generation/text/speech/other)
|
|
802
|
+
- [ ] If image generation: Use `gemini-3-pro-image-preview` model 🎨
|
|
664
803
|
- [ ] Confirm input/output formats
|
|
665
804
|
- [ ] Confirm if structured response is needed
|
|
666
805
|
- [ ] Confirm performance requirements (response time, concurrency)
|
|
@@ -696,76 +835,10 @@ pnpm add @supabase/supabase-js
|
|
|
696
835
|
- Function names should clearly express functionality
|
|
697
836
|
- Each feature gets its own independent function directory
|
|
698
837
|
|
|
699
|
-
### Step 6: Configure Environment Variables
|
|
700
|
-
|
|
701
|
-
**Configure in Supabase Dashboard:**
|
|
702
|
-
1. Go to Project Settings → Edge Functions → Secrets
|
|
703
|
-
2. Add environment variables:
|
|
704
|
-
- `AI_API_KEY`: Your AI service API key
|
|
705
|
-
- `AI_MODEL`: (Optional) Default model name
|
|
706
|
-
- `AI_MAX_TOKENS`: (Optional) Maximum token count
|
|
707
|
-
|
|
708
|
-
**Or use Supabase CLI:**
|
|
709
|
-
```bash
|
|
710
|
-
# Set secrets
|
|
711
|
-
supabase secrets set AI_API_KEY=your_api_key_here
|
|
712
|
-
supabase secrets set AI_MODEL=google/gemini-2.5-flash
|
|
713
|
-
supabase secrets set AI_MAX_TOKENS=2000
|
|
714
|
-
```
|
|
715
|
-
|
|
716
|
-
**Local Development Environment Variables:**
|
|
717
|
-
Create `supabase/.env.local` file (for Supabase Functions):
|
|
718
|
-
```bash
|
|
719
|
-
AI_API_KEY=your_api_key_here
|
|
720
|
-
AI_MODEL=google/gemini-2.5-flash
|
|
721
|
-
AI_MAX_TOKENS=2000
|
|
722
|
-
```
|
|
723
|
-
|
|
724
|
-
**Frontend Environment Variables:**
|
|
725
|
-
Configure in `.env` or `.env.local` file:
|
|
726
|
-
```bash
|
|
727
|
-
VITE_SUPABASE_URL=your_supabase_project_url
|
|
728
|
-
VITE_SUPABASE_ANON_KEY=your_supabase_anon_key
|
|
729
|
-
```
|
|
730
|
-
|
|
731
|
-
### Step 7: Testing
|
|
732
|
-
|
|
733
|
-
**Test Supabase Function Locally:**
|
|
734
|
-
```bash
|
|
735
|
-
# Start local Supabase
|
|
736
|
-
supabase start
|
|
737
|
-
|
|
738
|
-
# Deploy function locally
|
|
739
|
-
supabase functions serve <function-name>
|
|
740
|
-
|
|
741
|
-
# Test invocation (text example)
|
|
742
|
-
curl -i --location --request POST 'http://localhost:54321/functions/v1/<function-name>' \
|
|
743
|
-
--header 'Authorization: Bearer YOUR_ANON_KEY' \
|
|
744
|
-
--header 'Content-Type: application/json' \
|
|
745
|
-
--data '{"text":"test text","options":{"model":"google/gemini-2.5-flash"}}'
|
|
746
|
-
|
|
747
|
-
# Test invocation (image example)
|
|
748
|
-
curl -i --location --request POST 'http://localhost:54321/functions/v1/<function-name>' \
|
|
749
|
-
--header 'Authorization: Bearer YOUR_ANON_KEY' \
|
|
750
|
-
--header 'Content-Type: application/json' \
|
|
751
|
-
--data '{"image":"data:image/png;base64,...","prompt":"Please analyze this image"}'
|
|
752
|
-
```
|
|
753
|
-
|
|
754
|
-
**Deploy to Production:**
|
|
755
|
-
```bash
|
|
756
|
-
# Deploy function
|
|
757
|
-
supabase functions deploy <function-name>
|
|
758
|
-
|
|
759
|
-
# View logs
|
|
760
|
-
supabase functions logs <function-name>
|
|
761
|
-
```
|
|
762
|
-
|
|
763
838
|
|
|
764
839
|
## Best Practices
|
|
765
840
|
|
|
766
841
|
### Security
|
|
767
|
-
- ✅ **Never** expose API keys in the frontend
|
|
768
|
-
- ✅ Use environment variables to store sensitive information
|
|
769
842
|
- ✅ Implement request rate limiting
|
|
770
843
|
- ✅ Validate and sanitize user input
|
|
771
844
|
- ✅ Add request size limits
|
|
@@ -784,7 +857,7 @@ supabase functions logs <function-name>
|
|
|
784
857
|
const handleAIError = (error: any, statusCode: number) => {
|
|
785
858
|
const errorMap: Record<number, string> = {
|
|
786
859
|
400: "Invalid request parameters",
|
|
787
|
-
401: "
|
|
860
|
+
401: "Authentication failed",
|
|
788
861
|
402: "Insufficient account balance or quota exhausted",
|
|
789
862
|
403: "No permission to access this API",
|
|
790
863
|
404: "API endpoint does not exist",
|
|
@@ -814,11 +887,10 @@ const handleAIError = (error: any, statusCode: number) => {
|
|
|
814
887
|
|
|
815
888
|
**After completing AI integration, must:**
|
|
816
889
|
1. ✅ Test all error scenarios
|
|
817
|
-
2. ✅
|
|
818
|
-
3. ✅
|
|
819
|
-
4. ✅
|
|
820
|
-
5. ✅
|
|
821
|
-
6. ✅ Add usage documentation and examples
|
|
890
|
+
2. ✅ Check response format correctness
|
|
891
|
+
3. ✅ Test edge cases (extra-long input, special characters, etc.)
|
|
892
|
+
4. ✅ Confirm smooth user experience
|
|
893
|
+
5. ✅ Add usage documentation and examples
|
|
822
894
|
|
|
823
895
|
**Remember: AI integration is not "set it and forget it", requires continuous monitoring and optimization.**
|
|
824
896
|
|