miragedev-sdk 0.4.0 → 0.5.1
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/README.md +82 -3
- package/dist/ai/index.cjs +184 -0
- package/dist/ai/index.d.cts +37 -3
- package/dist/ai/index.d.ts +37 -3
- package/dist/ai/index.js +182 -1
- package/dist/{ai-B4sdf-PH.d.cts → ai-CdJK6ox8.d.cts} +21 -1
- package/dist/{ai-B4sdf-PH.d.ts → ai-CdJK6ox8.d.ts} +21 -1
- package/dist/index.d.cts +8 -8
- package/dist/index.d.ts +8 -8
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -32,7 +32,7 @@ AI-first SDK for building SAAS applications with Next.js. Build production-ready
|
|
|
32
32
|
### Option 1: Create New Project (Recommended)
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
|
-
npx miragedev create my-saas
|
|
35
|
+
npx miragedev-sdk create my-saas
|
|
36
36
|
cd my-saas
|
|
37
37
|
npm run dev
|
|
38
38
|
```
|
|
@@ -62,7 +62,7 @@ npm install posthog-node # For analytics
|
|
|
62
62
|
npm install @upstash/redis # For limits
|
|
63
63
|
npm install @trigger.dev/sdk # For jobs
|
|
64
64
|
|
|
65
|
-
npx miragedev init
|
|
65
|
+
npx miragedev-sdk init
|
|
66
66
|
```
|
|
67
67
|
|
|
68
68
|
**What gets created:**
|
|
@@ -402,14 +402,93 @@ const response = await createEmbeddings({
|
|
|
402
402
|
console.log(response.embeddings[0]) // [0.123, -0.456, ...]
|
|
403
403
|
```
|
|
404
404
|
|
|
405
|
+
**Image Generation:**
|
|
406
|
+
|
|
407
|
+
```typescript
|
|
408
|
+
import { generateImage } from 'miragedev-sdk/ai'
|
|
409
|
+
|
|
410
|
+
const result = await generateImage({
|
|
411
|
+
prompt: 'A serene mountain landscape at sunset',
|
|
412
|
+
model: 'dall-e-3',
|
|
413
|
+
size: '1024x1024',
|
|
414
|
+
quality: 'standard'
|
|
415
|
+
})
|
|
416
|
+
|
|
417
|
+
console.log(result.images[0].url) // https://oaidalleapiprodscus.blob...
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
**Client-Side Hook:**
|
|
421
|
+
|
|
422
|
+
```typescript
|
|
423
|
+
'use client'
|
|
424
|
+
import { useImageGeneration } from 'miragedev-sdk/ai'
|
|
425
|
+
|
|
426
|
+
export function ImageGenerator() {
|
|
427
|
+
const { generate, isLoading, result } = useImageGeneration()
|
|
428
|
+
|
|
429
|
+
return (
|
|
430
|
+
<div>
|
|
431
|
+
<button onClick={() => generate('A sunset')}>
|
|
432
|
+
{isLoading ? 'Generating...' : 'Generate'}
|
|
433
|
+
</button>
|
|
434
|
+
{result && <img src={result.images[0].url} alt="Generated" />}
|
|
435
|
+
</div>
|
|
436
|
+
)
|
|
437
|
+
}
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
**With Rate Limiting:**
|
|
441
|
+
|
|
442
|
+
```typescript
|
|
443
|
+
import { generateImage } from 'miragedev-sdk/ai'
|
|
444
|
+
import { checkRateLimit } from 'miragedev-sdk/limits'
|
|
445
|
+
|
|
446
|
+
const limit = await checkRateLimit({
|
|
447
|
+
key: `images:${userId}`,
|
|
448
|
+
limit: 10,
|
|
449
|
+
window: 3600
|
|
450
|
+
})
|
|
451
|
+
|
|
452
|
+
if (!limit.allowed) {
|
|
453
|
+
throw new Error('Rate limit exceeded')
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
const result = await generateImage({ prompt: 'A sunset' })
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
**Save to Permanent Storage:**
|
|
460
|
+
|
|
461
|
+
```typescript
|
|
462
|
+
import { generateImage } from 'miragedev-sdk/ai'
|
|
463
|
+
import { uploadFile } from 'miragedev-sdk/storage'
|
|
464
|
+
|
|
465
|
+
const result = await generateImage({ prompt: 'A sunset' })
|
|
466
|
+
|
|
467
|
+
// Download and upload to R2
|
|
468
|
+
const response = await fetch(result.images[0].url)
|
|
469
|
+
const buffer = await response.arrayBuffer()
|
|
470
|
+
|
|
471
|
+
await uploadFile({
|
|
472
|
+
file: Buffer.from(buffer),
|
|
473
|
+
key: `images/${userId}/${Date.now()}.png`,
|
|
474
|
+
contentType: 'image/png'
|
|
475
|
+
})
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
**Cost Warning:** DALL-E 3 costs $0.04-$0.12 per image. Always implement rate limiting.
|
|
479
|
+
|
|
405
480
|
**Environment Variables:**
|
|
406
481
|
|
|
407
482
|
```env
|
|
408
483
|
OPENAI_API_KEY=sk-...
|
|
409
484
|
```
|
|
410
485
|
|
|
486
|
+
**Supported Models:**
|
|
487
|
+
- ✅ DALL-E 2 (256x256, 512x512, 1024x1024)
|
|
488
|
+
- ✅ DALL-E 3 (1024x1024, 1792x1024, 1024x1792, HD quality)
|
|
489
|
+
|
|
411
490
|
**Supported Providers:**
|
|
412
|
-
- ✅ OpenAI (GPT-4, GPT-3.5, embeddings)
|
|
491
|
+
- ✅ OpenAI (GPT-4, GPT-3.5, embeddings, DALL-E)
|
|
413
492
|
- 🔜 Anthropic (Claude) - Coming soon
|
|
414
493
|
|
|
415
494
|
### 📦 Storage Module
|
package/dist/ai/index.cjs
CHANGED
|
@@ -4,6 +4,7 @@ var chunkTALL2IL5_cjs = require('../chunk-TALL2IL5.cjs');
|
|
|
4
4
|
var chunkBW4BLEIM_cjs = require('../chunk-BW4BLEIM.cjs');
|
|
5
5
|
require('../chunk-75ZPJI57.cjs');
|
|
6
6
|
var OpenAI = require('openai');
|
|
7
|
+
var react = require('react');
|
|
7
8
|
|
|
8
9
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
10
|
|
|
@@ -238,6 +239,59 @@ var OpenAIProvider = class {
|
|
|
238
239
|
);
|
|
239
240
|
}
|
|
240
241
|
}
|
|
242
|
+
/**
|
|
243
|
+
* Generate images from text prompts
|
|
244
|
+
*/
|
|
245
|
+
async generateImage(options) {
|
|
246
|
+
try {
|
|
247
|
+
if (!options.prompt || options.prompt.trim() === "") {
|
|
248
|
+
throw new chunkBW4BLEIM_cjs.MirageDevError(
|
|
249
|
+
"AI_CONFIG_INVALID",
|
|
250
|
+
"Prompt cannot be empty"
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
const model = options.model || "dall-e-3";
|
|
254
|
+
if (model === "dall-e-3" && options.n && options.n > 1) {
|
|
255
|
+
throw new chunkBW4BLEIM_cjs.MirageDevError(
|
|
256
|
+
"AI_CONFIG_INVALID",
|
|
257
|
+
"DALL-E 3 only supports generating 1 image at a time"
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
const params = {
|
|
261
|
+
model,
|
|
262
|
+
prompt: options.prompt,
|
|
263
|
+
n: options.n || 1,
|
|
264
|
+
size: options.size || "1024x1024",
|
|
265
|
+
response_format: options.responseFormat || "url"
|
|
266
|
+
};
|
|
267
|
+
if (model === "dall-e-3") {
|
|
268
|
+
if (options.quality) params.quality = options.quality;
|
|
269
|
+
if (options.style) params.style = options.style;
|
|
270
|
+
}
|
|
271
|
+
const response = await this.client.images.generate(params);
|
|
272
|
+
const result = {
|
|
273
|
+
images: (response.data || []).map((img) => ({
|
|
274
|
+
url: img.url || "",
|
|
275
|
+
revisedPrompt: img.revised_prompt
|
|
276
|
+
})),
|
|
277
|
+
metadata: {
|
|
278
|
+
model,
|
|
279
|
+
size: params.size || "1024x1024",
|
|
280
|
+
quality: params.quality || void 0
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
return result;
|
|
284
|
+
} catch (error) {
|
|
285
|
+
if (error instanceof chunkBW4BLEIM_cjs.MirageDevError) {
|
|
286
|
+
throw error;
|
|
287
|
+
}
|
|
288
|
+
throw new chunkBW4BLEIM_cjs.MirageDevError(
|
|
289
|
+
"AI_API_ERROR",
|
|
290
|
+
error instanceof Error ? error.message : "Unknown error occurred",
|
|
291
|
+
error
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
241
295
|
/**
|
|
242
296
|
* Map OpenAI finish reason to our format
|
|
243
297
|
*/
|
|
@@ -353,6 +407,129 @@ data: ${data}
|
|
|
353
407
|
}
|
|
354
408
|
});
|
|
355
409
|
}
|
|
410
|
+
function useChat(options = {}) {
|
|
411
|
+
const {
|
|
412
|
+
initialMessages = [],
|
|
413
|
+
stream = false,
|
|
414
|
+
model,
|
|
415
|
+
temperature,
|
|
416
|
+
maxTokens,
|
|
417
|
+
onMessage,
|
|
418
|
+
onResponse,
|
|
419
|
+
onError
|
|
420
|
+
} = options;
|
|
421
|
+
const [messages, setMessages] = react.useState(initialMessages);
|
|
422
|
+
const [streamingMessage, setStreamingMessage] = react.useState(null);
|
|
423
|
+
const [isLoading, setIsLoading] = react.useState(false);
|
|
424
|
+
const [error, setError] = react.useState(null);
|
|
425
|
+
const sendMessage = react.useCallback(
|
|
426
|
+
async (content) => {
|
|
427
|
+
const userMessage = { role: "user", content };
|
|
428
|
+
setMessages((prev) => [...prev, userMessage]);
|
|
429
|
+
setIsLoading(true);
|
|
430
|
+
setError(null);
|
|
431
|
+
onMessage?.(userMessage);
|
|
432
|
+
try {
|
|
433
|
+
if (stream) {
|
|
434
|
+
setStreamingMessage("");
|
|
435
|
+
await chatStream(
|
|
436
|
+
{
|
|
437
|
+
messages: [...messages, userMessage],
|
|
438
|
+
model,
|
|
439
|
+
temperature,
|
|
440
|
+
maxTokens
|
|
441
|
+
},
|
|
442
|
+
(chunk) => {
|
|
443
|
+
setStreamingMessage(chunk.content);
|
|
444
|
+
if (chunk.isComplete) {
|
|
445
|
+
const aiMessage = {
|
|
446
|
+
role: "assistant",
|
|
447
|
+
content: chunk.content
|
|
448
|
+
};
|
|
449
|
+
setMessages((prev) => [...prev, aiMessage]);
|
|
450
|
+
setStreamingMessage(null);
|
|
451
|
+
setIsLoading(false);
|
|
452
|
+
onResponse?.(aiMessage);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
);
|
|
456
|
+
} else {
|
|
457
|
+
const response = await chat({
|
|
458
|
+
messages: [...messages, userMessage],
|
|
459
|
+
model,
|
|
460
|
+
temperature,
|
|
461
|
+
maxTokens
|
|
462
|
+
});
|
|
463
|
+
const aiMessage = {
|
|
464
|
+
role: response.role,
|
|
465
|
+
content: response.content
|
|
466
|
+
};
|
|
467
|
+
setMessages((prev) => [...prev, aiMessage]);
|
|
468
|
+
setIsLoading(false);
|
|
469
|
+
onResponse?.(aiMessage);
|
|
470
|
+
}
|
|
471
|
+
} catch (err) {
|
|
472
|
+
const error2 = err instanceof Error ? err : new Error("Chat failed");
|
|
473
|
+
setError(error2);
|
|
474
|
+
setIsLoading(false);
|
|
475
|
+
onError?.(error2);
|
|
476
|
+
}
|
|
477
|
+
},
|
|
478
|
+
[messages, stream, model, temperature, maxTokens, onMessage, onResponse, onError]
|
|
479
|
+
);
|
|
480
|
+
const clear = react.useCallback(() => {
|
|
481
|
+
setMessages([]);
|
|
482
|
+
setStreamingMessage(null);
|
|
483
|
+
setError(null);
|
|
484
|
+
}, []);
|
|
485
|
+
return {
|
|
486
|
+
messages,
|
|
487
|
+
streamingMessage,
|
|
488
|
+
isLoading,
|
|
489
|
+
error,
|
|
490
|
+
sendMessage,
|
|
491
|
+
clear
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
function useImageGeneration(options) {
|
|
495
|
+
const [isLoading, setIsLoading] = react.useState(false);
|
|
496
|
+
const [error, setError] = react.useState(null);
|
|
497
|
+
const [result, setResult] = react.useState(null);
|
|
498
|
+
const generate = react.useCallback(async (prompt, imageOptions) => {
|
|
499
|
+
setIsLoading(true);
|
|
500
|
+
setError(null);
|
|
501
|
+
try {
|
|
502
|
+
const response = await fetch(options?.endpoint || "/api/ai/generate-image", {
|
|
503
|
+
method: "POST",
|
|
504
|
+
headers: { "Content-Type": "application/json" },
|
|
505
|
+
body: JSON.stringify({
|
|
506
|
+
prompt,
|
|
507
|
+
...imageOptions
|
|
508
|
+
})
|
|
509
|
+
});
|
|
510
|
+
if (!response.ok) {
|
|
511
|
+
throw new Error(`HTTP ${response.status}: ${await response.text()}`);
|
|
512
|
+
}
|
|
513
|
+
const data = await response.json();
|
|
514
|
+
setResult(data);
|
|
515
|
+
options?.onSuccess?.(data);
|
|
516
|
+
return data;
|
|
517
|
+
} catch (err) {
|
|
518
|
+
const error2 = err instanceof Error ? err : new Error("Unknown error");
|
|
519
|
+
setError(error2);
|
|
520
|
+
options?.onError?.(error2);
|
|
521
|
+
throw error2;
|
|
522
|
+
} finally {
|
|
523
|
+
setIsLoading(false);
|
|
524
|
+
}
|
|
525
|
+
}, [options]);
|
|
526
|
+
const reset = react.useCallback(() => {
|
|
527
|
+
setIsLoading(false);
|
|
528
|
+
setError(null);
|
|
529
|
+
setResult(null);
|
|
530
|
+
}, []);
|
|
531
|
+
return { generate, isLoading, error, result, reset };
|
|
532
|
+
}
|
|
356
533
|
|
|
357
534
|
// src/ai/index.ts
|
|
358
535
|
async function chat(options) {
|
|
@@ -367,6 +544,10 @@ async function createEmbeddings(options) {
|
|
|
367
544
|
const provider = getAIProvider();
|
|
368
545
|
return provider.createEmbeddings(options);
|
|
369
546
|
}
|
|
547
|
+
async function generateImage(options) {
|
|
548
|
+
const provider = getAIProvider();
|
|
549
|
+
return provider.generateImage(options);
|
|
550
|
+
}
|
|
370
551
|
|
|
371
552
|
Object.defineProperty(exports, "getAIConfig", {
|
|
372
553
|
enumerable: true,
|
|
@@ -381,3 +562,6 @@ exports.chatStream = chatStream;
|
|
|
381
562
|
exports.createEdgeStreamResponse = createEdgeStreamResponse;
|
|
382
563
|
exports.createEmbeddings = createEmbeddings;
|
|
383
564
|
exports.createSSEStream = createSSEStream;
|
|
565
|
+
exports.generateImage = generateImage;
|
|
566
|
+
exports.useChat = useChat;
|
|
567
|
+
exports.useImageGeneration = useImageGeneration;
|
package/dist/ai/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as AIConfig, C as ChatOptions,
|
|
2
|
-
export {
|
|
1
|
+
import { A as AIConfig, c as AIMessage, g as ImageGenerationResponse, I as ImageGenerationOptions, C as ChatOptions, e as ChatResponse, S as StreamChunk, E as EmbeddingOptions, f as EmbeddingResponse } from '../ai-CdJK6ox8.cjs';
|
|
2
|
+
export { d as AIFunction, a as AIProvider, b as AIRole } from '../ai-CdJK6ox8.cjs';
|
|
3
3
|
|
|
4
4
|
declare function setAIConfig(config: Partial<AIConfig>): void;
|
|
5
5
|
declare function getAIConfig(): AIConfig;
|
|
@@ -7,8 +7,42 @@ declare function getAIConfig(): AIConfig;
|
|
|
7
7
|
declare function createEdgeStreamResponse(callback: (write: (data: string) => Promise<void>) => Promise<void>): Response;
|
|
8
8
|
declare function createSSEStream(callback: (send: (event: string, data: string) => Promise<void>) => Promise<void>): Response;
|
|
9
9
|
|
|
10
|
+
interface UseChatOptions {
|
|
11
|
+
initialMessages?: AIMessage[];
|
|
12
|
+
stream?: boolean;
|
|
13
|
+
model?: string;
|
|
14
|
+
temperature?: number;
|
|
15
|
+
maxTokens?: number;
|
|
16
|
+
onMessage?: (message: AIMessage) => void;
|
|
17
|
+
onResponse?: (message: AIMessage) => void;
|
|
18
|
+
onError?: (error: Error) => void;
|
|
19
|
+
}
|
|
20
|
+
interface UseChatReturn {
|
|
21
|
+
messages: AIMessage[];
|
|
22
|
+
streamingMessage: string | null;
|
|
23
|
+
isLoading: boolean;
|
|
24
|
+
error: Error | null;
|
|
25
|
+
sendMessage: (content: string) => Promise<void>;
|
|
26
|
+
clear: () => void;
|
|
27
|
+
}
|
|
28
|
+
declare function useChat(options?: UseChatOptions): UseChatReturn;
|
|
29
|
+
|
|
30
|
+
interface UseImageGenerationOptions {
|
|
31
|
+
onSuccess?: (result: ImageGenerationResponse) => void;
|
|
32
|
+
onError?: (error: Error) => void;
|
|
33
|
+
endpoint?: string;
|
|
34
|
+
}
|
|
35
|
+
declare function useImageGeneration(options?: UseImageGenerationOptions): {
|
|
36
|
+
generate: (prompt: string, imageOptions?: Partial<ImageGenerationOptions>) => Promise<any>;
|
|
37
|
+
isLoading: boolean;
|
|
38
|
+
error: Error | null;
|
|
39
|
+
result: ImageGenerationResponse | null;
|
|
40
|
+
reset: () => void;
|
|
41
|
+
};
|
|
42
|
+
|
|
10
43
|
declare function chat(options: ChatOptions): Promise<ChatResponse>;
|
|
11
44
|
declare function chatStream(options: ChatOptions, onChunk: (chunk: StreamChunk) => void): Promise<void>;
|
|
12
45
|
declare function createEmbeddings(options: EmbeddingOptions): Promise<EmbeddingResponse>;
|
|
46
|
+
declare function generateImage(options: ImageGenerationOptions): Promise<ImageGenerationResponse>;
|
|
13
47
|
|
|
14
|
-
export { AIConfig, ChatOptions, ChatResponse, EmbeddingOptions, EmbeddingResponse, StreamChunk, chat, chatStream, createEdgeStreamResponse, createEmbeddings, createSSEStream, getAIConfig, setAIConfig };
|
|
48
|
+
export { AIConfig, AIMessage, ChatOptions, ChatResponse, EmbeddingOptions, EmbeddingResponse, ImageGenerationOptions, ImageGenerationResponse, StreamChunk, chat, chatStream, createEdgeStreamResponse, createEmbeddings, createSSEStream, generateImage, getAIConfig, setAIConfig, useChat, useImageGeneration };
|
package/dist/ai/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as AIConfig, C as ChatOptions,
|
|
2
|
-
export {
|
|
1
|
+
import { A as AIConfig, c as AIMessage, g as ImageGenerationResponse, I as ImageGenerationOptions, C as ChatOptions, e as ChatResponse, S as StreamChunk, E as EmbeddingOptions, f as EmbeddingResponse } from '../ai-CdJK6ox8.js';
|
|
2
|
+
export { d as AIFunction, a as AIProvider, b as AIRole } from '../ai-CdJK6ox8.js';
|
|
3
3
|
|
|
4
4
|
declare function setAIConfig(config: Partial<AIConfig>): void;
|
|
5
5
|
declare function getAIConfig(): AIConfig;
|
|
@@ -7,8 +7,42 @@ declare function getAIConfig(): AIConfig;
|
|
|
7
7
|
declare function createEdgeStreamResponse(callback: (write: (data: string) => Promise<void>) => Promise<void>): Response;
|
|
8
8
|
declare function createSSEStream(callback: (send: (event: string, data: string) => Promise<void>) => Promise<void>): Response;
|
|
9
9
|
|
|
10
|
+
interface UseChatOptions {
|
|
11
|
+
initialMessages?: AIMessage[];
|
|
12
|
+
stream?: boolean;
|
|
13
|
+
model?: string;
|
|
14
|
+
temperature?: number;
|
|
15
|
+
maxTokens?: number;
|
|
16
|
+
onMessage?: (message: AIMessage) => void;
|
|
17
|
+
onResponse?: (message: AIMessage) => void;
|
|
18
|
+
onError?: (error: Error) => void;
|
|
19
|
+
}
|
|
20
|
+
interface UseChatReturn {
|
|
21
|
+
messages: AIMessage[];
|
|
22
|
+
streamingMessage: string | null;
|
|
23
|
+
isLoading: boolean;
|
|
24
|
+
error: Error | null;
|
|
25
|
+
sendMessage: (content: string) => Promise<void>;
|
|
26
|
+
clear: () => void;
|
|
27
|
+
}
|
|
28
|
+
declare function useChat(options?: UseChatOptions): UseChatReturn;
|
|
29
|
+
|
|
30
|
+
interface UseImageGenerationOptions {
|
|
31
|
+
onSuccess?: (result: ImageGenerationResponse) => void;
|
|
32
|
+
onError?: (error: Error) => void;
|
|
33
|
+
endpoint?: string;
|
|
34
|
+
}
|
|
35
|
+
declare function useImageGeneration(options?: UseImageGenerationOptions): {
|
|
36
|
+
generate: (prompt: string, imageOptions?: Partial<ImageGenerationOptions>) => Promise<any>;
|
|
37
|
+
isLoading: boolean;
|
|
38
|
+
error: Error | null;
|
|
39
|
+
result: ImageGenerationResponse | null;
|
|
40
|
+
reset: () => void;
|
|
41
|
+
};
|
|
42
|
+
|
|
10
43
|
declare function chat(options: ChatOptions): Promise<ChatResponse>;
|
|
11
44
|
declare function chatStream(options: ChatOptions, onChunk: (chunk: StreamChunk) => void): Promise<void>;
|
|
12
45
|
declare function createEmbeddings(options: EmbeddingOptions): Promise<EmbeddingResponse>;
|
|
46
|
+
declare function generateImage(options: ImageGenerationOptions): Promise<ImageGenerationResponse>;
|
|
13
47
|
|
|
14
|
-
export { AIConfig, ChatOptions, ChatResponse, EmbeddingOptions, EmbeddingResponse, StreamChunk, chat, chatStream, createEdgeStreamResponse, createEmbeddings, createSSEStream, getAIConfig, setAIConfig };
|
|
48
|
+
export { AIConfig, AIMessage, ChatOptions, ChatResponse, EmbeddingOptions, EmbeddingResponse, ImageGenerationOptions, ImageGenerationResponse, StreamChunk, chat, chatStream, createEdgeStreamResponse, createEmbeddings, createSSEStream, generateImage, getAIConfig, setAIConfig, useChat, useImageGeneration };
|
package/dist/ai/index.js
CHANGED
|
@@ -3,6 +3,7 @@ export { getAIConfig, setAIConfig } from '../chunk-6YFK3S4F.js';
|
|
|
3
3
|
import { MirageDevError } from '../chunk-JUTTFY3W.js';
|
|
4
4
|
import '../chunk-MLKGABMK.js';
|
|
5
5
|
import OpenAI from 'openai';
|
|
6
|
+
import { useState, useCallback } from 'react';
|
|
6
7
|
|
|
7
8
|
var OpenAIProvider = class {
|
|
8
9
|
client;
|
|
@@ -233,6 +234,59 @@ var OpenAIProvider = class {
|
|
|
233
234
|
);
|
|
234
235
|
}
|
|
235
236
|
}
|
|
237
|
+
/**
|
|
238
|
+
* Generate images from text prompts
|
|
239
|
+
*/
|
|
240
|
+
async generateImage(options) {
|
|
241
|
+
try {
|
|
242
|
+
if (!options.prompt || options.prompt.trim() === "") {
|
|
243
|
+
throw new MirageDevError(
|
|
244
|
+
"AI_CONFIG_INVALID",
|
|
245
|
+
"Prompt cannot be empty"
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
const model = options.model || "dall-e-3";
|
|
249
|
+
if (model === "dall-e-3" && options.n && options.n > 1) {
|
|
250
|
+
throw new MirageDevError(
|
|
251
|
+
"AI_CONFIG_INVALID",
|
|
252
|
+
"DALL-E 3 only supports generating 1 image at a time"
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
const params = {
|
|
256
|
+
model,
|
|
257
|
+
prompt: options.prompt,
|
|
258
|
+
n: options.n || 1,
|
|
259
|
+
size: options.size || "1024x1024",
|
|
260
|
+
response_format: options.responseFormat || "url"
|
|
261
|
+
};
|
|
262
|
+
if (model === "dall-e-3") {
|
|
263
|
+
if (options.quality) params.quality = options.quality;
|
|
264
|
+
if (options.style) params.style = options.style;
|
|
265
|
+
}
|
|
266
|
+
const response = await this.client.images.generate(params);
|
|
267
|
+
const result = {
|
|
268
|
+
images: (response.data || []).map((img) => ({
|
|
269
|
+
url: img.url || "",
|
|
270
|
+
revisedPrompt: img.revised_prompt
|
|
271
|
+
})),
|
|
272
|
+
metadata: {
|
|
273
|
+
model,
|
|
274
|
+
size: params.size || "1024x1024",
|
|
275
|
+
quality: params.quality || void 0
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
return result;
|
|
279
|
+
} catch (error) {
|
|
280
|
+
if (error instanceof MirageDevError) {
|
|
281
|
+
throw error;
|
|
282
|
+
}
|
|
283
|
+
throw new MirageDevError(
|
|
284
|
+
"AI_API_ERROR",
|
|
285
|
+
error instanceof Error ? error.message : "Unknown error occurred",
|
|
286
|
+
error
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
236
290
|
/**
|
|
237
291
|
* Map OpenAI finish reason to our format
|
|
238
292
|
*/
|
|
@@ -348,6 +402,129 @@ data: ${data}
|
|
|
348
402
|
}
|
|
349
403
|
});
|
|
350
404
|
}
|
|
405
|
+
function useChat(options = {}) {
|
|
406
|
+
const {
|
|
407
|
+
initialMessages = [],
|
|
408
|
+
stream = false,
|
|
409
|
+
model,
|
|
410
|
+
temperature,
|
|
411
|
+
maxTokens,
|
|
412
|
+
onMessage,
|
|
413
|
+
onResponse,
|
|
414
|
+
onError
|
|
415
|
+
} = options;
|
|
416
|
+
const [messages, setMessages] = useState(initialMessages);
|
|
417
|
+
const [streamingMessage, setStreamingMessage] = useState(null);
|
|
418
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
419
|
+
const [error, setError] = useState(null);
|
|
420
|
+
const sendMessage = useCallback(
|
|
421
|
+
async (content) => {
|
|
422
|
+
const userMessage = { role: "user", content };
|
|
423
|
+
setMessages((prev) => [...prev, userMessage]);
|
|
424
|
+
setIsLoading(true);
|
|
425
|
+
setError(null);
|
|
426
|
+
onMessage?.(userMessage);
|
|
427
|
+
try {
|
|
428
|
+
if (stream) {
|
|
429
|
+
setStreamingMessage("");
|
|
430
|
+
await chatStream(
|
|
431
|
+
{
|
|
432
|
+
messages: [...messages, userMessage],
|
|
433
|
+
model,
|
|
434
|
+
temperature,
|
|
435
|
+
maxTokens
|
|
436
|
+
},
|
|
437
|
+
(chunk) => {
|
|
438
|
+
setStreamingMessage(chunk.content);
|
|
439
|
+
if (chunk.isComplete) {
|
|
440
|
+
const aiMessage = {
|
|
441
|
+
role: "assistant",
|
|
442
|
+
content: chunk.content
|
|
443
|
+
};
|
|
444
|
+
setMessages((prev) => [...prev, aiMessage]);
|
|
445
|
+
setStreamingMessage(null);
|
|
446
|
+
setIsLoading(false);
|
|
447
|
+
onResponse?.(aiMessage);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
);
|
|
451
|
+
} else {
|
|
452
|
+
const response = await chat({
|
|
453
|
+
messages: [...messages, userMessage],
|
|
454
|
+
model,
|
|
455
|
+
temperature,
|
|
456
|
+
maxTokens
|
|
457
|
+
});
|
|
458
|
+
const aiMessage = {
|
|
459
|
+
role: response.role,
|
|
460
|
+
content: response.content
|
|
461
|
+
};
|
|
462
|
+
setMessages((prev) => [...prev, aiMessage]);
|
|
463
|
+
setIsLoading(false);
|
|
464
|
+
onResponse?.(aiMessage);
|
|
465
|
+
}
|
|
466
|
+
} catch (err) {
|
|
467
|
+
const error2 = err instanceof Error ? err : new Error("Chat failed");
|
|
468
|
+
setError(error2);
|
|
469
|
+
setIsLoading(false);
|
|
470
|
+
onError?.(error2);
|
|
471
|
+
}
|
|
472
|
+
},
|
|
473
|
+
[messages, stream, model, temperature, maxTokens, onMessage, onResponse, onError]
|
|
474
|
+
);
|
|
475
|
+
const clear = useCallback(() => {
|
|
476
|
+
setMessages([]);
|
|
477
|
+
setStreamingMessage(null);
|
|
478
|
+
setError(null);
|
|
479
|
+
}, []);
|
|
480
|
+
return {
|
|
481
|
+
messages,
|
|
482
|
+
streamingMessage,
|
|
483
|
+
isLoading,
|
|
484
|
+
error,
|
|
485
|
+
sendMessage,
|
|
486
|
+
clear
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
function useImageGeneration(options) {
|
|
490
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
491
|
+
const [error, setError] = useState(null);
|
|
492
|
+
const [result, setResult] = useState(null);
|
|
493
|
+
const generate = useCallback(async (prompt, imageOptions) => {
|
|
494
|
+
setIsLoading(true);
|
|
495
|
+
setError(null);
|
|
496
|
+
try {
|
|
497
|
+
const response = await fetch(options?.endpoint || "/api/ai/generate-image", {
|
|
498
|
+
method: "POST",
|
|
499
|
+
headers: { "Content-Type": "application/json" },
|
|
500
|
+
body: JSON.stringify({
|
|
501
|
+
prompt,
|
|
502
|
+
...imageOptions
|
|
503
|
+
})
|
|
504
|
+
});
|
|
505
|
+
if (!response.ok) {
|
|
506
|
+
throw new Error(`HTTP ${response.status}: ${await response.text()}`);
|
|
507
|
+
}
|
|
508
|
+
const data = await response.json();
|
|
509
|
+
setResult(data);
|
|
510
|
+
options?.onSuccess?.(data);
|
|
511
|
+
return data;
|
|
512
|
+
} catch (err) {
|
|
513
|
+
const error2 = err instanceof Error ? err : new Error("Unknown error");
|
|
514
|
+
setError(error2);
|
|
515
|
+
options?.onError?.(error2);
|
|
516
|
+
throw error2;
|
|
517
|
+
} finally {
|
|
518
|
+
setIsLoading(false);
|
|
519
|
+
}
|
|
520
|
+
}, [options]);
|
|
521
|
+
const reset = useCallback(() => {
|
|
522
|
+
setIsLoading(false);
|
|
523
|
+
setError(null);
|
|
524
|
+
setResult(null);
|
|
525
|
+
}, []);
|
|
526
|
+
return { generate, isLoading, error, result, reset };
|
|
527
|
+
}
|
|
351
528
|
|
|
352
529
|
// src/ai/index.ts
|
|
353
530
|
async function chat(options) {
|
|
@@ -362,5 +539,9 @@ async function createEmbeddings(options) {
|
|
|
362
539
|
const provider = getAIProvider();
|
|
363
540
|
return provider.createEmbeddings(options);
|
|
364
541
|
}
|
|
542
|
+
async function generateImage(options) {
|
|
543
|
+
const provider = getAIProvider();
|
|
544
|
+
return provider.generateImage(options);
|
|
545
|
+
}
|
|
365
546
|
|
|
366
|
-
export { chat, chatStream, createEdgeStreamResponse, createEmbeddings, createSSEStream };
|
|
547
|
+
export { chat, chatStream, createEdgeStreamResponse, createEmbeddings, createSSEStream, generateImage, useChat, useImageGeneration };
|
|
@@ -68,5 +68,25 @@ type EmbeddingResponse = {
|
|
|
68
68
|
totalTokens: number;
|
|
69
69
|
};
|
|
70
70
|
};
|
|
71
|
+
type ImageGenerationOptions = {
|
|
72
|
+
prompt: string;
|
|
73
|
+
model?: 'dall-e-2' | 'dall-e-3';
|
|
74
|
+
size?: '1024x1024' | '1792x1024' | '1024x1792' | '256x256' | '512x512';
|
|
75
|
+
quality?: 'standard' | 'hd';
|
|
76
|
+
n?: number;
|
|
77
|
+
responseFormat?: 'url' | 'b64_json';
|
|
78
|
+
style?: 'vivid' | 'natural';
|
|
79
|
+
};
|
|
80
|
+
type ImageGenerationResponse = {
|
|
81
|
+
images: Array<{
|
|
82
|
+
url: string;
|
|
83
|
+
revisedPrompt?: string;
|
|
84
|
+
}>;
|
|
85
|
+
metadata?: {
|
|
86
|
+
model: string;
|
|
87
|
+
size: string;
|
|
88
|
+
quality?: string;
|
|
89
|
+
};
|
|
90
|
+
};
|
|
71
91
|
|
|
72
|
-
export type { AIConfig as A, ChatOptions as C, EmbeddingOptions as E, StreamChunk as S,
|
|
92
|
+
export type { AIConfig as A, ChatOptions as C, EmbeddingOptions as E, ImageGenerationOptions as I, StreamChunk as S, AIProvider as a, AIRole as b, AIMessage as c, AIFunction as d, ChatResponse as e, EmbeddingResponse as f, ImageGenerationResponse as g };
|
|
@@ -68,5 +68,25 @@ type EmbeddingResponse = {
|
|
|
68
68
|
totalTokens: number;
|
|
69
69
|
};
|
|
70
70
|
};
|
|
71
|
+
type ImageGenerationOptions = {
|
|
72
|
+
prompt: string;
|
|
73
|
+
model?: 'dall-e-2' | 'dall-e-3';
|
|
74
|
+
size?: '1024x1024' | '1792x1024' | '1024x1792' | '256x256' | '512x512';
|
|
75
|
+
quality?: 'standard' | 'hd';
|
|
76
|
+
n?: number;
|
|
77
|
+
responseFormat?: 'url' | 'b64_json';
|
|
78
|
+
style?: 'vivid' | 'natural';
|
|
79
|
+
};
|
|
80
|
+
type ImageGenerationResponse = {
|
|
81
|
+
images: Array<{
|
|
82
|
+
url: string;
|
|
83
|
+
revisedPrompt?: string;
|
|
84
|
+
}>;
|
|
85
|
+
metadata?: {
|
|
86
|
+
model: string;
|
|
87
|
+
size: string;
|
|
88
|
+
quality?: string;
|
|
89
|
+
};
|
|
90
|
+
};
|
|
71
91
|
|
|
72
|
-
export type { AIConfig as A, ChatOptions as C, EmbeddingOptions as E, StreamChunk as S,
|
|
92
|
+
export type { AIConfig as A, ChatOptions as C, EmbeddingOptions as E, ImageGenerationOptions as I, StreamChunk as S, AIProvider as a, AIRole as b, AIMessage as c, AIFunction as d, ChatResponse as e, EmbeddingResponse as f, ImageGenerationResponse as g };
|
package/dist/index.d.cts
CHANGED
|
@@ -4,8 +4,8 @@ import { B as BillingConfig } from './billing-Bv2V7KWF.cjs';
|
|
|
4
4
|
export { b as BillingProvider, C as CheckoutOptions, S as Subscription, a as SubscriptionStatus } from './billing-Bv2V7KWF.cjs';
|
|
5
5
|
import { a as EmailConfig } from './email-DZN1-bHa.cjs';
|
|
6
6
|
export { E as EmailOptions, b as EmailProvider, T as TemplateEmailOptions } from './email-DZN1-bHa.cjs';
|
|
7
|
-
import { A as AIConfig } from './ai-
|
|
8
|
-
export {
|
|
7
|
+
import { A as AIConfig } from './ai-CdJK6ox8.cjs';
|
|
8
|
+
export { d as AIFunction, c as AIMessage, a as AIProvider, b as AIRole, C as ChatOptions, e as ChatResponse, E as EmbeddingOptions, f as EmbeddingResponse, I as ImageGenerationOptions, g as ImageGenerationResponse, S as StreamChunk } from './ai-CdJK6ox8.cjs';
|
|
9
9
|
import { z } from 'zod';
|
|
10
10
|
export { F as FileMetadata, S as StorageProvider, U as UploadOptions, a as UploadResult } from './storage-B87mGs3T.cjs';
|
|
11
11
|
export { C as CircuitBreakerOptions, b as CircuitBreakerResult, L as LimitsProvider, R as RateLimitOptions, a as RateLimitResult } from './limits-DAOZz-ua.cjs';
|
|
@@ -137,11 +137,11 @@ declare const limitsConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
137
137
|
url: z.ZodString;
|
|
138
138
|
token: z.ZodString;
|
|
139
139
|
}, "strip", z.ZodTypeAny, {
|
|
140
|
-
token: string;
|
|
141
140
|
url: string;
|
|
142
|
-
}, {
|
|
143
141
|
token: string;
|
|
142
|
+
}, {
|
|
144
143
|
url: string;
|
|
144
|
+
token: string;
|
|
145
145
|
}>>;
|
|
146
146
|
redis: z.ZodOptional<z.ZodObject<{
|
|
147
147
|
url: z.ZodString;
|
|
@@ -156,8 +156,8 @@ declare const limitsConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
156
156
|
}, "strip", z.ZodTypeAny, {
|
|
157
157
|
provider: "upstash" | "redis";
|
|
158
158
|
upstash?: {
|
|
159
|
-
token: string;
|
|
160
159
|
url: string;
|
|
160
|
+
token: string;
|
|
161
161
|
} | undefined;
|
|
162
162
|
redis?: {
|
|
163
163
|
url: string;
|
|
@@ -166,8 +166,8 @@ declare const limitsConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
166
166
|
}, {
|
|
167
167
|
provider: "upstash" | "redis";
|
|
168
168
|
upstash?: {
|
|
169
|
-
token: string;
|
|
170
169
|
url: string;
|
|
170
|
+
token: string;
|
|
171
171
|
} | undefined;
|
|
172
172
|
redis?: {
|
|
173
173
|
url: string;
|
|
@@ -176,8 +176,8 @@ declare const limitsConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
176
176
|
}>, {
|
|
177
177
|
provider: "upstash" | "redis";
|
|
178
178
|
upstash?: {
|
|
179
|
-
token: string;
|
|
180
179
|
url: string;
|
|
180
|
+
token: string;
|
|
181
181
|
} | undefined;
|
|
182
182
|
redis?: {
|
|
183
183
|
url: string;
|
|
@@ -186,8 +186,8 @@ declare const limitsConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
186
186
|
}, {
|
|
187
187
|
provider: "upstash" | "redis";
|
|
188
188
|
upstash?: {
|
|
189
|
-
token: string;
|
|
190
189
|
url: string;
|
|
190
|
+
token: string;
|
|
191
191
|
} | undefined;
|
|
192
192
|
redis?: {
|
|
193
193
|
url: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -4,8 +4,8 @@ import { B as BillingConfig } from './billing-Bv2V7KWF.js';
|
|
|
4
4
|
export { b as BillingProvider, C as CheckoutOptions, S as Subscription, a as SubscriptionStatus } from './billing-Bv2V7KWF.js';
|
|
5
5
|
import { a as EmailConfig } from './email-DZN1-bHa.js';
|
|
6
6
|
export { E as EmailOptions, b as EmailProvider, T as TemplateEmailOptions } from './email-DZN1-bHa.js';
|
|
7
|
-
import { A as AIConfig } from './ai-
|
|
8
|
-
export {
|
|
7
|
+
import { A as AIConfig } from './ai-CdJK6ox8.js';
|
|
8
|
+
export { d as AIFunction, c as AIMessage, a as AIProvider, b as AIRole, C as ChatOptions, e as ChatResponse, E as EmbeddingOptions, f as EmbeddingResponse, I as ImageGenerationOptions, g as ImageGenerationResponse, S as StreamChunk } from './ai-CdJK6ox8.js';
|
|
9
9
|
import { z } from 'zod';
|
|
10
10
|
export { F as FileMetadata, S as StorageProvider, U as UploadOptions, a as UploadResult } from './storage-B87mGs3T.js';
|
|
11
11
|
export { C as CircuitBreakerOptions, b as CircuitBreakerResult, L as LimitsProvider, R as RateLimitOptions, a as RateLimitResult } from './limits-DAOZz-ua.js';
|
|
@@ -137,11 +137,11 @@ declare const limitsConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
137
137
|
url: z.ZodString;
|
|
138
138
|
token: z.ZodString;
|
|
139
139
|
}, "strip", z.ZodTypeAny, {
|
|
140
|
-
token: string;
|
|
141
140
|
url: string;
|
|
142
|
-
}, {
|
|
143
141
|
token: string;
|
|
142
|
+
}, {
|
|
144
143
|
url: string;
|
|
144
|
+
token: string;
|
|
145
145
|
}>>;
|
|
146
146
|
redis: z.ZodOptional<z.ZodObject<{
|
|
147
147
|
url: z.ZodString;
|
|
@@ -156,8 +156,8 @@ declare const limitsConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
156
156
|
}, "strip", z.ZodTypeAny, {
|
|
157
157
|
provider: "upstash" | "redis";
|
|
158
158
|
upstash?: {
|
|
159
|
-
token: string;
|
|
160
159
|
url: string;
|
|
160
|
+
token: string;
|
|
161
161
|
} | undefined;
|
|
162
162
|
redis?: {
|
|
163
163
|
url: string;
|
|
@@ -166,8 +166,8 @@ declare const limitsConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
166
166
|
}, {
|
|
167
167
|
provider: "upstash" | "redis";
|
|
168
168
|
upstash?: {
|
|
169
|
-
token: string;
|
|
170
169
|
url: string;
|
|
170
|
+
token: string;
|
|
171
171
|
} | undefined;
|
|
172
172
|
redis?: {
|
|
173
173
|
url: string;
|
|
@@ -176,8 +176,8 @@ declare const limitsConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
176
176
|
}>, {
|
|
177
177
|
provider: "upstash" | "redis";
|
|
178
178
|
upstash?: {
|
|
179
|
-
token: string;
|
|
180
179
|
url: string;
|
|
180
|
+
token: string;
|
|
181
181
|
} | undefined;
|
|
182
182
|
redis?: {
|
|
183
183
|
url: string;
|
|
@@ -186,8 +186,8 @@ declare const limitsConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
186
186
|
}, {
|
|
187
187
|
provider: "upstash" | "redis";
|
|
188
188
|
upstash?: {
|
|
189
|
-
token: string;
|
|
190
189
|
url: string;
|
|
190
|
+
token: string;
|
|
191
191
|
} | undefined;
|
|
192
192
|
redis?: {
|
|
193
193
|
url: string;
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "miragedev-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "AI-first SDK for building SAAS applications with Next.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"module": "./dist/index.js",
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
9
|
"bin": {
|
|
10
|
-
"miragedev": "./dist/cli/index.js"
|
|
10
|
+
"miragedev-sdk": "./dist/cli/index.js"
|
|
11
11
|
},
|
|
12
12
|
"exports": {
|
|
13
13
|
".": {
|