midnight-mcp 0.1.40 → 0.2.1

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 (100) hide show
  1. package/README.md +34 -0
  2. package/dist/bin.d.ts +1 -0
  3. package/dist/bin.js +10764 -0
  4. package/dist/index.d.ts +205 -3
  5. package/dist/index.js +10722 -15
  6. package/package.json +16 -6
  7. package/dist/config/compact-version.d.ts +0 -183
  8. package/dist/config/compact-version.js +0 -423
  9. package/dist/db/index.d.ts +0 -3
  10. package/dist/db/index.js +0 -2
  11. package/dist/db/vectorStore.d.ts +0 -69
  12. package/dist/db/vectorStore.js +0 -196
  13. package/dist/pipeline/embeddings.d.ts +0 -25
  14. package/dist/pipeline/embeddings.js +0 -103
  15. package/dist/pipeline/github.d.ts +0 -84
  16. package/dist/pipeline/github.js +0 -399
  17. package/dist/pipeline/index.d.ts +0 -11
  18. package/dist/pipeline/index.js +0 -6
  19. package/dist/pipeline/indexer.d.ts +0 -41
  20. package/dist/pipeline/indexer.js +0 -254
  21. package/dist/pipeline/parser.d.ts +0 -46
  22. package/dist/pipeline/parser.js +0 -436
  23. package/dist/pipeline/releases.d.ts +0 -112
  24. package/dist/pipeline/releases.js +0 -298
  25. package/dist/pipeline/repository.d.ts +0 -372
  26. package/dist/pipeline/repository.js +0 -520
  27. package/dist/prompts/index.d.ts +0 -3
  28. package/dist/prompts/index.js +0 -2
  29. package/dist/prompts/templates.d.ts +0 -26
  30. package/dist/prompts/templates.js +0 -443
  31. package/dist/resources/code.d.ts +0 -15
  32. package/dist/resources/code.js +0 -122
  33. package/dist/resources/content/code-content.d.ts +0 -6
  34. package/dist/resources/content/code-content.js +0 -802
  35. package/dist/resources/content/docs-content.d.ts +0 -14
  36. package/dist/resources/content/docs-content.js +0 -1202
  37. package/dist/resources/content/index.d.ts +0 -6
  38. package/dist/resources/content/index.js +0 -6
  39. package/dist/resources/docs.d.ts +0 -15
  40. package/dist/resources/docs.js +0 -98
  41. package/dist/resources/index.d.ts +0 -6
  42. package/dist/resources/index.js +0 -13
  43. package/dist/resources/schemas.d.ts +0 -16
  44. package/dist/resources/schemas.js +0 -407
  45. package/dist/scripts/index-repos.d.ts +0 -12
  46. package/dist/scripts/index-repos.js +0 -53
  47. package/dist/server.d.ts +0 -43
  48. package/dist/server.js +0 -693
  49. package/dist/services/index.d.ts +0 -6
  50. package/dist/services/index.js +0 -6
  51. package/dist/services/sampling.d.ts +0 -62
  52. package/dist/services/sampling.js +0 -277
  53. package/dist/tools/analyze.d.ts +0 -106
  54. package/dist/tools/analyze.js +0 -431
  55. package/dist/tools/generation.d.ts +0 -9
  56. package/dist/tools/generation.js +0 -285
  57. package/dist/tools/health.d.ts +0 -120
  58. package/dist/tools/health.js +0 -362
  59. package/dist/tools/index.d.ts +0 -14
  60. package/dist/tools/index.js +0 -22
  61. package/dist/tools/meta.d.ts +0 -61
  62. package/dist/tools/meta.js +0 -282
  63. package/dist/tools/repository/constants.d.ts +0 -19
  64. package/dist/tools/repository/constants.js +0 -324
  65. package/dist/tools/repository/handlers.d.ts +0 -373
  66. package/dist/tools/repository/handlers.js +0 -724
  67. package/dist/tools/repository/index.d.ts +0 -9
  68. package/dist/tools/repository/index.js +0 -13
  69. package/dist/tools/repository/schemas.d.ts +0 -153
  70. package/dist/tools/repository/schemas.js +0 -106
  71. package/dist/tools/repository/tools.d.ts +0 -7
  72. package/dist/tools/repository/tools.js +0 -484
  73. package/dist/tools/repository/validation.d.ts +0 -106
  74. package/dist/tools/repository/validation.js +0 -820
  75. package/dist/tools/repository.d.ts +0 -6
  76. package/dist/tools/repository.js +0 -7
  77. package/dist/tools/search.d.ts +0 -76
  78. package/dist/tools/search.js +0 -423
  79. package/dist/types/index.d.ts +0 -2
  80. package/dist/types/index.js +0 -2
  81. package/dist/types/mcp.d.ts +0 -187
  82. package/dist/types/mcp.js +0 -6
  83. package/dist/utils/cache.d.ts +0 -77
  84. package/dist/utils/cache.js +0 -172
  85. package/dist/utils/config.d.ts +0 -70
  86. package/dist/utils/config.js +0 -294
  87. package/dist/utils/errors.d.ts +0 -111
  88. package/dist/utils/errors.js +0 -165
  89. package/dist/utils/health.d.ts +0 -29
  90. package/dist/utils/health.js +0 -132
  91. package/dist/utils/hosted-api.d.ts +0 -67
  92. package/dist/utils/hosted-api.js +0 -119
  93. package/dist/utils/index.d.ts +0 -16
  94. package/dist/utils/index.js +0 -15
  95. package/dist/utils/logger.d.ts +0 -48
  96. package/dist/utils/logger.js +0 -124
  97. package/dist/utils/rate-limit.d.ts +0 -61
  98. package/dist/utils/rate-limit.js +0 -148
  99. package/dist/utils/validation.d.ts +0 -52
  100. package/dist/utils/validation.js +0 -255
