@cobbl-ai/sdk 0.1.0

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 ADDED
@@ -0,0 +1,516 @@
1
+ # @cobbl-ai/sdk
2
+
3
+ The official TypeScript/JavaScript SDK for [Cobbl](https://cobbl.ai) - a feedback-driven PromptOps platform for LLM applications.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@cobble-ai/sdk)](https://www.npmjs.com/package/@cobbl-ai/sdk)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ ## Features
9
+
10
+ - 🚀 **Simple API** - Run prompts and collect feedback with just a few lines of code
11
+ - 🔒 **Type-safe** - Full TypeScript support with comprehensive type definitions
12
+ - 🎯 **Framework agnostic** - Works with Node.js, Next.js, Express, and any JavaScript framework
13
+ - 📦 **Zero config** - Works out of the box with sensible defaults
14
+ - 🌐 **Cross-platform** - Supports both CommonJS and ES modules
15
+ - ⚡ **Optimized** - Minimal bundle size, tree-shakeable exports
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ # npm
21
+ npm install @cobbl-ai/sdk
22
+
23
+ # yarn
24
+ yarn add @cobbl-ai/sdk
25
+
26
+ # pnpm
27
+ pnpm add @cobbl-ai/sdk
28
+ ```
29
+
30
+ ## Quick Start
31
+
32
+ ```typescript
33
+ import { CobblClient } from '@cobbl-ai/sdk'
34
+
35
+ // Initialize the client
36
+ const client = new CobblClient({
37
+ apiKey: process.env.PROMPTI_API_KEY,
38
+ })
39
+
40
+ // Run a prompt
41
+ const result = await client.runPrompt('sales_summary', {
42
+ topic: 'Q4 Results',
43
+ tone: 'friendly',
44
+ audience: 'investors',
45
+ })
46
+
47
+ console.log(result.output) // AI-generated response
48
+ console.log(result.runId) // Save this to link feedback later
49
+
50
+ // Submit user feedback
51
+ await client.submitFeedback({
52
+ runId: result.runId,
53
+ helpful: 'not_helpful',
54
+ userFeedback: 'The response was too formal and lengthy',
55
+ })
56
+ ```
57
+
58
+ ## Configuration
59
+
60
+ ### Initializing the Client
61
+
62
+ ```typescript
63
+ import { CobblClient } from '@cobbl-ai/sdk'
64
+
65
+ const client = new CobblClient({
66
+ apiKey: 'your-api-key', // Your Cobbl API key
67
+ })
68
+ ```
69
+
70
+ ### Environment Variables
71
+
72
+ We recommend storing your API key in environment variables:
73
+
74
+ ```bash
75
+ # .env
76
+ PROMPTI_API_KEY=your_api_key_here
77
+ ```
78
+
79
+ Then load it in your application:
80
+
81
+ ```typescript
82
+ const client = new CobblClient({
83
+ apiKey: process.env.PROMPTI_API_KEY,
84
+ })
85
+ ```
86
+
87
+ ## API Reference
88
+
89
+ ### `runPrompt(promptSlug, input)`
90
+
91
+ Execute a prompt with the given input variables.
92
+
93
+ **Parameters:**
94
+
95
+ - `promptSlug` (string): The unique slug identifier for the prompt
96
+ - `input` (PromptInput): Input variables to populate the prompt template
97
+
98
+ **Returns:** `Promise<RunPromptResponse>`
99
+
100
+ **Response:**
101
+
102
+ ```typescript
103
+ {
104
+ runId: string // Unique ID for this run - use for feedback
105
+ output: string // AI-generated response
106
+ tokenUsage: {
107
+ inputTokens: number
108
+ outputTokens: number
109
+ totalTokens: number
110
+ }
111
+ renderedPrompt: string // The prompt sent to the LLM
112
+ promptVersion: {
113
+ // Metadata about the prompt version used
114
+ id: string
115
+ versionNumber: number
116
+ template: string
117
+ variables: Array<{
118
+ key: string
119
+ type: string
120
+ required: boolean
121
+ }>
122
+ provider: 'openai' | 'anthropic' | 'google'
123
+ model: string
124
+ // ... more fields
125
+ }
126
+ }
127
+ ```
128
+
129
+ **Example:**
130
+
131
+ ```typescript
132
+ const result = await client.runPrompt('customer_email', {
133
+ customerName: 'John Doe',
134
+ issue: 'login_problem',
135
+ urgency: 'high',
136
+ })
137
+
138
+ console.log(result.output)
139
+ // => "Dear John Doe, We understand you're experiencing login issues..."
140
+ ```
141
+
142
+ ### `submitFeedback(feedback)`
143
+
144
+ Submit user feedback for a prompt run.
145
+
146
+ **Parameters:**
147
+
148
+ - `feedback` (FeedbackSubmission):
149
+ - `runId` (string): The run ID from a previous `runPrompt` call
150
+ - `helpful` ('helpful' | 'not_helpful'): Whether the output was helpful
151
+ - `userFeedback` (string): Detailed feedback message
152
+
153
+ **Returns:** `Promise<SubmitFeedbackResponse>`
154
+
155
+ **Response:**
156
+
157
+ ```typescript
158
+ {
159
+ feedbackId: string // Unique ID for the feedback item
160
+ message: string // Success message
161
+ }
162
+ ```
163
+
164
+ **Example:**
165
+
166
+ ```typescript
167
+ await client.submitFeedback({
168
+ runId: result.runId,
169
+ helpful: 'not_helpful',
170
+ userFeedback: 'The tone was too casual for a professional email',
171
+ })
172
+ ```
173
+
174
+ ## Advanced Usage
175
+
176
+ ### Error Handling
177
+
178
+ The SDK throws `CobblError` for all error cases. You can catch and handle these errors:
179
+
180
+ ```typescript
181
+ import { CobblClient, CobblError } from '@cobbl-ai/sdk'
182
+
183
+ try {
184
+ const result = await client.runPrompt('my-prompt', { topic: 'test' })
185
+ } catch (error) {
186
+ if (error instanceof CobblError) {
187
+ console.error(`Error [${error.code}]: ${error.message}`)
188
+
189
+ // Handle specific error types
190
+ switch (error.code) {
191
+ case 'UNAUTHORIZED':
192
+ console.error('Invalid API key')
193
+ break
194
+ case 'NOT_FOUND':
195
+ console.error('Prompt not found')
196
+ break
197
+ case 'INVALID_REQUEST':
198
+ console.error('Invalid request:', error.details)
199
+ break
200
+ case 'RATE_LIMIT_EXCEEDED':
201
+ console.error('Rate limit exceeded, try again later')
202
+ break
203
+ default:
204
+ console.error('Unexpected error:', error)
205
+ }
206
+ } else {
207
+ console.error('Unknown error:', error)
208
+ }
209
+ }
210
+ ```
211
+
212
+ **Error Codes:**
213
+
214
+ - `INVALID_CONFIG` - Invalid SDK configuration
215
+ - `INVALID_REQUEST` - Malformed request (e.g., missing required fields)
216
+ - `UNAUTHORIZED` - Invalid or missing API key
217
+ - `NOT_FOUND` - Resource not found (e.g., prompt doesn't exist)
218
+ - `RATE_LIMIT_EXCEEDED` - Too many requests
219
+ - `SERVER_ERROR` - Server-side error
220
+ - `NETWORK_ERROR` - Network connectivity issue
221
+ - `API_ERROR` - Other API errors
222
+
223
+ ### TypeScript Support
224
+
225
+ The SDK is written in TypeScript and includes full type definitions:
226
+
227
+ ```typescript
228
+ import type {
229
+ PromptInput,
230
+ RunPromptResponse,
231
+ FeedbackSubmission,
232
+ TokenUsage,
233
+ } from '@cobbl-ai/sdk'
234
+
235
+ // Type-safe prompt inputs
236
+ const input: PromptInput = {
237
+ topic: 'AI Safety',
238
+ tone: 'professional',
239
+ }
240
+
241
+ // Type-safe response handling
242
+ const result: RunPromptResponse = await client.runPrompt('blog_post', input)
243
+
244
+ // Access token usage
245
+ const tokens: TokenUsage = result.tokenUsage
246
+ console.log(`Used ${tokens.totalTokens} tokens`)
247
+ ```
248
+
249
+ ### Framework Examples
250
+
251
+ #### Express.js
252
+
253
+ ```typescript
254
+ import express from 'express'
255
+ import { CobblClient } from '@cobbl-ai/sdk'
256
+
257
+ const app = express()
258
+ const cobbl = new CobblClient({
259
+ apiKey: process.env.PROMPTI_API_KEY,
260
+ })
261
+
262
+ app.post('/api/generate', async (req, res) => {
263
+ try {
264
+ const result = await cobbl.runPrompt('content_generator', req.body)
265
+ res.json({
266
+ output: result.output,
267
+ runId: result.runId,
268
+ })
269
+ } catch (error) {
270
+ res.status(500).json({ error: 'Failed to generate content' })
271
+ }
272
+ })
273
+
274
+ app.post('/api/feedback', async (req, res) => {
275
+ try {
276
+ await cobbl.submitFeedback(req.body)
277
+ res.json({ success: true })
278
+ } catch (error) {
279
+ res.status(500).json({ error: 'Failed to submit feedback' })
280
+ }
281
+ })
282
+ ```
283
+
284
+ #### Next.js API Routes
285
+
286
+ ```typescript
287
+ // app/api/generate/route.ts
288
+ import { CobblClient } from '@cobbl-ai/sdk'
289
+ import { NextResponse } from 'next/server'
290
+
291
+ const cobbl = new CobblClient({
292
+ apiKey: process.env.PROMPTI_API_KEY!,
293
+ })
294
+
295
+ export async function POST(request: Request) {
296
+ const body = await request.json()
297
+
298
+ try {
299
+ const result = await cobbl.runPrompt('summarizer', {
300
+ text: body.text,
301
+ length: 'short',
302
+ })
303
+
304
+ return NextResponse.json(result)
305
+ } catch (error) {
306
+ return NextResponse.json(
307
+ { error: 'Failed to generate summary' },
308
+ { status: 500 }
309
+ )
310
+ }
311
+ }
312
+ ```
313
+
314
+ #### React Component (Client-Side via API)
315
+
316
+ ```typescript
317
+ 'use client'
318
+
319
+ import { useState } from 'react'
320
+
321
+ export default function FeedbackForm({ runId }: { runId: string }) {
322
+ const [feedback, setFeedback] = useState('')
323
+ const [helpful, setHelpful] = useState<'helpful' | 'not_helpful'>('helpful')
324
+
325
+ const handleSubmit = async (e: React.FormEvent) => {
326
+ e.preventDefault()
327
+
328
+ // Call your API route that uses the SDK
329
+ await fetch('/api/feedback', {
330
+ method: 'POST',
331
+ headers: { 'Content-Type': 'application/json' },
332
+ body: JSON.stringify({
333
+ runId,
334
+ helpful,
335
+ userFeedback: feedback
336
+ })
337
+ })
338
+
339
+ setFeedback('')
340
+ }
341
+
342
+ return (
343
+ <form onSubmit={handleSubmit}>
344
+ <div>
345
+ <label>
346
+ <input
347
+ type="radio"
348
+ value="helpful"
349
+ checked={helpful === 'helpful'}
350
+ onChange={(e) => setHelpful(e.target.value as 'helpful')}
351
+ />
352
+ Helpful
353
+ </label>
354
+ <label>
355
+ <input
356
+ type="radio"
357
+ value="not_helpful"
358
+ checked={helpful === 'not_helpful'}
359
+ onChange={(e) => setHelpful(e.target.value as 'not_helpful')}
360
+ />
361
+ Not Helpful
362
+ </label>
363
+ </div>
364
+
365
+ <textarea
366
+ value={feedback}
367
+ onChange={(e) => setFeedback(e.target.value)}
368
+ placeholder="Tell us what could be improved..."
369
+ />
370
+
371
+ <button type="submit">Submit Feedback</button>
372
+ </form>
373
+ )
374
+ }
375
+ ```
376
+
377
+ ## Best Practices
378
+
379
+ ### 1. Store Run IDs for Feedback
380
+
381
+ Always save the `runId` returned from `runPrompt()` so users can provide feedback later:
382
+
383
+ ```typescript
384
+ // Store in database with your application data
385
+ const result = await client.runPrompt('recommendation', { userId: '123' })
386
+
387
+ await db.recommendations.create({
388
+ userId: '123',
389
+ content: result.output,
390
+ promptRunId: result.runId, // ← Save this!
391
+ })
392
+ ```
393
+
394
+ ### 2. Handle Errors Gracefully
395
+
396
+ Always wrap SDK calls in try-catch blocks and provide fallback behavior:
397
+
398
+ ```typescript
399
+ try {
400
+ const result = await client.runPrompt('greeting', { name: userName })
401
+ return result.output
402
+ } catch (error) {
403
+ // Log for debugging
404
+ console.error('Prompt failed:', error)
405
+
406
+ // Return fallback content
407
+ return `Hello, ${userName}!`
408
+ }
409
+ ```
410
+
411
+ ### 3. Use Environment-Specific API Keys
412
+
413
+ Use different API keys for development, staging, and production:
414
+
415
+ ```typescript
416
+ const client = new CobblClient({
417
+ apiKey: process.env.PROMPTI_API_KEY,
418
+ })
419
+ ```
420
+
421
+ ### 4. Implement Rate Limiting
422
+
423
+ Add rate limiting on your application side to avoid hitting API limits:
424
+
425
+ ```typescript
426
+ import rateLimit from 'express-rate-limit'
427
+
428
+ const limiter = rateLimit({
429
+ windowMs: 15 * 60 * 1000, // 15 minutes
430
+ max: 100, // limit each IP to 100 requests per windowMs
431
+ })
432
+
433
+ app.use('/api/generate', limiter)
434
+ ```
435
+
436
+ ## Development
437
+
438
+ ### Building from Source
439
+
440
+ ```bash
441
+ # Install dependencies
442
+ pnpm install
443
+
444
+ # Build the SDK
445
+ pnpm build
446
+
447
+ # Type check
448
+ pnpm typecheck
449
+
450
+ # Clean build artifacts
451
+ pnpm clean
452
+ ```
453
+
454
+ ### Project Structure
455
+
456
+ ```
457
+ sdk/
458
+ ├── src/
459
+ │ ├── client.ts # Main SDK client
460
+ │ ├── errors.ts # Error classes
461
+ │ ├── types.ts # Type definitions
462
+ │ ├── shared-types.ts # Inlined types from shared package
463
+ │ └── index.ts # Public exports
464
+ ├── dist/ # Compiled output (created by build)
465
+ │ ├── index.js # CommonJS bundle
466
+ │ ├── index.mjs # ES modules bundle
467
+ │ ├── index.d.ts # TypeScript declarations (CJS)
468
+ │ ├── index.d.mts # TypeScript declarations (ESM)
469
+ │ └── *.map # Source maps
470
+ ├── examples/ # Usage examples
471
+ ├── tsup.config.ts # Build configuration
472
+ ├── package.json
473
+ └── README.md
474
+ ```
475
+
476
+ ### Build System
477
+
478
+ This SDK uses [tsup](https://tsup.egoist.dev/) for building, which provides:
479
+
480
+ - **Zero config bundling** - Works out of the box
481
+ - **Dual package support** - Generates both CJS and ESM
482
+ - **Type bundling** - Inlines all type dependencies
483
+ - **Tree-shaking** - Removes unused code
484
+ - **Source maps** - For debugging
485
+
486
+ ### Publishing to npm
487
+
488
+ Before publishing, make sure to:
489
+
490
+ 1. Update the version in `package.json`
491
+ 2. Update `CHANGELOG.md`
492
+ 3. Build and test the package
493
+
494
+ ```bash
495
+ # Test the package locally
496
+ pnpm pack
497
+ # This creates cobbl-ai
498
+ -sdk-0.1.0.tgz that you can test
499
+
500
+ # Publish to npm (requires npm login)
501
+ pnpm publish --access public
502
+
503
+ # Or publish with tag (for beta/alpha releases)
504
+ pnpm publish --tag beta --access public
505
+ ```
506
+
507
+ ## Support
508
+
509
+ - 📧 Email: support@cobbl.ai
510
+ - 🐛 Issues: [GitHub Issues](https://github.com/your-org/cobbl-ai/issues)
511
+ - 📚 Documentation: [docs.cobbl.ai](https://docs.cobbl.ai)
512
+ - 💬 Discord: [Join our community](https://discord.gg/cobbl)
513
+
514
+ ## License
515
+
516
+ MIT © Cobbl