@boldvideo/bold-js 1.5.0 → 1.6.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/AGENTS.md CHANGED
@@ -46,11 +46,23 @@ This project uses [Changesets](https://github.com/changesets/changesets) with au
46
46
  - Removes the changeset files
47
47
  - When you merge that Release PR, the workflow automatically publishes to npm
48
48
 
49
+ ### Manual Release (when you need to publish immediately)
50
+
51
+ If you need to release immediately without waiting for the Release PR:
52
+
53
+ ```bash
54
+ pnpm changeset version # Consume changesets, bump version, update CHANGELOG
55
+ git add -A && git commit -m "chore: release vX.Y.Z"
56
+ git tag vX.Y.Z
57
+ git push origin main --tags
58
+ ```
59
+
60
+ The `release.yml` workflow will automatically publish to npm when it sees the `v*` tag.
61
+
49
62
  ### Important Notes
50
63
 
51
- - **Never run `pnpm changeset version` or `pnpm changeset publish` locally** - the GitHub Action handles this automatically
52
64
  - The CI workflow (`ci.yml`) runs `pnpm run build` which generates the `dist/` folder - this ensures compiled files are always included in the published package
53
- - The `release.yml` workflow can also publish when a `v*` tag is pushed (alternative release method)
65
+ - The `release.yml` workflow publishes when a `v*` tag is pushed
54
66
 
55
67
  ## Project Structure
56
68
 
@@ -84,7 +96,10 @@ bold.videos.search(query) // Search videos
84
96
  bold.playlists.list() // List playlists
85
97
  bold.playlists.get(id) // Get single playlist
86
98
  bold.ai.coach(opts) // AI RAG assistant (streaming)
87
- bold.ai.ask(videoId, opts)// Video Q&A (streaming)
99
+ bold.ai.ask(opts) // AI RAG assistant (alias for coach)
100
+ bold.ai.search(opts) // Semantic search with synthesis
101
+ bold.ai.chat(videoId, opts) // Video-scoped Q&A
102
+ bold.ai.recommend(opts) // AI-powered recommendations
88
103
  bold.trackEvent() // Track video events
89
104
  bold.trackPageView() // Track page views
90
105
  ```
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @boldvideo/bold-js
2
2
 
3
+ ## 1.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 71b3437: Add `bold.ai.recommend()` for AI-powered video recommendations
8
+
9
+ - New method `bold.ai.recommend({ topics, ...options })` returns personalized video recommendations based on topics
10
+ - Supports both streaming (default) and non-streaming modes
11
+ - Includes AI-generated guidance for learning paths
12
+ - New types: `RecommendOptions`, `RecommendResponse`, `Recommendation`, `RecommendationVideo`, `TopicInput`
13
+ - New `recommendations` event type in `AIEvent` union for streaming responses
14
+
15
+ ## 1.5.1
16
+
17
+ ### Patch Changes
18
+
19
+ - 21267d9: Fix SSE parsing to process final 'complete' event when stream closes without trailing newline
20
+
3
21
  ## 1.5.0
4
22
 
5
23
  ### Minor Changes
package/README.md CHANGED
@@ -26,86 +26,242 @@
26
26
  </a>
27
27
  </p>
28
28
 
29
- ## Usage
29
+ ---
30
30
 
31
- First, install the library:
31
+ ## Installation
32
32
 
33
- ```sh
33
+ ```bash
34
34
  npm install @boldvideo/bold-js
35
35
  ```
36
36
 
37
- Next, instantiate the client to establish a connection to your Bold Channel:
38
- ```js
39
- import { createClient } from "@boldvideo/bold-js";
37
+ ## Quick Start
40
38
 
41
- const bold = createClient('YOUR_API_KEY');
39
+ ```typescript
40
+ import { createClient } from '@boldvideo/bold-js';
41
+
42
+ const bold = createClient('your-api-key');
43
+
44
+ // Fetch videos
45
+ const videos = await bold.videos.list();
46
+
47
+ // Get AI-powered recommendations
48
+ const recs = await bold.ai.recommend({
49
+ topics: ['sales', 'negotiation'],
50
+ stream: false
51
+ });
52
+ console.log(recs.guidance);
42
53
  ```
43
54
 
44
- Now you're able to query any of your resources from Bold. For exmaple:
45
- ```js
46
- // fetches your channel settings, menus and featured playlists
47
- const settings = await bold.settings();
55
+ ---
56
+
57
+ ## API Reference
58
+
59
+ ### Videos
48
60
 
49
- // fetches the latest videos
61
+ ```typescript
62
+ // List latest videos
50
63
  const videos = await bold.videos.list();
51
64
 
52
- // fetches the latest playlists
65
+ // Get a single video
66
+ const video = await bold.videos.get('video-id');
67
+
68
+ // Search videos
69
+ const results = await bold.videos.search('pricing strategies');
70
+ ```
71
+
72
+ ### Playlists
73
+
74
+ ```typescript
75
+ // List all playlists
53
76
  const playlists = await bold.playlists.list();
54
77
 
78
+ // Get a single playlist with videos
79
+ const playlist = await bold.playlists.get('playlist-id');
55
80
  ```
56
81
 
57
- ### AI Search with Conversation Context
82
+ ### Settings
83
+
84
+ ```typescript
85
+ // Fetch channel settings, menus, and featured playlists
86
+ const settings = await bold.settings();
87
+ ```
88
+
89
+ ---
90
+
91
+ ## AI Methods
58
92
 
59
- Use the `context` parameter to enable multi-turn conversations:
93
+ All AI methods support both streaming (default) and non-streaming modes.
60
94
 
61
- ```js
62
- // First question
95
+ ### Recommend
96
+
97
+ Get AI-powered video recommendations based on topics — ideal for personalized learning paths, exam prep, and content discovery.
98
+
99
+ ```typescript
100
+ // Streaming (default)
101
+ const stream = await bold.ai.recommend({
102
+ topics: ['contract law', 'ethics', 'client management'],
103
+ context: 'I failed these topics on my certification exam'
104
+ });
105
+
106
+ for await (const event of stream) {
107
+ if (event.type === 'recommendations') {
108
+ event.recommendations.forEach(rec => {
109
+ console.log(`${rec.topic}:`);
110
+ rec.videos.forEach(v => console.log(` - ${v.title} (${v.relevance})`));
111
+ });
112
+ }
113
+ if (event.type === 'text_delta') {
114
+ process.stdout.write(event.delta); // AI guidance
115
+ }
116
+ }
117
+
118
+ // Non-streaming
119
+ const response = await bold.ai.recommend({
120
+ topics: ['sales', 'marketing'],
121
+ stream: false
122
+ });
123
+ console.log(response.guidance);
124
+ console.log(response.recommendations);
125
+ ```
126
+
127
+ **Options:**
128
+
129
+ | Parameter | Type | Description |
130
+ |-----------|------|-------------|
131
+ | `topics` | `string[]` \| `string` | Topics to find content for (required) |
132
+ | `stream` | `boolean` | `true` (default) for SSE, `false` for JSON |
133
+ | `limit` | `number` | Max videos per topic (default: 5, max: 20) |
134
+ | `collectionId` | `string` | Filter to a specific collection |
135
+ | `tags` | `string[]` | Filter by tags |
136
+ | `synthesize` | `boolean` | Include AI guidance (default: true) |
137
+ | `context` | `string` | User context for personalized guidance |
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
+ ```
159
+
160
+ ### Search
161
+
162
+ Semantic search with light synthesis.
163
+
164
+ ```typescript
165
+ const stream = await bold.ai.search({
166
+ prompt: 'pricing strategies',
167
+ limit: 10
168
+ });
169
+
170
+ for await (const event of stream) {
171
+ if (event.type === 'sources') {
172
+ console.log(`Found ${event.sources.length} results`);
173
+ }
174
+ }
175
+ ```
176
+
177
+ ### Chat
178
+
179
+ Video-scoped conversation for Q&A about a specific video.
180
+
181
+ ```typescript
182
+ const stream = await bold.ai.chat('video-id', {
183
+ prompt: 'What is discussed at the 5 minute mark?'
184
+ });
185
+
186
+ for await (const event of stream) {
187
+ if (event.type === 'text_delta') process.stdout.write(event.delta);
188
+ }
189
+ ```
190
+
191
+ ### Multi-turn Conversations
192
+
193
+ Use the `context` parameter for follow-up questions:
194
+
195
+ ```typescript
63
196
  const first = await bold.ai.search({
64
- prompt: "How do indie designers find clients?",
197
+ prompt: 'How do indie designers find clients?',
65
198
  stream: false
66
199
  });
67
- console.log(first.content);
68
200
 
69
- // Follow-up with context from previous response
70
201
  const followUp = await bold.ai.search({
71
- prompt: "What about cold outreach specifically?",
202
+ prompt: 'What about cold outreach specifically?',
72
203
  context: first.context,
73
204
  stream: false
74
205
  });
75
- console.log(followUp.content);
76
206
  ```
77
207
 
78
- ## Related Links
208
+ ---
79
209
 
80
- - **[Bold API Documentation](https://docs.boldvideo.io/docs/api)**
210
+ ## Analytics
81
211
 
82
- ## Contributing
212
+ Track video events and page views for analytics.
83
213
 
84
- See [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to this project.
214
+ ```typescript
215
+ // Track video events (play, pause, complete, etc.)
216
+ bold.trackEvent({
217
+ type: 'play',
218
+ videoId: 'video-id',
219
+ timestamp: 0
220
+ });
85
221
 
86
- ## Security
222
+ // Track page views
223
+ bold.trackPageView({
224
+ path: '/videos/my-video',
225
+ referrer: document.referrer
226
+ });
227
+ ```
87
228
 
88
- ### For Maintainers
229
+ ---
89
230
 
90
- The automated release process is secure by default:
91
- - NPM_TOKEN is only accessible to workflows on the main branch
92
- - External contributors' PRs cannot access secrets
93
- - Only maintainers with write access can merge to main
94
- - The changeset-release workflow only runs after merge to main
231
+ ## TypeScript
95
232
 
96
- ### Recommended Branch Protection
233
+ All types are exported for full TypeScript support:
97
234
 
98
- For additional security, enable these branch protection rules for `main`:
99
- - Require pull request reviews before merging
100
- - Dismiss stale pull request approvals when new commits are pushed
101
- - Require status checks to pass (CI workflow)
102
- - Require branches to be up to date before merging
103
- - Include administrators in these restrictions
235
+ ```typescript
236
+ import type {
237
+ Video,
238
+ Playlist,
239
+ Settings,
240
+ AIEvent,
241
+ AIResponse,
242
+ RecommendOptions,
243
+ RecommendResponse,
244
+ Recommendation,
245
+ Source
246
+ } from '@boldvideo/bold-js';
247
+ ```
104
248
 
105
- ## More Resources
249
+ ---
106
250
 
107
- ### Support
251
+ ## Related Links
252
+
253
+ - **[Bold API Documentation](https://docs.boldvideo.io/docs/api)**
254
+ - **[GitHub Repository](https://github.com/boldvideo/bold-js)**
255
+ - **[npm Package](https://www.npmjs.com/package/@boldvideo/bold-js)**
256
+
257
+ ## Contributing
258
+
259
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to this project.
260
+
261
+ ## Security
108
262
 
109
- - Bugs or Feature Requests? [Submit an issue](/../../issues/new).
263
+ See [SECURITY.md](SECURITY.md) for security policies and reporting vulnerabilities.
110
264
 
265
+ ## License
111
266
 
267
+ MIT
package/dist/index.cjs CHANGED
@@ -232,11 +232,14 @@ async function* parseSSE(response) {
232
232
  try {
233
233
  while (true) {
234
234
  const { done, value } = await reader.read();
235
- if (done)
236
- break;
237
- buffer += decoder.decode(value, { stream: true });
235
+ if (value) {
236
+ buffer += decoder.decode(value, { stream: true });
237
+ }
238
+ if (done) {
239
+ buffer += decoder.decode();
240
+ }
238
241
  const lines = buffer.split(/\r?\n\r?\n/);
239
- buffer = lines.pop() || "";
242
+ buffer = done ? "" : lines.pop() || "";
240
243
  for (const line of lines) {
241
244
  const trimmed = line.trim();
242
245
  if (!trimmed || !trimmed.startsWith("data:"))
@@ -254,6 +257,8 @@ async function* parseSSE(response) {
254
257
  } catch {
255
258
  }
256
259
  }
260
+ if (done)
261
+ break;
257
262
  }
258
263
  } finally {
259
264
  reader.releaseLock();
@@ -336,11 +341,31 @@ function createAI(config) {
336
341
  }
337
342
  return streamRequest(path, body, config);
338
343
  }
344
+ async function recommend(options) {
345
+ const path = "ai/recommend";
346
+ const body = { topics: options.topics };
347
+ if (options.limit)
348
+ body.limit = options.limit;
349
+ if (options.collectionId)
350
+ body.collection_id = options.collectionId;
351
+ if (options.tags)
352
+ body.tags = options.tags;
353
+ if (options.synthesize !== void 0)
354
+ body.synthesize = options.synthesize;
355
+ if (options.context)
356
+ body.context = options.context;
357
+ if (options.stream === false) {
358
+ body.stream = false;
359
+ return jsonRequest(path, body, config);
360
+ }
361
+ return streamRequest(path, body, config);
362
+ }
339
363
  return {
340
364
  ask,
341
365
  coach,
342
366
  search,
343
- chat
367
+ chat,
368
+ recommend
344
369
  };
345
370
  }
346
371
 
package/dist/index.d.ts CHANGED
@@ -223,6 +223,9 @@ type AIEvent = {
223
223
  } | {
224
224
  type: "clarification";
225
225
  questions: string[];
226
+ } | {
227
+ type: "recommendations";
228
+ recommendations: Recommendation[];
226
229
  } | {
227
230
  type: "message_complete";
228
231
  content: string;
@@ -288,6 +291,52 @@ interface ChatOptions {
288
291
  stream?: boolean;
289
292
  conversationId?: string;
290
293
  }
294
+ /**
295
+ * A recommended video with relevance score
296
+ */
297
+ interface RecommendationVideo {
298
+ video_id: string;
299
+ title: string;
300
+ playback_id: string;
301
+ relevance: number;
302
+ why: string;
303
+ }
304
+ /**
305
+ * A topic recommendation with its videos
306
+ */
307
+ interface Recommendation {
308
+ topic: string;
309
+ position: number;
310
+ videos: RecommendationVideo[];
311
+ }
312
+ /**
313
+ * Topic input format for recommendations
314
+ */
315
+ type TopicInput = string | {
316
+ q: string;
317
+ priority?: number;
318
+ };
319
+ /**
320
+ * Options for bold.ai.recommend()
321
+ */
322
+ interface RecommendOptions {
323
+ topics: TopicInput[] | string;
324
+ stream?: boolean;
325
+ limit?: number;
326
+ collectionId?: string;
327
+ tags?: string[];
328
+ synthesize?: boolean;
329
+ context?: string;
330
+ }
331
+ /**
332
+ * Non-streaming response for recommend endpoint
333
+ */
334
+ interface RecommendResponse {
335
+ id: string;
336
+ recommendations: Recommendation[];
337
+ guidance: string;
338
+ sources: Source[];
339
+ }
291
340
 
292
341
  /**
293
342
  * AI client interface for type-safe method overloading
@@ -357,6 +406,28 @@ interface AIClient {
357
406
  stream?: true;
358
407
  }): Promise<AsyncIterable<AIEvent>>;
359
408
  chat(videoId: string, options: ChatOptions): Promise<AsyncIterable<AIEvent> | AIResponse>;
409
+ /**
410
+ * Recommend - AI-powered video recommendations
411
+ *
412
+ * @example
413
+ * // Streaming (default)
414
+ * const stream = await bold.ai.recommend({ topics: ["sales", "negotiation"] });
415
+ * for await (const event of stream) {
416
+ * if (event.type === "recommendations") console.log(event.recommendations);
417
+ * }
418
+ *
419
+ * @example
420
+ * // Non-streaming
421
+ * const response = await bold.ai.recommend({ topics: ["sales"], stream: false });
422
+ * console.log(response.guidance);
423
+ */
424
+ recommend(options: RecommendOptions & {
425
+ stream: false;
426
+ }): Promise<RecommendResponse>;
427
+ recommend(options: RecommendOptions & {
428
+ stream?: true;
429
+ }): Promise<AsyncIterable<AIEvent>>;
430
+ recommend(options: RecommendOptions): Promise<AsyncIterable<AIEvent> | RecommendResponse>;
360
431
  }
361
432
 
362
433
  type ClientOptions = {
@@ -401,4 +472,4 @@ declare const DEFAULT_API_BASE_URL = "https://app.boldvideo.io/api/v1/";
401
472
  */
402
473
  declare const DEFAULT_INTERNAL_API_BASE_URL = "https://app.boldvideo.io/i/v1/";
403
474
 
404
- 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, SearchOptions, Settings, Source, ThemeColors, ThemeConfig, Video, VideoAttachment, VideoDownloadUrls, VideoMetadata, VideoSubtitles, VideoTranscript, createClient };
475
+ 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, TopicInput, Video, VideoAttachment, VideoDownloadUrls, VideoMetadata, VideoSubtitles, VideoTranscript, createClient };
package/dist/index.js CHANGED
@@ -194,11 +194,14 @@ async function* parseSSE(response) {
194
194
  try {
195
195
  while (true) {
196
196
  const { done, value } = await reader.read();
197
- if (done)
198
- break;
199
- buffer += decoder.decode(value, { stream: true });
197
+ if (value) {
198
+ buffer += decoder.decode(value, { stream: true });
199
+ }
200
+ if (done) {
201
+ buffer += decoder.decode();
202
+ }
200
203
  const lines = buffer.split(/\r?\n\r?\n/);
201
- buffer = lines.pop() || "";
204
+ buffer = done ? "" : lines.pop() || "";
202
205
  for (const line of lines) {
203
206
  const trimmed = line.trim();
204
207
  if (!trimmed || !trimmed.startsWith("data:"))
@@ -216,6 +219,8 @@ async function* parseSSE(response) {
216
219
  } catch {
217
220
  }
218
221
  }
222
+ if (done)
223
+ break;
219
224
  }
220
225
  } finally {
221
226
  reader.releaseLock();
@@ -298,11 +303,31 @@ function createAI(config) {
298
303
  }
299
304
  return streamRequest(path, body, config);
300
305
  }
306
+ async function recommend(options) {
307
+ const path = "ai/recommend";
308
+ const body = { topics: options.topics };
309
+ if (options.limit)
310
+ body.limit = options.limit;
311
+ if (options.collectionId)
312
+ body.collection_id = options.collectionId;
313
+ if (options.tags)
314
+ body.tags = options.tags;
315
+ if (options.synthesize !== void 0)
316
+ body.synthesize = options.synthesize;
317
+ if (options.context)
318
+ body.context = options.context;
319
+ if (options.stream === false) {
320
+ body.stream = false;
321
+ return jsonRequest(path, body, config);
322
+ }
323
+ return streamRequest(path, body, config);
324
+ }
301
325
  return {
302
326
  ask,
303
327
  coach,
304
328
  search,
305
- chat
329
+ chat,
330
+ recommend
306
331
  };
307
332
  }
308
333
 
package/llms.txt CHANGED
@@ -13,33 +13,109 @@ const bold = createClient('your-api-key');
13
13
  const videos = await bold.videos.list();
14
14
  const video = await bold.videos.get('video-id');
15
15
 
16
+ // AI-powered recommendations
17
+ const recs = await bold.ai.recommend({ topics: ['sales', 'negotiation'], stream: false });
18
+ console.log(recs.guidance);
19
+
16
20
  // AI streaming
17
- const stream = await bold.ai.coach({ message: "How do I price my SaaS?" });
21
+ const stream = await bold.ai.coach({ prompt: 'How do I price my SaaS?' });
18
22
  for await (const event of stream) {
19
- if (event.type === 'token') process.stdout.write(event.content);
23
+ if (event.type === 'text_delta') process.stdout.write(event.delta);
20
24
  }
21
25
  ```
22
26
 
23
27
  ## API Reference
24
28
 
29
+ ### Client
30
+
25
31
  - `createClient(apiKey, options?)` - Create SDK instance
32
+
33
+ ### Content
34
+
26
35
  - `bold.settings()` - Channel settings, menus, featured playlists
27
36
  - `bold.videos.list()` - List videos
28
37
  - `bold.videos.get(id)` - Get video by ID
29
38
  - `bold.videos.search(query)` - Search videos
30
39
  - `bold.playlists.list()` - List playlists
31
40
  - `bold.playlists.get(id)` - Get playlist by ID
32
- - `bold.ai.coach(options)` - AI RAG assistant, returns `AsyncIterable<CoachEvent>`
33
- - `bold.ai.ask(videoId, options)` - Video Q&A, returns `AsyncIterable<CoachEvent>`
34
- - `bold.trackEvent(event)` - Track video analytics
41
+
42
+ ### AI Methods
43
+
44
+ All AI methods return `AsyncIterable<AIEvent>` (streaming) or `Promise<AIResponse>` (non-streaming).
45
+
46
+ - `bold.ai.recommend(options)` - AI-powered video recommendations based on topics
47
+ - `bold.ai.coach(options)` - Library-wide RAG assistant (alias: `ask`)
48
+ - `bold.ai.ask(options)` - Library-wide RAG assistant
49
+ - `bold.ai.search(options)` - Semantic search with synthesis
50
+ - `bold.ai.chat(videoId, options)` - Video-scoped Q&A conversation
51
+
52
+ ### Analytics
53
+
54
+ - `bold.trackEvent(event)` - Track video events (play, pause, complete)
35
55
  - `bold.trackPageView(data)` - Track page views
36
56
 
57
+ ## AI Options
58
+
59
+ ### RecommendOptions
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
+ synthesize?: boolean; // Include AI guidance (default: true)
69
+ context?: string; // User context for personalization
70
+ }
71
+ ```
72
+
73
+ ### AskOptions / CoachOptions
74
+
75
+ ```typescript
76
+ {
77
+ prompt: string; // Question to ask (required)
78
+ stream?: boolean; // Default: true
79
+ conversationId?: string; // Continue existing conversation
80
+ collectionId?: string; // Filter to collection
81
+ }
82
+ ```
83
+
84
+ ### SearchOptions
85
+
86
+ ```typescript
87
+ {
88
+ prompt: string; // Search query (required)
89
+ stream?: boolean; // Default: true
90
+ limit?: number; // Max results
91
+ collectionId?: string; // Filter to collection
92
+ videoId?: string; // Search within specific video
93
+ context?: AIContextMessage[]; // Conversation context
94
+ }
95
+ ```
96
+
97
+ ### ChatOptions
98
+
99
+ ```typescript
100
+ {
101
+ prompt: string; // Question about the video (required)
102
+ stream?: boolean; // Default: true
103
+ conversationId?: string; // Continue existing conversation
104
+ }
105
+ ```
106
+
37
107
  ## Types
38
108
 
39
- Key types exported: `Video`, `Playlist`, `Settings`, `Portal`, `CoachEvent`, `CoachOptions`, `AskOptions`, `Citation`
109
+ Key types exported:
110
+
111
+ - `Video`, `Playlist`, `Settings`, `Portal`
112
+ - `AIEvent`, `AIResponse`, `Source`, `AIUsage`
113
+ - `AskOptions`, `SearchOptions`, `ChatOptions`
114
+ - `RecommendOptions`, `RecommendResponse`, `Recommendation`, `RecommendationVideo`, `TopicInput`
40
115
 
41
116
  ## Links
42
117
 
43
118
  - [GitHub](https://github.com/boldvideo/bold-js)
44
119
  - [npm](https://www.npmjs.com/package/@boldvideo/bold-js)
120
+ - [API Docs](https://docs.boldvideo.io/docs/api)
45
121
  - [Types Source](https://github.com/boldvideo/bold-js/blob/main/src/lib/types.ts)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@boldvideo/bold-js",
3
3
  "license": "MIT",
4
- "version": "1.5.0",
4
+ "version": "1.6.0",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
7
7
  "types": "dist/index.d.ts",