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
@@ -0,0 +1,180 @@
1
+ import { z } from 'zod';
2
+ import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
3
+ /**
4
+ * Reading what a brain covers: which channels have one, and how much of each
5
+ * channel it actually reached.
6
+ */
7
+ export declare const listBrainsSchema: {};
8
+ export declare const listBrainsOutputSchema: {
9
+ total: z.ZodNumber;
10
+ count: z.ZodNumber;
11
+ offset: z.ZodNumber;
12
+ hasMore: z.ZodBoolean;
13
+ nextOffset: z.ZodOptional<z.ZodNumber>;
14
+ brains: z.ZodArray<z.ZodObject<{
15
+ channelId: z.ZodString;
16
+ name: z.ZodString;
17
+ handle: z.ZodString;
18
+ channelUrl: z.ZodString;
19
+ language: z.ZodString;
20
+ createdAt: z.ZodString;
21
+ updatedAt: z.ZodString;
22
+ hasProfile: z.ZodBoolean;
23
+ videoCount: z.ZodNumber;
24
+ indexedCount: z.ZodNumber;
25
+ chunkCount: z.ZodNumber;
26
+ }, "strip", z.ZodTypeAny, {
27
+ name: string;
28
+ channelId: string;
29
+ handle: string;
30
+ channelUrl: string;
31
+ videoCount: number;
32
+ chunkCount: number;
33
+ indexedCount: number;
34
+ language: string;
35
+ createdAt: string;
36
+ updatedAt: string;
37
+ hasProfile: boolean;
38
+ }, {
39
+ name: string;
40
+ channelId: string;
41
+ handle: string;
42
+ channelUrl: string;
43
+ videoCount: number;
44
+ chunkCount: number;
45
+ indexedCount: number;
46
+ language: string;
47
+ createdAt: string;
48
+ updatedAt: string;
49
+ hasProfile: boolean;
50
+ }>, "many">;
51
+ };
52
+ export declare function listBrainsHandler(): Promise<CallToolResult>;
53
+ export declare const getBrainInfoSchema: {
54
+ channel: z.ZodString;
55
+ includeVideos: z.ZodDefault<z.ZodBoolean>;
56
+ };
57
+ export declare const getBrainInfoOutputSchema: {
58
+ channelId: z.ZodString;
59
+ name: z.ZodString;
60
+ handle: z.ZodString;
61
+ channelUrl: z.ZodString;
62
+ language: z.ZodString;
63
+ createdAt: z.ZodString;
64
+ updatedAt: z.ZodString;
65
+ hasProfile: z.ZodBoolean;
66
+ stats: z.ZodObject<{
67
+ videoCount: z.ZodNumber;
68
+ excludedCount: z.ZodNumber;
69
+ indexedCount: z.ZodNumber;
70
+ noCaptionsCount: z.ZodNumber;
71
+ failedCount: z.ZodNumber;
72
+ pendingCount: z.ZodNumber;
73
+ chunkCount: z.ZodNumber;
74
+ totalWords: z.ZodNumber;
75
+ medianWordsPerMinute: z.ZodNumber;
76
+ firstUpload: z.ZodOptional<z.ZodString>;
77
+ lastUpload: z.ZodOptional<z.ZodString>;
78
+ uploadsPerMonth: z.ZodArray<z.ZodObject<{
79
+ month: z.ZodString;
80
+ videos: z.ZodNumber;
81
+ }, "strip", z.ZodTypeAny, {
82
+ month: string;
83
+ videos: number;
84
+ }, {
85
+ month: string;
86
+ videos: number;
87
+ }>, "many">;
88
+ recurringPhrases: z.ZodOptional<z.ZodArray<z.ZodObject<{
89
+ phrase: z.ZodString;
90
+ videoCount: z.ZodNumber;
91
+ occurrences: z.ZodNumber;
92
+ }, "strip", z.ZodTypeAny, {
93
+ videoCount: number;
94
+ phrase: string;
95
+ occurrences: number;
96
+ }, {
97
+ videoCount: number;
98
+ phrase: string;
99
+ occurrences: number;
100
+ }>, "many">>;
101
+ }, "strip", z.ZodTypeAny, {
102
+ videoCount: number;
103
+ chunkCount: number;
104
+ excludedCount: number;
105
+ indexedCount: number;
106
+ noCaptionsCount: number;
107
+ failedCount: number;
108
+ pendingCount: number;
109
+ totalWords: number;
110
+ medianWordsPerMinute: number;
111
+ uploadsPerMonth: {
112
+ month: string;
113
+ videos: number;
114
+ }[];
115
+ firstUpload?: string | undefined;
116
+ lastUpload?: string | undefined;
117
+ recurringPhrases?: {
118
+ videoCount: number;
119
+ phrase: string;
120
+ occurrences: number;
121
+ }[] | undefined;
122
+ }, {
123
+ videoCount: number;
124
+ chunkCount: number;
125
+ excludedCount: number;
126
+ indexedCount: number;
127
+ noCaptionsCount: number;
128
+ failedCount: number;
129
+ pendingCount: number;
130
+ totalWords: number;
131
+ medianWordsPerMinute: number;
132
+ uploadsPerMonth: {
133
+ month: string;
134
+ videos: number;
135
+ }[];
136
+ firstUpload?: string | undefined;
137
+ lastUpload?: string | undefined;
138
+ recurringPhrases?: {
139
+ videoCount: number;
140
+ phrase: string;
141
+ occurrences: number;
142
+ }[] | undefined;
143
+ }>;
144
+ videos: z.ZodOptional<z.ZodArray<z.ZodObject<{
145
+ videoId: z.ZodString;
146
+ title: z.ZodString;
147
+ url: z.ZodString;
148
+ uploadDate: z.ZodString;
149
+ durationSeconds: z.ZodNumber;
150
+ state: z.ZodEnum<["pending", "indexed", "no-captions", "failed", "excluded"]>;
151
+ chunkCount: z.ZodNumber;
152
+ wordCount: z.ZodNumber;
153
+ error: z.ZodOptional<z.ZodString>;
154
+ }, "strip", z.ZodTypeAny, {
155
+ title: string;
156
+ durationSeconds: number;
157
+ url: string;
158
+ uploadDate: string;
159
+ videoId: string;
160
+ state: "pending" | "indexed" | "no-captions" | "failed" | "excluded";
161
+ chunkCount: number;
162
+ wordCount: number;
163
+ error?: string | undefined;
164
+ }, {
165
+ title: string;
166
+ durationSeconds: number;
167
+ url: string;
168
+ uploadDate: string;
169
+ videoId: string;
170
+ state: "pending" | "indexed" | "no-captions" | "failed" | "excluded";
171
+ chunkCount: number;
172
+ wordCount: number;
173
+ error?: string | undefined;
174
+ }>, "many">>;
175
+ };
176
+ export declare function getBrainInfoHandler({ channel, includeVideos, }: {
177
+ channel: string;
178
+ includeVideos: boolean;
179
+ }): Promise<CallToolResult>;
180
+ //# sourceMappingURL=brain-info.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brain-info.d.ts","sourceRoot":"","sources":["../../src/tools/brain-info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAYzE;;;GAGG;AAIH,eAAO,MAAM,gBAAgB,IAAK,CAAC;AAEnC,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAGlC,CAAC;AAEF,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,cAAc,CAAC,CAgBjE;AAsBD,eAAO,MAAM,kBAAkB;;;CAM9B,CAAC;AAEF,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAWpC,CAAC;AAEF,wBAAsB,mBAAmB,CAAC,EACxC,OAAO,EACP,aAAa,GACd,EAAE;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,OAAO,CAAC;CACxB,GAAG,OAAO,CAAC,cAAc,CAAC,CA+D1B"}
@@ -0,0 +1,108 @@
1
+ import { z } from 'zod';
2
+ import { brainStatsSchema, brainSummarySchema, brainVideoStateSchema, } from '../brain-schemas.js';
3
+ import { resolveBrain } from '../utils/brain-lookup.js';
4
+ import { hasProfile, listManifests } from '../utils/brain-storage.js';
5
+ import { pageInfo, toolResult } from '../utils/format.js';
6
+ import { paginationShape } from '../schemas.js';
7
+ /**
8
+ * Reading what a brain covers: which channels have one, and how much of each
9
+ * channel it actually reached.
10
+ */
11
+ // -- list_brains ---------------------------------------------------------
12
+ export const listBrainsSchema = {};
13
+ export const listBrainsOutputSchema = {
14
+ brains: z.array(brainSummarySchema),
15
+ ...paginationShape,
16
+ };
17
+ export async function listBrainsHandler() {
18
+ const manifests = await listManifests();
19
+ const brains = manifests.map(summarize);
20
+ const lines = brains.length === 0
21
+ ? ['No brains have been built yet.', '', 'Call build_brain with a channel URL or handle.']
22
+ : brains.map((brain) => `${brain.name} (${brain.handle || brain.channelId}) — ${brain.indexedCount}/${brain.videoCount} videos, ${brain.chunkCount.toLocaleString()} passages, updated ${brain.updatedAt.slice(0, 10)}${brain.hasProfile ? ', has a profile' : ''}`);
23
+ return toolResult(lines.join('\n'), {
24
+ brains,
25
+ ...pageInfo(brains.length, brains.length),
26
+ });
27
+ }
28
+ function summarize(manifest) {
29
+ const { channelId, name, handle, channelUrl } = manifest.channel;
30
+ return {
31
+ channelId,
32
+ name,
33
+ handle,
34
+ channelUrl,
35
+ language: manifest.language,
36
+ createdAt: manifest.createdAt,
37
+ updatedAt: manifest.updatedAt,
38
+ hasProfile: hasProfile(channelId),
39
+ videoCount: manifest.stats.videoCount,
40
+ indexedCount: manifest.stats.indexedCount,
41
+ chunkCount: manifest.stats.chunkCount,
42
+ };
43
+ }
44
+ // -- get_brain_info ------------------------------------------------------
45
+ export const getBrainInfoSchema = {
46
+ channel: z.string().describe('Channel URL, @handle, name, or channel id of an existing brain'),
47
+ includeVideos: z
48
+ .boolean()
49
+ .default(false)
50
+ .describe('List every video and its state. Long for a large channel. Default: false'),
51
+ };
52
+ export const getBrainInfoOutputSchema = {
53
+ channelId: z.string(),
54
+ name: z.string(),
55
+ handle: z.string(),
56
+ channelUrl: z.string(),
57
+ language: z.string(),
58
+ createdAt: z.string(),
59
+ updatedAt: z.string(),
60
+ hasProfile: z.boolean(),
61
+ stats: brainStatsSchema,
62
+ videos: z.array(brainVideoStateSchema).optional(),
63
+ };
64
+ export async function getBrainInfoHandler({ channel, includeVideos, }) {
65
+ const manifest = await resolveBrain(channel);
66
+ const { channelId, name, handle, channelUrl } = manifest.channel;
67
+ const { stats } = manifest;
68
+ const videos = Object.values(manifest.videos);
69
+ const lines = [
70
+ `${name} (${handle || channelId})`,
71
+ `${stats.indexedCount} of ${stats.videoCount} videos indexed from ${manifest.language} captions · ${stats.chunkCount.toLocaleString()} passages · ${stats.totalWords.toLocaleString()} words`,
72
+ `${stats.medianWordsPerMinute} words per minute (median)`,
73
+ stats.firstUpload === undefined
74
+ ? 'No upload dates reported'
75
+ : `Uploads from ${stats.firstUpload} to ${stats.lastUpload ?? stats.firstUpload}`,
76
+ `Updated ${manifest.updatedAt}`,
77
+ ];
78
+ if (stats.noCaptionsCount > 0)
79
+ lines.push(`${stats.noCaptionsCount} videos have no captions`);
80
+ if (stats.excludedCount > 0) {
81
+ lines.push(`${stats.excludedCount} videos are outside the filters this brain was built with`);
82
+ }
83
+ if (stats.failedCount + stats.pendingCount > 0) {
84
+ lines.push(`${stats.failedCount + stats.pendingCount} videos still to read — call build_brain to continue`);
85
+ }
86
+ if (stats.recurringPhrases === undefined) {
87
+ lines.push('', 'Repeated phrases have not been measured yet — the last build did not finish. Call build_brain to complete it.');
88
+ }
89
+ else if (stats.recurringPhrases.length > 0) {
90
+ lines.push('', 'Phrases repeated across videos:', ...stats.recurringPhrases.map((entry) => ` "${entry.phrase}" — ${entry.videoCount} videos, ${entry.occurrences} times`));
91
+ }
92
+ if (includeVideos) {
93
+ lines.push('', ...videos.map((video) => `${video.state.padEnd(12)} ${video.uploadDate || ' '} ${video.title}${video.error === undefined ? '' : ` (${video.error})`}`));
94
+ }
95
+ return toolResult(lines.join('\n'), {
96
+ channelId,
97
+ name,
98
+ handle,
99
+ channelUrl,
100
+ language: manifest.language,
101
+ createdAt: manifest.createdAt,
102
+ updatedAt: manifest.updatedAt,
103
+ hasProfile: hasProfile(channelId),
104
+ stats,
105
+ ...(includeVideos ? { videos } : {}),
106
+ });
107
+ }
108
+ //# sourceMappingURL=brain-info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brain-info.js","sourceRoot":"","sources":["../../src/tools/brain-info.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,120 @@
1
+ import { z } from 'zod';
2
+ import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
3
+ export declare const buildBrainSchema: {
4
+ channel: z.ZodString;
5
+ maxVideos: z.ZodDefault<z.ZodNumber>;
6
+ language: z.ZodDefault<z.ZodString>;
7
+ since: z.ZodOptional<z.ZodString>;
8
+ minDurationSeconds: z.ZodDefault<z.ZodNumber>;
9
+ };
10
+ export declare const buildBrainOutputSchema: {
11
+ channelId: z.ZodString;
12
+ name: z.ZodString;
13
+ handle: z.ZodString;
14
+ channelUrl: z.ZodString;
15
+ language: z.ZodString;
16
+ considered: z.ZodNumber;
17
+ processed: z.ZodNumber;
18
+ skipped: z.ZodNumber;
19
+ excluded: z.ZodNumber;
20
+ stoppedEarly: z.ZodBoolean;
21
+ stopReason: z.ZodOptional<z.ZodString>;
22
+ stats: z.ZodObject<{
23
+ videoCount: z.ZodNumber;
24
+ excludedCount: z.ZodNumber;
25
+ indexedCount: z.ZodNumber;
26
+ noCaptionsCount: z.ZodNumber;
27
+ failedCount: z.ZodNumber;
28
+ pendingCount: z.ZodNumber;
29
+ chunkCount: z.ZodNumber;
30
+ totalWords: z.ZodNumber;
31
+ medianWordsPerMinute: z.ZodNumber;
32
+ firstUpload: z.ZodOptional<z.ZodString>;
33
+ lastUpload: z.ZodOptional<z.ZodString>;
34
+ uploadsPerMonth: z.ZodArray<z.ZodObject<{
35
+ month: z.ZodString;
36
+ videos: z.ZodNumber;
37
+ }, "strip", z.ZodTypeAny, {
38
+ month: string;
39
+ videos: number;
40
+ }, {
41
+ month: string;
42
+ videos: number;
43
+ }>, "many">;
44
+ recurringPhrases: z.ZodOptional<z.ZodArray<z.ZodObject<{
45
+ phrase: z.ZodString;
46
+ videoCount: z.ZodNumber;
47
+ occurrences: z.ZodNumber;
48
+ }, "strip", z.ZodTypeAny, {
49
+ videoCount: number;
50
+ phrase: string;
51
+ occurrences: number;
52
+ }, {
53
+ videoCount: number;
54
+ phrase: string;
55
+ occurrences: number;
56
+ }>, "many">>;
57
+ }, "strip", z.ZodTypeAny, {
58
+ videoCount: number;
59
+ chunkCount: number;
60
+ excludedCount: number;
61
+ indexedCount: number;
62
+ noCaptionsCount: number;
63
+ failedCount: number;
64
+ pendingCount: number;
65
+ totalWords: number;
66
+ medianWordsPerMinute: number;
67
+ uploadsPerMonth: {
68
+ month: string;
69
+ videos: number;
70
+ }[];
71
+ firstUpload?: string | undefined;
72
+ lastUpload?: string | undefined;
73
+ recurringPhrases?: {
74
+ videoCount: number;
75
+ phrase: string;
76
+ occurrences: number;
77
+ }[] | undefined;
78
+ }, {
79
+ videoCount: number;
80
+ chunkCount: number;
81
+ excludedCount: number;
82
+ indexedCount: number;
83
+ noCaptionsCount: number;
84
+ failedCount: number;
85
+ pendingCount: number;
86
+ totalWords: number;
87
+ medianWordsPerMinute: number;
88
+ uploadsPerMonth: {
89
+ month: string;
90
+ videos: number;
91
+ }[];
92
+ firstUpload?: string | undefined;
93
+ lastUpload?: string | undefined;
94
+ recurringPhrases?: {
95
+ videoCount: number;
96
+ phrase: string;
97
+ occurrences: number;
98
+ }[] | undefined;
99
+ }>;
100
+ };
101
+ /**
102
+ * Build or extend a channel brain.
103
+ *
104
+ * Idempotent by construction: it reads what is missing and leaves what is
105
+ * already there, so calling it again after an interruption continues, and
106
+ * calling it on a finished brain picks up new uploads. That is also why there
107
+ * is no separate refresh tool.
108
+ *
109
+ * The filters describe the brain rather than just this call, so a build makes
110
+ * the brain match them: narrowing one discards the passages of videos it now
111
+ * excludes, and widening it reads them again.
112
+ */
113
+ export declare function buildBrainHandler({ channel, maxVideos, language, since, minDurationSeconds, }: {
114
+ channel: string;
115
+ maxVideos: number;
116
+ language: string;
117
+ since?: string;
118
+ minDurationSeconds: number;
119
+ }): Promise<CallToolResult>;
120
+ //# sourceMappingURL=build-brain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-brain.d.ts","sourceRoot":"","sources":["../../src/tools/build-brain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AASzE,eAAO,MAAM,gBAAgB;;;;;;CA6B5B,CAAC;AAEF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAalC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAsB,iBAAiB,CAAC,EACtC,OAAO,EACP,SAAS,EACT,QAAQ,EACR,KAAK,EACL,kBAAkB,GACnB,EAAE;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kBAAkB,EAAE,MAAM,CAAC;CAC5B,GAAG,OAAO,CAAC,cAAc,CAAC,CA+B1B"}
@@ -0,0 +1,123 @@
1
+ import { z } from 'zod';
2
+ import { brainStatsSchema } from '../brain-schemas.js';
3
+ import { buildBrain } from '../utils/brain-build.js';
4
+ import { withBuildLock } from '../utils/brain-lock.js';
5
+ import { readManifest } from '../utils/brain-storage.js';
6
+ import { toolResult } from '../utils/format.js';
7
+ import { assertChannelId, assertLanguageTag } from '../utils/validate.js';
8
+ import { getChannelInfo, listVideos } from '../utils/youtube.js';
9
+ export const buildBrainSchema = {
10
+ channel: z.string().describe('Channel URL, @handle, or name'),
11
+ maxVideos: z
12
+ .number()
13
+ .int()
14
+ .min(1)
15
+ .max(500)
16
+ .default(100)
17
+ .describe('How many of the most recent videos to consider. Default: 100'),
18
+ language: z
19
+ .string()
20
+ .default('en')
21
+ .describe('Caption language to read. A brain holds one language; build a separate one to read another. Default: en'),
22
+ since: z
23
+ .string()
24
+ .optional()
25
+ .describe("Only videos published on or after this date (YYYY-MM-DD), read from each video's own metadata rather than guessed at. Re-applied on every call, so narrowing or widening it takes effect without a rebuild."),
26
+ minDurationSeconds: z
27
+ .number()
28
+ .int()
29
+ .min(0)
30
+ .default(0)
31
+ .describe('Skip anything shorter, to leave out shorts and clips. Re-applied on every call, like since. Default: 0'),
32
+ };
33
+ export const buildBrainOutputSchema = {
34
+ channelId: z.string(),
35
+ name: z.string(),
36
+ handle: z.string(),
37
+ channelUrl: z.string(),
38
+ language: z.string(),
39
+ considered: z.number().int().describe('Videos the filters kept'),
40
+ processed: z.number().int().describe('Videos read during this call'),
41
+ skipped: z.number().int().describe('Videos already in the brain'),
42
+ excluded: z.number().int().describe('Videos ruled out by since or minDurationSeconds'),
43
+ stoppedEarly: z.boolean(),
44
+ stopReason: z.string().optional(),
45
+ stats: brainStatsSchema,
46
+ };
47
+ /**
48
+ * Build or extend a channel brain.
49
+ *
50
+ * Idempotent by construction: it reads what is missing and leaves what is
51
+ * already there, so calling it again after an interruption continues, and
52
+ * calling it on a finished brain picks up new uploads. That is also why there
53
+ * is no separate refresh tool.
54
+ *
55
+ * The filters describe the brain rather than just this call, so a build makes
56
+ * the brain match them: narrowing one discards the passages of videos it now
57
+ * excludes, and widening it reads them again.
58
+ */
59
+ export async function buildBrainHandler({ channel, maxVideos, language, since, minDurationSeconds, }) {
60
+ assertLanguageTag(language);
61
+ const info = await getChannelInfo(channel);
62
+ assertChannelId(info.channelId);
63
+ const result = await withBuildLock(info.channelId, async () => buildBrain({
64
+ channel: info,
65
+ videos: await listUploads(info.channelUrl, maxVideos),
66
+ existing: await readManifest(info.channelId),
67
+ language,
68
+ minDurationSeconds,
69
+ ...(since === undefined ? {} : { since }),
70
+ }));
71
+ return toolResult(render(info.name, result), {
72
+ channelId: info.channelId,
73
+ name: info.name,
74
+ handle: info.handle,
75
+ channelUrl: info.channelUrl,
76
+ language,
77
+ considered: result.considered,
78
+ processed: result.processed,
79
+ skipped: result.skipped,
80
+ excluded: result.excluded,
81
+ stoppedEarly: result.stoppedEarly,
82
+ ...(result.stopReason === undefined ? {} : { stopReason: result.stopReason }),
83
+ stats: result.manifest.stats,
84
+ });
85
+ }
86
+ /**
87
+ * The channel's uploads, newest first.
88
+ *
89
+ * Deliberately the uploads tab rather than the channel itself. A bare channel
90
+ * URL expands to every tab it has — shorts, live, releases — so `--playlist-end`
91
+ * applies per tab and asking for two videos can return eight, from four
92
+ * different places. The slice is belt and braces for a channel whose tabs
93
+ * yt-dlp expands anyway.
94
+ */
95
+ async function listUploads(channelUrl, maxVideos) {
96
+ const uploads = `${channelUrl.replace(/\/+$/, '')}/videos`;
97
+ // No fallback to the bare channel URL. Every channel has an uploads tab, so a
98
+ // failure here is a failure worth reporting — throttling, a network fault, a
99
+ // channel that no longer exists — and retrying it against a URL that expands
100
+ // to more work would double the load while reporting the wrong cause.
101
+ return (await listVideos(uploads, maxVideos)).slice(0, maxVideos);
102
+ }
103
+ function render(name, result) {
104
+ const { stats } = result.manifest;
105
+ const lines = [
106
+ `Brain for ${name}: ${stats.indexedCount} of ${stats.videoCount} videos indexed, ${stats.chunkCount.toLocaleString()} passages.`,
107
+ '',
108
+ `Considered ${result.considered} videos · read ${result.processed} · already had ${result.skipped}${result.excluded > 0 ? ` · ${result.excluded} outside the filters` : ''}`,
109
+ ];
110
+ if (stats.noCaptionsCount > 0)
111
+ lines.push(`${stats.noCaptionsCount} have no captions`);
112
+ if (stats.failedCount > 0) {
113
+ lines.push(`${stats.failedCount} could not be read — call build_brain again to retry them`);
114
+ }
115
+ if (stats.pendingCount > 0)
116
+ lines.push(`${stats.pendingCount} not read yet`);
117
+ if (result.stopReason !== undefined) {
118
+ lines.push('', `Stopped early: ${result.stopReason}`, 'Call build_brain again to continue.');
119
+ }
120
+ lines.push('', 'Ask it something with ask_brain.');
121
+ return lines.join('\n');
122
+ }
123
+ //# sourceMappingURL=build-brain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-brain.js","sourceRoot":"","sources":["../../src/tools/build-brain.ts"],"names":[],"mappings":"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"}
@@ -78,18 +78,18 @@ export declare const extractClipsOutputSchema: {
78
78
  durationSeconds: z.ZodNumber;
79
79
  }, "strip", z.ZodTypeAny, {
80
80
  title: string;
81
- videoId: string;
82
- filePath: string;
83
81
  durationSeconds: number;
84
82
  startSeconds: number;
85
83
  endSeconds: number;
86
- }, {
87
- title: string;
88
84
  videoId: string;
89
85
  filePath: string;
86
+ }, {
87
+ title: string;
90
88
  durationSeconds: number;
91
89
  startSeconds: number;
92
90
  endSeconds: number;
91
+ videoId: string;
92
+ filePath: string;
93
93
  }>, "many">;
