youtube-knowledge-mcp 2.0.2 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/README.md +66 -4
  2. package/dist/brain-schemas.d.ts +502 -0
  3. package/dist/brain-schemas.d.ts.map +1 -0
  4. package/dist/brain-schemas.js +113 -0
  5. package/dist/brain-schemas.js.map +1 -0
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +86 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/prompts.d.ts.map +1 -1
  10. package/dist/prompts.js +42 -0
  11. package/dist/prompts.js.map +1 -1
  12. package/dist/resources.d.ts.map +1 -1
  13. package/dist/resources.js +66 -0
  14. package/dist/resources.js.map +1 -1
  15. package/dist/schemas.d.ts +67 -56
  16. package/dist/schemas.d.ts.map +1 -1
  17. package/dist/schemas.js +25 -4
  18. package/dist/schemas.js.map +1 -1
  19. package/dist/tools/ask-brain.d.ts +62 -0
  20. package/dist/tools/ask-brain.d.ts.map +1 -0
  21. package/dist/tools/ask-brain.js +70 -0
  22. package/dist/tools/ask-brain.js.map +1 -0
  23. package/dist/tools/batch.d.ts +10 -10
  24. package/dist/tools/batch.js +2 -2
  25. package/dist/tools/batch.js.map +1 -1
  26. package/dist/tools/brain-info.d.ts +180 -0
  27. package/dist/tools/brain-info.d.ts.map +1 -0
  28. package/dist/tools/brain-info.js +108 -0
  29. package/dist/tools/brain-info.js.map +1 -0
  30. package/dist/tools/build-brain.d.ts +120 -0
  31. package/dist/tools/build-brain.d.ts.map +1 -0
  32. package/dist/tools/build-brain.js +123 -0
  33. package/dist/tools/build-brain.js.map +1 -0
  34. package/dist/tools/clips.d.ts +4 -4
  35. package/dist/tools/fetch-videos.d.ts +8 -8
  36. package/dist/tools/get-chapters.d.ts +2 -2
  37. package/dist/tools/get-comments.d.ts +2 -2
  38. package/dist/tools/get-transcript.d.ts +2 -2
  39. package/dist/tools/library.d.ts +9 -7
  40. package/dist/tools/library.d.ts.map +1 -1
  41. package/dist/tools/library.js +10 -4
  42. package/dist/tools/library.js.map +1 -1
  43. package/dist/tools/list-library.d.ts +4 -4
  44. package/dist/tools/manage-brain.d.ts +39 -0
  45. package/dist/tools/manage-brain.d.ts.map +1 -0
  46. package/dist/tools/manage-brain.js +53 -0
  47. package/dist/tools/manage-brain.js.map +1 -0
  48. package/dist/tools/search-channels.d.ts +4 -4
  49. package/dist/tools/search-transcript.d.ts +2 -2
  50. package/dist/tools/search-videos.d.ts +8 -8
  51. package/dist/utils/brain-build.d.ts +40 -0
  52. package/dist/utils/brain-build.d.ts.map +1 -0
  53. package/dist/utils/brain-build.js +211 -0
  54. package/dist/utils/brain-build.js.map +1 -0
  55. package/dist/utils/brain-chunks.d.ts +33 -0
  56. package/dist/utils/brain-chunks.d.ts.map +1 -0
  57. package/dist/utils/brain-chunks.js +87 -0
  58. package/dist/utils/brain-chunks.js.map +1 -0
  59. package/dist/utils/brain-index.d.ts +27 -0
  60. package/dist/utils/brain-index.d.ts.map +1 -0
  61. package/dist/utils/brain-index.js +100 -0
  62. package/dist/utils/brain-index.js.map +1 -0
  63. package/dist/utils/brain-ingest.d.ts +57 -0
  64. package/dist/utils/brain-ingest.d.ts.map +1 -0
  65. package/dist/utils/brain-ingest.js +127 -0
  66. package/dist/utils/brain-ingest.js.map +1 -0
  67. package/dist/utils/brain-lock.d.ts +20 -0
  68. package/dist/utils/brain-lock.d.ts.map +1 -0
  69. package/dist/utils/brain-lock.js +93 -0
  70. package/dist/utils/brain-lock.js.map +1 -0
  71. package/dist/utils/brain-lookup.d.ts +3 -0
  72. package/dist/utils/brain-lookup.d.ts.map +1 -0
  73. package/dist/utils/brain-lookup.js +62 -0
  74. package/dist/utils/brain-lookup.js.map +1 -0
  75. package/dist/utils/brain-paths.d.ts +19 -0
  76. package/dist/utils/brain-paths.d.ts.map +1 -0
  77. package/dist/utils/brain-paths.js +34 -0
  78. package/dist/utils/brain-paths.js.map +1 -0
  79. package/dist/utils/brain-phrases.d.ts +31 -0
  80. package/dist/utils/brain-phrases.d.ts.map +1 -0
  81. package/dist/utils/brain-phrases.js +116 -0
  82. package/dist/utils/brain-phrases.js.map +1 -0
  83. package/dist/utils/brain-stats.d.ts +25 -0
  84. package/dist/utils/brain-stats.d.ts.map +1 -0
  85. package/dist/utils/brain-stats.js +64 -0
  86. package/dist/utils/brain-stats.js.map +1 -0
  87. package/dist/utils/brain-storage.d.ts +28 -0
  88. package/dist/utils/brain-storage.d.ts.map +1 -0
  89. package/dist/utils/brain-storage.js +87 -0
  90. package/dist/utils/brain-storage.js.map +1 -0
  91. package/dist/utils/clips.js +4 -4
  92. package/dist/utils/clips.js.map +1 -1
  93. package/dist/utils/json-file.d.ts +36 -0
  94. package/dist/utils/json-file.d.ts.map +1 -0
  95. package/dist/utils/json-file.js +45 -0
  96. package/dist/utils/json-file.js.map +1 -0
  97. package/dist/utils/paths.d.ts +9 -0
  98. package/dist/utils/paths.d.ts.map +1 -0
  99. package/dist/utils/paths.js +13 -0
  100. package/dist/utils/paths.js.map +1 -0
  101. package/dist/utils/search-index.d.ts +22 -7
  102. package/dist/utils/search-index.d.ts.map +1 -1
  103. package/dist/utils/search-index.js +17 -4
  104. package/dist/utils/search-index.js.map +1 -1
  105. package/dist/utils/storage.d.ts +14 -44
  106. package/dist/utils/storage.d.ts.map +1 -1
  107. package/dist/utils/storage.js +37 -80
  108. package/dist/utils/storage.js.map +1 -1
  109. package/dist/utils/transcript.d.ts +5 -4
  110. package/dist/utils/transcript.d.ts.map +1 -1
  111. package/dist/utils/transcript.js +3 -0
  112. package/dist/utils/transcript.js.map +1 -1
  113. package/dist/utils/validate.d.ts +1 -0
  114. package/dist/utils/validate.d.ts.map +1 -1
  115. package/dist/utils/validate.js +18 -0
  116. package/dist/utils/validate.js.map +1 -1
  117. package/dist/utils/youtube.d.ts +14 -0
  118. package/dist/utils/youtube.d.ts.map +1 -1
  119. package/dist/utils/youtube.js +19 -13
  120. package/dist/utils/youtube.js.map +1 -1
  121. package/package.json +1 -1
