@cobbl-ai/sdk 0.1.0 → 0.1.2

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/dist/index.js CHANGED
@@ -29,28 +29,76 @@ var CobblError = class _CobblError extends Error {
29
29
  };
30
30
  }
31
31
  };
32
+ var handleErrorResponse = async (response) => {
33
+ let errorData;
34
+ try {
35
+ errorData = await response.json();
36
+ } catch {
37
+ throw new CobblError(
38
+ `HTTP ${response.status}: ${response.statusText}`,
39
+ "API_ERROR",
40
+ { status: response.status }
41
+ );
42
+ }
43
+ const message = errorData.error || errorData.message || "Unknown error";
44
+ const details = errorData.details;
45
+ switch (response.status) {
46
+ case 400:
47
+ throw new CobblError(message, "INVALID_REQUEST", details);
48
+ case 401:
49
+ throw new CobblError(message, "UNAUTHORIZED", details);
50
+ case 403:
51
+ throw new CobblError(message, "FORBIDDEN", details);
52
+ case 404:
53
+ throw new CobblError(message, "NOT_FOUND", details);
54
+ case 410:
55
+ throw new CobblError(message, "ARCHIVED", details);
56
+ case 429:
57
+ throw new CobblError(message, "RATE_LIMIT_EXCEEDED", details);
58
+ case 500:
59
+ case 502:
60
+ case 503:
61
+ case 504:
62
+ throw new CobblError(message, "SERVER_ERROR", details);
63
+ default:
64
+ throw new CobblError(message, "API_ERROR", {
65
+ status: response.status,
66
+ ...details
67
+ });
68
+ }
69
+ };
32
70
 
33
- // src/client.ts
71
+ // src/admin.ts
34
72
  var REQUEST_TIMEOUT_MS = 3e4;
