youtube-knowledge-mcp 2.0.1 → 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.
- package/README.md +110 -12
- package/dist/brain-schemas.d.ts +502 -0
- package/dist/brain-schemas.d.ts.map +1 -0
- package/dist/brain-schemas.js +113 -0
- package/dist/brain-schemas.js.map +1 -0
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +20 -5
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +86 -0
- package/dist/index.js.map +1 -1
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +42 -0
- package/dist/prompts.js.map +1 -1
- package/dist/resources.d.ts.map +1 -1
- package/dist/resources.js +66 -0
- package/dist/resources.js.map +1 -1
- package/dist/schemas.d.ts +67 -56
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +25 -4
- package/dist/schemas.js.map +1 -1
- package/dist/tools/ask-brain.d.ts +62 -0
- package/dist/tools/ask-brain.d.ts.map +1 -0
- package/dist/tools/ask-brain.js +70 -0
- package/dist/tools/ask-brain.js.map +1 -0
- package/dist/tools/batch.d.ts +10 -10
- package/dist/tools/batch.js +2 -2
- package/dist/tools/batch.js.map +1 -1
- package/dist/tools/brain-info.d.ts +180 -0
- package/dist/tools/brain-info.d.ts.map +1 -0
- package/dist/tools/brain-info.js +108 -0
- package/dist/tools/brain-info.js.map +1 -0
- package/dist/tools/build-brain.d.ts +120 -0
- package/dist/tools/build-brain.d.ts.map +1 -0
- package/dist/tools/build-brain.js +123 -0
- package/dist/tools/build-brain.js.map +1 -0
- package/dist/tools/clips.d.ts +4 -4
- package/dist/tools/fetch-videos.d.ts +8 -8
- package/dist/tools/get-chapters.d.ts +2 -2
- package/dist/tools/get-comments.d.ts +2 -2
- package/dist/tools/get-transcript.d.ts +2 -2
- package/dist/tools/library.d.ts +9 -7
- package/dist/tools/library.d.ts.map +1 -1
- package/dist/tools/library.js +10 -4
- package/dist/tools/library.js.map +1 -1
- package/dist/tools/list-library.d.ts +4 -4
- package/dist/tools/manage-brain.d.ts +39 -0
- package/dist/tools/manage-brain.d.ts.map +1 -0
- package/dist/tools/manage-brain.js +53 -0
- package/dist/tools/manage-brain.js.map +1 -0
- package/dist/tools/search-channels.d.ts +4 -4
- package/dist/tools/search-transcript.d.ts +2 -2
- package/dist/tools/search-videos.d.ts +8 -8
- package/dist/utils/brain-build.d.ts +40 -0
- package/dist/utils/brain-build.d.ts.map +1 -0
- package/dist/utils/brain-build.js +211 -0
- package/dist/utils/brain-build.js.map +1 -0
- package/dist/utils/brain-chunks.d.ts +33 -0
- package/dist/utils/brain-chunks.d.ts.map +1 -0
- package/dist/utils/brain-chunks.js +87 -0
- package/dist/utils/brain-chunks.js.map +1 -0
- package/dist/utils/brain-index.d.ts +27 -0
- package/dist/utils/brain-index.d.ts.map +1 -0
- package/dist/utils/brain-index.js +100 -0
- package/dist/utils/brain-index.js.map +1 -0
- package/dist/utils/brain-ingest.d.ts +57 -0
- package/dist/utils/brain-ingest.d.ts.map +1 -0
- package/dist/utils/brain-ingest.js +127 -0
- package/dist/utils/brain-ingest.js.map +1 -0
- package/dist/utils/brain-lock.d.ts +20 -0
- package/dist/utils/brain-lock.d.ts.map +1 -0
- package/dist/utils/brain-lock.js +93 -0
- package/dist/utils/brain-lock.js.map +1 -0
- package/dist/utils/brain-lookup.d.ts +3 -0
- package/dist/utils/brain-lookup.d.ts.map +1 -0
- package/dist/utils/brain-lookup.js +62 -0
- package/dist/utils/brain-lookup.js.map +1 -0
- package/dist/utils/brain-paths.d.ts +19 -0
- package/dist/utils/brain-paths.d.ts.map +1 -0
- package/dist/utils/brain-paths.js +34 -0
- package/dist/utils/brain-paths.js.map +1 -0
- package/dist/utils/brain-phrases.d.ts +31 -0
- package/dist/utils/brain-phrases.d.ts.map +1 -0
- package/dist/utils/brain-phrases.js +116 -0
- package/dist/utils/brain-phrases.js.map +1 -0
- package/dist/utils/brain-stats.d.ts +25 -0
- package/dist/utils/brain-stats.d.ts.map +1 -0
- package/dist/utils/brain-stats.js +64 -0
- package/dist/utils/brain-stats.js.map +1 -0
- package/dist/utils/brain-storage.d.ts +28 -0
- package/dist/utils/brain-storage.d.ts.map +1 -0
- package/dist/utils/brain-storage.js +87 -0
- package/dist/utils/brain-storage.js.map +1 -0
- package/dist/utils/clips.js +4 -4
- package/dist/utils/clips.js.map +1 -1
- package/dist/utils/json-file.d.ts +36 -0
- package/dist/utils/json-file.d.ts.map +1 -0
- package/dist/utils/json-file.js +45 -0
- package/dist/utils/json-file.js.map +1 -0
- package/dist/utils/paths.d.ts +9 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +13 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/preflight.d.ts.map +1 -1
- package/dist/utils/preflight.js +14 -2
- package/dist/utils/preflight.js.map +1 -1
- package/dist/utils/search-index.d.ts +22 -7
- package/dist/utils/search-index.d.ts.map +1 -1
- package/dist/utils/search-index.js +17 -4
- package/dist/utils/search-index.js.map +1 -1
- package/dist/utils/storage.d.ts +14 -44
- package/dist/utils/storage.d.ts.map +1 -1
- package/dist/utils/storage.js +37 -80
- package/dist/utils/storage.js.map +1 -1
- package/dist/utils/transcript.d.ts +5 -4
- package/dist/utils/transcript.d.ts.map +1 -1
- package/dist/utils/transcript.js +3 -0
- package/dist/utils/transcript.js.map +1 -1
- package/dist/utils/validate.d.ts +1 -0
- package/dist/utils/validate.d.ts.map +1 -1
- package/dist/utils/validate.js +18 -0
- package/dist/utils/validate.js.map +1 -1
- package/dist/utils/youtube.d.ts +14 -0
- package/dist/utils/youtube.d.ts.map +1 -1
- package/dist/utils/youtube.js +19 -13
- package/dist/utils/youtube.js.map +1 -1
- package/dist/utils/ytdlp.d.ts.map +1 -1
- package/dist/utils/ytdlp.js +56 -6
- package/dist/utils/ytdlp.js.map +1 -1
- package/package.json +2 -2
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
|
|
@@ -130,6 +141,12 @@ Restart your client after updating configuration.
|
|
|
130
141
|
|
|
131
142
|
The server supports Streamable HTTP transport for remote access via Claude's official connectors.
|
|
132
143
|
|
|
144
|
+
**Every remote setup is your own deployment.** There is no shared instance to
|
|
145
|
+
point a connector at, by design: every call shells out to yt-dlp, so a single
|
|
146
|
+
host serving other people's traffic is a host YouTube rate-limits for all of
|
|
147
|
+
them. The button below deploys this repository into your own Render account, in
|
|
148
|
+
about two minutes and without cloning anything.
|
|
149
|
+
|
|
133
150
|
#### Self-hosted
|
|
134
151
|
|
|
135
152
|
```bash
|
|
@@ -142,28 +159,58 @@ The server listens on `PORT` (default 3000). Set `PORT` environment variable to
|
|
|
142
159
|
#### Docker
|
|
143
160
|
|
|
144
161
|
```bash
|
|
145
|
-
npm run build
|
|
146
162
|
docker build -t youtube-knowledge-mcp .
|
|
147
|
-
|
|
163
|
+
|
|
164
|
+
TOKEN=$(openssl rand -hex 32) && echo "MCP_AUTH_TOKEN=$TOKEN"
|
|
165
|
+
docker run -p 3000:10000 -e MCP_AUTH_TOKEN="$TOKEN" youtube-knowledge-mcp
|
|
148
166
|
```
|
|
149
167
|
|
|
168
|
+
The token is printed because nothing else will print it: the server logs that a
|
|
169
|
+
token is required, never its value. Send it as `Authorization: Bearer $TOKEN`.
|
|
170
|
+
|
|
171
|
+
The image sets `PORT=10000` and exposes it; publish it on whatever host port you
|
|
172
|
+
like. The build happens inside the image, so no local `npm run build` first.
|
|
173
|
+
|
|
150
174
|
#### Deploy to Render
|
|
151
175
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
176
|
+
[](https://render.com/deploy?repo=https://github.com/teobouancheau/youtube-knowledge-mcp)
|
|
177
|
+
|
|
178
|
+
The button opens Render's Blueprint flow against [`render.yaml`](render.yaml) in
|
|
179
|
+
this repository, which builds the Docker image, points the health check at
|
|
180
|
+
`/health` and generates an `MCP_AUTH_TOKEN` for you. No fork, no clone, no
|
|
181
|
+
settings to fill in — the service is yours, on your account.
|
|
182
|
+
|
|
183
|
+
1. Click the button and confirm. Render builds the image and deploys it.
|
|
184
|
+
2. Open the service's **Environment** tab and copy the generated
|
|
185
|
+
`MCP_AUTH_TOKEN`. The HTTP transport rejects every request without it, so a
|
|
186
|
+
URL that leaks is not an open server.
|
|
187
|
+
3. Add `https://<your-service>.onrender.com/mcp` as a custom connector, with
|
|
188
|
+
`Authorization: Bearer <token>`.
|
|
189
|
+
|
|
190
|
+
Worth doing once the service exists: set `MCP_ALLOWED_HOSTS` to your service's
|
|
191
|
+
hostname (`<your-service>.onrender.com`). It cannot be filled in from the
|
|
192
|
+
Blueprint, since the hostname does not exist until the service does, and it
|
|
193
|
+
rejects requests arriving under any other name.
|
|
194
|
+
|
|
195
|
+
Your instance does not follow this repository. The Blueprint sets
|
|
196
|
+
`autoDeployTrigger: off`, because auto-deploying would run code pushed here
|
|
197
|
+
inside your account, under your token, without you reading it first. To take a
|
|
198
|
+
newer version, use **Manual Deploy** on the service.
|
|
199
|
+
|
|
200
|
+
The free plan sleeps after inactivity, so the first call after a pause waits for
|
|
201
|
+
a cold start. Any paid plan removes that.
|
|
156
202
|
|
|
157
203
|
#### Connect via Claude.ai
|
|
158
204
|
|
|
159
205
|
1. Go to **Settings > Connectors**
|
|
160
206
|
2. Click **Add custom connector**
|
|
161
207
|
3. Enter your server URL (e.g., `https://your-app.onrender.com/mcp`)
|
|
162
|
-
4.
|
|
208
|
+
4. Add the `Authorization: Bearer <token>` header if you set `MCP_AUTH_TOKEN`
|
|
209
|
+
5. Click **Add**
|
|
163
210
|
|
|
164
211
|
## MCP Tools
|
|
165
212
|
|
|
166
|
-
|
|
213
|
+
33 tools. The 14 read-only ones work over both transports; the 19 that touch
|
|
167
214
|
your filesystem are registered only in local (stdio) mode, so a remote
|
|
168
215
|
deployment cannot reach the host's disk.
|
|
169
216
|
|
|
@@ -222,22 +269,56 @@ keyframe-aligned cut. All of these require ffmpeg.
|
|
|
222
269
|
| `save_to_library` | `videoId`, `title`, `content`, `contentType`, `channel`, `tags` | Path to the saved note |
|
|
223
270
|
| `list_library` | `tag` | Saved items, newest first |
|
|
224
271
|
| `get_library_item` | `videoId`, `contentType` | The saved markdown and its metadata |
|
|
225
|
-
| `search_library` | `query`, `limit`
|
|
272
|
+
| `search_library` | `query`, `limit`, `offset` | Ranked matches with excerpts |
|
|
226
273
|
| `update_library_tags` | `videoId`, `add`, `remove`, `replace` | The updated tags |
|
|
227
274
|
| `delete_library_item` | `videoId`, `contentType` | What was deleted |
|
|
228
275
|
| `rebuild_library_index` | — | Number of notes reindexed |
|
|
229
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
|
+
|
|
230
308
|
## Prompts
|
|
231
309
|
|
|
232
310
|
Reusable workflows your client can invoke directly: `summarize_video`,
|
|
233
311
|
`extract_skill`, `compare_videos`, `research_topic`, `channel_deep_dive`,
|
|
234
|
-
`clip_from_quote` (find a phrase, then cut the clip around it), and
|
|
235
|
-
`review_library` (
|
|
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).
|
|
236
316
|
|
|
237
317
|
## Resources
|
|
238
318
|
|
|
239
319
|
- `youtube://transcript/{videoId}` — a timestamped transcript, fetched and cached on first read
|
|
240
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)
|
|
241
322
|
|
|
242
323
|
## Error codes
|
|
243
324
|
|
|
@@ -265,7 +346,7 @@ All optional.
|
|
|
265
346
|
| `MCP_ALLOWED_HOSTS` | unset | Comma-separated Host allowlist; enables DNS-rebinding protection |
|
|
266
347
|
| `MCP_ALLOWED_ORIGINS` | unset | Comma-separated Origin allowlist |
|
|
267
348
|
| `MCP_BIND_HOST` | `0.0.0.0` | Interface to bind |
|
|
268
|
-
| `PORT` | `3000` | HTTP port
|
|
349
|
+
| `PORT` | `3000` | HTTP port. The Docker image sets `10000`; Render and similar platforms inject their own |
|
|
269
350
|
| `MCP_RATE_LIMIT` | `60` | Requests per window, per client |
|
|
270
351
|
| `MCP_RATE_WINDOW_MS` | `60000` | Rate-limit window |
|
|
271
352
|
| `MCP_SESSION_IDLE_MS` | `1800000` | Close HTTP sessions idle this long |
|
|
@@ -286,6 +367,11 @@ Content is stored in `~/.youtube-knowledge/`:
|
|
|
286
367
|
│ ├── metadata.json
|
|
287
368
|
│ ├── summary.md
|
|
288
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
|
|
289
375
|
├── downloads/ # Full downloads
|
|
290
376
|
├── clips/ # Extracted clips
|
|
291
377
|
├── frames/ # Captured stills
|
|
@@ -358,6 +444,18 @@ editor can import.
|
|
|
358
444
|
`save_to_library` stores it; `search_library` searches across everything saved
|
|
359
445
|
with full-text ranking.
|
|
360
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
|
+
|
|
361
459
|
## Testing
|
|
362
460
|
|
|
363
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"}
|