package/README.md CHANGED
@@ -39,6 +39,17 @@ Supports both **local** (stdio) and **remote** (Streamable HTTP) transports.
39
39
  - **Read them back**, and **search across all of them** with full-text ranking
40
40
  - **Tag, retag and delete**
41
41
 
42
+ **Build a brain for a channel** (local mode)
43
+
44
+ - **Read a whole channel** into a searchable corpus of timestamped passages, in
45
+ any caption language, resumable and safe to interrupt — a second run continues
46
+ where it stopped and picks up new uploads
47
+ - **Ask what a creator has said** about anything, across every video, and get
48
+ back the moments themselves with links that open the video there
49
+ - **Measure the channel**: how much was readable, its upload rhythm, its
50
+ speaking rate, and the phrases it repeats across videos
51
+ - **Keep a written profile** beside the corpus, grounded in passages you can cite
52
+
42
53
  **Built to stay working**
43
54
 
44
55
  - WebVTT parsed by the W3C reference implementation, not a hand-written matcher
@@ -199,7 +210,7 @@ a cold start. Any paid plan removes that.
199
210
 
200
211
  ## MCP Tools
201
212
 
202
- 27 tools. The 14 read-only ones work over both transports; the 13 that touch
213
+ 33 tools. The 14 read-only ones work over both transports; the 19 that touch
203
214
  your filesystem are registered only in local (stdio) mode, so a remote
