@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/README.md +179 -55
- package/dist/admin.d.mts +90 -0
- package/dist/admin.d.ts +90 -0
- package/dist/admin.js +185 -0
- package/dist/admin.js.map +1 -0
- package/dist/admin.mjs +182 -0
- package/dist/admin.mjs.map +1 -0
- package/dist/cobbl-sdk.global.js +2 -0
- package/dist/cobbl-sdk.global.js.map +1 -0
- package/dist/errors-BaYZ2rGo.d.mts +208 -0
- package/dist/errors-BaYZ2rGo.d.ts +208 -0
- package/dist/index.d.mts +3 -348
- package/dist/index.d.ts +3 -348
- package/dist/index.js +222 -75
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +221 -75
- package/dist/index.mjs.map +1 -1
- package/dist/public.d.mts +130 -0
- package/dist/public.d.ts +130 -0
- package/dist/public.js +271 -0
- package/dist/public.js.map +1 -0
- package/dist/public.mjs +268 -0
- package/dist/public.mjs.map +1 -0
- package/package.json +40 -11
- package/src/__tests__/client.test.ts +362 -107
- package/src/__tests__/integration.test.ts +129 -38
- package/src/admin.ts +184 -0
- package/src/browser.ts +12 -0
- package/src/errors.ts +49 -0
- package/src/index.ts +35 -10
- package/src/public.ts +270 -0
- package/src/types.ts +164 -58
- package/src/validation.ts +52 -0
- package/src/client.ts +0 -257
package/src/public.ts
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cobbl SDK - Public API Client
|
|
3
|
+
*
|
|
4
|
+
* A lightweight client for public-facing feedback operations.
|
|
5
|
+
* Use this in client-side or user-facing contexts.
|
|
6
|
+
* No authentication required - designed for end-user feedback submission.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { CobblPublicClient } from '@cobbl-ai/sdk/public'
|
|
11
|
+
*
|
|
12
|
+
* const client = new CobblPublicClient({
|
|
13
|
+
* baseUrl: 'https://api.cobbl.ai' // Optional, defaults to production
|
|
14
|
+
* })
|
|
15
|
+
*
|
|
16
|
+
* // Submit feedback
|
|
17
|
+
* const { id } = await client.createFeedback({
|
|
18
|
+
* runId: 'run_abc123',
|
|
19
|
+
* helpful: 'not_helpful'
|
|
20
|
+
* })
|
|
21
|
+
*
|
|
22
|
+
* // Update feedback with details later
|
|
23
|
+
* await client.updateFeedback(id, {
|
|
24
|
+
* userFeedback: 'Too formal'
|
|
25
|
+
* })
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import type {
|
|
30
|
+
CreateFeedbackRequest,
|
|
31
|
+
CreateFeedbackResponse,
|
|
32
|
+
UpdateFeedbackRequest,
|
|
33
|
+
UpdateFeedbackResponse,
|
|
34
|
+
} from './types'
|
|
35
|
+
import { CobblError, handleErrorResponse } from './errors'
|
|
36
|
+
import { validateCreateFeedback, validateUpdateFeedback } from './validation'
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Configuration options for CobblPublicClient
|
|
40
|
+
*/
|
|
41
|
+
export interface CobblPublicConfig {
|
|
42
|
+
/**
|
|
43
|
+
* Base URL for the API
|
|
44
|
+
* @optional
|
|
45
|
+
* @default 'https://api.cobbl.ai'
|
|
46
|
+
* @internal
|
|
47
|
+
* @example 'http://localhost:5001/your-project/us-central1/externalApi' // For local development
|
|
48
|
+
*/
|
|
49
|
+
baseUrl?: string
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const REQUEST_TIMEOUT_MS = 30_000
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Public API Client for Cobbl
|
|
56
|
+
*
|
|
57
|
+
* Provides methods to submit and update feedback via the public API.
|
|
58
|
+
* This client is suitable for use in client-side or user-facing contexts.
|
|
59
|
+
* No authentication required - designed for end-user feedback submission.
|
|
60
|
+
*/
|
|
61
|
+
export class CobblPublicClient {
|
|
62
|
+
private readonly baseUrl: string
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Initialize the Cobbl Public SDK client
|
|
66
|
+
*
|
|
67
|
+
* @param config - Configuration object
|
|
68
|
+
* @param config.baseUrl - Optional base URL for the API (defaults to 'https://api.cobbl.ai')
|
|
69
|
+
*/
|
|
70
|
+
constructor(config: CobblPublicConfig = {}) {
|
|
71
|
+
this.baseUrl = config.baseUrl?.trim() || 'https://api.cobbl.ai'
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Create user feedback for a prompt run
|
|
76
|
+
* Supports segmented feedback - you can provide just helpful, just userFeedback, or both
|
|
77
|
+
* Use updateFeedback to add additional data later
|
|
78
|
+
*
|
|
79
|
+
* @param feedback - Feedback submission data
|
|
80
|
+
* @param feedback.runId - The run ID from a previous runPrompt call
|
|
81
|
+
* @param feedback.helpful - Whether the output was helpful ('helpful' or 'not_helpful') - optional
|
|
82
|
+
* @param feedback.userFeedback - Detailed feedback message from the user - optional
|
|
83
|
+
* @returns Promise containing the created feedback ID
|
|
84
|
+
*
|
|
85
|
+
* @throws {CobblError} When the request fails or API returns an error
|
|
86
|
+
*
|
|
87
|
+
* @example Submit just thumbs down first
|
|
88
|
+
* ```typescript
|
|
89
|
+
* const { id } = await client.createFeedback({
|
|
90
|
+
* runId: result.runId,
|
|
91
|
+
* helpful: 'not_helpful'
|
|
92
|
+
* })
|
|
93
|
+
* // Later, add details
|
|
94
|
+
* await client.updateFeedback(id, {
|
|
95
|
+
* userFeedback: 'The response was too formal and lengthy'
|
|
96
|
+
* })
|
|
97
|
+
* ```
|
|
98
|
+
*
|
|
99
|
+
* @example Submit both at once
|
|
100
|
+
* ```typescript
|
|
101
|
+
* await client.createFeedback({
|
|
102
|
+
* runId: result.runId,
|
|
103
|
+
* helpful: 'not_helpful',
|
|
104
|
+
* userFeedback: 'The response was too formal and lengthy'
|
|
105
|
+
* })
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
async createFeedback(
|
|
109
|
+
feedback: CreateFeedbackRequest
|
|
110
|
+
): Promise<CreateFeedbackResponse> {
|
|
111
|
+
const validationError = validateCreateFeedback(feedback)
|
|
112
|
+
if (validationError) {
|
|
113
|
+
throw new CobblError(validationError, 'INVALID_REQUEST')
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
// Build request body with only provided fields
|
|
118
|
+
const body: CreateFeedbackRequest = {
|
|
119
|
+
runId: feedback.runId.trim(),
|
|
120
|
+
helpful: feedback.helpful,
|
|
121
|
+
userFeedback: feedback.userFeedback?.trim(),
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const response = await this.makeRequest('/public/v1/feedback', {
|
|
125
|
+
method: 'POST',
|
|
126
|
+
body: JSON.stringify(body),
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
if (!response.ok) {
|
|
130
|
+
await handleErrorResponse(response)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const data = (await response.json()) as {
|
|
134
|
+
id: string
|
|
135
|
+
message: string
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
id: data.id,
|
|
140
|
+
message: data.message,
|
|
141
|
+
}
|
|
142
|
+
} catch (error) {
|
|
143
|
+
if (error instanceof CobblError) {
|
|
144
|
+
throw error
|
|
145
|
+
}
|
|
146
|
+
throw new CobblError(
|
|
147
|
+
`Failed to create feedback: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
148
|
+
'NETWORK_ERROR'
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Update existing feedback with additional data
|
|
155
|
+
* Use this to add helpful sentiment or detailed feedback after initial submission
|
|
156
|
+
*
|
|
157
|
+
* @param id - The ID returned from createFeedback
|
|
158
|
+
* @param update - The data to update
|
|
159
|
+
* @param update.helpful - Whether the output was helpful ('helpful' or 'not_helpful') - optional
|
|
160
|
+
* @param update.userFeedback - Detailed feedback message from the user - optional
|
|
161
|
+
* @returns Promise containing the updated feedback ID
|
|
162
|
+
*
|
|
163
|
+
* @throws {CobblError} When the request fails or API returns an error
|
|
164
|
+
*
|
|
165
|
+
* @example Add details after initial thumbs down
|
|
166
|
+
* ```typescript
|
|
167
|
+
* // First, submit just the rating
|
|
168
|
+
* const { id } = await client.createFeedback({
|
|
169
|
+
* runId: result.runId,
|
|
170
|
+
* helpful: 'not_helpful'
|
|
171
|
+
* })
|
|
172
|
+
*
|
|
173
|
+
* // Later, add detailed feedback
|
|
174
|
+
* await client.updateFeedback(id, {
|
|
175
|
+
* userFeedback: 'The response was too formal and lengthy'
|
|
176
|
+
* })
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
async updateFeedback(
|
|
180
|
+
id: string,
|
|
181
|
+
update: UpdateFeedbackRequest
|
|
182
|
+
): Promise<UpdateFeedbackResponse> {
|
|
183
|
+
if (!id || id.trim().length === 0) {
|
|
184
|
+
throw new CobblError('id is required', 'INVALID_REQUEST')
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const validationError = validateUpdateFeedback(update)
|
|
188
|
+
if (validationError) {
|
|
189
|
+
throw new CobblError(validationError, 'INVALID_REQUEST')
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
try {
|
|
193
|
+
// Build request body with only provided fields
|
|
194
|
+
const body: UpdateFeedbackRequest = {
|
|
195
|
+
helpful: update.helpful,
|
|
196
|
+
userFeedback: update.userFeedback?.trim(),
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const response = await this.makeRequest(
|
|
200
|
+
`/public/v1/feedback/${id.trim()}`,
|
|
201
|
+
{
|
|
202
|
+
method: 'PATCH',
|
|
203
|
+
body: JSON.stringify(body),
|
|
204
|
+
}
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
if (!response.ok) {
|
|
208
|
+
await handleErrorResponse(response)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const data = (await response.json()) as {
|
|
212
|
+
id: string
|
|
213
|
+
message: string
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return {
|
|
217
|
+
id: data.id,
|
|
218
|
+
message: data.message,
|
|
219
|
+
}
|
|
220
|
+
} catch (error) {
|
|
221
|
+
if (error instanceof CobblError) {
|
|
222
|
+
throw error
|
|
223
|
+
}
|
|
224
|
+
throw new CobblError(
|
|
225
|
+
`Failed to update feedback: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
226
|
+
'NETWORK_ERROR'
|
|
227
|
+
)
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Make an HTTP request to the Cobbl API
|
|
233
|
+
* @private
|
|
234
|
+
*/
|
|
235
|
+
private async makeRequest(
|
|
236
|
+
path: string,
|
|
237
|
+
options: RequestInit
|
|
238
|
+
): Promise<Response> {
|
|
239
|
+
const url = `${this.baseUrl}${path}`
|
|
240
|
+
|
|
241
|
+
const controller = new AbortController()
|
|
242
|
+
const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS)
|
|
243
|
+
|
|
244
|
+
try {
|
|
245
|
+
const response = await fetch(url, {
|
|
246
|
+
...options,
|
|
247
|
+
headers: {
|
|
248
|
+
'Content-Type': 'application/json',
|
|
249
|
+
...options.headers,
|
|
250
|
+
},
|
|
251
|
+
signal: controller.signal,
|
|
252
|
+
})
|
|
253
|
+
|
|
254
|
+
return response
|
|
255
|
+
} finally {
|
|
256
|
+
clearTimeout(timeoutId)
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Export the client
|
|
262
|
+
export { CobblError } from './errors'
|
|
263
|
+
export type { CobblErrorCode } from './errors'
|
|
264
|
+
export type {
|
|
265
|
+
CreateFeedbackRequest,
|
|
266
|
+
CreateFeedbackResponse,
|
|
267
|
+
UpdateFeedbackRequest,
|
|
268
|
+
UpdateFeedbackResponse,
|
|
269
|
+
Helpful,
|
|
270
|
+
} from './types'
|
package/src/types.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Type definitions for the Cobbl SDK
|
|
3
|
+
*
|
|
4
|
+
* All types are defined locally to keep the SDK self-contained.
|
|
5
|
+
* These match the API contract and are used as type hints for SDK consumers.
|
|
3
6
|
*/
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
|
|
9
|
+
// ─── SDK Config ──────────────────────────────────────────────
|
|
6
10
|
|
|
7
11
|
/**
|
|
8
12
|
* Configuration options for the CobblClient
|
|
@@ -13,82 +17,184 @@ export interface CobblConfig {
|
|
|
13
17
|
* @required
|
|
14
18
|
*/
|
|
15
19
|
apiKey: string
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Base URL for the API
|
|
23
|
+
* @optional
|
|
24
|
+
* @default 'https://api.cobbl.ai'
|
|
25
|
+
* @internal
|
|
26
|
+
* @example 'http://localhost:5001/your-project/us-central1/externalApi' // For local development
|
|
27
|
+
*/
|
|
28
|
+
baseUrl?: string
|
|
16
29
|
}
|
|
17
30
|
|
|
31
|
+
// ─── Feedback Types ──────────────────────────────────────────
|
|
32
|
+
|
|
18
33
|
/**
|
|
19
|
-
*
|
|
34
|
+
* Whether the AI output was helpful
|
|
20
35
|
*/
|
|
21
|
-
export
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
36
|
+
export type Helpful = 'helpful' | 'not_helpful'
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Request payload for creating feedback
|
|
40
|
+
* Supports segmented feedback submission - at least one of helpful or userFeedback required
|
|
41
|
+
*/
|
|
42
|
+
export interface CreateFeedbackRequest {
|
|
25
43
|
runId: string
|
|
44
|
+
helpful?: Helpful
|
|
45
|
+
userFeedback?: string
|
|
46
|
+
}
|
|
26
47
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
48
|
+
/**
|
|
49
|
+
* Response from creating feedback
|
|
50
|
+
*/
|
|
51
|
+
export interface CreateFeedbackResponse {
|
|
52
|
+
id: string
|
|
53
|
+
message: string
|
|
54
|
+
}
|
|
31
55
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Request payload for updating feedback
|
|
58
|
+
* At least one of helpful or userFeedback required
|
|
59
|
+
*/
|
|
60
|
+
export interface UpdateFeedbackRequest {
|
|
61
|
+
helpful?: Helpful
|
|
62
|
+
userFeedback?: string
|
|
63
|
+
}
|
|
36
64
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Response from updating feedback
|
|
67
|
+
*/
|
|
68
|
+
export interface UpdateFeedbackResponse {
|
|
69
|
+
id: string
|
|
70
|
+
message: string
|
|
71
|
+
}
|
|
41
72
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
73
|
+
// ─── Prompt Types ────────────────────────────────────────────
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Supported LLM providers
|
|
77
|
+
*/
|
|
78
|
+
export type Provider = 'openai' | 'anthropic' | 'google'
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Configuration for a variable in the prompt
|
|
82
|
+
*/
|
|
83
|
+
export interface VariableConfig {
|
|
84
|
+
key: string
|
|
85
|
+
type: 'string' | 'number' | 'boolean' | 'list' | 'object'
|
|
86
|
+
required: boolean
|
|
87
|
+
description?: string
|
|
46
88
|
}
|
|
47
89
|
|
|
48
90
|
/**
|
|
49
|
-
*
|
|
91
|
+
* Input values provided when executing a prompt
|
|
50
92
|
*/
|
|
51
|
-
export
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
*/
|
|
56
|
-
runId: string
|
|
93
|
+
export type PromptInput = Record<
|
|
94
|
+
string,
|
|
95
|
+
string | number | boolean | unknown[] | Record<string, unknown>
|
|
96
|
+
>
|
|
57
97
|
|
|
58
|
-
|
|
59
|
-
* Whether the output was helpful
|
|
60
|
-
* @required
|
|
61
|
-
*/
|
|
62
|
-
helpful: Helpful
|
|
98
|
+
// ─── Token Usage ─────────────────────────────────────────────
|
|
63
99
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
100
|
+
/**
|
|
101
|
+
* Token usage breakdown for a completed prompt run
|
|
102
|
+
*/
|
|
103
|
+
export interface TokenUsage {
|
|
104
|
+
inputTokens: number
|
|
105
|
+
outputTokens: number
|
|
106
|
+
totalTokens: number
|
|
69
107
|
}
|
|
70
108
|
|
|
109
|
+
// ─── Analytics ───────────────────────────────────────────────
|
|
110
|
+
|
|
71
111
|
/**
|
|
72
|
-
*
|
|
112
|
+
* Aggregated analytics for a prompt or prompt version
|
|
73
113
|
*/
|
|
74
|
-
export interface
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
114
|
+
export interface PromptAggregatedAnalytics {
|
|
115
|
+
runs: {
|
|
116
|
+
totalCount: number
|
|
117
|
+
successCount: number
|
|
118
|
+
errorCount: number
|
|
119
|
+
totalProviderMs: number
|
|
120
|
+
totalRequestMs: number
|
|
121
|
+
successRate: number
|
|
122
|
+
errorRate: number
|
|
123
|
+
avgProviderMs: number
|
|
124
|
+
avgRequestMs: number
|
|
125
|
+
}
|
|
126
|
+
feedback: {
|
|
127
|
+
totalCount: number
|
|
128
|
+
helpfulCount: number
|
|
129
|
+
notHelpfulCount: number
|
|
130
|
+
helpfulRate: number
|
|
131
|
+
}
|
|
132
|
+
}
|
|
79
133
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
134
|
+
// ─── Prompt Version ──────────────────────────────────────────
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Base fields shared across all prompt version sources
|
|
138
|
+
*/
|
|
139
|
+
interface PromptVersionBase {
|
|
140
|
+
id: string
|
|
141
|
+
schemaVersion: number
|
|
142
|
+
createdAt: Date
|
|
143
|
+
updatedAt: Date
|
|
144
|
+
tenantId: string
|
|
145
|
+
environmentId: string
|
|
146
|
+
promptId: string
|
|
147
|
+
versionNumber: number
|
|
148
|
+
template: string
|
|
149
|
+
variables: VariableConfig[]
|
|
150
|
+
provider: Provider
|
|
151
|
+
model: string
|
|
152
|
+
status: 'draft' | 'active' | 'inactive'
|
|
153
|
+
parentVersionId: string | null
|
|
154
|
+
analytics: PromptAggregatedAnalytics
|
|
155
|
+
publishedAt: Date | null
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Manually created prompt version (by a user or from feedback edits)
|
|
160
|
+
*/
|
|
161
|
+
interface PromptVersionManual extends PromptVersionBase {
|
|
162
|
+
source: 'manual'
|
|
163
|
+
authorId: string
|
|
164
|
+
authorName: string | null
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* AI-generated prompt version suggestion from feedback issue assessment
|
|
169
|
+
*/
|
|
170
|
+
interface PromptVersionIssueLlmSuggestion extends PromptVersionBase {
|
|
171
|
+
source: 'issue_llm_suggestion'
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Prompt version - discriminated union by source
|
|
176
|
+
*/
|
|
177
|
+
export type PromptVersionClient =
|
|
178
|
+
| PromptVersionManual
|
|
179
|
+
| PromptVersionIssueLlmSuggestion
|
|
180
|
+
|
|
181
|
+
// ─── API Request/Response Types ──────────────────────────────
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Request payload for running a prompt
|
|
185
|
+
*/
|
|
186
|
+
export interface RunPromptRequest {
|
|
187
|
+
promptSlug: string
|
|
188
|
+
input: PromptInput
|
|
84
189
|
}
|
|
85
190
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
TokenUsage
|
|
93
|
-
|
|
94
|
-
|
|
191
|
+
/**
|
|
192
|
+
* Response from running a prompt
|
|
193
|
+
*/
|
|
194
|
+
export interface RunPromptResponse {
|
|
195
|
+
runId: string
|
|
196
|
+
output: string
|
|
197
|
+
tokenUsage: TokenUsage
|
|
198
|
+
renderedPrompt: string
|
|
199
|
+
promptVersion: PromptVersionClient
|
|
200
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CreateFeedbackRequest,
|
|
3
|
+
UpdateFeedbackRequest,
|
|
4
|
+
Helpful,
|
|
5
|
+
} from './types'
|
|
6
|
+
|
|
7
|
+
const VALID_HELPFUL_VALUES: Helpful[] = ['helpful', 'not_helpful']
|
|
8
|
+
|
|
9
|
+
export function validateCreateFeedback(
|
|
10
|
+
feedback: CreateFeedbackRequest
|
|
11
|
+
): string | null {
|
|
12
|
+
if (!feedback.runId || feedback.runId.trim().length === 0) {
|
|
13
|
+
return 'runId is required'
|
|
14
|
+
}
|
|
15
|
+
if (
|
|
16
|
+
feedback.helpful !== undefined &&
|
|
17
|
+
!VALID_HELPFUL_VALUES.includes(feedback.helpful)
|
|
18
|
+
) {
|
|
19
|
+
return 'helpful must be "helpful" or "not_helpful"'
|
|
20
|
+
}
|
|
21
|
+
if (
|
|
22
|
+
feedback.userFeedback !== undefined &&
|
|
23
|
+
feedback.userFeedback.trim().length === 0
|
|
24
|
+
) {
|
|
25
|
+
return 'userFeedback cannot be empty'
|
|
26
|
+
}
|
|
27
|
+
if (feedback.helpful === undefined && feedback.userFeedback === undefined) {
|
|
28
|
+
return 'At least one of helpful or userFeedback is required'
|
|
29
|
+
}
|
|
30
|
+
return null
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function validateUpdateFeedback(
|
|
34
|
+
update: UpdateFeedbackRequest
|
|
35
|
+
): string | null {
|
|
36
|
+
if (
|
|
37
|
+
update.helpful !== undefined &&
|
|
38
|
+
!VALID_HELPFUL_VALUES.includes(update.helpful)
|
|
39
|
+
) {
|
|
40
|
+
return 'helpful must be "helpful" or "not_helpful"'
|
|
41
|
+
}
|
|
42
|
+
if (
|
|
43
|
+
update.userFeedback !== undefined &&
|
|
44
|
+
update.userFeedback.trim().length === 0
|
|
45
|
+
) {
|
|
46
|
+
return 'userFeedback cannot be empty'
|
|
47
|
+
}
|
|
48
|
+
if (update.helpful === undefined && update.userFeedback === undefined) {
|
|
49
|
+
return 'At least one of helpful or userFeedback is required'
|
|
50
|
+
}
|
|
51
|
+
return null
|
|
52
|
+
}
|