94
94
  failures: z.ZodArray<z.ZodObject<{
95
95
  start: z.ZodString;
@@ -21,23 +21,23 @@ export declare const fetchVideosOutputSchema: {
21
21
  viewCount: z.ZodOptional<z.ZodNumber>;
22
22
  uploadDate: z.ZodOptional<z.ZodString>;
23
23
  }, "strip", z.ZodTypeAny, {
24
- url: string;
25
- title: string;
26
24
  id: string;
27
- durationFormatted: string;
25
+ title: string;
28
26
  durationSeconds: number;
27
+ durationFormatted: string;
28
+ url: string;
29
29
  channel?: string | undefined;
30
- uploadDate?: string | undefined;
31
30
  viewCount?: number | undefined;
31
+ uploadDate?: string | undefined;
32
32
  }, {
33
- url: string;
34
- title: string;
35
33
  id: string;
36
- durationFormatted: string;
34
+ title: string;
37
35
  durationSeconds: number;
36
+ durationFormatted: string;
37
+ url: string;
38
38
  channel?: string | undefined;
39
- uploadDate?: string | undefined;
40
39
  viewCount?: number | undefined;
40
+ uploadDate?: string | undefined;
41
41
  }>, "many">;
42
42
  };
43
43
  export declare function fetchVideosHandler({ url, limit, }: {
@@ -13,15 +13,15 @@ export declare const getChaptersOutputSchema: {
13
13
  endFormatted: z.ZodString;
14
14
  url: z.ZodString;
15
15
  }, "strip", z.ZodTypeAny, {
16
- url: string;
17
16
  title: string;
17
+ url: string;
18
18
  startSeconds: number;
19
19
  startFormatted: string;
20
20
  endSeconds: number;
21
21
  endFormatted: string;
22
22
  }, {
23
- url: string;
24
23
  title: string;
24
+ url: string;
25
25
  startSeconds: number;
26
26
  startFormatted: string;
27
27
  endSeconds: number;
@@ -16,14 +16,14 @@ export declare const getCommentsOutputSchema: {
16
16
  likeCount: z.ZodNumber;
17
17
  isPinned: z.ZodBoolean;
18
18
  }, "strip", z.ZodTypeAny, {
19
- text: string;
20
19
  likeCount: number;
21
20
  author: string;
21
+ text: string;
22
22
  isPinned: boolean;
23
23
  }, {
24
- text: string;
25
24
  likeCount: number;
26
25
  author: string;
26
+ text: string;
27
27
  isPinned: boolean;
28
28
  }>, "many">;
29
29
  };
@@ -20,13 +20,13 @@ export declare const getTranscriptOutputSchema: {
20
20
  endSeconds: z.ZodNumber;
21
21
  text: z.ZodString;
22
22
  }, "strip", z.ZodTypeAny, {
23
- text: string;
24
23
  startSeconds: number;
25
24
  endSeconds: number;
26
- }, {
27
25
  text: string;
26
+ }, {
28
27
  startSeconds: number;
29
28
  endSeconds: number;
29
+ text: string;
30
30
  }>, "many">;
31
31
  wordCount: z.ZodNumber;
32
32
  chapter: z.ZodOptional<z.ZodString>;