204
215
  deployment cannot reach the host's disk.
205
216
 
@@ -258,22 +269,56 @@ keyframe-aligned cut. All of these require ffmpeg.
258
269
  | `save_to_library` | `videoId`, `title`, `content`, `contentType`, `channel`, `tags` | Path to the saved note |
259
270
  | `list_library` | `tag` | Saved items, newest first |
260
271
  | `get_library_item` | `videoId`, `contentType` | The saved markdown and its metadata |
261
- | `search_library` | `query`, `limit` | Ranked matches with excerpts |
272
+ | `search_library` | `query`, `limit`, `offset` | Ranked matches with excerpts |
262
273
  | `update_library_tags` | `videoId`, `add`, `remove`, `replace` | The updated tags |
263
274
  | `delete_library_item` | `videoId`, `contentType` | What was deleted |
264
275
  | `rebuild_library_index` | — | Number of notes reindexed |
265
276
 
277
+ ### Channel brains — local only
278
+
279
+ | Tool | Key parameters | Returns |
280
+ | -------------------- | ----------------------------------------------------------------- | ------------------------------------------------ |
281
+ | `build_brain` | `channel`, `maxVideos`, `language`, `since`, `minDurationSeconds` | What was read, what was ruled out, and the stats |
282
+ | `ask_brain` | `channel`, `query`, `limit`, `offset` | Passages with timestamps and `?t=` links |
283
+ | `list_brains` | — | Every brain built locally |
284
+ | `get_brain_info` | `channel`, `includeVideos` | Coverage, statistics and repeated phrases |
285
+ | `save_brain_profile` | `channel`, `content` | Path to the saved profile |
286
+ | `delete_brain` | `channel` | What was removed |
287
+
288
+ `build_brain` is the only one that touches the network. The rest resolve a
289
+ channel from what is already on disk, so they work offline and cost nothing to
290
+ call.
291
+
292
+ A brain holds one caption language; pass `language` to read another, and build a
293
+ separate brain per language.
294
+
295
+ `since` and `minDurationSeconds` describe the brain, not just the call that
296
+ passed them. They are re-applied every time, so narrowing one drops the passages
297
+ of the videos it excludes and widening it reads them back — which is why
298
+ `build_brain` is annotated as destructive. Whether a video qualifies is decided
299
+ from the date and length already recorded, so changing your mind costs no
300
+ requests until there is something new to fetch. Those values come from each
301
+ video's own metadata, never from a guess: a flat channel listing does not carry
302
+ a publication date at all.
303
+
304
+ `build_brain` also repairs. If the passage file is lost or truncated, the videos
305
+ it can no longer account for are read again on the next call rather than being
306
+ skipped forever as already done.
307
+
266
308
  ## Prompts
267
309
 
268
310
  Reusable workflows your client can invoke directly: `summarize_video`,
269
311
  `extract_skill`, `compare_videos`, `research_topic`, `channel_deep_dive`,
270
- `clip_from_quote` (find a phrase, then cut the clip around it), and
271
- `review_library` (local only).
312
+ `clip_from_quote` (find a phrase, then cut the clip around it), and — local
313
+ only — `review_library`, `create_brain` (build a channel's corpus, then write
314
+ its profile from it) and `ask_creator` (answer a question strictly from a
315
+ brain, with citations).
272
316
 
273
317
  ## Resources
274
318
 
275
319
  - `youtube://transcript/{videoId}` — a timestamped transcript, fetched and cached on first read