35
- var CobblClient = class {
73
+ var CobblAdminClient = class {
36
74
  /**
37
- * Initialize the Cobbl SDK client
75
+ * Initialize the Cobbl Admin SDK client
38
76
  *
39
77
  * @param config - Configuration object
40
78
  * @param config.apiKey - Your Cobbl API key
79
+ * @param config.baseUrl - Optional base URL for the API (defaults to 'https://api.cobbl.ai')
41
80
  *
42
- * @example
81
+ * @example Production (uses default URL)
43
82
  * ```typescript
44
- * const client = new CobblClient({
83
+ * const client = new CobblAdminClient({
45
84
  * apiKey: process.env.COBBL_API_KEY
46
85
  * })
47
86
  * ```
87
+ *
88
+ * @example Local development with Firebase emulators
89
+ * ```typescript
90
+ * const client = new CobblAdminClient({
91
+ * apiKey: process.env.COBBL_API_KEY,
92
+ * baseUrl: 'http://localhost:5001/your-project-id/us-central1/externalApi'
93
+ * })
94
+ * ```
48
95
  */
49
96
  constructor(config) {
50
97
  if (!config.apiKey || config.apiKey.trim().length === 0) {
51
98
  throw new CobblError("API key is required", "INVALID_CONFIG");
52
99
  }
53
100
  this.apiKey = config.apiKey;
101
+ this.baseUrl = config.baseUrl?.trim() || "https://api.cobbl.ai";
54
102
  }
55
103
  /**
56
104
  * Execute a prompt with the given input variables
@@ -78,7 +126,7 @@ var CobblClient = class {
78
126
  throw new CobblError("promptSlug is required", "INVALID_REQUEST");
79
127
  }
80
128
  try {
81
- const response = await this.makeRequest("/prompt/run", {
129
+ const response = await this.makeRequest("/admin/v1/prompt/run", {
82
130
  method: "POST",
83
131
  body: JSON.stringify({
84
132
  promptSlug: promptSlug.trim(),
@@ -86,7 +134,7 @@ var CobblClient = class {
86
134
  })
87
135
  });
88
136
  if (!response.ok) {
89
- await this.handleErrorResponse(response);
137
+ await handleErrorResponse(response);
90
138
  }
91
139
  const data = await response.json();
92
140
  return {
@@ -107,53 +155,191 @@ var CobblClient = class {
107
155
  }
108
156
  }
109
157
  /**
110
- * Submit user feedback for a prompt run
158
+ * Make an HTTP request to the Cobbl API
159
+ * @private
160
+ */
161
+ async makeRequest(path, options) {
162
+ const url = `${this.baseUrl}${path}`;
163
+ const controller = new AbortController();
164
+ const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
165
+ try {
166
+ const response = await fetch(url, {
167
+ ...options,
168
+ headers: {
169
+ "Content-Type": "application/json",
170
+ Authorization: `Bearer ${this.apiKey}`,
171
+ ...options.headers
172
+ },
173
+ signal: controller.signal
174
+ });
175
+ return response;
176
+ } finally {
177
+ clearTimeout(timeoutId);
178
+ }
179
+ }
180
+ };
181
+
182
+ // src/validation.ts
183
+ var VALID_HELPFUL_VALUES = ["helpful", "not_helpful"];
184
+ function validateCreateFeedback(feedback) {
185
+ if (!feedback.runId || feedback.runId.trim().length === 0) {
186
+ return "runId is required";
187
+ }
188
+ if (feedback.helpful !== void 0 && !VALID_HELPFUL_VALUES.includes(feedback.helpful)) {
189
+ return 'helpful must be "helpful" or "not_helpful"';
190
+ }
191
+ if (feedback.userFeedback !== void 0 && feedback.userFeedback.trim().length === 0) {
192
+ return "userFeedback cannot be empty";
193
+ }
194
+ if (feedback.helpful === void 0 && feedback.userFeedback === void 0) {
195
+ return "At least one of helpful or userFeedback is required";
196
+ }
197
+ return null;
198
+ }
199
+ function validateUpdateFeedback(update) {
200
+ if (update.helpful !== void 0 && !VALID_HELPFUL_VALUES.includes(update.helpful)) {
201
+ return 'helpful must be "helpful" or "not_helpful"';
202
+ }
203
+ if (update.userFeedback !== void 0 && update.userFeedback.trim().length === 0) {
204
+ return "userFeedback cannot be empty";
205
+ }
206
+ if (update.helpful === void 0 && update.userFeedback === void 0) {
207
+ return "At least one of helpful or userFeedback is required";
208
+ }
209
+ return null;
210
+ }
211
+
212
+ // src/public.ts
213
+ var REQUEST_TIMEOUT_MS2 = 3e4;
214
+ var CobblPublicClient = class {
215
+ /**
216
+ * Initialize the Cobbl Public SDK client
217
+ *
218
+ * @param config - Configuration object
219
+ * @param config.baseUrl - Optional base URL for the API (defaults to 'https://api.cobbl.ai')
220
+ */
221
+ constructor(config = {}) {
222
+ this.baseUrl = config.baseUrl?.trim() || "https://api.cobbl.ai";
223
+ }
224
+ /**
225
+ * Create user feedback for a prompt run
226
+ * Supports segmented feedback - you can provide just helpful, just userFeedback, or both
227
+ * Use updateFeedback to add additional data later
111
228
  *
112
229
  * @param feedback - Feedback submission data
113
230
  * @param feedback.runId - The run ID from a previous runPrompt call
114
- * @param feedback.helpful - Whether the output was helpful ('helpful' or 'not_helpful')
115
- * @param feedback.userFeedback - Detailed feedback message from the user
231
+ * @param feedback.helpful - Whether the output was helpful ('helpful' or 'not_helpful') - optional
232
+ * @param feedback.userFeedback - Detailed feedback message from the user - optional
116
233
  * @returns Promise containing the created feedback ID
117
234
  *
118
235
  * @throws {CobblError} When the request fails or API returns an error
119
236
  *
120
- * @example
237
+ * @example Submit just thumbs down first
121
238
  * ```typescript
122
- * await client.submitFeedback({
239
+ * const { id } = await client.createFeedback({
240
+ * runId: result.runId,
241
+ * helpful: 'not_helpful'
242
+ * })
243
+ * // Later, add details
244
+ * await client.updateFeedback(id, {
245
+ * userFeedback: 'The response was too formal and lengthy'
246
+ * })
247
+ * ```
248
+ *
249
+ * @example Submit both at once
250
+ * ```typescript
251
+ * await client.createFeedback({
123
252
  * runId: result.runId,
124
253
  * helpful: 'not_helpful',
125
254
  * userFeedback: 'The response was too formal and lengthy'
126
255
  * })
127
256
  * ```
128
257
  */
129
- async submitFeedback(feedback) {
130
- if (!feedback.runId || feedback.runId.trim().length === 0) {
131
- throw new CobblError("runId is required", "INVALID_REQUEST");
258
+ async createFeedback(feedback) {
259
+ const validationError = validateCreateFeedback(feedback);
260
+ if (validationError) {
261
+ throw new CobblError(validationError, "INVALID_REQUEST");
132
262
  }
133
- if (!feedback.userFeedback || feedback.userFeedback.trim().length === 0) {
134
- throw new CobblError("userFeedback is required", "INVALID_REQUEST");
135
- }
136
- if (!feedback.helpful || !["helpful", "not_helpful"].includes(feedback.helpful)) {
263
+ try {
264
+ const body = {
265
+ runId: feedback.runId.trim(),
266
+ helpful: feedback.helpful,
267
+ userFeedback: feedback.userFeedback?.trim()
268
+ };
269
+ const response = await this.makeRequest("/public/v1/feedback", {
270
+ method: "POST",
271
+ body: JSON.stringify(body)
272
+ });
273
+ if (!response.ok) {
274
+ await handleErrorResponse(response);
275
+ }
276
+ const data = await response.json();
277
+ return {
278
+ id: data.id,
279
+ message: data.message
280
+ };
281
+ } catch (error) {
282
+ if (error instanceof CobblError) {
283
+ throw error;
284
+ }
137
285
  throw new CobblError(
138
- 'helpful must be either "helpful" or "not_helpful"',
139
- "INVALID_REQUEST"
286
+ `Failed to create feedback: ${error instanceof Error ? error.message : "Unknown error"}`,
287
+ "NETWORK_ERROR"
140
288
  );
141
289
  }
290
+ }
291
+ /**
292
+ * Update existing feedback with additional data
293
+ * Use this to add helpful sentiment or detailed feedback after initial submission
294
+ *
295
+ * @param id - The ID returned from createFeedback
296
+ * @param update - The data to update
297
+ * @param update.helpful - Whether the output was helpful ('helpful' or 'not_helpful') - optional
298
+ * @param update.userFeedback - Detailed feedback message from the user - optional
299
+ * @returns Promise containing the updated feedback ID
300
+ *
301
+ * @throws {CobblError} When the request fails or API returns an error
302
+ *
303
+ * @example Add details after initial thumbs down
304
+ * ```typescript
305
+ * // First, submit just the rating
306
+ * const { id } = await client.createFeedback({
307
+ * runId: result.runId,
308
+ * helpful: 'not_helpful'
309
+ * })
310
+ *
311
+ * // Later, add detailed feedback
312
+ * await client.updateFeedback(id, {
313
+ * userFeedback: 'The response was too formal and lengthy'
314
+ * })
315
+ * ```
316
+ */
317
+ async updateFeedback(id, update) {
318
+ if (!id || id.trim().length === 0) {
319
+ throw new CobblError("id is required", "INVALID_REQUEST");
320
+ }
321
+ const validationError = validateUpdateFeedback(update);
322
+ if (validationError) {
323
+ throw new CobblError(validationError, "INVALID_REQUEST");
324
+ }
142
325
  try {
143
- const response = await this.makeRequest("/feedback", {
144
- method: "POST",
145
- body: JSON.stringify({
146
- runId: feedback.runId.trim(),
147
- helpful: feedback.helpful,
148
- userFeedback: feedback.userFeedback.trim()
149
- })
150
- });
326
+ const body = {
327
+ helpful: update.helpful,
328
+ userFeedback: update.userFeedback?.trim()
329
+ };
330
+ const response = await this.makeRequest(
331
+ `/public/v1/feedback/${id.trim()}`,
332
+ {
333
+ method: "PATCH",
334
+ body: JSON.stringify(body)
335
+ }
336
+ );
151
337
  if (!response.ok) {
152
- await this.handleErrorResponse(response);
338
+ await handleErrorResponse(response);
153
339
  }
154
340
  const data = await response.json();
155
341
  return {
156
- feedbackId: data.feedbackId,
342
+ id: data.id,
157
343
  message: data.message
158
344
  };
159
345
  } catch (error) {
@@ -161,7 +347,7 @@ var CobblClient = class {
161
347
  throw error;
162
348
  }
163
349
  throw new CobblError(
164
- `Failed to submit feedback: ${error instanceof Error ? error.message : "Unknown error"}`,
350
+ `Failed to update feedback: ${error instanceof Error ? error.message : "Unknown error"}`,
165
351
  "NETWORK_ERROR"
166
352
  );
167
353
  }
@@ -171,16 +357,14 @@ var CobblClient = class {
171
357
  * @private
172
358
  */
173
359
  async makeRequest(path, options) {
174
- const baseUrl = process.env.COBBL_API_URL || "https://api.cobbl.ai";
175
- const url = `${baseUrl}${path}`;
360
+ const url = `${this.baseUrl}${path}`;
176
361
  const controller = new AbortController();
177
- const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
362
+ const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS2);
178
363
  try {
179
364
  const response = await fetch(url, {
180
365
  ...options,
181
366
  headers: {
182
367
  "Content-Type": "application/json",
183
- Authorization: `Bearer ${this.apiKey}`,
184
368
  ...options.headers
185
369
  },
186
370
  signal: controller.signal
@@ -190,47 +374,10 @@ var CobblClient = class {
190
374
  clearTimeout(timeoutId);
191
375
  }
192
376
  }
193
- /**
194
- * Handle error responses from the API
195
- * @private
196
- */
197
- async handleErrorResponse(response) {
198
- let errorData;
199
- try {
200
- errorData = await response.json();
201
- } catch {
202
- throw new CobblError(
203
- `HTTP ${response.status}: ${response.statusText}`,
204
- "API_ERROR",
205
- { status: response.status }
206
- );
207
- }
208
- const message = errorData.error || errorData.message || "Unknown error";
209
- const details = errorData.details;
210
- switch (response.status) {
211
- case 400:
212
- throw new CobblError(message, "INVALID_REQUEST", details);
213
- case 401:
214
- throw new CobblError(message, "UNAUTHORIZED", details);
215
- case 404:
216
- throw new CobblError(message, "NOT_FOUND", details);
217
- case 429:
218
- throw new CobblError(message, "RATE_LIMIT_EXCEEDED", details);
219
- case 500:
220
- case 502:
221
- case 503:
222
- case 504:
223
- throw new CobblError(message, "SERVER_ERROR", details);
224
- default:
225
- throw new CobblError(message, "API_ERROR", {
226
- status: response.status,
227
- ...details
228
- });
229
- }
230
- }
231
377
  };
232
378
 
233
- exports.CobblClient = CobblClient;
379
+ exports.CobblAdminClient = CobblAdminClient;
234
380
  exports.CobblError = CobblError;
381
+ exports.CobblPublicClient = CobblPublicClient;
235
382
  //# sourceMappingURL=index.js.map
236
383
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Error types that can be thrown by the Cobbl SDK\n */\nexport type CobblErrorCode =\n | 'INVALID_CONFIG'\n | 'INVALID_REQUEST'\n | 'UNAUTHORIZED'\n | 'NOT_FOUND'\n | 'RATE_LIMIT_EXCEEDED'\n | 'SERVER_ERROR'\n | 'NETWORK_ERROR'\n | 'API_ERROR'\n\n/**\n * Custom error class for Cobbl SDK errors\n *\n * @example\n * ```typescript\n * try {\n * await client.runPrompt('my-prompt', { topic: 'test' })\n * } catch (error) {\n * if (error instanceof CobblError) {\n * console.error(`Error [${error.code}]: ${error.message}`)\n * console.error('Details:', error.details)\n * }\n * }\n * ```\n */\nexport class CobblError extends Error {\n /**\n * Error code indicating the type of error\n */\n public readonly code: CobblErrorCode\n\n /**\n * Additional details about the error (e.g., missing variables, validation issues)\n */\n public readonly details?: unknown\n\n constructor(message: string, code: CobblErrorCode, details?: unknown) {\n super(message)\n this.name = 'CobblError'\n this.code = code\n this.details = details\n\n // Maintains proper stack trace for where error was thrown (V8 only)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, CobblError)\n }\n }\n\n /**\n * Check if an error is a CobblError\n */\n static isCobblError(error: unknown): error is CobblError {\n return error instanceof CobblError\n }\n\n /**\n * Convert error to JSON-serializable object\n */\n toJSON() {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n details: this.details,\n }\n }\n}\n","/**\n * CobblClient - SDK for the Cobbl platform\n *\n * Provides methods to run prompts and submit feedback to the Cobbl API.\n */\n\nimport type { PromptInput, PromptVersionClient } from '@prompti/shared'\nimport type {\n RunPromptResponse,\n SubmitFeedbackResponse,\n CobblConfig,\n TokenUsage,\n FeedbackSubmission,\n} from './types'\nimport { CobblError } from './errors'\n\nconst REQUEST_TIMEOUT_MS = 30_000\n\nexport class CobblClient {\n private readonly apiKey: string\n\n /**\n * Initialize the Cobbl SDK client\n *\n * @param config - Configuration object\n * @param config.apiKey - Your Cobbl API key\n *\n * @example\n * ```typescript\n * const client = new CobblClient({\n * apiKey: process.env.COBBL_API_KEY\n * })\n * ```\n */\n constructor(config: CobblConfig) {\n if (!config.apiKey || config.apiKey.trim().length === 0) {\n throw new CobblError('API key is required', 'INVALID_CONFIG')\n }\n\n this.apiKey = config.apiKey\n }\n\n /**\n * Execute a prompt with the given input variables\n *\n * @param promptSlug - The unique slug identifier for the prompt\n * @param input - Input variables to populate the prompt template\n * @returns Promise containing the prompt execution results\n *\n * @throws {CobblError} When the request fails or API returns an error\n *\n * @example\n * ```typescript\n * const result = await client.runPrompt('sales_summary', {\n * topic: 'Q4 Results',\n * tone: 'friendly',\n * audience: 'investors'\n * })\n *\n * console.log(result.output) // AI-generated response\n * console.log(result.runId) // Save this to link feedback later\n * ```\n */\n async runPrompt(\n promptSlug: string,\n input: PromptInput\n ): Promise<RunPromptResponse> {\n if (!promptSlug || promptSlug.trim().length === 0) {\n throw new CobblError('promptSlug is required', 'INVALID_REQUEST')\n }\n\n try {\n const response = await this.makeRequest('/prompt/run', {\n method: 'POST',\n body: JSON.stringify({\n promptSlug: promptSlug.trim(),\n input,\n }),\n })\n\n if (!response.ok) {\n await this.handleErrorResponse(response)\n }\n\n const data = (await response.json()) as {\n runId: string\n output: string\n tokenUsage: TokenUsage\n renderedPrompt: string\n promptVersion: PromptVersionClient\n }\n\n return {\n runId: data.runId,\n output: data.output,\n tokenUsage: data.tokenUsage,\n renderedPrompt: data.renderedPrompt,\n promptVersion: data.promptVersion,\n }\n } catch (error) {\n if (error instanceof CobblError) {\n throw error\n }\n throw new CobblError(\n `Failed to run prompt: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'NETWORK_ERROR'\n )\n }\n }\n\n /**\n * Submit user feedback for a prompt run\n *\n * @param feedback - Feedback submission data\n * @param feedback.runId - The run ID from a previous runPrompt call\n * @param feedback.helpful - Whether the output was helpful ('helpful' or 'not_helpful')\n * @param feedback.userFeedback - Detailed feedback message from the user\n * @returns Promise containing the created feedback ID\n *\n * @throws {CobblError} When the request fails or API returns an error\n *\n * @example\n * ```typescript\n * await client.submitFeedback({\n * runId: result.runId,\n * helpful: 'not_helpful',\n * userFeedback: 'The response was too formal and lengthy'\n * })\n * ```\n */\n async submitFeedback(\n feedback: FeedbackSubmission\n ): Promise<SubmitFeedbackResponse> {\n if (!feedback.runId || feedback.runId.trim().length === 0) {\n throw new CobblError('runId is required', 'INVALID_REQUEST')\n }\n\n if (!feedback.userFeedback || feedback.userFeedback.trim().length === 0) {\n throw new CobblError('userFeedback is required', 'INVALID_REQUEST')\n }\n\n if (\n !feedback.helpful ||\n !['helpful', 'not_helpful'].includes(feedback.helpful)\n ) {\n throw new CobblError(\n 'helpful must be either \"helpful\" or \"not_helpful\"',\n 'INVALID_REQUEST'\n )\n }\n\n try {\n const response = await this.makeRequest('/feedback', {\n method: 'POST',\n body: JSON.stringify({\n runId: feedback.runId.trim(),\n helpful: feedback.helpful,\n userFeedback: feedback.userFeedback.trim(),\n }),\n })\n\n if (!response.ok) {\n await this.handleErrorResponse(response)\n }\n\n const data = (await response.json()) as {\n feedbackId: string\n message: string\n }\n\n return {\n feedbackId: data.feedbackId,\n message: data.message,\n }\n } catch (error) {\n if (error instanceof CobblError) {\n throw error\n }\n throw new CobblError(\n `Failed to submit feedback: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'NETWORK_ERROR'\n )\n }\n }\n\n /**\n * Make an HTTP request to the Cobbl API\n * @private\n */\n private async makeRequest(\n path: string,\n options: RequestInit\n ): Promise<Response> {\n const baseUrl = process.env.COBBL_API_URL || 'https://api.cobbl.ai'\n const url = `${baseUrl}${path}`\n\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS)\n\n try {\n const response = await fetch(url, {\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n ...options.headers,\n },\n signal: controller.signal,\n })\n\n return response\n } finally {\n clearTimeout(timeoutId)\n }\n }\n\n /**\n * Handle error responses from the API\n * @private\n */\n private async handleErrorResponse(response: Response): Promise<never> {\n let errorData: any\n try {\n errorData = await response.json()\n } catch {\n throw new CobblError(\n `HTTP ${response.status}: ${response.statusText}`,\n 'API_ERROR',\n { status: response.status }\n )\n }\n\n const message = errorData.error || errorData.message || 'Unknown error'\n const details = errorData.details\n\n switch (response.status) {\n case 400:\n throw new CobblError(message, 'INVALID_REQUEST', details)\n case 401:\n throw new CobblError(message, 'UNAUTHORIZED', details)\n case 404:\n throw new CobblError(message, 'NOT_FOUND', details)\n case 429:\n throw new CobblError(message, 'RATE_LIMIT_EXCEEDED', details)\n case 500:\n case 502:\n case 503:\n case 504:\n throw new CobblError(message, 'SERVER_ERROR', details)\n default:\n throw new CobblError(message, 'API_ERROR', {\n status: response.status,\n ...details,\n })\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/admin.ts","../src/validation.ts","../src/public.ts"],"names":["REQUEST_TIMEOUT_MS"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Error types that can be thrown by the Cobbl SDK\n */\nexport type CobblErrorCode =\n | 'INVALID_CONFIG'\n | 'INVALID_REQUEST'\n | 'UNAUTHORIZED'\n | 'FORBIDDEN'\n | 'NOT_FOUND'\n | 'ARCHIVED'\n | 'RATE_LIMIT_EXCEEDED'\n | 'SERVER_ERROR'\n | 'NETWORK_ERROR'\n | 'API_ERROR'\n\n/**\n * Custom error class for Cobbl SDK errors\n *\n * @example\n * ```typescript\n * try {\n * await client.runPrompt('my-prompt', { topic: 'test' })\n * } catch (error) {\n * if (error instanceof CobblError) {\n * console.error(`Error [${error.code}]: ${error.message}`)\n * console.error('Details:', error.details)\n * }\n * }\n * ```\n */\nexport class CobblError extends Error {\n /**\n * Error code indicating the type of error\n */\n public readonly code: CobblErrorCode\n\n /**\n * Additional details about the error (e.g., missing variables, validation issues)\n */\n public readonly details?: unknown\n\n constructor(message: string, code: CobblErrorCode, details?: unknown) {\n super(message)\n this.name = 'CobblError'\n this.code = code\n this.details = details\n\n // Maintains proper stack trace for where error was thrown (V8 only)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, CobblError)\n }\n }\n\n /**\n * Check if an error is a CobblError\n */\n static isCobblError(error: unknown): error is CobblError {\n return error instanceof CobblError\n }\n\n /**\n * Convert error to JSON-serializable object\n */\n toJSON() {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n details: this.details,\n }\n }\n}\n\n/**\n * Handle error responses from the API\n * @internal\n */\nexport const handleErrorResponse = async (\n response: Response\n): Promise<never> => {\n let errorData: any\n try {\n errorData = await response.json()\n } catch {\n throw new CobblError(\n `HTTP ${response.status}: ${response.statusText}`,\n 'API_ERROR',\n { status: response.status }\n )\n }\n\n const message = errorData.error || errorData.message || 'Unknown error'\n const details = errorData.details\n\n switch (response.status) {\n case 400:\n throw new CobblError(message, 'INVALID_REQUEST', details)\n case 401:\n throw new CobblError(message, 'UNAUTHORIZED', details)\n case 403:\n throw new CobblError(message, 'FORBIDDEN', details)\n case 404:\n throw new CobblError(message, 'NOT_FOUND', details)\n case 410:\n throw new CobblError(message, 'ARCHIVED', details)\n case 429:\n throw new CobblError(message, 'RATE_LIMIT_EXCEEDED', details)\n case 500:\n case 502:\n case 503:\n case 504:\n throw new CobblError(message, 'SERVER_ERROR', details)\n default:\n throw new CobblError(message, 'API_ERROR', {\n status: response.status,\n ...details,\n })\n }\n}\n","/**\n * Cobbl SDK - Admin API Client\n *\n * A client for admin/server-side operations like running prompts.\n * Use this in server-side contexts where you need to execute prompts.\n *\n * @example\n * ```typescript\n * import { CobblAdminClient } from '@cobbl-ai/sdk/admin'\n *\n * const client = new CobblAdminClient({\n * apiKey: process.env.COBBL_API_KEY\n * })\n *\n * // Run a prompt\n * const result = await client.runPrompt('sales_summary', {\n * topic: 'Q4 Results',\n * tone: 'friendly'\n * })\n *\n * console.log(result.output)\n * console.log(result.runId) // Use this to link feedback later\n * ```\n */\n\nimport type { PromptInput, PromptVersionClient } from './types'\nimport type { CobblConfig, RunPromptResponse, TokenUsage } from './types'\nimport { CobblError, handleErrorResponse } from './errors'\n\nconst REQUEST_TIMEOUT_MS = 30_000\n\n/**\n * Admin API Client for Cobbl\n *\n * Provides methods to run prompts via the admin API.\n * This client is suitable for use in server-side contexts.\n */\nexport class CobblAdminClient {\n private readonly apiKey: string\n private readonly baseUrl: string\n\n /**\n * Initialize the Cobbl Admin SDK client\n *\n * @param config - Configuration object\n * @param config.apiKey - Your Cobbl API key\n * @param config.baseUrl - Optional base URL for the API (defaults to 'https://api.cobbl.ai')\n *\n * @example Production (uses default URL)\n * ```typescript\n * const client = new CobblAdminClient({\n * apiKey: process.env.COBBL_API_KEY\n * })\n * ```\n *\n * @example Local development with Firebase emulators\n * ```typescript\n * const client = new CobblAdminClient({\n * apiKey: process.env.COBBL_API_KEY,\n * baseUrl: 'http://localhost:5001/your-project-id/us-central1/externalApi'\n * })\n * ```\n */\n constructor(config: CobblConfig) {\n if (!config.apiKey || config.apiKey.trim().length === 0) {\n throw new CobblError('API key is required', 'INVALID_CONFIG')\n }\n\n this.apiKey = config.apiKey\n this.baseUrl = config.baseUrl?.trim() || 'https://api.cobbl.ai'\n }\n\n /**\n * Execute a prompt with the given input variables\n *\n * @param promptSlug - The unique slug identifier for the prompt\n * @param input - Input variables to populate the prompt template\n * @returns Promise containing the prompt execution results\n *\n * @throws {CobblError} When the request fails or API returns an error\n *\n * @example\n * ```typescript\n * const result = await client.runPrompt('sales_summary', {\n * topic: 'Q4 Results',\n * tone: 'friendly',\n * audience: 'investors'\n * })\n *\n * console.log(result.output) // AI-generated response\n * console.log(result.runId) // Save this to link feedback later\n * ```\n */\n async runPrompt(\n promptSlug: string,\n input: PromptInput\n ): Promise<RunPromptResponse> {\n if (!promptSlug || promptSlug.trim().length === 0) {\n throw new CobblError('promptSlug is required', 'INVALID_REQUEST')\n }\n\n try {\n const response = await this.makeRequest('/admin/v1/prompt/run', {\n method: 'POST',\n body: JSON.stringify({\n promptSlug: promptSlug.trim(),\n input,\n }),\n })\n\n if (!response.ok) {\n await handleErrorResponse(response)\n }\n\n const data = (await response.json()) as {\n runId: string\n output: string\n tokenUsage: TokenUsage\n renderedPrompt: string\n promptVersion: PromptVersionClient\n }\n\n return {\n runId: data.runId,\n output: data.output,\n tokenUsage: data.tokenUsage,\n renderedPrompt: data.renderedPrompt,\n promptVersion: data.promptVersion,\n }\n } catch (error) {\n if (error instanceof CobblError) {\n throw error\n }\n throw new CobblError(\n `Failed to run prompt: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'NETWORK_ERROR'\n )\n }\n }\n\n /**\n * Make an HTTP request to the Cobbl API\n * @private\n */\n private async makeRequest(\n path: string,\n options: RequestInit\n ): Promise<Response> {\n const url = `${this.baseUrl}${path}`\n\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS)\n\n try {\n const response = await fetch(url, {\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n ...options.headers,\n },\n signal: controller.signal,\n })\n\n return response\n } finally {\n clearTimeout(timeoutId)\n }\n }\n}\n\n// Export the client\nexport { CobblError } from './errors'\nexport type { CobblErrorCode } from './errors'\nexport type {\n CobblConfig,\n TokenUsage,\n RunPromptRequest,\n RunPromptResponse,\n PromptInput,\n PromptVersionClient,\n Provider,\n VariableConfig,\n} from './types'\n","import type {\n CreateFeedbackRequest,\n UpdateFeedbackRequest,\n Helpful,\n} from './types'\n\nconst VALID_HELPFUL_VALUES: Helpful[] = ['helpful', 'not_helpful']\n\nexport function validateCreateFeedback(\n feedback: CreateFeedbackRequest\n): string | null {\n if (!feedback.runId || feedback.runId.trim().length === 0) {\n return 'runId is required'\n }\n if (\n feedback.helpful !== undefined &&\n !VALID_HELPFUL_VALUES.includes(feedback.helpful)\n ) {\n return 'helpful must be \"helpful\" or \"not_helpful\"'\n }\n if (\n feedback.userFeedback !== undefined &&\n feedback.userFeedback.trim().length === 0\n ) {\n return 'userFeedback cannot be empty'\n }\n if (feedback.helpful === undefined && feedback.userFeedback === undefined) {\n return 'At least one of helpful or userFeedback is required'\n }\n return null\n}\n\nexport function validateUpdateFeedback(\n update: UpdateFeedbackRequest\n): string | null {\n if (\n update.helpful !== undefined &&\n !VALID_HELPFUL_VALUES.includes(update.helpful)\n ) {\n return 'helpful must be \"helpful\" or \"not_helpful\"'\n }\n if (\n update.userFeedback !== undefined &&\n update.userFeedback.trim().length === 0\n ) {\n return 'userFeedback cannot be empty'\n }\n if (update.helpful === undefined && update.userFeedback === undefined) {\n return 'At least one of helpful or userFeedback is required'\n }\n return null\n}\n","/**\n * Cobbl SDK - Public API Client\n *\n * A lightweight client for public-facing feedback operations.\n * Use this in client-side or user-facing contexts.\n * No authentication required - designed for end-user feedback submission.\n *\n * @example\n * ```typescript\n * import { CobblPublicClient } from '@cobbl-ai/sdk/public'\n *\n * const client = new CobblPublicClient({\n * baseUrl: 'https://api.cobbl.ai' // Optional, defaults to production\n * })\n *\n * // Submit feedback\n * const { id } = await client.createFeedback({\n * runId: 'run_abc123',\n * helpful: 'not_helpful'\n * })\n *\n * // Update feedback with details later\n * await client.updateFeedback(id, {\n * userFeedback: 'Too formal'\n * })\n * ```\n */\n\nimport type {\n CreateFeedbackRequest,\n CreateFeedbackResponse,\n UpdateFeedbackRequest,\n UpdateFeedbackResponse,\n} from './types'\nimport { CobblError, handleErrorResponse } from './errors'\nimport { validateCreateFeedback, validateUpdateFeedback } from './validation'\n\n/**\n * Configuration options for CobblPublicClient\n */\nexport interface CobblPublicConfig {\n /**\n * Base URL for the API\n * @optional\n * @default 'https://api.cobbl.ai'\n * @internal\n * @example 'http://localhost:5001/your-project/us-central1/externalApi' // For local development\n */\n baseUrl?: string\n}\n\nconst REQUEST_TIMEOUT_MS = 30_000\n\n/**\n * Public API Client for Cobbl\n *\n * Provides methods to submit and update feedback via the public API.\n * This client is suitable for use in client-side or user-facing contexts.\n * No authentication required - designed for end-user feedback submission.\n */\nexport class CobblPublicClient {\n private readonly baseUrl: string\n\n /**\n * Initialize the Cobbl Public SDK client\n *\n * @param config - Configuration object\n * @param config.baseUrl - Optional base URL for the API (defaults to 'https://api.cobbl.ai')\n */\n constructor(config: CobblPublicConfig = {}) {\n this.baseUrl = config.baseUrl?.trim() || 'https://api.cobbl.ai'\n }\n\n /**\n * Create user feedback for a prompt run\n * Supports segmented feedback - you can provide just helpful, just userFeedback, or both\n * Use updateFeedback to add additional data later\n *\n * @param feedback - Feedback submission data\n * @param feedback.runId - The run ID from a previous runPrompt call\n * @param feedback.helpful - Whether the output was helpful ('helpful' or 'not_helpful') - optional\n * @param feedback.userFeedback - Detailed feedback message from the user - optional\n * @returns Promise containing the created feedback ID\n *\n * @throws {CobblError} When the request fails or API returns an error\n *\n * @example Submit just thumbs down first\n * ```typescript\n * const { id } = await client.createFeedback({\n * runId: result.runId,\n * helpful: 'not_helpful'\n * })\n * // Later, add details\n * await client.updateFeedback(id, {\n * userFeedback: 'The response was too formal and lengthy'\n * })\n * ```\n *\n * @example Submit both at once\n * ```typescript\n * await client.createFeedback({\n * runId: result.runId,\n * helpful: 'not_helpful',\n * userFeedback: 'The response was too formal and lengthy'\n * })\n * ```\n */\n async createFeedback(\n feedback: CreateFeedbackRequest\n ): Promise<CreateFeedbackResponse> {\n const validationError = validateCreateFeedback(feedback)\n if (validationError) {\n throw new CobblError(validationError, 'INVALID_REQUEST')\n }\n\n try {\n // Build request body with only provided fields\n const body: CreateFeedbackRequest = {\n runId: feedback.runId.trim(),\n helpful: feedback.helpful,\n userFeedback: feedback.userFeedback?.trim(),\n }\n\n const response = await this.makeRequest('/public/v1/feedback', {\n method: 'POST',\n body: JSON.stringify(body),\n })\n\n if (!response.ok) {\n await handleErrorResponse(response)\n }\n\n const data = (await response.json()) as {\n id: string\n message: string\n }\n\n return {\n id: data.id,\n message: data.message,\n }\n } catch (error) {\n if (error instanceof CobblError) {\n throw error\n }\n throw new CobblError(\n `Failed to create feedback: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'NETWORK_ERROR'\n )\n }\n }\n\n /**\n * Update existing feedback with additional data\n * Use this to add helpful sentiment or detailed feedback after initial submission\n *\n * @param id - The ID returned from createFeedback\n * @param update - The data to update\n * @param update.helpful - Whether the output was helpful ('helpful' or 'not_helpful') - optional\n * @param update.userFeedback - Detailed feedback message from the user - optional\n * @returns Promise containing the updated feedback ID\n *\n * @throws {CobblError} When the request fails or API returns an error\n *\n * @example Add details after initial thumbs down\n * ```typescript\n * // First, submit just the rating\n * const { id } = await client.createFeedback({\n * runId: result.runId,\n * helpful: 'not_helpful'\n * })\n *\n * // Later, add detailed feedback\n * await client.updateFeedback(id, {\n * userFeedback: 'The response was too formal and lengthy'\n * })\n * ```\n */\n async updateFeedback(\n id: string,\n update: UpdateFeedbackRequest\n ): Promise<UpdateFeedbackResponse> {\n if (!id || id.trim().length === 0) {\n throw new CobblError('id is required', 'INVALID_REQUEST')\n }\n\n const validationError = validateUpdateFeedback(update)\n if (validationError) {\n throw new CobblError(validationError, 'INVALID_REQUEST')\n }\n\n try {\n // Build request body with only provided fields\n const body: UpdateFeedbackRequest = {\n helpful: update.helpful,\n userFeedback: update.userFeedback?.trim(),\n }\n\n const response = await this.makeRequest(\n `/public/v1/feedback/${id.trim()}`,\n {\n method: 'PATCH',\n body: JSON.stringify(body),\n }\n )\n\n if (!response.ok) {\n await handleErrorResponse(response)\n }\n\n const data = (await response.json()) as {\n id: string\n message: string\n }\n\n return {\n id: data.id,\n message: data.message,\n }\n } catch (error) {\n if (error instanceof CobblError) {\n throw error\n }\n throw new CobblError(\n `Failed to update feedback: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'NETWORK_ERROR'\n )\n }\n }\n\n /**\n * Make an HTTP request to the Cobbl API\n * @private\n */\n private async makeRequest(\n path: string,\n options: RequestInit\n ): Promise<Response> {\n const url = `${this.baseUrl}${path}`\n\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS)\n\n try {\n const response = await fetch(url, {\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers,\n },\n signal: controller.signal,\n })\n\n return response\n } finally {\n clearTimeout(timeoutId)\n }\n }\n}\n\n// Export the client\nexport { CobblError } from './errors'\nexport type { CobblErrorCode } from './errors'\nexport type {\n CreateFeedbackRequest,\n CreateFeedbackResponse,\n UpdateFeedbackRequest,\n UpdateFeedbackResponse,\n Helpful,\n} from './types'\n"]}