@boldvideo/bold-js 1.6.1 → 1.7.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/CHANGELOG.md +38 -0
- package/README.md +75 -37
- package/dist/index.cjs +19 -18
- package/dist/index.d.ts +82 -73
- package/dist/index.js +19 -18
- package/llms.txt +21 -27
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# @boldvideo/bold-js
|
|
2
2
|
|
|
3
|
+
## 1.7.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- e6fb51b: Align SDK with Bold AI API v1 specification
|
|
8
|
+
|
|
9
|
+
**Breaking Changes:**
|
|
10
|
+
|
|
11
|
+
- Video-scoped chat: pass `videoId` in options instead of as separate arg: `bold.ai.chat({ videoId, prompt })`
|
|
12
|
+
- `Source.timestamp_end` and `Source.playback_id` are now required (were optional)
|
|
13
|
+
- `AIUsage` now uses `input_tokens`/`output_tokens` (was `prompt_tokens`/`completion_tokens`/`total_tokens`)
|
|
14
|
+
- Removed `TopicInput` type - `RecommendationsOptions.topics` now only accepts `string[]`
|
|
15
|
+
- `RecommendationsOptions.context` is now `AIContextMessage[]` (was `string`)
|
|
16
|
+
|
|
17
|
+
**New:**
|
|
18
|
+
|
|
19
|
+
- `bold.ai.chat(opts)` - Single method for all chat (pass `videoId` to scope to a video)
|
|
20
|
+
- `bold.ai.recommendations(opts)` - AI-powered video recommendations (replaces `recommend`)
|
|
21
|
+
- `ChatOptions.videoId` - Scope chat to a specific video
|
|
22
|
+
- `ChatOptions.currentTime` - Pass current playback position for context
|
|
23
|
+
|
|
24
|
+
**Deprecated (still work, will be removed in v2):**
|
|
25
|
+
|
|
26
|
+
- `bold.ai.ask()` → use `bold.ai.chat()`
|
|
27
|
+
- `bold.ai.coach()` → use `bold.ai.chat()`
|
|
28
|
+
- `bold.ai.recommend()` → use `bold.ai.recommendations()`
|
|
29
|
+
- `AskOptions` type → use `ChatOptions`
|
|
30
|
+
- `RecommendOptions` type → use `RecommendationsOptions`
|
|
31
|
+
- `RecommendResponse` type → use `RecommendationsResponse`
|
|
32
|
+
|
|
33
|
+
**Type Changes:**
|
|
34
|
+
|
|
35
|
+
- Added `Source.id` field (chunk identifier)
|
|
36
|
+
- Added `conversation_id` and `video_id` to `message_start` event
|
|
37
|
+
- Added `conversation_id`, `recommendations`, `guidance` to `message_complete` event
|
|
38
|
+
- Simplified `clarification` event to include `content` field
|
|
39
|
+
- Removed legacy event types: `token`, `answer`, `complete`
|
|
40
|
+
|
|
3
41
|
## 1.6.1
|
|
4
42
|
|
|
5
43
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -44,8 +44,8 @@ const bold = createClient('your-api-key');
|
|
|
44
44
|
// Fetch videos
|
|
45
45
|
const videos = await bold.videos.list();
|
|
46
46
|
|
|
47
|
-
//
|
|
48
|
-
const recs = await bold.ai.
|
|
47
|
+
// AI-powered recommendations
|
|
48
|
+
const recs = await bold.ai.recommendations({
|
|
49
49
|
topics: ['sales', 'negotiation'],
|
|
50
50
|
stream: false
|
|
51
51
|
});
|
|
@@ -92,15 +92,47 @@ const settings = await bold.settings();
|
|
|
92
92
|
|
|
93
93
|
All AI methods support both streaming (default) and non-streaming modes.
|
|
94
94
|
|
|
95
|
-
###
|
|
95
|
+
### Chat
|
|
96
|
+
|
|
97
|
+
Library-wide conversational AI for deep Q&A across your entire video library.
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
// Streaming (default)
|
|
101
|
+
const stream = await bold.ai.chat({ prompt: 'How do I price my SaaS?' });
|
|
102
|
+
|
|
103
|
+
for await (const event of stream) {
|
|
104
|
+
if (event.type === 'text_delta') process.stdout.write(event.delta);
|
|
105
|
+
if (event.type === 'sources') console.log('Sources:', event.sources);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Non-streaming
|
|
109
|
+
const response = await bold.ai.chat({
|
|
110
|
+
prompt: 'What are the best closing techniques?',
|
|
111
|
+
stream: false
|
|
112
|
+
});
|
|
113
|
+
console.log(response.content);
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Options:**
|
|
117
|
+
|
|
118
|
+
| Parameter | Type | Description |
|
|
119
|
+
|-----------|------|-------------|
|
|
120
|
+
| `prompt` | `string` | The user's question (required) |
|
|
121
|
+
| `stream` | `boolean` | `true` (default) for SSE, `false` for JSON |
|
|
122
|
+
| `videoId` | `string` | If provided, scope to this video instead of whole library |
|
|
123
|
+
| `currentTime` | `number` | Current playback position (only with `videoId`) |
|
|
124
|
+
| `conversationId` | `string` | Pass to continue existing conversation |
|
|
125
|
+
| `collectionId` | `string` | Filter to a specific collection |
|
|
126
|
+
| `tags` | `string[]` | Filter by tags |
|
|
127
|
+
|
|
128
|
+
### Recommendations
|
|
96
129
|
|
|
97
130
|
Get AI-powered video recommendations based on topics — ideal for personalized learning paths, exam prep, and content discovery.
|
|
98
131
|
|
|
99
132
|
```typescript
|
|
100
133
|
// Streaming (default)
|
|
101
|
-
const stream = await bold.ai.
|
|
134
|
+
const stream = await bold.ai.recommendations({
|
|
102
135
|
topics: ['contract law', 'ethics', 'client management'],
|
|
103
|
-
context: 'I failed these topics on my certification exam'
|
|
104
136
|
});
|
|
105
137
|
|
|
106
138
|
for await (const event of stream) {
|
|
@@ -116,7 +148,7 @@ for await (const event of stream) {
|
|
|
116
148
|
}
|
|
117
149
|
|
|
118
150
|
// Non-streaming
|
|
119
|
-
const response = await bold.ai.
|
|
151
|
+
const response = await bold.ai.recommendations({
|
|
120
152
|
topics: ['sales', 'marketing'],
|
|
121
153
|
stream: false
|
|
122
154
|
});
|
|
@@ -128,38 +160,17 @@ console.log(response.recommendations);
|
|
|
128
160
|
|
|
129
161
|
| Parameter | Type | Description |
|
|
130
162
|
|-----------|------|-------------|
|
|
131
|
-
| `topics` | `string[]`
|
|
163
|
+
| `topics` | `string[]` | Topics to find content for (required) |
|
|
132
164
|
| `stream` | `boolean` | `true` (default) for SSE, `false` for JSON |
|
|
133
165
|
| `limit` | `number` | Max videos per topic (default: 5, max: 20) |
|
|
134
166
|
| `collectionId` | `string` | Filter to a specific collection |
|
|
135
167
|
| `tags` | `string[]` | Filter by tags |
|
|
136
168
|
| `includeGuidance` | `boolean` | Include AI learning path narrative (default: true) |
|
|
137
|
-
| `context` | `
|
|
138
|
-
|
|
139
|
-
### Coach / Ask
|
|
140
|
-
|
|
141
|
-
Library-wide RAG assistant for answering questions across your entire video library.
|
|
142
|
-
|
|
143
|
-
```typescript
|
|
144
|
-
// Streaming
|
|
145
|
-
const stream = await bold.ai.coach({ prompt: 'How do I price my SaaS?' });
|
|
146
|
-
|
|
147
|
-
for await (const event of stream) {
|
|
148
|
-
if (event.type === 'text_delta') process.stdout.write(event.delta);
|
|
149
|
-
if (event.type === 'sources') console.log('Sources:', event.sources);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// Non-streaming
|
|
153
|
-
const response = await bold.ai.ask({
|
|
154
|
-
prompt: 'What are the best closing techniques?',
|
|
155
|
-
stream: false
|
|
156
|
-
});
|
|
157
|
-
console.log(response.content);
|
|
158
|
-
```
|
|
169
|
+
| `context` | `AIContextMessage[]` | Previous conversation turns for follow-ups |
|
|
159
170
|
|
|
160
171
|
### Search
|
|
161
172
|
|
|
162
|
-
|
|
173
|
+
Fast semantic search with a brief AI-generated summary.
|
|
163
174
|
|
|
164
175
|
```typescript
|
|
165
176
|
const stream = await bold.ai.search({
|
|
@@ -174,12 +185,13 @@ for await (const event of stream) {
|
|
|
174
185
|
}
|
|
175
186
|
```
|
|
176
187
|
|
|
177
|
-
### Chat
|
|
188
|
+
### Video-Scoped Chat
|
|
178
189
|
|
|
179
|
-
|
|
190
|
+
Chat about a specific video by passing `videoId`. Uses only that video's transcript as context.
|
|
180
191
|
|
|
181
192
|
```typescript
|
|
182
|
-
const stream = await bold.ai.chat(
|
|
193
|
+
const stream = await bold.ai.chat({
|
|
194
|
+
videoId: 'video-id',
|
|
183
195
|
prompt: 'What is discussed at the 5 minute mark?'
|
|
184
196
|
});
|
|
185
197
|
|
|
@@ -187,8 +199,9 @@ for await (const event of stream) {
|
|
|
187
199
|
if (event.type === 'text_delta') process.stdout.write(event.delta);
|
|
188
200
|
}
|
|
189
201
|
|
|
190
|
-
// With playback context
|
|
191
|
-
const stream = await bold.ai.chat(
|
|
202
|
+
// With playback context (coming soon)
|
|
203
|
+
const stream = await bold.ai.chat({
|
|
204
|
+
videoId: 'video-id',
|
|
192
205
|
prompt: 'What does she mean by that?',
|
|
193
206
|
currentTime: 847 // seconds
|
|
194
207
|
});
|
|
@@ -245,8 +258,10 @@ import type {
|
|
|
245
258
|
Settings,
|
|
246
259
|
AIEvent,
|
|
247
260
|
AIResponse,
|
|
248
|
-
|
|
249
|
-
|
|
261
|
+
ChatOptions,
|
|
262
|
+
SearchOptions,
|
|
263
|
+
RecommendationsOptions,
|
|
264
|
+
RecommendationsResponse,
|
|
250
265
|
Recommendation,
|
|
251
266
|
Source
|
|
252
267
|
} from '@boldvideo/bold-js';
|
|
@@ -254,6 +269,29 @@ import type {
|
|
|
254
269
|
|
|
255
270
|
---
|
|
256
271
|
|
|
272
|
+
## Migration from v1.6.x
|
|
273
|
+
|
|
274
|
+
### Method Changes
|
|
275
|
+
|
|
276
|
+
| Old | New | Notes |
|
|
277
|
+
|-----|-----|-------|
|
|
278
|
+
| `bold.ai.ask(opts)` | `bold.ai.chat(opts)` | `ask()` still works but is deprecated |
|
|
279
|
+
| `bold.ai.coach(opts)` | `bold.ai.chat(opts)` | `coach()` still works but is deprecated |
|
|
280
|
+
| `bold.ai.chat(videoId, opts)` | `bold.ai.chat({ videoId, ...opts })` | Pass `videoId` in options |
|
|
281
|
+
| `bold.ai.recommend(opts)` | `bold.ai.recommendations(opts)` | `recommend()` still works but is deprecated |
|
|
282
|
+
|
|
283
|
+
### Type Renames
|
|
284
|
+
|
|
285
|
+
| Old Type | New Type |
|
|
286
|
+
|----------|----------|
|
|
287
|
+
| `AskOptions` | `ChatOptions` |
|
|
288
|
+
| `RecommendOptions` | `RecommendationsOptions` |
|
|
289
|
+
| `RecommendResponse` | `RecommendationsResponse` |
|
|
290
|
+
|
|
291
|
+
The old types are still exported as aliases for backward compatibility.
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
257
295
|
## Related Links
|
|
258
296
|
|
|
259
297
|
- **[Bold API Documentation](https://docs.boldvideo.io/docs/api)**
|
package/dist/index.cjs
CHANGED
|
@@ -250,7 +250,7 @@ async function* parseSSE(response) {
|
|
|
250
250
|
try {
|
|
251
251
|
const event = JSON.parse(json);
|
|
252
252
|
yield event;
|
|
253
|
-
if (event.type === "
|
|
253
|
+
if (event.type === "message_complete" || event.type === "error") {
|
|
254
254
|
await reader.cancel();
|
|
255
255
|
return;
|
|
256
256
|
}
|
|
@@ -301,21 +301,29 @@ async function jsonRequest(path, body, config) {
|
|
|
301
301
|
return response.json();
|
|
302
302
|
}
|
|
303
303
|
function createAI(config) {
|
|
304
|
-
async function
|
|
305
|
-
const
|
|
304
|
+
async function chat(options) {
|
|
305
|
+
const isVideoScoped = !!options.videoId;
|
|
306
|
+
const basePath = isVideoScoped ? `ai/videos/${options.videoId}/chat` : "ai/chat";
|
|
307
|
+
const path = options.conversationId ? `${basePath}/${options.conversationId}` : basePath;
|
|
306
308
|
const body = { prompt: options.prompt };
|
|
307
309
|
if (options.collectionId)
|
|
308
310
|
body.collection_id = options.collectionId;
|
|
309
311
|
if (options.tags)
|
|
310
312
|
body.tags = options.tags;
|
|
313
|
+
if (isVideoScoped && options.currentTime !== void 0) {
|
|
314
|
+
body.current_time = options.currentTime;
|
|
315
|
+
}
|
|
311
316
|
if (options.stream === false) {
|
|
312
317
|
body.stream = false;
|
|
313
318
|
return jsonRequest(path, body, config);
|
|
314
319
|
}
|
|
315
320
|
return streamRequest(path, body, config);
|
|
316
321
|
}
|
|
322
|
+
async function ask(options) {
|
|
323
|
+
return chat(options);
|
|
324
|
+
}
|
|
317
325
|
async function coach(options) {
|
|
318
|
-
return
|
|
326
|
+
return chat(options);
|
|
319
327
|
}
|
|
320
328
|
async function search(options) {
|
|
321
329
|
const path = "ai/search";
|
|
@@ -336,19 +344,8 @@ function createAI(config) {
|
|
|
336
344
|
}
|
|
337
345
|
return streamRequest(path, body, config);
|
|
338
346
|
}
|
|
339
|
-
async function
|
|
340
|
-
const path =
|
|
341
|
-
const body = { prompt: options.prompt };
|
|
342
|
-
if (options.currentTime !== void 0)
|
|
343
|
-
body.current_time = options.currentTime;
|
|
344
|
-
if (options.stream === false) {
|
|
345
|
-
body.stream = false;
|
|
346
|
-
return jsonRequest(path, body, config);
|
|
347
|
-
}
|
|
348
|
-
return streamRequest(path, body, config);
|
|
349
|
-
}
|
|
350
|
-
async function recommend(options) {
|
|
351
|
-
const path = "ai/recommend";
|
|
347
|
+
async function recommendations(options) {
|
|
348
|
+
const path = "ai/recommendations";
|
|
352
349
|
const body = { topics: options.topics };
|
|
353
350
|
if (options.limit)
|
|
354
351
|
body.limit = options.limit;
|
|
@@ -366,11 +363,15 @@ function createAI(config) {
|
|
|
366
363
|
}
|
|
367
364
|
return streamRequest(path, body, config);
|
|
368
365
|
}
|
|
366
|
+
async function recommend(options) {
|
|
367
|
+
return recommendations(options);
|
|
368
|
+
}
|
|
369
369
|
return {
|
|
370
|
+
chat,
|
|
370
371
|
ask,
|
|
371
372
|
coach,
|
|
372
373
|
search,
|
|
373
|
-
|
|
374
|
+
recommendations,
|
|
374
375
|
recommend
|
|
375
376
|
};
|
|
376
377
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -182,21 +182,21 @@ type Settings = {
|
|
|
182
182
|
* Source citation from AI responses
|
|
183
183
|
*/
|
|
184
184
|
interface Source {
|
|
185
|
+
id: string;
|
|
185
186
|
video_id: string;
|
|
186
187
|
title: string;
|
|
187
|
-
timestamp: number;
|
|
188
|
-
timestamp_end?: number;
|
|
189
188
|
text: string;
|
|
190
|
-
|
|
189
|
+
timestamp: number;
|
|
190
|
+
timestamp_end: number;
|
|
191
|
+
playback_id: string;
|
|
191
192
|
speaker?: string;
|
|
192
193
|
}
|
|
193
194
|
/**
|
|
194
195
|
* Token usage statistics
|
|
195
196
|
*/
|
|
196
197
|
interface AIUsage {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
total_tokens: number;
|
|
198
|
+
input_tokens: number;
|
|
199
|
+
output_tokens: number;
|
|
200
200
|
}
|
|
201
201
|
/**
|
|
202
202
|
* SSE event types for AI streaming responses
|
|
@@ -204,42 +204,36 @@ interface AIUsage {
|
|
|
204
204
|
type AIEvent = {
|
|
205
205
|
type: "message_start";
|
|
206
206
|
id: string;
|
|
207
|
-
|
|
207
|
+
conversation_id?: string;
|
|
208
|
+
video_id?: string;
|
|
208
209
|
} | {
|
|
209
210
|
type: "sources";
|
|
210
211
|
sources: Source[];
|
|
211
|
-
query?: string;
|
|
212
212
|
} | {
|
|
213
213
|
type: "text_delta";
|
|
214
214
|
delta: string;
|
|
215
|
-
} | {
|
|
216
|
-
type: "token";
|
|
217
|
-
content: string;
|
|
218
|
-
} | {
|
|
219
|
-
type: "answer";
|
|
220
|
-
content: string;
|
|
221
|
-
response_id?: string;
|
|
222
|
-
context?: AIContextMessage[];
|
|
223
215
|
} | {
|
|
224
216
|
type: "clarification";
|
|
217
|
+
content: string;
|
|
225
218
|
questions: string[];
|
|
226
219
|
} | {
|
|
227
220
|
type: "recommendations";
|
|
228
221
|
recommendations: Recommendation[];
|
|
229
222
|
} | {
|
|
230
223
|
type: "message_complete";
|
|
224
|
+
id: string;
|
|
225
|
+
conversation_id?: string;
|
|
231
226
|
content: string;
|
|
232
227
|
sources: Source[];
|
|
233
228
|
usage?: AIUsage;
|
|
234
229
|
context?: AIContextMessage[];
|
|
235
|
-
|
|
236
|
-
|
|
230
|
+
recommendations?: Recommendation[];
|
|
231
|
+
guidance?: string;
|
|
237
232
|
} | {
|
|
238
233
|
type: "error";
|
|
239
234
|
code: string;
|
|
240
235
|
message: string;
|
|
241
236
|
retryable: boolean;
|
|
242
|
-
details?: Record<string, unknown>;
|
|
243
237
|
};
|
|
244
238
|
/**
|
|
245
239
|
* Non-streaming AI response
|
|
@@ -253,15 +247,31 @@ interface AIResponse {
|
|
|
253
247
|
context?: AIContextMessage[];
|
|
254
248
|
}
|
|
255
249
|
/**
|
|
256
|
-
* Options for bold.ai.
|
|
250
|
+
* Options for bold.ai.chat()
|
|
251
|
+
*
|
|
252
|
+
* If `videoId` is provided, scopes chat to that video (hits /ai/videos/:id/chat).
|
|
253
|
+
* Otherwise, searches your entire library (hits /ai/chat).
|
|
257
254
|
*/
|
|
258
|
-
interface
|
|
255
|
+
interface ChatOptions {
|
|
259
256
|
prompt: string;
|
|
260
257
|
stream?: boolean;
|
|
261
258
|
conversationId?: string;
|
|
262
259
|
collectionId?: string;
|
|
263
260
|
tags?: string[];
|
|
261
|
+
/**
|
|
262
|
+
* If provided, scope chat to a specific video instead of the whole library.
|
|
263
|
+
*/
|
|
264
|
+
videoId?: string;
|
|
265
|
+
/**
|
|
266
|
+
* Current playback position in seconds. Only used when videoId is set.
|
|
267
|
+
* Helps AI understand what the viewer just watched.
|
|
268
|
+
*/
|
|
269
|
+
currentTime?: number;
|
|
264
270
|
}
|
|
271
|
+
/**
|
|
272
|
+
* @deprecated Use ChatOptions instead
|
|
273
|
+
*/
|
|
274
|
+
type AskOptions = ChatOptions;
|
|
265
275
|
/**
|
|
266
276
|
* Conversation message for AI context
|
|
267
277
|
*/
|
|
@@ -281,19 +291,6 @@ interface SearchOptions {
|
|
|
281
291
|
tags?: string[];
|
|
282
292
|
context?: AIContextMessage[];
|
|
283
293
|
}
|
|
284
|
-
/**
|
|
285
|
-
* Options for bold.ai.chat()
|
|
286
|
-
*
|
|
287
|
-
* conversationId: Pass to continue an existing conversation (multi-turn chat).
|
|
288
|
-
* If omitted, a new conversation is created. The id is returned in the
|
|
289
|
-
* message_start event - capture it to pass to subsequent requests.
|
|
290
|
-
*/
|
|
291
|
-
interface ChatOptions {
|
|
292
|
-
prompt: string;
|
|
293
|
-
stream?: boolean;
|
|
294
|
-
conversationId?: string;
|
|
295
|
-
currentTime?: number;
|
|
296
|
-
}
|
|
297
294
|
/**
|
|
298
295
|
* A recommended video with relevance score
|
|
299
296
|
*/
|
|
@@ -309,57 +306,75 @@ interface RecommendationVideo {
|
|
|
309
306
|
*/
|
|
310
307
|
interface Recommendation {
|
|
311
308
|
topic: string;
|
|
312
|
-
position: number;
|
|
313
309
|
videos: RecommendationVideo[];
|
|
314
310
|
}
|
|
315
311
|
/**
|
|
316
|
-
*
|
|
317
|
-
*/
|
|
318
|
-
type TopicInput = string | {
|
|
319
|
-
q: string;
|
|
320
|
-
priority?: number;
|
|
321
|
-
};
|
|
322
|
-
/**
|
|
323
|
-
* Options for bold.ai.recommend()
|
|
312
|
+
* Options for bold.ai.recommendations()
|
|
324
313
|
*/
|
|
325
|
-
interface
|
|
326
|
-
topics:
|
|
314
|
+
interface RecommendationsOptions {
|
|
315
|
+
topics: string[];
|
|
327
316
|
stream?: boolean;
|
|
328
317
|
limit?: number;
|
|
329
318
|
collectionId?: string;
|
|
330
319
|
tags?: string[];
|
|
331
320
|
includeGuidance?: boolean;
|
|
332
|
-
context?:
|
|
321
|
+
context?: AIContextMessage[];
|
|
333
322
|
}
|
|
334
323
|
/**
|
|
335
|
-
*
|
|
324
|
+
* @deprecated Use RecommendationsOptions instead
|
|
325
|
+
*/
|
|
326
|
+
type RecommendOptions = RecommendationsOptions;
|
|
327
|
+
/**
|
|
328
|
+
* Non-streaming response for recommendations endpoint
|
|
336
329
|
*/
|
|
337
|
-
interface
|
|
330
|
+
interface RecommendationsResponse {
|
|
338
331
|
id: string;
|
|
339
332
|
recommendations: Recommendation[];
|
|
340
333
|
guidance: string;
|
|
341
334
|
sources: Source[];
|
|
335
|
+
context?: AIContextMessage[];
|
|
336
|
+
usage?: AIUsage;
|
|
342
337
|
}
|
|
338
|
+
/**
|
|
339
|
+
* @deprecated Use RecommendationsResponse instead
|
|
340
|
+
*/
|
|
341
|
+
type RecommendResponse = RecommendationsResponse;
|
|
343
342
|
|
|
344
343
|
/**
|
|
345
344
|
* AI client interface for type-safe method overloading
|
|
346
345
|
*/
|
|
347
346
|
interface AIClient {
|
|
348
347
|
/**
|
|
349
|
-
*
|
|
348
|
+
* Chat - Conversational AI for Q&A
|
|
349
|
+
*
|
|
350
|
+
* If `videoId` is provided, scopes to that video. Otherwise searches your entire library.
|
|
350
351
|
*
|
|
351
352
|
* @example
|
|
352
|
-
* //
|
|
353
|
-
* const stream = await bold.ai.
|
|
353
|
+
* // Library-wide Q&A
|
|
354
|
+
* const stream = await bold.ai.chat({ prompt: "How do I price my SaaS?" });
|
|
354
355
|
* for await (const event of stream) {
|
|
355
356
|
* if (event.type === "text_delta") process.stdout.write(event.delta);
|
|
356
357
|
* }
|
|
357
358
|
*
|
|
358
359
|
* @example
|
|
360
|
+
* // Video-scoped Q&A
|
|
361
|
+
* const stream = await bold.ai.chat({ videoId: "vid_xyz", prompt: "What does she mean?" });
|
|
362
|
+
*
|
|
363
|
+
* @example
|
|
359
364
|
* // Non-streaming
|
|
360
|
-
* const response = await bold.ai.
|
|
365
|
+
* const response = await bold.ai.chat({ prompt: "How do I price my SaaS?", stream: false });
|
|
361
366
|
* console.log(response.content);
|
|
362
367
|
*/
|
|
368
|
+
chat(options: ChatOptions & {
|
|
369
|
+
stream: false;
|
|
370
|
+
}): Promise<AIResponse>;
|
|
371
|
+
chat(options: ChatOptions & {
|
|
372
|
+
stream?: true;
|
|
373
|
+
}): Promise<AsyncIterable<AIEvent>>;
|
|
374
|
+
chat(options: ChatOptions): Promise<AsyncIterable<AIEvent> | AIResponse>;
|
|
375
|
+
/**
|
|
376
|
+
* @deprecated Use chat() instead. Will be removed in a future version.
|
|
377
|
+
*/
|
|
363
378
|
ask(options: AskOptions & {
|
|
364
379
|
stream: false;
|
|
365
380
|
}): Promise<AIResponse>;
|
|
@@ -368,7 +383,7 @@ interface AIClient {
|
|
|
368
383
|
}): Promise<AsyncIterable<AIEvent>>;
|
|
369
384
|
ask(options: AskOptions): Promise<AsyncIterable<AIEvent> | AIResponse>;
|
|
370
385
|
/**
|
|
371
|
-
*
|
|
386
|
+
* @deprecated Use chat() instead. Will be removed in a future version.
|
|
372
387
|
*/
|
|
373
388
|
coach(options: AskOptions & {
|
|
374
389
|
stream: false;
|
|
@@ -394,36 +409,30 @@ interface AIClient {
|
|
|
394
409
|
}): Promise<AsyncIterable<AIEvent>>;
|
|
395
410
|
search(options: SearchOptions): Promise<AsyncIterable<AIEvent> | AIResponse>;
|
|
396
411
|
/**
|
|
397
|
-
*
|
|
398
|
-
*
|
|
399
|
-
* @example
|
|
400
|
-
* const stream = await bold.ai.chat("video-id", { prompt: "What is discussed at 5 minutes?" });
|
|
401
|
-
* for await (const event of stream) {
|
|
402
|
-
* if (event.type === "text_delta") process.stdout.write(event.delta);
|
|
403
|
-
* }
|
|
404
|
-
*/
|
|
405
|
-
chat(videoId: string, options: ChatOptions & {
|
|
406
|
-
stream: false;
|
|
407
|
-
}): Promise<AIResponse>;
|
|
408
|
-
chat(videoId: string, options: ChatOptions & {
|
|
409
|
-
stream?: true;
|
|
410
|
-
}): Promise<AsyncIterable<AIEvent>>;
|
|
411
|
-
chat(videoId: string, options: ChatOptions): Promise<AsyncIterable<AIEvent> | AIResponse>;
|
|
412
|
-
/**
|
|
413
|
-
* Recommend - AI-powered video recommendations
|
|
412
|
+
* Recommendations - AI-powered video recommendations
|
|
414
413
|
*
|
|
415
414
|
* @example
|
|
416
415
|
* // Streaming (default)
|
|
417
|
-
* const stream = await bold.ai.
|
|
416
|
+
* const stream = await bold.ai.recommendations({ topics: ["sales", "negotiation"] });
|
|
418
417
|
* for await (const event of stream) {
|
|
419
418
|
* if (event.type === "recommendations") console.log(event.recommendations);
|
|
420
419
|
* }
|
|
421
420
|
*
|
|
422
421
|
* @example
|
|
423
422
|
* // Non-streaming
|
|
424
|
-
* const response = await bold.ai.
|
|
423
|
+
* const response = await bold.ai.recommendations({ topics: ["sales"], stream: false });
|
|
425
424
|
* console.log(response.guidance);
|
|
426
425
|
*/
|
|
426
|
+
recommendations(options: RecommendationsOptions & {
|
|
427
|
+
stream: false;
|
|
428
|
+
}): Promise<RecommendationsResponse>;
|
|
429
|
+
recommendations(options: RecommendationsOptions & {
|
|
430
|
+
stream?: true;
|
|
431
|
+
}): Promise<AsyncIterable<AIEvent>>;
|
|
432
|
+
recommendations(options: RecommendationsOptions): Promise<AsyncIterable<AIEvent> | RecommendationsResponse>;
|
|
433
|
+
/**
|
|
434
|
+
* @deprecated Use recommendations() instead. Will be removed in a future version.
|
|
435
|
+
*/
|
|
427
436
|
recommend(options: RecommendOptions & {
|
|
428
437
|
stream: false;
|
|
429
438
|
}): Promise<RecommendResponse>;
|
|
@@ -475,4 +484,4 @@ declare const DEFAULT_API_BASE_URL = "https://app.boldvideo.io/api/v1/";
|
|
|
475
484
|
*/
|
|
476
485
|
declare const DEFAULT_INTERNAL_API_BASE_URL = "https://app.boldvideo.io/i/v1/";
|
|
477
486
|
|
|
478
|
-
export { AIContextMessage, AIEvent, AIResponse, AIUsage, Account, AccountAI, AskOptions, AssistantConfig, ChatOptions, ClientOptions, DEFAULT_API_BASE_URL, DEFAULT_INTERNAL_API_BASE_URL, MenuItem, Playlist, Portal, PortalDisplay, PortalLayout, PortalNavigation, PortalTheme, RecommendOptions, RecommendResponse, Recommendation, RecommendationVideo, SearchOptions, Settings, Source, ThemeColors, ThemeConfig,
|
|
487
|
+
export { AIContextMessage, AIEvent, AIResponse, AIUsage, Account, AccountAI, AskOptions, AssistantConfig, ChatOptions, ClientOptions, DEFAULT_API_BASE_URL, DEFAULT_INTERNAL_API_BASE_URL, MenuItem, Playlist, Portal, PortalDisplay, PortalLayout, PortalNavigation, PortalTheme, RecommendOptions, RecommendResponse, Recommendation, RecommendationVideo, RecommendationsOptions, RecommendationsResponse, SearchOptions, Settings, Source, ThemeColors, ThemeConfig, Video, VideoAttachment, VideoDownloadUrls, VideoMetadata, VideoSubtitles, VideoTranscript, createClient };
|
package/dist/index.js
CHANGED
|
@@ -212,7 +212,7 @@ async function* parseSSE(response) {
|
|
|
212
212
|
try {
|
|
213
213
|
const event = JSON.parse(json);
|
|
214
214
|
yield event;
|
|
215
|
-
if (event.type === "
|
|
215
|
+
if (event.type === "message_complete" || event.type === "error") {
|
|
216
216
|
await reader.cancel();
|
|
217
217
|
return;
|
|
218
218
|
}
|
|
@@ -263,21 +263,29 @@ async function jsonRequest(path, body, config) {
|
|
|
263
263
|
return response.json();
|
|
264
264
|
}
|
|
265
265
|
function createAI(config) {
|
|
266
|
-
async function
|
|
267
|
-
const
|
|
266
|
+
async function chat(options) {
|
|
267
|
+
const isVideoScoped = !!options.videoId;
|
|
268
|
+
const basePath = isVideoScoped ? `ai/videos/${options.videoId}/chat` : "ai/chat";
|
|
269
|
+
const path = options.conversationId ? `${basePath}/${options.conversationId}` : basePath;
|
|
268
270
|
const body = { prompt: options.prompt };
|
|
269
271
|
if (options.collectionId)
|
|
270
272
|
body.collection_id = options.collectionId;
|
|
271
273
|
if (options.tags)
|
|
272
274
|
body.tags = options.tags;
|
|
275
|
+
if (isVideoScoped && options.currentTime !== void 0) {
|
|
276
|
+
body.current_time = options.currentTime;
|
|
277
|
+
}
|
|
273
278
|
if (options.stream === false) {
|
|
274
279
|
body.stream = false;
|
|
275
280
|
return jsonRequest(path, body, config);
|
|
276
281
|
}
|
|
277
282
|
return streamRequest(path, body, config);
|
|
278
283
|
}
|
|
284
|
+
async function ask(options) {
|
|
285
|
+
return chat(options);
|
|
286
|
+
}
|
|
279
287
|
async function coach(options) {
|
|
280
|
-
return
|
|
288
|
+
return chat(options);
|
|
281
289
|
}
|
|
282
290
|
async function search(options) {
|
|
283
291
|
const path = "ai/search";
|
|
@@ -298,19 +306,8 @@ function createAI(config) {
|
|
|
298
306
|
}
|
|
299
307
|
return streamRequest(path, body, config);
|
|
300
308
|
}
|
|
301
|
-
async function
|
|
302
|
-
const path =
|
|
303
|
-
const body = { prompt: options.prompt };
|
|
304
|
-
if (options.currentTime !== void 0)
|
|
305
|
-
body.current_time = options.currentTime;
|
|
306
|
-
if (options.stream === false) {
|
|
307
|
-
body.stream = false;
|
|
308
|
-
return jsonRequest(path, body, config);
|
|
309
|
-
}
|
|
310
|
-
return streamRequest(path, body, config);
|
|
311
|
-
}
|
|
312
|
-
async function recommend(options) {
|
|
313
|
-
const path = "ai/recommend";
|
|
309
|
+
async function recommendations(options) {
|
|
310
|
+
const path = "ai/recommendations";
|
|
314
311
|
const body = { topics: options.topics };
|
|
315
312
|
if (options.limit)
|
|
316
313
|
body.limit = options.limit;
|
|
@@ -328,11 +325,15 @@ function createAI(config) {
|
|
|
328
325
|
}
|
|
329
326
|
return streamRequest(path, body, config);
|
|
330
327
|
}
|
|
328
|
+
async function recommend(options) {
|
|
329
|
+
return recommendations(options);
|
|
330
|
+
}
|
|
331
331
|
return {
|
|
332
|
+
chat,
|
|
332
333
|
ask,
|
|
333
334
|
coach,
|
|
334
335
|
search,
|
|
335
|
-
|
|
336
|
+
recommendations,
|
|
336
337
|
recommend
|
|
337
338
|
};
|
|
338
339
|
}
|
package/llms.txt
CHANGED
|
@@ -14,11 +14,11 @@ const videos = await bold.videos.list();
|
|
|
14
14
|
const video = await bold.videos.get('video-id');
|
|
15
15
|
|
|
16
16
|
// AI-powered recommendations
|
|
17
|
-
const recs = await bold.ai.
|
|
17
|
+
const recs = await bold.ai.recommendations({ topics: ['sales', 'negotiation'], stream: false });
|
|
18
18
|
console.log(recs.guidance);
|
|
19
19
|
|
|
20
20
|
// AI streaming
|
|
21
|
-
const stream = await bold.ai.
|
|
21
|
+
const stream = await bold.ai.chat({ prompt: 'How do I price my SaaS?' });
|
|
22
22
|
for await (const event of stream) {
|
|
23
23
|
if (event.type === 'text_delta') process.stdout.write(event.delta);
|
|
24
24
|
}
|
|
@@ -43,11 +43,14 @@ for await (const event of stream) {
|
|
|
43
43
|
|
|
44
44
|
All AI methods return `AsyncIterable<AIEvent>` (streaming) or `Promise<AIResponse>` (non-streaming).
|
|
45
45
|
|
|
46
|
-
- `bold.ai.
|
|
47
|
-
- `bold.ai.coach(options)` - Library-wide RAG assistant (alias: `ask`)
|
|
48
|
-
- `bold.ai.ask(options)` - Library-wide RAG assistant
|
|
46
|
+
- `bold.ai.chat(options)` - Conversational AI for Q&A (pass `videoId` to scope to a video)
|
|
49
47
|
- `bold.ai.search(options)` - Semantic search with synthesis
|
|
50
|
-
- `bold.ai.
|
|
48
|
+
- `bold.ai.recommendations(options)` - AI-powered video recommendations based on topics
|
|
49
|
+
|
|
50
|
+
**Deprecated aliases** (still work but will be removed):
|
|
51
|
+
- `bold.ai.ask(options)` → use `chat()`
|
|
52
|
+
- `bold.ai.coach(options)` → use `chat()`
|
|
53
|
+
- `bold.ai.recommend(options)` → use `recommendations()`
|
|
51
54
|
|
|
52
55
|
### Analytics
|
|
53
56
|
|
|
@@ -56,26 +59,14 @@ All AI methods return `AsyncIterable<AIEvent>` (streaming) or `Promise<AIRespons
|
|
|
56
59
|
|
|
57
60
|
## AI Options
|
|
58
61
|
|
|
59
|
-
###
|
|
60
|
-
|
|
61
|
-
```typescript
|
|
62
|
-
{
|
|
63
|
-
topics: string[] | string; // Topics to find content for (required)
|
|
64
|
-
stream?: boolean; // Default: true
|
|
65
|
-
limit?: number; // Max videos per topic (default: 5, max: 20)
|
|
66
|
-
collectionId?: string; // Filter to collection
|
|
67
|
-
tags?: string[]; // Filter by tags
|
|
68
|
-
includeGuidance?: boolean; // Include AI learning path narrative (default: true)
|
|
69
|
-
context?: string; // User context for personalization
|
|
70
|
-
}
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
### AskOptions / CoachOptions
|
|
62
|
+
### ChatOptions
|
|
74
63
|
|
|
75
64
|
```typescript
|
|
76
65
|
{
|
|
77
66
|
prompt: string; // Question to ask (required)
|
|
78
67
|
stream?: boolean; // Default: true
|
|
68
|
+
videoId?: string; // If set, scope to this video
|
|
69
|
+
currentTime?: number; // Current playback position (with videoId)
|
|
79
70
|
conversationId?: string; // Continue existing conversation
|
|
80
71
|
collectionId?: string; // Filter to collection
|
|
81
72
|
tags?: string[]; // Filter by tags
|
|
@@ -96,14 +87,17 @@ All AI methods return `AsyncIterable<AIEvent>` (streaming) or `Promise<AIRespons
|
|
|
96
87
|
}
|
|
97
88
|
```
|
|
98
89
|
|
|
99
|
-
###
|
|
90
|
+
### RecommendationsOptions
|
|
100
91
|
|
|
101
92
|
```typescript
|
|
102
93
|
{
|
|
103
|
-
|
|
94
|
+
topics: string[]; // Topics to find content for (required)
|
|
104
95
|
stream?: boolean; // Default: true
|
|
105
|
-
|
|
106
|
-
|
|
96
|
+
limit?: number; // Max videos per topic (default: 5, max: 20)
|
|
97
|
+
collectionId?: string; // Filter to collection
|
|
98
|
+
tags?: string[]; // Filter by tags
|
|
99
|
+
includeGuidance?: boolean; // Include AI learning path narrative (default: true)
|
|
100
|
+
context?: AIContextMessage[]; // Previous conversation turns for follow-ups
|
|
107
101
|
}
|
|
108
102
|
```
|
|
109
103
|
|
|
@@ -113,8 +107,8 @@ Key types exported:
|
|
|
113
107
|
|
|
114
108
|
- `Video`, `Playlist`, `Settings`, `Portal`
|
|
115
109
|
- `AIEvent`, `AIResponse`, `Source`, `AIUsage`
|
|
116
|
-
- `
|
|
117
|
-
- `
|
|
110
|
+
- `ChatOptions`, `SearchOptions`
|
|
111
|
+
- `RecommendationsOptions`, `RecommendationsResponse`, `Recommendation`, `RecommendationVideo`
|
|
118
112
|
|
|
119
113
|
## Links
|
|
120
114
|
|