@nextsparkjs/plugin-ai 0.1.0-beta.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.
Files changed (34) hide show
  1. package/.env.example +79 -0
  2. package/README.md +529 -0
  3. package/api/README.md +65 -0
  4. package/api/ai-history/[id]/route.ts +112 -0
  5. package/api/embeddings/route.ts +129 -0
  6. package/api/generate/route.ts +160 -0
  7. package/docs/01-getting-started/01-introduction.md +237 -0
  8. package/docs/01-getting-started/02-installation.md +447 -0
  9. package/docs/01-getting-started/03-configuration.md +416 -0
  10. package/docs/02-features/01-text-generation.md +523 -0
  11. package/docs/02-features/02-embeddings.md +241 -0
  12. package/docs/02-features/03-ai-history.md +549 -0
  13. package/docs/03-advanced-usage/01-core-utilities.md +500 -0
  14. package/docs/04-use-cases/01-content-generation.md +453 -0
  15. package/entities/ai-history/ai-history.config.ts +123 -0
  16. package/entities/ai-history/ai-history.fields.ts +330 -0
  17. package/entities/ai-history/messages/en.json +56 -0
  18. package/entities/ai-history/messages/es.json +56 -0
  19. package/entities/ai-history/migrations/001_ai_history_table.sql +167 -0
  20. package/entities/ai-history/migrations/002_ai_history_metas.sql +103 -0
  21. package/lib/ai-history-meta-service.ts +379 -0
  22. package/lib/ai-history-service.ts +391 -0
  23. package/lib/ai-sdk.ts +7 -0
  24. package/lib/core-utils.ts +217 -0
  25. package/lib/plugin-env.ts +252 -0
  26. package/lib/sanitize.ts +122 -0
  27. package/lib/save-example.ts +237 -0
  28. package/lib/server-env.ts +104 -0
  29. package/package.json +23 -0
  30. package/plugin.config.ts +55 -0
  31. package/public/docs/login-404-error.png +0 -0
  32. package/tsconfig.json +47 -0
  33. package/tsconfig.tsbuildinfo +1 -0
  34. package/types/ai.types.ts +51 -0