276
320
  - `youtube://library/{videoId}/{summary|skill}` — a saved note (local only, and enumerable)
321
+ - `youtube://brain/{channelId}/{manifest|profile}` — what a channel brain covers, or the profile written from it (local only, and enumerable)
277
322
 
278
323
  ## Error codes
279
324
 
@@ -322,6 +367,11 @@ Content is stored in `~/.youtube-knowledge/`:
322
367
  │ ├── metadata.json
323
368
  │ ├── summary.md
324
369
  │ └── skill.md
370
+ ├── brains/ # Channel brains
371
+ │ └── {channel_id}/
372
+ │ ├── manifest.json # What the brain covers, and where a build stopped
373
+ │ ├── chunks.json # The timestamped passages
374
+ │ └── profile.md # The written account, if one was saved
325
375
  ├── downloads/ # Full downloads
326
376
  ├── clips/ # Extracted clips
327
377
  ├── frames/ # Captured stills
@@ -394,6 +444,18 @@ editor can import.
394
444
  `save_to_library` stores it; `search_library` searches across everything saved
395
445
  with full-text ranking.
396
446
 
447
+ ### Build a brain for a creator
448
+
449
+ ```
450
+ "Build a brain for @Fireship, then tell me everything they've said about Rust"
451
+ ```
452
+
453
+ `build_brain` reads the channel into timestamped passages — interrupt it and
454
+ call it again to continue. `ask_brain` then answers from what was actually
455
+ said, returning the moments themselves so every claim can be checked against
456
+ the video. Run `build_brain` again a month later and it reads only the new
457
+ uploads.
458
+
397
459
  ## Testing
398
460
 
