midnight-mcp 0.2.16 → 0.2.17
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/dist/bin.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
startHttpServer,
|
|
4
4
|
startServer
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-GDUMSS3E.js";
|
|
6
6
|
import {
|
|
7
7
|
setOutputFormat
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-S33OTE35.js";
|
|
9
9
|
|
|
10
10
|
// src/bin.ts
|
|
11
11
|
import { config } from "dotenv";
|
|
@@ -13,7 +13,7 @@ import { resolve } from "path";
|
|
|
13
13
|
import yargs from "yargs";
|
|
14
14
|
import { hideBin } from "yargs/helpers";
|
|
15
15
|
config({ path: resolve(process.cwd(), ".env") });
|
|
16
|
-
var CURRENT_VERSION = "0.2.
|
|
16
|
+
var CURRENT_VERSION = "0.2.17";
|
|
17
17
|
process.on("uncaughtException", (error) => {
|
|
18
18
|
console.error("Uncaught exception:", error);
|
|
19
19
|
process.exit(1);
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
validateNumber,
|
|
26
26
|
validateQuery,
|
|
27
27
|
vectorStore
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-S33OTE35.js";
|
|
29
29
|
|
|
30
30
|
// src/tools/search/schemas.ts
|
|
31
31
|
import { z } from "zod";
|
|
@@ -171,38 +171,53 @@ function finalizeResponse(response, cacheKey, warnings) {
|
|
|
171
171
|
});
|
|
172
172
|
return finalResponse;
|
|
173
173
|
}
|
|
174
|
-
async function
|
|
175
|
-
const validation = validateSearchInput(
|
|
174
|
+
async function performSearch(query, limit, config) {
|
|
175
|
+
const validation = validateSearchInput(query, limit);
|
|
176
176
|
if (!validation.success) {
|
|
177
177
|
return validation.error;
|
|
178
178
|
}
|
|
179
|
-
const { sanitizedQuery, limit, warnings } = validation.context;
|
|
180
|
-
logger.debug(
|
|
179
|
+
const { sanitizedQuery, limit: validatedLimit, warnings } = validation.context;
|
|
180
|
+
logger.debug(`Searching ${config.searchType}`, {
|
|
181
181
|
query: sanitizedQuery,
|
|
182
182
|
mode: isHostedMode() ? "hosted" : "local"
|
|
183
183
|
});
|
|
184
184
|
const cacheKey = createCacheKey(
|
|
185
|
-
|
|
185
|
+
config.searchType,
|
|
186
186
|
sanitizedQuery,
|
|
187
|
-
|
|
188
|
-
|
|
187
|
+
validatedLimit,
|
|
188
|
+
...config.cacheKeyExtra
|
|
189
189
|
);
|
|
190
190
|
const cached = checkSearchCache(cacheKey);
|
|
191
191
|
if (cached) return cached;
|
|
192
192
|
const hostedResult = await tryHostedSearch(
|
|
193
|
-
|
|
194
|
-
() =>
|
|
193
|
+
config.searchType,
|
|
194
|
+
() => config.hostedSearchFn(sanitizedQuery, validatedLimit),
|
|
195
195
|
cacheKey,
|
|
196
196
|
warnings
|
|
197
197
|
);
|
|
198
|
-
if (hostedResult)
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
198
|
+
if (hostedResult) {
|
|
199
|
+
return { ...hostedResult.result, ...config.hostedResultExtra };
|
|
200
|
+
}
|
|
201
|
+
const filter = config.buildFilter();
|
|
202
|
+
let results = await vectorStore.search(sanitizedQuery, validatedLimit, filter);
|
|
203
|
+
if (config.postFilter) {
|
|
204
|
+
results = config.postFilter(results);
|
|
205
|
+
}
|
|
204
206
|
const response = {
|
|
205
|
-
results: results.map(
|
|
207
|
+
results: results.map(config.transformResult),
|
|
208
|
+
totalResults: results.length,
|
|
209
|
+
query: sanitizedQuery,
|
|
210
|
+
...config.extraFields
|
|
211
|
+
};
|
|
212
|
+
return finalizeResponse(response, cacheKey, warnings);
|
|
213
|
+
}
|
|
214
|
+
async function searchCompact(input) {
|
|
215
|
+
return performSearch(input.query, input.limit, {
|
|
216
|
+
searchType: "compact",
|
|
217
|
+
cacheKeyExtra: [input.filter?.repository],
|
|
218
|
+
hostedSearchFn: (query, limit) => searchCompactHosted(query, limit),
|
|
219
|
+
buildFilter: () => ({ language: "compact", ...input.filter }),
|
|
220
|
+
transformResult: (r) => ({
|
|
206
221
|
code: r.content,
|
|
207
222
|
relevanceScore: r.score,
|
|
208
223
|
source: {
|
|
@@ -212,49 +227,19 @@ async function searchCompact(input) {
|
|
|
212
227
|
},
|
|
213
228
|
codeType: r.metadata.codeType,
|
|
214
229
|
name: r.metadata.codeName
|
|
215
|
-
})
|
|
216
|
-
|
|
217
|
-
query: sanitizedQuery
|
|
218
|
-
};
|
|
219
|
-
return finalizeResponse(response, cacheKey, warnings);
|
|
230
|
+
})
|
|
231
|
+
});
|
|
220
232
|
}
|
|
221
233
|
async function searchTypeScript(input) {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
query: sanitizedQuery,
|
|
229
|
-
mode: isHostedMode() ? "hosted" : "local"
|
|
230
|
-
});
|
|
231
|
-
const cacheKey = createCacheKey(
|
|
232
|
-
"typescript",
|
|
233
|
-
sanitizedQuery,
|
|
234
|
-
limit,
|
|
235
|
-
input.includeTypes
|
|
236
|
-
);
|
|
237
|
-
const cached = checkSearchCache(cacheKey);
|
|
238
|
-
if (cached) return cached;
|
|
239
|
-
const hostedResult = await tryHostedSearch(
|
|
240
|
-
"typescript",
|
|
241
|
-
() => searchTypeScriptHosted(sanitizedQuery, limit, input.includeTypes),
|
|
242
|
-
cacheKey,
|
|
243
|
-
warnings
|
|
244
|
-
);
|
|
245
|
-
if (hostedResult) return hostedResult.result;
|
|
246
|
-
const filter = {
|
|
247
|
-
language: "typescript"
|
|
248
|
-
};
|
|
249
|
-
const results = await vectorStore.search(sanitizedQuery, limit, filter);
|
|
250
|
-
let filteredResults = results;
|
|
251
|
-
if (!input.includeTypes) {
|
|
252
|
-
filteredResults = results.filter(
|
|
234
|
+
return performSearch(input.query, input.limit, {
|
|
235
|
+
searchType: "typescript",
|
|
236
|
+
cacheKeyExtra: [input.includeTypes],
|
|
237
|
+
hostedSearchFn: (query, limit) => searchTypeScriptHosted(query, limit, input.includeTypes),
|
|
238
|
+
buildFilter: () => ({ language: "typescript" }),
|
|
239
|
+
postFilter: (results) => input.includeTypes ? results : results.filter(
|
|
253
240
|
(r) => r.metadata.codeType !== "type" && r.metadata.codeType !== "interface"
|
|
254
|
-
)
|
|
255
|
-
|
|
256
|
-
const response = {
|
|
257
|
-
results: filteredResults.map((r) => ({
|
|
241
|
+
),
|
|
242
|
+
transformResult: (r) => ({
|
|
258
243
|
code: r.content,
|
|
259
244
|
relevanceScore: r.score,
|
|
260
245
|
source: {
|
|
@@ -265,49 +250,23 @@ async function searchTypeScript(input) {
|
|
|
265
250
|
codeType: r.metadata.codeType,
|
|
266
251
|
name: r.metadata.codeName,
|
|
267
252
|
isExported: r.metadata.isPublic
|
|
268
|
-
})
|
|
269
|
-
|
|
270
|
-
query: sanitizedQuery
|
|
271
|
-
};
|
|
272
|
-
return finalizeResponse(response, cacheKey, warnings);
|
|
253
|
+
})
|
|
254
|
+
});
|
|
273
255
|
}
|
|
274
256
|
async function searchDocs(input) {
|
|
275
|
-
const validation = validateSearchInput(input.query, input.limit);
|
|
276
|
-
if (!validation.success) {
|
|
277
|
-
return validation.error;
|
|
278
|
-
}
|
|
279
|
-
const { sanitizedQuery, limit, warnings } = validation.context;
|
|
280
|
-
logger.debug("Searching documentation", {
|
|
281
|
-
query: sanitizedQuery,
|
|
282
|
-
mode: isHostedMode() ? "hosted" : "local"
|
|
283
|
-
});
|
|
284
|
-
const cacheKey = createCacheKey(
|
|
285
|
-
"docs",
|
|
286
|
-
sanitizedQuery,
|
|
287
|
-
limit,
|
|
288
|
-
input.category
|
|
289
|
-
);
|
|
290
|
-
const cached = checkSearchCache(cacheKey);
|
|
291
|
-
if (cached) return cached;
|
|
292
257
|
const freshnessHint = "For guaranteed freshness, use midnight-fetch-docs with the path from these results (e.g., /develop/faq)";
|
|
293
|
-
|
|
294
|
-
"docs",
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
if (input.category !== "all") {
|
|
306
|
-
filter.repository = "midnightntwrk/midnight-docs";
|
|
307
|
-
}
|
|
308
|
-
const results = await vectorStore.search(sanitizedQuery, limit, filter);
|
|
309
|
-
const response = {
|
|
310
|
-
results: results.map((r) => ({
|
|
258
|
+
return performSearch(input.query, input.limit, {
|
|
259
|
+
searchType: "docs",
|
|
260
|
+
cacheKeyExtra: [input.category],
|
|
261
|
+
hostedSearchFn: (query, limit) => searchDocsHosted(query, limit, input.category),
|
|
262
|
+
buildFilter: () => {
|
|
263
|
+
const filter = { language: "markdown" };
|
|
264
|
+
if (input.category !== "all") {
|
|
265
|
+
filter.repository = "midnightntwrk/midnight-docs";
|
|
266
|
+
}
|
|
267
|
+
return filter;
|
|
268
|
+
},
|
|
269
|
+
transformResult: (r) => ({
|
|
311
270
|
content: r.content,
|
|
312
271
|
relevanceScore: r.score,
|
|
313
272
|
source: {
|
|
@@ -315,13 +274,13 @@ async function searchDocs(input) {
|
|
|
315
274
|
filePath: r.metadata.filePath,
|
|
316
275
|
section: r.metadata.codeName
|
|
317
276
|
}
|
|
318
|
-
})
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
277
|
+
}),
|
|
278
|
+
extraFields: {
|
|
279
|
+
category: input.category,
|
|
280
|
+
hint: freshnessHint
|
|
281
|
+
},
|
|
282
|
+
hostedResultExtra: { hint: freshnessHint }
|
|
283
|
+
});
|
|
325
284
|
}
|
|
326
285
|
var DOCS_BASE_URL = "https://docs.midnight.network";
|
|
327
286
|
var FETCH_TIMEOUT = 15e3;
|
|
@@ -354,7 +313,7 @@ function extractContentFromHtml(html, extractSection) {
|
|
|
354
313
|
const headingRegex = /<h([1-6])[^>]*class="[^"]*anchor[^"]*"[^>]*id="([^"]*)"[^>]*>([^<]*(?:<[^/][^>]*>[^<]*<\/[^>]+>)*[^<]*)/gi;
|
|
355
314
|
let headingMatch;
|
|
356
315
|
while ((headingMatch = headingRegex.exec(articleHtml)) !== null) {
|
|
357
|
-
const text = headingMatch[3].replace(/<[^>]+>/g, "").replace(/\u200B/g, "").
|
|
316
|
+
const text = headingMatch[3].replace(/<[^>]+>/g, "").replace(/\u200B/g, "").trim();
|
|
358
317
|
if (text) {
|
|
359
318
|
headings.push({
|
|
360
319
|
level: parseInt(headingMatch[1]),
|
|
@@ -406,7 +365,24 @@ async function fetchDocs(input) {
|
|
|
406
365
|
suggestion: `Use a clean path like '/develop/faq' or '/getting-started/installation'`
|
|
407
366
|
};
|
|
408
367
|
}
|
|
409
|
-
|
|
368
|
+
let url;
|
|
369
|
+
try {
|
|
370
|
+
const constructed = new URL(normalizedPath, DOCS_BASE_URL);
|
|
371
|
+
if (constructed.origin !== new URL(DOCS_BASE_URL).origin) {
|
|
372
|
+
return {
|
|
373
|
+
error: "Invalid path",
|
|
374
|
+
details: ["Path resulted in a URL outside the documentation domain"],
|
|
375
|
+
suggestion: `Use a clean path like '/develop/faq' or '/getting-started/installation'`
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
url = constructed.href;
|
|
379
|
+
} catch {
|
|
380
|
+
return {
|
|
381
|
+
error: "Invalid path",
|
|
382
|
+
details: ["Could not construct a valid URL from the path"],
|
|
383
|
+
suggestion: `Use a clean path like '/develop/faq' or '/getting-started/installation'`
|
|
384
|
+
};
|
|
385
|
+
}
|
|
410
386
|
logger.debug("Fetching live documentation", { url, extractSection });
|
|
411
387
|
try {
|
|
412
388
|
const controller = new AbortController();
|
|
@@ -800,7 +776,19 @@ async function compileContract(code, options = {}) {
|
|
|
800
776
|
serviceAvailable: response.status < 500
|
|
801
777
|
};
|
|
802
778
|
}
|
|
803
|
-
const
|
|
779
|
+
const rawResult = await response.json();
|
|
780
|
+
if (typeof rawResult !== "object" || rawResult === null || !("success" in rawResult)) {
|
|
781
|
+
logger.error("Compiler API returned unexpected response format", {
|
|
782
|
+
response: JSON.stringify(rawResult).slice(0, 200)
|
|
783
|
+
});
|
|
784
|
+
return {
|
|
785
|
+
success: false,
|
|
786
|
+
message: "Compiler service returned an unexpected response format",
|
|
787
|
+
error: "INVALID_RESPONSE",
|
|
788
|
+
serviceAvailable: true
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
const result = rawResult;
|
|
804
792
|
if (result.success) {
|
|
805
793
|
const outputInfo = typeof result.output === "object" && result.output !== null ? result.output : {};
|
|
806
794
|
logger.info("Compilation successful", {
|
|
@@ -1710,10 +1698,7 @@ var REPO_ALIASES = {
|
|
|
1710
1698
|
lucentlabs: { owner: "statera-protocol", repo: "statera-protocol-midnight" },
|
|
1711
1699
|
stablecoin: { owner: "statera-protocol", repo: "statera-protocol-midnight" },
|
|
1712
1700
|
"midnight-bank": { owner: "nel349", repo: "midnight-bank" },
|
|
1713
|
-
bank: { owner: "nel349", repo: "midnight-bank" }
|
|
1714
|
-
zkbadge: { owner: "Imdavyking", repo: "zkbadge" },
|
|
1715
|
-
badge: { owner: "Imdavyking", repo: "zkbadge" },
|
|
1716
|
-
davyking: { owner: "Imdavyking", repo: "zkbadge" }
|
|
1701
|
+
bank: { owner: "nel349", repo: "midnight-bank" }
|
|
1717
1702
|
};
|
|
1718
1703
|
var EXAMPLES = [
|
|
1719
1704
|
{
|
|
@@ -1837,21 +1822,6 @@ var EXAMPLES = [
|
|
|
1837
1822
|
"Private transfers"
|
|
1838
1823
|
]
|
|
1839
1824
|
},
|
|
1840
|
-
{
|
|
1841
|
-
name: "zkBadge (Davyking)",
|
|
1842
|
-
repository: "Imdavyking/zkbadge",
|
|
1843
|
-
description: "3rd place Mini DApp winner. Privacy-preserving identity and access control. Issue verifiable credentials (e.g., age proof) without revealing personal data. Only 'verified' status stored on-chain.",
|
|
1844
|
-
category: "identity",
|
|
1845
|
-
complexity: "intermediate",
|
|
1846
|
-
mainFile: "contract/src/zkbadge.compact",
|
|
1847
|
-
features: [
|
|
1848
|
-
"ZK credentials",
|
|
1849
|
-
"Off-chain verification",
|
|
1850
|
-
"On-chain badges",
|
|
1851
|
-
"Access control",
|
|
1852
|
-
"Reputation system"
|
|
1853
|
-
]
|
|
1854
|
-
},
|
|
1855
1825
|
// Core Partner - PaimaStudios (Gaming Infrastructure)
|
|
1856
1826
|
{
|
|
1857
1827
|
name: "Midnight Game 2 (PaimaStudios)",
|
|
@@ -4176,7 +4146,7 @@ async function getDocumentation(uri) {
|
|
|
4176
4146
|
if (file) {
|
|
4177
4147
|
return file.content;
|
|
4178
4148
|
}
|
|
4179
|
-
} catch (
|
|
4149
|
+
} catch (_error) {
|
|
4180
4150
|
logger.warn(`Could not fetch doc from GitHub: ${uri}`);
|
|
4181
4151
|
}
|
|
4182
4152
|
}
|
|
@@ -4282,7 +4252,7 @@ async function getCode(uri) {
|
|
|
4282
4252
|
return file.content;
|
|
4283
4253
|
}
|
|
4284
4254
|
}
|
|
4285
|
-
} catch (
|
|
4255
|
+
} catch (_error) {
|
|
4286
4256
|
logger.warn(`Could not fetch code from GitHub: ${uri}`);
|
|
4287
4257
|
}
|
|
4288
4258
|
}
|
|
@@ -5198,7 +5168,8 @@ async function requestCompletion(messages, options = {}) {
|
|
|
5198
5168
|
);
|
|
5199
5169
|
markSamplingFailed();
|
|
5200
5170
|
throw new Error(
|
|
5201
|
-
"Sampling not supported by this client - use Claude Desktop for this feature"
|
|
5171
|
+
"Sampling not supported by this client - use Claude Desktop for this feature",
|
|
5172
|
+
{ cause: error }
|
|
5202
5173
|
);
|
|
5203
5174
|
}
|
|
5204
5175
|
throw error;
|
|
@@ -5880,7 +5851,10 @@ async function checkForUpdates() {
|
|
|
5880
5851
|
lastChecked: Date.now()
|
|
5881
5852
|
};
|
|
5882
5853
|
}
|
|
5883
|
-
} catch {
|
|
5854
|
+
} catch (error) {
|
|
5855
|
+
logger.debug("Version check failed (non-blocking)", {
|
|
5856
|
+
error: error instanceof Error ? error.message : String(error)
|
|
5857
|
+
});
|
|
5884
5858
|
}
|
|
5885
5859
|
}
|
|
5886
5860
|
function maybeCheckForUpdates() {
|
|
@@ -5889,7 +5863,10 @@ function maybeCheckForUpdates() {
|
|
|
5889
5863
|
toolCallCount = 0;
|
|
5890
5864
|
const fiveMinutes = 5 * 60 * 1e3;
|
|
5891
5865
|
if (Date.now() - versionCheckResult.lastChecked > fiveMinutes) {
|
|
5892
|
-
checkForUpdates().catch(() => {
|
|
5866
|
+
checkForUpdates().catch((error) => {
|
|
5867
|
+
logger.debug("Periodic version check failed", {
|
|
5868
|
+
error: error instanceof Error ? error.message : String(error)
|
|
5869
|
+
});
|
|
5893
5870
|
});
|
|
5894
5871
|
}
|
|
5895
5872
|
}
|
|
@@ -5956,7 +5933,10 @@ function sendLogToClient(level, loggerName, data) {
|
|
|
5956
5933
|
data
|
|
5957
5934
|
}
|
|
5958
5935
|
});
|
|
5959
|
-
} catch {
|
|
5936
|
+
} catch (error) {
|
|
5937
|
+
logger.debug("Failed to send log notification to client", {
|
|
5938
|
+
error: error instanceof Error ? error.message : String(error)
|
|
5939
|
+
});
|
|
5960
5940
|
}
|
|
5961
5941
|
}
|
|
5962
5942
|
function sendProgressNotification(progressToken, progress, total, message) {
|
|
@@ -5971,7 +5951,10 @@ function sendProgressNotification(progressToken, progress, total, message) {
|
|
|
5971
5951
|
...message && { message }
|
|
5972
5952
|
}
|
|
5973
5953
|
});
|
|
5974
|
-
} catch {
|
|
5954
|
+
} catch (error) {
|
|
5955
|
+
logger.debug("Failed to send progress notification", {
|
|
5956
|
+
error: error instanceof Error ? error.message : String(error)
|
|
5957
|
+
});
|
|
5975
5958
|
}
|
|
5976
5959
|
}
|
|
5977
5960
|
function createServer() {
|
|
@@ -6404,7 +6387,10 @@ function setupSampling(server) {
|
|
|
6404
6387
|
}
|
|
6405
6388
|
async function initializeServer() {
|
|
6406
6389
|
logger.info("Initializing Midnight MCP Server...");
|
|
6407
|
-
checkForUpdates().catch(() => {
|
|
6390
|
+
checkForUpdates().catch((error) => {
|
|
6391
|
+
logger.debug("Startup version check failed (non-blocking)", {
|
|
6392
|
+
error: error instanceof Error ? error.message : String(error)
|
|
6393
|
+
});
|
|
6408
6394
|
});
|
|
6409
6395
|
try {
|
|
6410
6396
|
await vectorStore.initialize();
|
|
@@ -7874,7 +7860,7 @@ async function getFile(input) {
|
|
|
7874
7860
|
);
|
|
7875
7861
|
}
|
|
7876
7862
|
let content = file.content;
|
|
7877
|
-
|
|
7863
|
+
const totalLines = content.split("\n").length;
|
|
7878
7864
|
let lineRange;
|
|
7879
7865
|
if (input.startLine || input.endLine) {
|
|
7880
7866
|
const lines = content.split("\n");
|
|
@@ -11186,4 +11172,4 @@ export {
|
|
|
11186
11172
|
startServer,
|
|
11187
11173
|
startHttpServer
|
|
11188
11174
|
};
|
|
11189
|
-
//# sourceMappingURL=chunk-
|
|
11175
|
+
//# sourceMappingURL=chunk-GDUMSS3E.js.map
|
|
@@ -245,13 +245,6 @@ var DEFAULT_REPOSITORIES = [
|
|
|
245
245
|
patterns: ["**/*.compact", "**/*.ts", "**/*.md"],
|
|
246
246
|
exclude: ["node_modules/**", "dist/**"]
|
|
247
247
|
},
|
|
248
|
-
{
|
|
249
|
-
owner: "Imdavyking",
|
|
250
|
-
repo: "zkbadge",
|
|
251
|
-
branch: "main",
|
|
252
|
-
patterns: ["**/*.compact", "**/*.ts", "**/*.md"],
|
|
253
|
-
exclude: ["node_modules/**", "dist/**"]
|
|
254
|
-
},
|
|
255
248
|
// Core Partner - PaimaStudios (Gaming Infrastructure)
|
|
256
249
|
{
|
|
257
250
|
owner: "PaimaStudios",
|
|
@@ -858,13 +851,15 @@ var GitHubClient = class {
|
|
|
858
851
|
* This is safe because malicious patterns could only come from internal config.
|
|
859
852
|
*/
|
|
860
853
|
filterFilesByPatterns(files, patterns, exclude) {
|
|
861
|
-
const
|
|
854
|
+
const compilePattern = (pattern) => {
|
|
862
855
|
const regexPattern = pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*").replace(/\./g, "\\.");
|
|
863
|
-
return new RegExp(`^${regexPattern}$`)
|
|
856
|
+
return new RegExp(`^${regexPattern}$`);
|
|
864
857
|
};
|
|
858
|
+
const includeRegexes = patterns.map(compilePattern);
|
|
859
|
+
const excludeRegexes = exclude.map(compilePattern);
|
|
865
860
|
return files.filter((file) => {
|
|
866
|
-
const matchesInclude =
|
|
867
|
-
const matchesExclude =
|
|
861
|
+
const matchesInclude = includeRegexes.some((re) => re.test(file));
|
|
862
|
+
const matchesExclude = excludeRegexes.some((re) => re.test(file));
|
|
868
863
|
return matchesInclude && !matchesExclude;
|
|
869
864
|
});
|
|
870
865
|
}
|
|
@@ -883,11 +878,19 @@ var GitHubClient = class {
|
|
|
883
878
|
logger.info(
|
|
884
879
|
`Found ${filteredFiles.length} matching files in ${owner}/${repo}`
|
|
885
880
|
);
|
|
881
|
+
const BATCH_SIZE = 5;
|
|
886
882
|
const files = [];
|
|
887
|
-
for (
|
|
888
|
-
const
|
|
889
|
-
|
|
890
|
-
|
|
883
|
+
for (let i = 0; i < filteredFiles.length; i += BATCH_SIZE) {
|
|
884
|
+
const batch = filteredFiles.slice(i, i + BATCH_SIZE);
|
|
885
|
+
const results = await Promise.all(
|
|
886
|
+
batch.map(
|
|
887
|
+
(filePath) => this.getFileContent(owner, repo, filePath, branch)
|
|
888
|
+
)
|
|
889
|
+
);
|
|
890
|
+
for (const file of results) {
|
|
891
|
+
if (file) {
|
|
892
|
+
files.push(file);
|
|
893
|
+
}
|
|
891
894
|
}
|
|
892
895
|
}
|
|
893
896
|
return files;
|
|
@@ -1232,9 +1235,18 @@ var EmbeddingGenerator = class {
|
|
|
1232
1235
|
model: this.model,
|
|
1233
1236
|
input: text
|
|
1234
1237
|
});
|
|
1238
|
+
const embedding = response.data[0].embedding;
|
|
1239
|
+
const EXPECTED_DIMENSIONS = 1536;
|
|
1240
|
+
if (!embedding || embedding.length !== EXPECTED_DIMENSIONS) {
|
|
1241
|
+
logger.warn("Unexpected embedding dimensions", {
|
|
1242
|
+
expected: EXPECTED_DIMENSIONS,
|
|
1243
|
+
actual: embedding?.length ?? 0,
|
|
1244
|
+
model: this.model
|
|
1245
|
+
});
|
|
1246
|
+
}
|
|
1235
1247
|
return {
|
|
1236
1248
|
text,
|
|
1237
|
-
embedding
|
|
1249
|
+
embedding,
|
|
1238
1250
|
model: this.model,
|
|
1239
1251
|
tokenCount: response.usage?.total_tokens
|
|
1240
1252
|
};
|
|
@@ -1593,7 +1605,7 @@ var releaseTracker = new ReleaseTracker();
|
|
|
1593
1605
|
|
|
1594
1606
|
// src/utils/health.ts
|
|
1595
1607
|
var startTime = Date.now();
|
|
1596
|
-
var VERSION = "0.2.
|
|
1608
|
+
var VERSION = "0.2.17";
|
|
1597
1609
|
async function checkGitHubAPI() {
|
|
1598
1610
|
const start = Date.now();
|
|
1599
1611
|
try {
|
|
@@ -1621,7 +1633,7 @@ async function checkGitHubAPI() {
|
|
|
1621
1633
|
}
|
|
1622
1634
|
async function checkVectorStore() {
|
|
1623
1635
|
try {
|
|
1624
|
-
const { vectorStore: vectorStore2 } = await import("./db-
|
|
1636
|
+
const { vectorStore: vectorStore2 } = await import("./db-SWEQRS2S.js");
|
|
1625
1637
|
if (vectorStore2) {
|
|
1626
1638
|
return {
|
|
1627
1639
|
status: "pass",
|
|
@@ -1806,6 +1818,9 @@ var Cache = class {
|
|
|
1806
1818
|
if (this.cache.size >= this.options.maxSize) {
|
|
1807
1819
|
this.evictOldest();
|
|
1808
1820
|
}
|
|
1821
|
+
if (this.cache.size > 0 && this.cache.size % 100 === 0) {
|
|
1822
|
+
this.prune();
|
|
1823
|
+
}
|
|
1809
1824
|
const now = Date.now();
|
|
1810
1825
|
this.cache.set(key, {
|
|
1811
1826
|
value,
|
|
@@ -1917,12 +1932,6 @@ var metadataCache = new Cache({
|
|
|
1917
1932
|
maxSize: 100,
|
|
1918
1933
|
name: "metadata"
|
|
1919
1934
|
});
|
|
1920
|
-
function pruneAllCaches() {
|
|
1921
|
-
searchCache.prune();
|
|
1922
|
-
fileCache.prune();
|
|
1923
|
-
metadataCache.prune();
|
|
1924
|
-
}
|
|
1925
|
-
setInterval(pruneAllCaches, 5 * 60 * 1e3);
|
|
1926
1935
|
|
|
1927
1936
|
// src/utils/hosted-api.ts
|
|
1928
1937
|
var API_TIMEOUT = 15e3;
|
|
@@ -1991,7 +2000,8 @@ async function makeRequest(url, endpoint, options) {
|
|
|
1991
2000
|
} catch (error) {
|
|
1992
2001
|
if (error instanceof Error && error.name === "AbortError") {
|
|
1993
2002
|
throw new Error(
|
|
1994
|
-
`Request to ${endpoint} timed out after ${API_TIMEOUT / 1e3}s
|
|
2003
|
+
`Request to ${endpoint} timed out after ${API_TIMEOUT / 1e3}s.`,
|
|
2004
|
+
{ cause: error }
|
|
1995
2005
|
);
|
|
1996
2006
|
}
|
|
1997
2007
|
throw error;
|
|
@@ -2065,7 +2075,10 @@ function trackToolCall(tool, success, durationMs, version) {
|
|
|
2065
2075
|
apiRequest("/v1/track/tool", {
|
|
2066
2076
|
method: "POST",
|
|
2067
2077
|
body: JSON.stringify({ tool, success, durationMs, version })
|
|
2068
|
-
}).catch(() => {
|
|
2078
|
+
}).catch((error) => {
|
|
2079
|
+
logger.debug("Tracking call failed (non-blocking)", {
|
|
2080
|
+
error: String(error)
|
|
2081
|
+
});
|
|
2069
2082
|
});
|
|
2070
2083
|
}
|
|
2071
2084
|
|
|
@@ -2096,7 +2109,7 @@ function serialize(data) {
|
|
|
2096
2109
|
}
|
|
2097
2110
|
|
|
2098
2111
|
// src/utils/version.ts
|
|
2099
|
-
var CURRENT_VERSION = "0.2.
|
|
2112
|
+
var CURRENT_VERSION = "0.2.17";
|
|
2100
2113
|
|
|
2101
2114
|
// src/db/vectorStore.ts
|
|
2102
2115
|
var VectorStore = class {
|
|
@@ -2137,9 +2150,23 @@ var VectorStore = class {
|
|
|
2137
2150
|
return;
|
|
2138
2151
|
}
|
|
2139
2152
|
try {
|
|
2140
|
-
const
|
|
2141
|
-
|
|
2142
|
-
|
|
2153
|
+
const validDocuments = documents.filter((d) => {
|
|
2154
|
+
if (!d.embedding || d.embedding.length === 0) {
|
|
2155
|
+
logger.warn("Document missing embedding, skipping", {
|
|
2156
|
+
id: d.id,
|
|
2157
|
+
filePath: d.metadata.filePath
|
|
2158
|
+
});
|
|
2159
|
+
return false;
|
|
2160
|
+
}
|
|
2161
|
+
return true;
|
|
2162
|
+
});
|
|
2163
|
+
if (validDocuments.length === 0) {
|
|
2164
|
+
logger.warn("No documents with valid embeddings to store");
|
|
2165
|
+
return;
|
|
2166
|
+
}
|
|
2167
|
+
const ids = validDocuments.map((d) => d.id);
|
|
2168
|
+
const embeddings = validDocuments.map((d) => d.embedding);
|
|
2169
|
+
const metadatas = validDocuments.map((d) => ({
|
|
2143
2170
|
repository: d.metadata.repository,
|
|
2144
2171
|
filePath: d.metadata.filePath,
|
|
2145
2172
|
language: d.metadata.language,
|
|
@@ -2149,14 +2176,14 @@ var VectorStore = class {
|
|
|
2149
2176
|
codeName: d.metadata.codeName,
|
|
2150
2177
|
isPublic: d.metadata.isPublic
|
|
2151
2178
|
}));
|
|
2152
|
-
const documentContents =
|
|
2179
|
+
const documentContents = validDocuments.map((d) => d.content);
|
|
2153
2180
|
await this.collection.add({
|
|
2154
2181
|
ids,
|
|
2155
2182
|
embeddings,
|
|
2156
2183
|
metadatas,
|
|
2157
2184
|
documents: documentContents
|
|
2158
2185
|
});
|
|
2159
|
-
logger.debug(`Added ${
|
|
2186
|
+
logger.debug(`Added ${validDocuments.length} documents to vector store`);
|
|
2160
2187
|
} catch (error) {
|
|
2161
2188
|
logger.error("Failed to add documents to vector store", {
|
|
2162
2189
|
error: String(error)
|
|
@@ -2305,4 +2332,4 @@ export {
|
|
|
2305
2332
|
serialize,
|
|
2306
2333
|
CURRENT_VERSION
|
|
2307
2334
|
};
|
|
2308
|
-
//# sourceMappingURL=chunk-
|
|
2335
|
+
//# sourceMappingURL=chunk-S33OTE35.js.map
|
package/dist/index.js
CHANGED
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
promptDefinitions,
|
|
10
10
|
startHttpServer,
|
|
11
11
|
startServer
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-GDUMSS3E.js";
|
|
13
13
|
import {
|
|
14
14
|
logger
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-S33OTE35.js";
|
|
16
16
|
export {
|
|
17
17
|
allResources,
|
|
18
18
|
allTools,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "midnight-mcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.17",
|
|
4
4
|
"description": "Model Context Protocol Server for Midnight Blockchain Development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -15,9 +15,11 @@
|
|
|
15
15
|
"dev": "NODE_ENV=development tsup --watch",
|
|
16
16
|
"test": "vitest",
|
|
17
17
|
"test:coverage": "vitest --coverage",
|
|
18
|
+
"lint": "eslint src/",
|
|
19
|
+
"lint:fix": "eslint src/ --fix",
|
|
18
20
|
"format": "prettier --write src/**/*.ts",
|
|
19
21
|
"prepublishOnly": "npm run typecheck && npm run build",
|
|
20
|
-
"ci": "npm run typecheck && npm run build && npm test"
|
|
22
|
+
"ci": "npm run typecheck && npm run lint && npm run build && npm test"
|
|
21
23
|
},
|
|
22
24
|
"keywords": [
|
|
23
25
|
"midnight",
|
|
@@ -43,16 +45,19 @@
|
|
|
43
45
|
"zod": "^3.22.4"
|
|
44
46
|
},
|
|
45
47
|
"devDependencies": {
|
|
48
|
+
"@eslint/js": "^10.0.1",
|
|
46
49
|
"@types/express": "^5.0.6",
|
|
47
50
|
"@types/js-yaml": "^4.0.9",
|
|
48
51
|
"@types/node": "^20.10.0",
|
|
49
52
|
"@types/tar": "^6.1.13",
|
|
50
53
|
"@types/yargs": "^17.0.35",
|
|
54
|
+
"eslint": "^10.0.2",
|
|
51
55
|
"prettier": "^3.1.0",
|
|
52
56
|
"tar": "^7.5.2",
|
|
53
57
|
"tsup": "^8.5.1",
|
|
54
58
|
"tsx": "^4.6.2",
|
|
55
59
|
"typescript": "^5.3.2",
|
|
60
|
+
"typescript-eslint": "^8.56.1",
|
|
56
61
|
"vitest": "^1.0.0"
|
|
57
62
|
},
|
|
58
63
|
"engines": {
|