@@ -0,0 +1,453 @@
1
+ # Content Generation Use Case
2
+
3
+ ## Overview
4
+
5
+ One of the most common and proven use cases for the AI plugin is **automated content generation**. This use case is already in production, generating marketing copy, product descriptions, blog posts, and more.
6
+
7
+ ## Real-World Application
8
+
9
+ **Status:** ✅ In Production
10
+ **Use:** Content creation workflows, automated copywriting
11
+ **Models:** GPT-4o Mini, Claude Haiku, Llama 3.2
12
+ **Results:** 10x faster content production with consistent quality
13
+
14
+ ## Common Content Types
15
+
16
+ ### 1. Product Descriptions
17
+
18
+ **Use Case:** E-commerce, catalogs, marketplaces
19
+
20
+ **Example Implementation:**
21
+
22
+ ```typescript
23
+ // app/api/content/product-description/route.ts
24
+ import { NextRequest, NextResponse } from 'next/server'
25
+ import { generateText } from 'ai'
26
+ import { selectModel, calculateCost, extractTokens } from '@/contents/plugins/ai/lib/core-utils'
27
+ import { authenticateRequest } from '@/core/lib/api/auth/dual-auth'
28
+
29
+ export async function POST(request: NextRequest) {
30
+ const auth = await authenticateRequest(request)
31
+ if (!auth.success) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
32
+
33
+ const { productName, features, targetAudience = 'general consumers' } = await request.json()
34
+
35
+ const selection = await selectModel('gpt-4o-mini')
36
+
37
+ const result = await generateText({
38
+ model: selection.model,
39
+ system: `You are an expert e-commerce copywriter. Write compelling, SEO-friendly product descriptions that convert.`,
40
+ prompt: `
41
+ Product: ${productName}
42
+ Features: ${features.join(', ')}
43
+ Target Audience: ${targetAudience}
44
+
45
+ Write a compelling product description (100-150 words) that:
46
+ - Highlights key benefits
47
+ - Uses persuasive language
48
+ - Includes relevant keywords
49
+ - Ends with a call-to-action
50
+ `.trim(),
51
+ maxOutputTokens: 300,
52
+ temperature: 0.7
53
+ })
54
+
55
+ const tokens = extractTokens(result)
56
+ const cost = calculateCost(tokens, selection.costConfig)
57
+
58
+ return NextResponse.json({
59
+ description: result.text,
60
+ wordCount: result.text.split(' ').length,
61
+ cost,
62
+ tokens
63
+ })
64
+ }
65
+ ```
66
+
67
+ **Usage:**
68
+ ```bash
69
+ curl -X POST /api/content/product-description \
70
+ -H "Content-Type: application/json" \
71
+ -d '{
72
+ "productName": "Wireless Noise-Canceling Headphones",
73
+ "features": ["Active noise cancellation", "30-hour battery", "Bluetooth 5.0", "Comfortable ear cups"],
74
+ "targetAudience": "remote workers and travelers"
75
+ }'
76
+ ```
77
+
78
+ **Response:**
79
+ ```json
80
+ {
81
+ "description": "Experience uninterrupted focus with our premium Wireless Noise-Canceling Headphones. Featuring advanced active noise cancellation technology, these headphones create your personal sound sanctuary wherever you go. With an impressive 30-hour battery life and Bluetooth 5.0 connectivity, you'll enjoy seamless audio all day long. The plush, comfortable ear cups ensure hours of fatigue-free listening, perfect for remote work, travel, or simply escaping into your favorite music. Upgrade your audio experience today and discover the difference true wireless freedom makes.",
82
+ "wordCount": 89,
83
+ "cost": 0.00032,
84
+ "tokens": { "input": 85, "output": 105, "total": 190 }
85
+ }
86
+ ```
87
+
88
+ ### 2. Blog Post Generation
89
+
90
+ **Use Case:** Content marketing, SEO, thought leadership
91
+
92
+ **Example Implementation:**
93
+
94
+ ```typescript
95
+ // app/api/content/blog-post/route.ts
96
+ export async function POST(request: NextRequest) {
97
+ const { topic, keywords, tone = 'professional', length = 'medium' } = await request.json()
98
+
99
+ const lengthGuide = {
100
+ short: { words: '400-600', tokens: 800 },
101
+ medium: { words: '800-1200', tokens: 1500 },
102
+ long: { words: '1500-2000', tokens: 2500 }
103
+ }
104
+
105
+ const guide = lengthGuide[length] || lengthGuide.medium
106
+
107
+ const selection = await selectModel('claude-3-5-haiku-20241022')
108
+
109
+ const result = await generateText({
110
+ model: selection.model,
111
+ system: `You are a professional content writer specializing in engaging, SEO-optimized blog posts.`,
112
+ prompt: `
113
+ Topic: ${topic}
114
+ Target Keywords: ${keywords.join(', ')}
115
+ Tone: ${tone}
116
+ Length: ${guide.words} words
117
+
118
+ Write a complete blog post with:
119
+ 1. Attention-grabbing title
120
+ 2. Compelling introduction
121
+ 3. Well-structured body with H2/H3 headings
122
+ 4. Key takeaways
123
+ 5. Strong conclusion with CTA
124
+
125
+ Include keywords naturally and maintain ${tone} tone throughout.
126
+ `.trim(),
127
+ maxOutputTokens: guide.tokens,
128
+ temperature: 0.8
129
+ })
130
+
131
+ const tokens = extractTokens(result)
132
+ const cost = calculateCost(tokens, selection.costConfig)
133
+
134
+ // Parse title and content
135
+ const lines = result.text.split('\n')
136
+ const title = lines[0].replace(/^#+\s*/, '')
137
+ const content = lines.slice(1).join('\n').trim()
138
+
139
+ return NextResponse.json({
140
+ title,
141
+ content,
142
+ wordCount: content.split(' ').length,
143
+ cost,
144
+ tokens
145
+ })
146
+ }
147
+ ```
148
+
149
+ ### 3. Marketing Copy
150
+
151
+ **Use Case:** Ads, landing pages, email campaigns
152
+
153
+ **Example - Email Subject Lines:**
154
+
155
+ ```typescript
156
+ // app/api/content/email-subject/route.ts
157
+ export async function POST(request: NextRequest) {
158
+ const { campaign, offer, audience } = await request.json()
159
+
160
+ const selection = await selectModel('gpt-4o-mini')
161
+
162
+ const result = await generateText({
163
+ model: selection.model,
164
+ system: `You are a direct response copywriter specializing in high-converting email subject lines.`,
165
+ prompt: `
166
+ Campaign: ${campaign}
167
+ Offer: ${offer}
168
+ Audience: ${audience}
169
+
170
+ Generate 10 compelling email subject lines that:
171
+ - Create urgency or curiosity
172
+ - Are 40-60 characters
173
+ - Include power words
174
+ - Encourage opens
175
+
176
+ Format: One per line, numbered
177
+ `.trim(),
178
+ maxOutputTokens: 400,
179
+ temperature: 0.9 // High creativity
180
+ })
181
+
182
+ // Parse subject lines
183
+ const subjectLines = result.text
184
+ .split('\n')
185
+ .filter(line => line.match(/^\d+\./))
186
+ .map(line => line.replace(/^\d+\.\s*/, '').trim())
187
+
188
+ return NextResponse.json({
189
+ subjectLines,
190
+ count: subjectLines.length,
191
+ cost: calculateCost(extractTokens(result), selection.costConfig)
192
+ })
193
+ }
194
+ ```
195
+
196
+ ### 4. Social Media Posts
197
+
198
+ **Use Case:** Social media management, engagement
199
+
200
+ **Example - Multi-Platform Posts:**
201
+
202
+ ```typescript
203
+ // app/api/content/social-post/route.ts
204
+ export async function POST(request: NextRequest) {
205
+ const { topic, platforms = ['twitter', 'linkedin', 'facebook'] } = await request.json()
206
+
207
+ const selection = await selectModel('gpt-4o-mini')
208
+
209
+ const platformGuides = {
210
+ twitter: { limit: '280 characters', style: 'concise and witty' },
211
+ linkedin: { limit: '150 words', style: 'professional and insightful' },
212
+ facebook: { limit: '100 words', style: 'conversational and engaging' },
213
+ instagram: { limit: '150 words', style: 'visual and inspiring' }
214
+ }
215
+
216
+ const posts = {}
217
+
218
+ for (const platform of platforms) {
219
+ const guide = platformGuides[platform]
220
+
221
+ const result = await generateText({
222
+ model: selection.model,
223
+ system: `You are a social media expert creating ${guide.style} content for ${platform}.`,
224
+ prompt: `
225
+ Topic: ${topic}
226
+ Platform: ${platform}
227
+ Limit: ${guide.limit}
228
+ Style: ${guide.style}
229
+
230
+ Create an engaging post with:
231
+ ${platform === 'twitter' ? '- Relevant hashtags (2-3)' : ''}
232
+ ${platform === 'instagram' ? '- Relevant hashtags (5-10)' : ''}
233
+ ${platform === 'linkedin' ? '- Professional tone' : ''}
234
+ - Call-to-action
235
+ - Platform-appropriate formatting
236
+ `.trim(),
237
+ maxOutputTokens: 200,
238
+ temperature: 0.8
239
+ })
240
+
241
+ posts[platform] = result.text
242
+ }
243
+
244
+ return NextResponse.json({ posts })
245
+ }
246
+ ```
247
+
248
+ ## Batch Processing
249
+
250
+ **Generate Multiple Items at Once:**
251
+
252
+ ```typescript
253
+ // app/api/content/batch-descriptions/route.ts
254
+ export async function POST(request: NextRequest) {
255
+ const { products } = await request.json() // Array of products
256
+
257
+ const selection = await selectModel('gpt-4o-mini')
258
+ const results = []
259
+ let totalCost = 0
260
+
261
+ for (const product of products) {
262
+ const result = await generateText({
263
+ model: selection.model,
264
+ system: 'You are a product copywriter.',
265
+ prompt: `Write a 50-word description for: ${product.name}`,
266
+ maxOutputTokens: 100
267
+ })
268
+
269
+ const tokens = extractTokens(result)
270
+ const cost = calculateCost(tokens, selection.costConfig)
271
+ totalCost += cost
272
+
273
+ results.push({
274
+ productId: product.id,
275
+ description: result.text,
276
+ cost
277
+ })
278
+ }
279
+
280
+ return NextResponse.json({
281
+ results,
282
+ count: results.length,
283
+ totalCost
284
+ })
285
+ }
286
+ ```
287
+
288
+ ## Content Refinement
289
+
290
+ **Improve Existing Content:**
291
+
292
+ ```typescript
293
+ // app/api/content/refine/route.ts
294
+ export async function POST(request: NextRequest) {
295
+ const { content, instructions = 'Improve clarity and engagement' } = await request.json()
296
+
297
+ const selection = await selectModel('claude-3-5-haiku-20241022')
298
+
299
+ const result = await generateText({
300
+ model: selection.model,
301
+ system: 'You are an expert editor improving content quality.',
302
+ prompt: `
303
+ Original Content:
304
+ ${content}
305
+
306
+ Instructions:
307
+ ${instructions}
308
+
309
+ Provide the refined version with improvements in:
310
+ - Clarity and readability
311
+ - Engagement and flow
312
+ - Grammar and style
313
+ - SEO optimization (if applicable)
314
+ `.trim(),
315
+ maxOutputTokens: content.split(' ').length * 2, // Allow expansion
316
+ temperature: 0.6
317
+ })
318
+
319
+ return NextResponse.json({
320
+ original: content,
321
+ refined: result.text,
322
+ improvement: 'Content refined successfully',
323
+ cost: calculateCost(extractTokens(result), selection.costConfig)
324
+ })
325
+ }
326
+ ```
327
+
328
+ ## Integration with Entities
329
+
330
+ **Link Generated Content to Products:**
331
+
332
+ ```typescript
333
+ import { AIHistoryService } from '@/contents/plugins/ai/lib/ai-history-service'
334
+
335
+ export async function generateAndSaveDescription(productId: string) {
336
+ // Start operation tracking
337
+ const historyId = await AIHistoryService.startOperation({
338
+ userId: session.user.id,
339
+ operation: 'generate',
340
+ model: 'gpt-4o-mini',
341
+ provider: 'openai',
342
+ relatedEntityType: 'products',
343
+ relatedEntityId: productId
344
+ })
345
+
346
+ try {
347
+ // Get product data
348
+ const product = await getProduct(productId)
349
+
350
+ // Generate description
351
+ const result = await generateText({
352
+ model: selection.model,
353
+ prompt: `Write a description for: ${product.name}`
354
+ })
355
+
356
+ // Update product
357
+ await updateProduct(productId, {
358
+ description: result.text,
359
+ ai_generated: true
360
+ })
361
+
362
+ // Complete tracking
363
+ await AIHistoryService.completeOperation({
364
+ historyId,
365
+ tokensUsed: result.usage.totalTokens,
366
+ tokensInput: result.usage.inputTokens,
367
+ tokensOutput: result.usage.outputTokens,
368
+ creditsUsed: 0,
369
+ estimatedCost: cost,
370
+ balanceAfter: user.balance,
371
+ userId: session.user.id,
372
+ metas: {
373
+ contentType: 'product-description',
374
+ productName: product.name
375
+ }
376
+ })
377
+
378
+ return { description: result.text, cost }
379
+ } catch (error) {
380
+ await AIHistoryService.failOperation({
381
+ historyId,
382
+ errorMessage: error.message
383
+ })
384
+ throw error
385
+ }
386
+ }
387
+ ```
388
+
389
+ ## Cost Optimization
390
+
391
+ ### 1. Use Appropriate Models
392
+
393
+ ```typescript
394
+ // ✅ Development: Free local model
395
+ const devModel = 'llama3.2:3b'
396
+
397
+ // ✅ Production bulk: Cheap cloud model
398
+ const bulkModel = 'gpt-4o-mini' // $0.00015 input / $0.0006 output
399
+
400
+ // ✅ Production premium: Quality model
401
+ const premiumModel = 'gpt-4o' // $0.0025 input / $0.01 output
402
+ ```
403
+
404
+ ### 2. Optimize Token Usage
405
+
406
+ ```typescript
407
+ // ✅ Good: Specific, concise prompt
408
+ const prompt = `Write a 50-word product description for ${productName}`
409
+ // Uses ~15 input tokens
410
+
411
+ // ❌ Bad: Verbose, wasteful prompt
412
+ const prompt = `
413
+ I need you to please help me write a comprehensive product description.
414
+ The product is called ${productName} and I would like you to make it
415
+ engaging and informative. Please use around 50 words or so. Thank you!
416
+ `
417
+ // Uses ~40 input tokens (2.6x more expensive)
418
+ ```
419
+
420
+ ### 3. Cache Common Prompts
421
+
422
+ ```typescript
423
+ // Cache system prompts
424
+ const SYSTEM_PROMPTS = {
425
+ productDescription: 'You are an expert e-commerce copywriter...',
426
+ blogPost: 'You are a professional content writer...',
427
+ emailSubject: 'You are a direct response copywriter...'
428
+ }
429
+
430
+ // Reuse across requests
431
+ const result = await generateText({
432
+ model: selection.model,
433
+ system: SYSTEM_PROMPTS.productDescription,
434
+ prompt: userPrompt
435
+ })
436
+ ```
437
+
438
+ ## Best Practices
439
+
440
+ 1. **Validate Input** - Ensure product/content data is complete
441
+ 2. **Set Appropriate Temperature** - Lower for factual, higher for creative
442
+ 3. **Limit Output Tokens** - Don't over-allocate
443
+ 4. **Track Costs** - Monitor per-generation costs
444
+ 5. **A/B Test** - Compare models and prompts
445
+ 6. **Save Examples** - Use `saveExample: true` for training
446
+ 7. **Batch When Possible** - Generate multiple items efficiently
447
+ 8. **Link to Entities** - Track which content was generated for what
448
+
449
+ ## Next Steps
450
+
451
+ - **[Semantic Search](./02-semantic-search.md)** - Search content by meaning
452
+ - **[AI Auditing](./03-ai-auditing.md)** - Quality control with AI
453
+ - **[Custom Endpoints](../04-advanced-usage/02-custom-endpoints.md)** - Build specialized generators
@@ -0,0 +1,123 @@
1
+ /**
2
+ * AI History Entity Configuration
3
+ *
4
+ * Generic audit trail for all AI interactions across plugins.
5
+ * Tracks operations, costs, performance metrics, and results.
6
+ * Supports polymorphic relationships to any entity type.
7
+ *
8
+ * Updated according to new 5-section structure from refactoring plan.
9
+ * All table names, API paths, and metadata are now derived automatically from slug.
10
+ */
11
+
12
+ import { History } from 'lucide-react'
13
+ import type { EntityConfig } from '@nextsparkjs/core/lib/entities/types'
14
+ import { aiHistoryFields } from './ai-history.fields'
15
+
16
+ export const aiHistoryEntityConfig: EntityConfig = {
17
+ // ==========================================
18
+ // 1. BASIC IDENTIFICATION
19
+ // ==========================================
20
+ slug: 'ai-history', // Single source of truth - derives tableName, apiPath, metaTableName, i18nNamespace
21
+ enabled: true,
22
+ names: {
23
+ singular: 'AI History',
24
+ plural: 'AI History'
25
+ },
26
+ icon: History,
27
+
28
+ // ==========================================
29
+ // 2. ACCESS AND SCOPE CONFIGURATION
30
+ // ==========================================
31
+ access: {
32
+ public: false, // Users can only see their own history
33
+ api: true, // Has external API via API key
34
+ metadata: true, // ✅ Uses ai_history_metas table for flexible metadata
35
+ shared: false // REQUIRED: Private data (user-owned)
36
+ },
37
+
38
+ // ==========================================
39
+ // 3. UI/UX FEATURES
40
+ // ==========================================
41
+ ui: {
42
+ dashboard: {
43
+ showInMenu: true,
44
+ showInTopbar: false
45
+ },
46
+ public: {
47
+ hasArchivePage: false,
48
+ hasSinglePage: true
49
+ },
50
+ features: {
51
+ searchable: true, // Search by operation, model, provider, relatedEntityType
52
+ sortable: true, // Sort by date, cost, status, tokens
53
+ filterable: true, // Filter by status, operation, provider, model
54
+ bulkOperations: true, // Delete multiple history items
55
+ importExport: false // Sensitive data, keep internal
56
+ }
57
+ },
58
+
59
+ // ==========================================
60
+ // 4. PERMISSIONS SYSTEM
61
+ // ==========================================
62
+ permissions: {
63
+ actions: [
64
+ {
65
+ action: 'create',
66
+ label: 'Create AI history',
67
+ description: 'Can create AI history entries (typically via API)',
68
+ roles: ['owner', 'admin', 'member'],
69
+ },
70
+ {
71
+ action: 'read',
72
+ label: 'View AI history',
73
+ description: 'Can view AI history entries (users see their own via API filtering)',
74
+ roles: ['owner', 'admin', 'member'],
75
+ },
76
+ {
77
+ action: 'list',
78
+ label: 'List AI history',
79
+ description: 'Can list AI history entries',
80
+ roles: ['owner', 'admin', 'member'],
81
+ },
82
+ {
83
+ action: 'update',
84
+ label: 'Edit AI history',
85
+ description: 'Can modify AI history entries (immutable for most users)',
86
+ roles: ['owner', 'admin'],
87
+ },
88
+ {
89
+ action: 'delete',
90
+ label: 'Delete AI history',
91
+ description: 'Can delete AI history entries (users can delete their own)',
92
+ roles: ['owner', 'admin', 'member'],
93
+ dangerous: true,
94
+ },
95
+ ],
96
+ },
97
+
98
+ // ==========================================
99
+ // 5. INTERNATIONALIZATION
100
+ // ==========================================
101
+ i18n: {
102
+ fallbackLocale: 'en',
103
+ loaders: {
104
+ es: () => import('./messages/es.json'),
105
+ en: () => import('./messages/en.json')
106
+ }
107
+ },
108
+
109
+ // ==========================================
110
+ // FIELDS (imported from separate file)
111
+ // ==========================================
112
+ fields: aiHistoryFields,
113
+
114
+ // ==========================================
115
+ // AUTOMATIC SYSTEM DERIVATIONS
116
+ // ==========================================
117
+ // The following properties are automatically derived from the slug:
118
+ // - tableName: 'ai_history' (slug with dashes replaced by underscores)
119
+ // - metaTableName: 'ai_history_metas' (tableName + '_metas')
120
+ // - apiPath: '/api/v1/ai-history' (slug API Route)
121
+ // - i18nNamespace: 'ai-history' (slug as namespace)
122
+ // - foreignKey in metadata: 'entityId' (generic for all entities)
123
+ }