@@ -1,399 +0,0 @@
1
- import { Octokit } from "octokit";
2
- import { config, logger, updateRateLimit, shouldProceedWithRequest, getRateLimitStatus, } from "../utils/index.js";
3
- // Retry configuration
4
- const RETRY_CONFIG = {
5
- maxRetries: 3,
6
- baseDelayMs: 1000,
7
- maxDelayMs: 10000,
8
- };
9
- /**
10
- * Retry wrapper with exponential backoff
11
- */
12
- async function withRetry(operation, operationName) {
13
- let lastError = null;
14
- for (let attempt = 1; attempt <= RETRY_CONFIG.maxRetries; attempt++) {
15
- try {
16
- return await operation();
17
- }
18
- catch (error) {
19
- lastError = error;
20
- const isRetryable = isRetryableError(error);
21
- if (!isRetryable || attempt === RETRY_CONFIG.maxRetries) {
22
- logger.error(`${operationName} failed after ${attempt} attempt(s)`, {
23
- error: String(error),
24
- attempt,
25
- });
26
- throw enhanceError(error, operationName);
27
- }
28
- const delay = Math.min(RETRY_CONFIG.baseDelayMs * Math.pow(2, attempt - 1), RETRY_CONFIG.maxDelayMs);
29
- logger.warn(`${operationName} failed, retrying in ${delay}ms...`, {
30
- attempt,
31
- error: String(error),
32
- });
33
- await sleep(delay);
34
- }
35
- }
36
- throw lastError;
37
- }
38
- /**
39
- * Check if an error is retryable
40
- */
41
- function isRetryableError(error) {
42
- if (error instanceof Error) {
43
- const message = error.message.toLowerCase();
44
- // Retry on network errors, rate limits, and server errors
45
- return (message.includes("network") ||
46
- message.includes("timeout") ||
47
- message.includes("econnreset") ||
48
- message.includes("rate limit") ||
49
- message.includes("403") ||
50
- message.includes("500") ||
51
- message.includes("502") ||
52
- message.includes("503") ||
53
- message.includes("504"));
54
- }
55
- return false;
56
- }
57
- /**
58
- * Enhance error with more context
59
- */
60
- function enhanceError(error, operation) {
61
- const originalMessage = error instanceof Error ? error.message : String(error);
62
- // Provide user-friendly error messages
63
- if (originalMessage.includes("rate limit") ||
64
- originalMessage.includes("403")) {
65
- return new Error(`GitHub API rate limit exceeded during ${operation}. ` +
66
- `Add a GITHUB_TOKEN to your config to increase limits from 60 to 5000 requests/hour.`);
67
- }
68
- if (originalMessage.includes("404")) {
69
- return new Error(`Resource not found during ${operation}. ` +
70
- `Check that the repository/file exists and is accessible.`);
71
- }
72
- if (originalMessage.includes("timeout") ||
73
- originalMessage.includes("network")) {
74
- return new Error(`Network error during ${operation}. ` +
75
- `Check your internet connection and try again.`);
76
- }
77
- return new Error(`${operation} failed: ${originalMessage}`);
78
- }
79
- /**
80
- * Sleep for a given number of milliseconds
81
- */
82
- function sleep(ms) {
83
- return new Promise((resolve) => setTimeout(resolve, ms));
84
- }
85
- class SimpleCache {
86
- cache = new Map();
87
- ttlMs;
88
- constructor(ttlMinutes = 10) {
89
- this.ttlMs = ttlMinutes * 60 * 1000;
90
- }
91
- get(key) {
92
- const entry = this.cache.get(key);
93
- if (!entry)
94
- return null;
95
- if (Date.now() - entry.timestamp > this.ttlMs) {
96
- this.cache.delete(key);
97
- return null;
98
- }
99
- return entry.data;
100
- }
101
- set(key, data) {
102
- this.cache.set(key, { data, timestamp: Date.now() });
103
- }
104
- clear() {
105
- this.cache.clear();
106
- }
107
- }
108
- export class GitHubClient {
109
- octokit;
110
- fileCache = new SimpleCache(15); // 15 min cache for files
111
- treeCache = new SimpleCache(10); // 10 min cache for trees
112
- repoInfoCache = new SimpleCache(10); // 10 min cache for repo info
113
- constructor(token) {
114
- this.octokit = new Octokit({
115
- auth: token || config.githubToken,
116
- request: {
117
- timeout: 10000, // 10 second timeout for API calls
118
- },
119
- });
120
- }
121
- /**
122
- * Get repository information
123
- */
124
- async getRepositoryInfo(owner, repo) {
125
- const cacheKey = `repo:${owner}/${repo}`;
126
- const cached = this.repoInfoCache.get(cacheKey);
127
- if (cached) {
128
- logger.debug(`Cache hit for repo info: ${cacheKey}`);
129
- return cached;
130
- }
131
- try {
132
- const { data: repoData } = await withRetry(() => this.octokit.rest.repos.get({ owner, repo }), `getRepositoryInfo(${owner}/${repo})`);
133
- const { data: commits } = await withRetry(() => this.octokit.rest.repos.listCommits({ owner, repo, per_page: 1 }), `getCommits(${owner}/${repo})`);
134
- const lastCommit = commits[0]
135
- ? {
136
- sha: commits[0].sha,
137
- message: commits[0].commit.message,
138
- author: commits[0].commit.author?.name || "Unknown",
139
- date: commits[0].commit.author?.date || "",
140
- url: commits[0].html_url,
141
- }
142
- : null;
143
- const result = {
144
- owner,
145
- repo,
146
- branch: repoData.default_branch,
147
- lastCommit,
148
- fileCount: 0, // Will be updated during tree fetch
149
- };
150
- this.repoInfoCache.set(cacheKey, result);
151
- return result;
152
- }
153
- catch (error) {
154
- logger.error(`Failed to get repository info for ${owner}/${repo}`, {
155
- error: String(error),
156
- });
157
- throw error;
158
- }
159
- }
160
- /**
161
- * Get file content from a repository
162
- */
163
- async getFileContent(owner, repo, path, ref) {
164
- const cacheKey = `file:${owner}/${repo}/${path}@${ref || "main"}`;
165
- const cached = this.fileCache.get(cacheKey);
166
- if (cached) {
167
- logger.debug(`Cache hit for file: ${cacheKey}`);
168
- return cached;
169
- }
170
- try {
171
- const { data } = await withRetry(() => this.octokit.rest.repos.getContent({ owner, repo, path, ref }), `getFileContent(${owner}/${repo}/${path})`);
172
- if (Array.isArray(data) || data.type !== "file") {
173
- return null;
174
- }
175
- const content = data.encoding === "base64"
176
- ? Buffer.from(data.content, "base64").toString("utf-8")
177
- : data.content;
178
- const result = {
179
- path: data.path,
180
- content,
181
- sha: data.sha,
182
- size: data.size,
183
- encoding: data.encoding,
184
- };
185
- this.fileCache.set(cacheKey, result);
186
- return result;
187
- }
188
- catch (error) {
189
- logger.warn(`Failed to get file ${path} from ${owner}/${repo}`, {
190
- error: String(error),
191
- });
192
- return null;
193
- }
194
- }
195
- /**
196
- * Get repository tree (list of all files)
197
- */
198
- async getRepositoryTree(owner, repo, ref) {
199
- const cacheKey = `tree:${owner}/${repo}@${ref || "main"}`;
200
- const cached = this.treeCache.get(cacheKey);
201
- if (cached) {
202
- logger.debug(`Cache hit for tree: ${cacheKey}`);
203
- return cached;
204
- }
205
- try {
206
- const { data: refData } = await withRetry(() => this.octokit.rest.git.getRef({
207
- owner,
208
- repo,
209
- ref: `heads/${ref || "main"}`,
210
- }), `getRef(${owner}/${repo})`);
211
- const { data: treeData } = await withRetry(() => this.octokit.rest.git.getTree({
212
- owner,
213
- repo,
214
- tree_sha: refData.object.sha,
215
- recursive: "true",
216
- }), `getTree(${owner}/${repo})`);
217
- const result = treeData.tree
218
- .filter((item) => item.type === "blob" && item.path)
219
- .map((item) => item.path);
220
- this.treeCache.set(cacheKey, result);
221
- return result;
222
- }
223
- catch (error) {
224
- logger.error(`Failed to get repository tree for ${owner}/${repo}`, {
225
- error: String(error),
226
- });
227
- throw error;
228
- }
229
- }
230
- /**
231
- * Filter files by patterns
232
- */
233
- filterFilesByPatterns(files, patterns, exclude) {
234
- const matchPattern = (file, pattern) => {
235
- // Convert glob pattern to regex
236
- const regexPattern = pattern
237
- .replace(/\*\*/g, ".*")
238
- .replace(/\*/g, "[^/]*")
239
- .replace(/\./g, "\\.");
240
- return new RegExp(`^${regexPattern}$`).test(file);
241
- };
242
- return files.filter((file) => {
243
- const matchesInclude = patterns.some((p) => matchPattern(file, p));
244
- const matchesExclude = exclude.some((p) => matchPattern(file, p));
245
- return matchesInclude && !matchesExclude;
246
- });
247
- }
248
- /**
249
- * Fetch all files from a repository matching patterns
250
- */
251
- async fetchRepositoryFiles(repoConfig) {
252
- const { owner, repo, branch, patterns, exclude } = repoConfig;
253
- logger.info(`Fetching files from ${owner}/${repo}...`);
254
- const allFiles = await this.getRepositoryTree(owner, repo, branch);
255
- const filteredFiles = this.filterFilesByPatterns(allFiles, patterns, exclude);
256
- logger.info(`Found ${filteredFiles.length} matching files in ${owner}/${repo}`);
257
- const files = [];
258
- for (const filePath of filteredFiles) {
259
- const file = await this.getFileContent(owner, repo, filePath, branch);
260
- if (file) {
261
- files.push(file);
262
- }
263
- }
264
- return files;
265
- }
266
- /**
267
- * Get recent commits
268
- */
269
- async getRecentCommits(owner, repo, since, perPage = 30) {
270
- try {
271
- const params = {
272
- owner,
273
- repo,
274
- per_page: perPage,
275
- };
276
- if (since) {
277
- params.since = since;
278
- }
279
- const { data } = await this.octokit.rest.repos.listCommits(params);
280
- return data.map((commit) => ({
281
- sha: commit.sha,
282
- message: commit.commit.message,
283
- author: commit.commit.author?.name || "Unknown",
284
- date: commit.commit.author?.date || "",
285
- url: commit.html_url,
286
- }));
287
- }
288
- catch (error) {
289
- logger.error(`Failed to get commits for ${owner}/${repo}`, {
290
- error: String(error),
291
- });
292
- return [];
293
- }
294
- }
295
- /**
296
- * Get files changed in recent commits
297
- */
298
- async getChangedFiles(owner, repo, since) {
299
- try {
300
- const commits = await this.getRecentCommits(owner, repo, since);
301
- const changedFiles = new Set();
302
- for (const commit of commits) {
303
- const { data } = await this.octokit.rest.repos.getCommit({
304
- owner,
305
- repo,
306
- ref: commit.sha,
307
- });
308
- data.files?.forEach((file) => {
309
- if (file.filename) {
310
- changedFiles.add(file.filename);
311
- }
312
- });
313
- }
314
- return Array.from(changedFiles);
315
- }
316
- catch (error) {
317
- logger.error(`Failed to get changed files for ${owner}/${repo}`, {
318
- error: String(error),
319
- });
320
- return [];
321
- }
322
- }
323
- /**
324
- * Search code in repositories
325
- */
326
- async searchCode(query, owner, repo, language) {
327
- try {
328
- let q = query;
329
- if (owner && repo) {
330
- q += ` repo:${owner}/${repo}`;
331
- }
332
- else if (owner) {
333
- q += ` user:${owner}`;
334
- }
335
- if (language) {
336
- q += ` language:${language}`;
337
- }
338
- const { data } = await this.octokit.rest.search.code({
339
- q,
340
- per_page: 30,
341
- });
342
- return data.items.map((item) => ({
343
- path: item.path,
344
- repository: item.repository.full_name,
345
- url: item.html_url,
346
- }));
347
- }
348
- catch (error) {
349
- logger.warn(`Code search failed for query: ${query}`, {
350
- error: String(error),
351
- });
352
- return [];
353
- }
354
- }
355
- /**
356
- * Get current rate limit status from GitHub API
357
- */
358
- async getRateLimit() {
359
- try {
360
- const { data } = await this.octokit.rest.rateLimit.get();
361
- const rateLimit = {
362
- limit: data.rate.limit,
363
- remaining: data.rate.remaining,
364
- reset: new Date(data.rate.reset * 1000),
365
- used: data.rate.used,
366
- };
367
- // Update the global rate limit tracker
368
- updateRateLimit(rateLimit);
369
- return rateLimit;
370
- }
371
- catch (error) {
372
- logger.warn("Failed to get rate limit", { error: String(error) });
373
- // Return defaults if we can't get rate limit
374
- return {
375
- limit: 60,
376
- remaining: 60,
377
- reset: new Date(Date.now() + 3600000),
378
- used: 0,
379
- };
380
- }
381
- }
382
- /**
383
- * Check if it's safe to make API requests
384
- */
385
- checkRateLimit() {
386
- const check = shouldProceedWithRequest();
387
- const status = getRateLimitStatus();
388
- if (!check.proceed) {
389
- logger.warn("Rate limit check failed", { reason: check.reason });
390
- }
391
- return {
392
- proceed: check.proceed,
393
- reason: check.reason,
394
- status,
395
- };
396
- }
397
- }
398
- export const githubClient = new GitHubClient();
399
- //# sourceMappingURL=github.js.map
@@ -1,11 +0,0 @@
1
- export { GitHubClient, githubClient } from "./github.js";
2
- export type { GitHubFile, GitHubCommit, RepositoryInfo } from "./github.js";
3
- export { parseFile, parseCompactFile, parseTypeScriptFile, parseMarkdownFile, } from "./parser.js";
4
- export type { ParsedFile, CodeUnit } from "./parser.js";
5
- export { EmbeddingGenerator, embeddingGenerator } from "./embeddings.js";
6
- export type { EmbeddingResult } from "./embeddings.js";
7
- export { indexRepository, indexAllRepositories, incrementalUpdate, } from "./indexer.js";
8
- export type { IndexStats } from "./indexer.js";
9
- export { ReleaseTracker, releaseTracker } from "./releases.js";
10
- export type { Release, ChangelogEntry, VersionInfo } from "./releases.js";
11
- //# sourceMappingURL=index.d.ts.map
@@ -1,6 +0,0 @@
1
- export { GitHubClient, githubClient } from "./github.js";
2
- export { parseFile, parseCompactFile, parseTypeScriptFile, parseMarkdownFile, } from "./parser.js";
3
- export { EmbeddingGenerator, embeddingGenerator } from "./embeddings.js";
4
- export { indexRepository, indexAllRepositories, incrementalUpdate, } from "./indexer.js";
5
- export { ReleaseTracker, releaseTracker } from "./releases.js";
6
- //# sourceMappingURL=index.js.map
@@ -1,41 +0,0 @@
1
- import { RepositoryConfig } from "../utils/index.js";
2
- export interface IndexStats {
3
- totalFiles: number;
4
- totalChunks: number;
5
- totalCodeUnits: number;
6
- repositoriesIndexed: string[];
7
- lastIndexed: string;
8
- }
9
- export interface ChunkMetadata {
10
- repository: string;
11
- filePath: string;
12
- language: string;
13
- chunkType: "code_unit" | "file_chunk";
14
- codeUnitType?: string;
15
- codeUnitName?: string;
16
- startLine: number;
17
- endLine: number;
18
- isPublic: boolean;
19
- repoVersion?: string;
20
- pragmaVersion?: string;
21
- indexedAt?: string;
22
- }
23
- /**
24
- * Index a single repository
25
- */
26
- export declare function indexRepository(repoConfig: RepositoryConfig): Promise<{
27
- fileCount: number;
28
- chunkCount: number;
29
- }>;
30
- /**
31
- * Index all configured repositories
32
- */
33
- export declare function indexAllRepositories(): Promise<IndexStats>;
34
- /**
35
- * Incremental update - only index changed files
36
- */
37
- export declare function incrementalUpdate(repoConfig: RepositoryConfig, since: string): Promise<{
38
- fileCount: number;
39
- chunkCount: number;
40
- }>;
41
- //# sourceMappingURL=indexer.d.ts.map