399
461
  ```bash
@@ -0,0 +1,502 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * The shapes a channel brain is made of.
4
+ *
5
+ * Split from `schemas.ts` only for size; the rule there applies here too — a
6
+ * shape is declared once and used by both the persistence layer and the tools
7
+ * that report it, so the file on disk and the tool result cannot drift apart.
8
+ */
9
+ /** Why a video is, or is not, part of the corpus. */
10
+ export declare const brainVideoStateSchema: z.ZodObject<{
11
+ videoId: z.ZodString;
12
+ title: z.ZodString;
13
+ url: z.ZodString;
14
+ uploadDate: z.ZodString;
15
+ durationSeconds: z.ZodNumber;
16
+ state: z.ZodEnum<["pending", "indexed", "no-captions", "failed", "excluded"]>;
17
+ chunkCount: z.ZodNumber;
18
+ wordCount: z.ZodNumber;
19
+ error: z.ZodOptional<z.ZodString>;
20
+ }, "strip", z.ZodTypeAny, {
21
+ title: string;
22
+ durationSeconds: number;
23
+ url: string;
24
+ uploadDate: string;
25
+ videoId: string;
26
+ state: "pending" | "indexed" | "no-captions" | "failed" | "excluded";
27
+ chunkCount: number;
28
+ wordCount: number;
29
+ error?: string | undefined;
30
+ }, {
31
+ title: string;
32
+ durationSeconds: number;
33
+ url: string;
34
+ uploadDate: string;
35
+ videoId: string;
36
+ state: "pending" | "indexed" | "no-captions" | "failed" | "excluded";
37
+ chunkCount: number;
38
+ wordCount: number;
39
+ error?: string | undefined;
40
+ }>;
41
+ export type BrainVideoState = z.infer<typeof brainVideoStateSchema>;
42
+ /** One passage of speech, addressable by timestamp. */
43
+ export declare const brainChunkSchema: z.ZodObject<{
44
+ id: z.ZodString;
45
+ videoId: z.ZodString;
46
+ title: z.ZodString;
47
+ startSeconds: z.ZodNumber;
48
+ endSeconds: z.ZodNumber;
49
+ text: z.ZodString;
50
+ }, "strip", z.ZodTypeAny, {
51
+ id: string;
52
+ title: string;
53
+ startSeconds: number;
54
+ endSeconds: number;
55
+ text: string;
56
+ videoId: string;
57
+ }, {
58
+ id: string;
59
+ title: string;
60
+ startSeconds: number;
61
+ endSeconds: number;
62
+ text: string;
63
+ videoId: string;
64
+ }>;
65
+ export type BrainChunk = z.infer<typeof brainChunkSchema>;
66
+ export declare const brainChunkFileSchema: z.ZodObject<{
67
+ version: z.ZodNumber;
68
+ chunks: z.ZodArray<z.ZodObject<{
69
+ id: z.ZodString;
70
+ videoId: z.ZodString;
71
+ title: z.ZodString;
72
+ startSeconds: z.ZodNumber;
73
+ endSeconds: z.ZodNumber;
74
+ text: z.ZodString;
75
+ }, "strip", z.ZodTypeAny, {
76
+ id: string;
77
+ title: string;
78
+ startSeconds: number;
79
+ endSeconds: number;
80
+ text: string;
81
+ videoId: string;
82
+ }, {
83
+ id: string;
84
+ title: string;
85
+ startSeconds: number;
86
+ endSeconds: number;
87
+ text: string;
88
+ videoId: string;
89
+ }>, "many">;
90
+ }, "strip", z.ZodTypeAny, {
91
+ version: number;
92
+ chunks: {
93
+ id: string;
94
+ title: string;
95
+ startSeconds: number;
96
+ endSeconds: number;
97
+ text: string;
98
+ videoId: string;
99
+ }[];
100
+ }, {
101
+ version: number;
102
+ chunks: {
103
+ id: string;
104
+ title: string;
105
+ startSeconds: number;
106
+ endSeconds: number;
107
+ text: string;
108
+ videoId: string;
109
+ }[];
110
+ }>;
111
+ export declare const brainPhraseSchema: z.ZodObject<{
112
+ phrase: z.ZodString;
113
+ videoCount: z.ZodNumber;
114
+ occurrences: z.ZodNumber;
115
+ }, "strip", z.ZodTypeAny, {
116
+ videoCount: number;
117
+ phrase: string;
118
+ occurrences: number;
119
+ }, {
120
+ videoCount: number;
121
+ phrase: string;
122
+ occurrences: number;
123
+ }>;
124
+ export declare const brainMonthlyUploadsSchema: z.ZodObject<{
125
+ month: z.ZodString;
126
+ videos: z.ZodNumber;
127
+ }, "strip", z.ZodTypeAny, {
128
+ month: string;
129
+ videos: number;
130
+ }, {
131
+ month: string;
132
+ videos: number;
133
+ }>;
134
+ /**
135
+ * What the server can state about a channel without inferring anything.
136
+ *
137
+ * Everything here is counted or measured. Claims about what a creator thinks
138
+ * belong in the profile, which a model writes from quotes it can cite.
139
+ */
140
+ export declare const brainStatsSchema: z.ZodObject<{
141
+ videoCount: z.ZodNumber;
142
+ excludedCount: z.ZodNumber;
143
+ indexedCount: z.ZodNumber;
144
+ noCaptionsCount: z.ZodNumber;
145
+ failedCount: z.ZodNumber;
146
+ pendingCount: z.ZodNumber;
147
+ chunkCount: z.ZodNumber;
148
+ totalWords: z.ZodNumber;
149
+ medianWordsPerMinute: z.ZodNumber;
150
+ firstUpload: z.ZodOptional<z.ZodString>;
151
+ lastUpload: z.ZodOptional<z.ZodString>;
152
+ uploadsPerMonth: z.ZodArray<z.ZodObject<{
153
+ month: z.ZodString;
154
+ videos: z.ZodNumber;
155
+ }, "strip", z.ZodTypeAny, {
156
+ month: string;
157
+ videos: number;
158
+ }, {
159
+ month: string;
160
+ videos: number;
161
+ }>, "many">;
162
+ recurringPhrases: z.ZodOptional<z.ZodArray<z.ZodObject<{
163
+ phrase: z.ZodString;
164
+ videoCount: z.ZodNumber;
165
+ occurrences: z.ZodNumber;
166
+ }, "strip", z.ZodTypeAny, {
167
+ videoCount: number;
168
+ phrase: string;
169
+ occurrences: number;
170
+ }, {
171
+ videoCount: number;
172
+ phrase: string;
173
+ occurrences: number;
174
+ }>, "many">>;
175
+ }, "strip", z.ZodTypeAny, {
176
+ videoCount: number;
177
+ chunkCount: number;
178
+ excludedCount: number;
179
+ indexedCount: number;
180
+ noCaptionsCount: number;
181
+ failedCount: number;
182
+ pendingCount: number;
183
+ totalWords: number;
184
+ medianWordsPerMinute: number;
185
+ uploadsPerMonth: {
186
+ month: string;
187
+ videos: number;
188
+ }[];
189
+ firstUpload?: string | undefined;
190
+ lastUpload?: string | undefined;
191
+ recurringPhrases?: {
192
+ videoCount: number;
193
+ phrase: string;
194
+ occurrences: number;
195
+ }[] | undefined;
196
+ }, {
197
+ videoCount: number;
198
+ chunkCount: number;
199
+ excludedCount: number;
200
+ indexedCount: number;
201
+ noCaptionsCount: number;
202
+ failedCount: number;
203
+ pendingCount: number;
204
+ totalWords: number;
205
+ medianWordsPerMinute: number;
206
+ uploadsPerMonth: {
207
+ month: string;
208
+ videos: number;
209
+ }[];
210
+ firstUpload?: string | undefined;
211
+ lastUpload?: string | undefined;
212
+ recurringPhrases?: {
213
+ videoCount: number;
214
+ phrase: string;
215
+ occurrences: number;
216
+ }[] | undefined;
217
+ }>;
218
+ export type BrainStats = z.infer<typeof brainStatsSchema>;
219
+ /** The on-disk document. */
220
+ export declare const brainManifestSchema: z.ZodObject<{
221
+ version: z.ZodNumber;
222
+ channel: z.ZodObject<{
223
+ name: z.ZodString;
224
+ channelId: z.ZodString;
225
+ handle: z.ZodString;
226
+ subscriberCount: z.ZodNumber;
227
+ channelUrl: z.ZodString;
228
+ description: z.ZodString;
229
+ }, "strip", z.ZodTypeAny, {
230
+ description: string;
231
+ name: string;
232
+ channelId: string;
233
+ handle: string;
234
+ subscriberCount: number;
235
+ channelUrl: string;
236
+ }, {
237
+ description: string;
238
+ name: string;
239
+ channelId: string;
240
+ handle: string;
241
+ subscriberCount: number;
242
+ channelUrl: string;
243
+ }>;
244
+ /**
245
+ * A brain is built from one caption language. Defaulted rather than required
246
+ * so a manifest written before this existed still reads back.
247
+ */
248
+ language: z.ZodDefault<z.ZodString>;
249
+ createdAt: z.ZodString;
250
+ updatedAt: z.ZodString;
251
+ videos: z.ZodType<Record<string, {
252
+ title: string;
253
+ durationSeconds: number;
254
+ url: string;
255
+ uploadDate: string;
256
+ videoId: string;
257
+ state: "pending" | "indexed" | "no-captions" | "failed" | "excluded";
258
+ chunkCount: number;
259
+ wordCount: number;
260
+ error?: string | undefined;
261
+ }>, z.ZodTypeDef, Record<string, unknown>>;
262
+ stats: z.ZodObject<{
263
+ videoCount: z.ZodNumber;
264
+ excludedCount: z.ZodNumber;
265
+ indexedCount: z.ZodNumber;
266
+ noCaptionsCount: z.ZodNumber;
267
+ failedCount: z.ZodNumber;
268
+ pendingCount: z.ZodNumber;
269
+ chunkCount: z.ZodNumber;
270
+ totalWords: z.ZodNumber;
271
+ medianWordsPerMinute: z.ZodNumber;
272
+ firstUpload: z.ZodOptional<z.ZodString>;
273
+ lastUpload: z.ZodOptional<z.ZodString>;
274
+ uploadsPerMonth: z.ZodArray<z.ZodObject<{
275
+ month: z.ZodString;
276
+ videos: z.ZodNumber;
277
+ }, "strip", z.ZodTypeAny, {
278
+ month: string;
279
+ videos: number;
280
+ }, {
281
+ month: string;
282
+ videos: number;
283
+ }>, "many">;
284
+ recurringPhrases: z.ZodOptional<z.ZodArray<z.ZodObject<{
285
+ phrase: z.ZodString;
286
+ videoCount: z.ZodNumber;
287
+ occurrences: z.ZodNumber;
288
+ }, "strip", z.ZodTypeAny, {
289
+ videoCount: number;
290
+ phrase: string;
291
+ occurrences: number;
292
+ }, {
293
+ videoCount: number;
294
+ phrase: string;
295
+ occurrences: number;
296
+ }>, "many">>;
297
+ }, "strip", z.ZodTypeAny, {
298
+ videoCount: number;
299
+ chunkCount: number;
300
+ excludedCount: number;
301
+ indexedCount: number;
302
+ noCaptionsCount: number;
303
+ failedCount: number;
304
+ pendingCount: number;
305
+ totalWords: number;
306
+ medianWordsPerMinute: number;
307
+ uploadsPerMonth: {
308
+ month: string;
309
+ videos: number;
310
+ }[];
311
+ firstUpload?: string | undefined;
312
+ lastUpload?: string | undefined;
313
+ recurringPhrases?: {
314
+ videoCount: number;
315
+ phrase: string;
316
+ occurrences: number;
317
+ }[] | undefined;
318
+ }, {
319
+ videoCount: number;
320
+ chunkCount: number;
321
+ excludedCount: number;
322
+ indexedCount: number;
323
+ noCaptionsCount: number;
324
+ failedCount: number;
325
+ pendingCount: number;
326
+ totalWords: number;
327
+ medianWordsPerMinute: number;
328
+ uploadsPerMonth: {
329
+ month: string;
330
+ videos: number;
331
+ }[];
332
+ firstUpload?: string | undefined;
333
+ lastUpload?: string | undefined;
334
+ recurringPhrases?: {
335
+ videoCount: number;
336
+ phrase: string;
337
+ occurrences: number;
338
+ }[] | undefined;
339
+ }>;
340
+ }, "strip", z.ZodTypeAny, {
341
+ channel: {
342
+ description: string;
343
+ name: string;
344
+ channelId: string;
345
+ handle: string;
346
+ subscriberCount: number;
347
+ channelUrl: string;
348
+ };
349
+ version: number;
350
+ videos: Record<string, {
351
+ title: string;
352
+ durationSeconds: number;
353
+ url: string;
354
+ uploadDate: string;
355
+ videoId: string;
356
+ state: "pending" | "indexed" | "no-captions" | "failed" | "excluded";
357
+ chunkCount: number;
358
+ wordCount: number;
359
+ error?: string | undefined;
360
+ }>;
361
+ language: string;
362
+ createdAt: string;
363
+ updatedAt: string;
364
+ stats: {
365
+ videoCount: number;
366
+ chunkCount: number;
367
+ excludedCount: number;
368
+ indexedCount: number;
369
+ noCaptionsCount: number;
370
+ failedCount: number;
371
+ pendingCount: number;
372
+ totalWords: number;
373
+ medianWordsPerMinute: number;
374
+ uploadsPerMonth: {
375
+ month: string;
376
+ videos: number;
377
+ }[];
378
+ firstUpload?: string | undefined;
379
+ lastUpload?: string | undefined;
380
+ recurringPhrases?: {
381
+ videoCount: number;
382
+ phrase: string;
383
+ occurrences: number;
384
+ }[] | undefined;
385
+ };
386
+ }, {
387
+ channel: {
388
+ description: string;
389
+ name: string;
390
+ channelId: string;
391
+ handle: string;
392
+ subscriberCount: number;
393
+ channelUrl: string;
394
+ };
395
+ version: number;
396
+ videos: Record<string, unknown>;
397
+ createdAt: string;
398
+ updatedAt: string;
399
+ stats: {
400
+ videoCount: number;
401
+ chunkCount: number;
402
+ excludedCount: number;
403
+ indexedCount: number;
404
+ noCaptionsCount: number;
405
+ failedCount: number;
406
+ pendingCount: number;
407
+ totalWords: number;
408
+ medianWordsPerMinute: number;
409
+ uploadsPerMonth: {
410
+ month: string;
411
+ videos: number;
412
+ }[];
413
+ firstUpload?: string | undefined;
414
+ lastUpload?: string | undefined;
415
+ recurringPhrases?: {
416
+ videoCount: number;
417
+ phrase: string;
418
+ occurrences: number;
419
+ }[] | undefined;
420
+ };
421
+ language?: string | undefined;
422
+ }>;
423
+ export type BrainManifest = z.infer<typeof brainManifestSchema>;
424
+ /** A retrieval result: a moment in a video, with the link that opens it. */
425
+ export declare const brainPassageSchema: z.ZodObject<{
426
+ videoId: z.ZodString;
427
+ title: z.ZodString;
428
+ startSeconds: z.ZodNumber;
429
+ startFormatted: z.ZodString;
430
+ endSeconds: z.ZodNumber;
431
+ score: z.ZodNumber;
432
+ text: z.ZodString;
433
+ url: z.ZodString;
434
+ }, "strip", z.ZodTypeAny, {
435
+ title: string;
436
+ url: string;
437
+ startSeconds: number;
438
+ startFormatted: string;
439
+ endSeconds: number;
440
+ text: string;
441
+ videoId: string;
442
+ score: number;
443
+ }, {
444
+ title: string;
445
+ url: string;
446
+ startSeconds: number;
447
+ startFormatted: string;
448
+ endSeconds: number;
449
+ text: string;
450
+ videoId: string;
451
+ score: number;
452
+ }>;
453
+ export type BrainPassage = z.infer<typeof brainPassageSchema>;
454
+ /** One row of list_brains. */
455
+ export declare const brainSummarySchema: z.ZodObject<{
456
+ channelId: z.ZodString;
457
+ name: z.ZodString;
458
+ handle: z.ZodString;
459
+ channelUrl: z.ZodString;
460
+ language: z.ZodString;
461
+ createdAt: z.ZodString;
462
+ updatedAt: z.ZodString;
463
+ hasProfile: z.ZodBoolean;
464
+ videoCount: z.ZodNumber;
465
+ indexedCount: z.ZodNumber;
466
+ chunkCount: z.ZodNumber;
467
+ }, "strip", z.ZodTypeAny, {
468
+ name: string;
469
+ channelId: string;
470
+ handle: string;
471
+ channelUrl: string;
472
+ videoCount: number;
473
+ chunkCount: number;
474
+ indexedCount: number;
475
+ language: string;
476
+ createdAt: string;
477
+ updatedAt: string;
478
+ hasProfile: boolean;
479
+ }, {
480
+ name: string;
481
+ channelId: string;
482
+ handle: string;
483
+ channelUrl: string;
484
+ videoCount: number;
485
+ chunkCount: number;
486
+ indexedCount: number;
487
+ language: string;
488
+ createdAt: string;
489
+ updatedAt: string;
490
+ hasProfile: boolean;
491
+ }>;
492
+ export declare const brainLockSchema: z.ZodObject<{
493
+ pid: z.ZodNumber;
494
+ startedAt: z.ZodString;
495
+ }, "strip", z.ZodTypeAny, {
496
+ pid: number;
497
+ startedAt: string;
498
+ }, {
499
+ pid: number;
500
+ startedAt: string;
501
+ }>;
502
+ //# sourceMappingURL=brain-schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brain-schemas.d.ts","sourceRoot":"","sources":["../src/brain-schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;GAMG;AAEH,qDAAqD;AACrD,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAchC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,uDAAuD;AACvD,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;EAO3B,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAG/B,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;EAI5B,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;;;;;;EAGpC,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmB3B,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,4BAA4B;AAC5B,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;IAG9B;;;OAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAMH,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,4EAA4E;AAC5E,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;EAS7B,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,8BAA8B;AAC9B,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAY7B,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;EAG1B,CAAC"}