midnight-mcp 0.2.6 → 0.2.8
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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Midnight MCP Server
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/midnight-mcp)
|
|
4
|
-
[](https://
|
|
4
|
+
[](https://npm-stat.com/charts.html?package=midnight-mcp)
|
|
5
5
|
[](./LICENSE)
|
|
6
6
|
[](https://www.typescriptlang.org/)
|
|
7
7
|
[](https://github.com/Olanetsoft/midnight-mcp/actions/workflows/ci.yml)
|
|
@@ -264,4 +264,6 @@ The hosted API runs on Cloudflare Workers + Vectorize. See [api/README.md](./api
|
|
|
264
264
|
|
|
265
265
|
MIT
|
|
266
266
|
|
|
267
|
-
|
|
267
|
+
## Stargazers ⭐️
|
|
268
|
+
|
|
269
|
+
[](https://star-history.com/#Olanetsoft/midnight-mcp&Date)
|
package/dist/bin.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
startHttpServer,
|
|
4
4
|
startServer
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-QPQOD3S6.js";
|
|
6
6
|
import {
|
|
7
7
|
setOutputFormat
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-VQTI7YUU.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.8";
|
|
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-VQTI7YUU.js";
|
|
29
29
|
|
|
30
30
|
// src/tools/search/schemas.ts
|
|
31
31
|
import { z } from "zod";
|
|
@@ -794,8 +794,18 @@ async function explainCircuit(input) {
|
|
|
794
794
|
const circuit = parsed.codeUnits.find((u) => u.type === "circuit");
|
|
795
795
|
if (!circuit) {
|
|
796
796
|
return {
|
|
797
|
-
|
|
798
|
-
|
|
797
|
+
circuitName: "unknown",
|
|
798
|
+
isPublic: false,
|
|
799
|
+
parameters: [],
|
|
800
|
+
returnType: "unknown",
|
|
801
|
+
explanation: "No circuit definition found in the provided code. Make sure to provide a complete circuit definition including the 'circuit' keyword.",
|
|
802
|
+
operations: [],
|
|
803
|
+
zkImplications: [
|
|
804
|
+
"Unable to analyze - no valid circuit found in the provided code"
|
|
805
|
+
],
|
|
806
|
+
privacyConsiderations: [
|
|
807
|
+
"Provide a complete circuit definition for privacy analysis"
|
|
808
|
+
]
|
|
799
809
|
};
|
|
800
810
|
}
|
|
801
811
|
const operations = [];
|
|
@@ -1115,7 +1125,13 @@ var GetFileInputSchema = z3.object({
|
|
|
1115
1125
|
"Repository name (e.g., 'compact', 'midnight-js', 'example-counter')"
|
|
1116
1126
|
),
|
|
1117
1127
|
path: z3.string().describe("File path within repository"),
|
|
1118
|
-
ref: z3.string().optional().describe("Branch, tag, or commit SHA (default: main)")
|
|
1128
|
+
ref: z3.string().optional().describe("Branch, tag, or commit SHA (default: main)"),
|
|
1129
|
+
startLine: z3.number().int().positive().optional().describe(
|
|
1130
|
+
"Start line number (1-based, inclusive). Use to request specific sections of large files."
|
|
1131
|
+
),
|
|
1132
|
+
endLine: z3.number().int().positive().optional().describe(
|
|
1133
|
+
"End line number (1-based, inclusive). Use with startLine to get a specific range."
|
|
1134
|
+
)
|
|
1119
1135
|
});
|
|
1120
1136
|
var ListExamplesInputSchema = z3.object({
|
|
1121
1137
|
category: z3.enum(["counter", "bboard", "token", "voting", "all"]).optional().default("all").describe("Filter by example type")
|
|
@@ -4530,15 +4546,22 @@ Please help me debug by:
|
|
|
4530
4546
|
|
|
4531
4547
|
// src/services/sampling.ts
|
|
4532
4548
|
var samplingCallback = null;
|
|
4549
|
+
var samplingFailedPermanently = false;
|
|
4533
4550
|
function isSamplingAvailable() {
|
|
4551
|
+
if (samplingFailedPermanently) return false;
|
|
4534
4552
|
return samplingCallback !== null;
|
|
4535
4553
|
}
|
|
4554
|
+
function markSamplingFailed() {
|
|
4555
|
+
samplingFailedPermanently = true;
|
|
4556
|
+
logger.warn("Sampling marked as permanently unavailable for this session");
|
|
4557
|
+
}
|
|
4536
4558
|
function registerSamplingCallback(callback) {
|
|
4537
4559
|
samplingCallback = callback;
|
|
4560
|
+
samplingFailedPermanently = false;
|
|
4538
4561
|
logger.info("Sampling capability registered");
|
|
4539
4562
|
}
|
|
4540
4563
|
async function requestCompletion(messages, options = {}) {
|
|
4541
|
-
if (!samplingCallback) {
|
|
4564
|
+
if (!samplingCallback || samplingFailedPermanently) {
|
|
4542
4565
|
throw new Error(
|
|
4543
4566
|
"Sampling not available - client does not support this capability"
|
|
4544
4567
|
);
|
|
@@ -4561,11 +4584,25 @@ async function requestCompletion(messages, options = {}) {
|
|
|
4561
4584
|
messageCount: messages.length,
|
|
4562
4585
|
maxTokens: request.maxTokens
|
|
4563
4586
|
});
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4587
|
+
try {
|
|
4588
|
+
const response = await samplingCallback(request);
|
|
4589
|
+
if (response.content.type !== "text") {
|
|
4590
|
+
throw new Error("Unexpected response content type");
|
|
4591
|
+
}
|
|
4592
|
+
return response.content.text;
|
|
4593
|
+
} catch (error) {
|
|
4594
|
+
const errorStr = String(error);
|
|
4595
|
+
if (errorStr.includes("-32601") || errorStr.includes("Method not found") || errorStr.includes("not supported")) {
|
|
4596
|
+
logger.warn(
|
|
4597
|
+
"Client does not support sampling/createMessage, disabling sampling for this session"
|
|
4598
|
+
);
|
|
4599
|
+
markSamplingFailed();
|
|
4600
|
+
throw new Error(
|
|
4601
|
+
"Sampling not supported by this client - use Claude Desktop for this feature"
|
|
4602
|
+
);
|
|
4603
|
+
}
|
|
4604
|
+
throw error;
|
|
4567
4605
|
}
|
|
4568
|
-
return response.content.text;
|
|
4569
4606
|
}
|
|
4570
4607
|
async function generateContract(requirements, options = {}) {
|
|
4571
4608
|
if (!isSamplingAvailable()) {
|
|
@@ -5164,6 +5201,17 @@ function registerResourceHandlers(server) {
|
|
|
5164
5201
|
"midnight://schema/"
|
|
5165
5202
|
];
|
|
5166
5203
|
const validPrefix = resourceTypes.find((p) => uri.startsWith(p));
|
|
5204
|
+
let suggestion = validPrefix ? `Check the resource path after '${validPrefix}'` : `Valid resource prefixes: ${resourceTypes.join(", ")}`;
|
|
5205
|
+
if (uri.includes("://resources/")) {
|
|
5206
|
+
const resourceName = uri.split("://resources/").pop() || "";
|
|
5207
|
+
if (resourceName.includes("template") || resourceName.includes("pattern") || resourceName.includes("example")) {
|
|
5208
|
+
suggestion = `Try: midnight://code/templates/${resourceName} or midnight://code/examples/${resourceName} or midnight://code/patterns/${resourceName}`;
|
|
5209
|
+
} else if (resourceName.includes("doc") || resourceName.includes("reference") || resourceName.includes("guide")) {
|
|
5210
|
+
suggestion = `Try: midnight://docs/${resourceName}`;
|
|
5211
|
+
} else {
|
|
5212
|
+
suggestion = `'midnight://resources/' is not valid. Use: midnight://docs/, midnight://code/, or midnight://schema/`;
|
|
5213
|
+
}
|
|
5214
|
+
}
|
|
5167
5215
|
return {
|
|
5168
5216
|
contents: [
|
|
5169
5217
|
{
|
|
@@ -5171,8 +5219,9 @@ function registerResourceHandlers(server) {
|
|
|
5171
5219
|
mimeType: "application/json",
|
|
5172
5220
|
text: serialize({
|
|
5173
5221
|
error: `Resource not found: ${uri}`,
|
|
5174
|
-
suggestion
|
|
5175
|
-
hint: "Use ListResources to see all available resources"
|
|
5222
|
+
suggestion,
|
|
5223
|
+
hint: "Use ListResources to see all available resources",
|
|
5224
|
+
validPrefixes: resourceTypes
|
|
5176
5225
|
})
|
|
5177
5226
|
}
|
|
5178
5227
|
]
|
|
@@ -6525,8 +6574,112 @@ function resolveRepo(repoName) {
|
|
|
6525
6574
|
}
|
|
6526
6575
|
return null;
|
|
6527
6576
|
}
|
|
6577
|
+
var MAX_FILE_CONTENT_LENGTH = 5e4;
|
|
6578
|
+
var TRUNCATION_RATIOS = {
|
|
6579
|
+
compact: { top: 0.8, bottom: 0.2 },
|
|
6580
|
+
// 40KB top, 10KB bottom
|
|
6581
|
+
typescript: { top: 0.5, bottom: 0.5 },
|
|
6582
|
+
// 25KB each
|
|
6583
|
+
javascript: { top: 0.5, bottom: 0.5 },
|
|
6584
|
+
default: { top: 0.6, bottom: 0.4 }
|
|
6585
|
+
// Slight preference for top
|
|
6586
|
+
};
|
|
6587
|
+
function detectLanguage(filePath) {
|
|
6588
|
+
const ext = filePath.split(".").pop()?.toLowerCase();
|
|
6589
|
+
switch (ext) {
|
|
6590
|
+
case "compact":
|
|
6591
|
+
return "compact";
|
|
6592
|
+
case "ts":
|
|
6593
|
+
case "tsx":
|
|
6594
|
+
return "typescript";
|
|
6595
|
+
case "js":
|
|
6596
|
+
case "jsx":
|
|
6597
|
+
case "mjs":
|
|
6598
|
+
return "javascript";
|
|
6599
|
+
default:
|
|
6600
|
+
return "default";
|
|
6601
|
+
}
|
|
6602
|
+
}
|
|
6603
|
+
function smartTruncate(content, filePath = "", maxLength = MAX_FILE_CONTENT_LENGTH) {
|
|
6604
|
+
if (content.length <= maxLength) {
|
|
6605
|
+
return { content, truncated: false };
|
|
6606
|
+
}
|
|
6607
|
+
const language = detectLanguage(filePath);
|
|
6608
|
+
const ratio = TRUNCATION_RATIOS[language] || TRUNCATION_RATIOS.default;
|
|
6609
|
+
const lines = content.split("\n");
|
|
6610
|
+
const totalLines = lines.length;
|
|
6611
|
+
const topLength = Math.floor(maxLength * ratio.top);
|
|
6612
|
+
const bottomLength = maxLength - topLength;
|
|
6613
|
+
const firstPart = content.slice(0, topLength);
|
|
6614
|
+
const lastPart = content.slice(-bottomLength);
|
|
6615
|
+
const omittedBytes = content.length - maxLength;
|
|
6616
|
+
const firstPartLines = firstPart.split("\n").length;
|
|
6617
|
+
const lastPartLines = lastPart.split("\n").length;
|
|
6618
|
+
const omittedStartLine = firstPartLines + 1;
|
|
6619
|
+
const omittedEndLine = totalLines - lastPartLines;
|
|
6620
|
+
const languageContext = language === "compact" ? "Compact files: pragma and imports preserved at top (critical for compilation)" : language === "typescript" || language === "javascript" ? "TS/JS files: balanced truncation preserves imports AND exports" : "Balanced truncation applied";
|
|
6621
|
+
const truncatedContent = firstPart + `
|
|
6622
|
+
|
|
6623
|
+
/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
6624
|
+
CONTENT TRUNCATED: Lines ${omittedStartLine}-${omittedEndLine} omitted (${omittedBytes.toLocaleString()} bytes)
|
|
6625
|
+
${languageContext}
|
|
6626
|
+
|
|
6627
|
+
To get the omitted content, call this tool again with:
|
|
6628
|
+
- startLine: ${omittedStartLine}, endLine: ${Math.min(omittedStartLine + 200, omittedEndLine)} (first part of omitted)
|
|
6629
|
+
- startLine: ${Math.max(omittedStartLine, omittedEndLine - 200)}, endLine: ${omittedEndLine} (last part of omitted)
|
|
6630
|
+
|
|
6631
|
+
Or request the full middle section:
|
|
6632
|
+
- startLine: ${omittedStartLine}, endLine: ${omittedEndLine}
|
|
6633
|
+
\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
|
|
6634
|
+
|
|
6635
|
+
` + lastPart;
|
|
6636
|
+
return {
|
|
6637
|
+
content: truncatedContent,
|
|
6638
|
+
truncated: true,
|
|
6639
|
+
truncationInfo: {
|
|
6640
|
+
originalSize: content.length,
|
|
6641
|
+
keptBytes: maxLength,
|
|
6642
|
+
omittedBytes,
|
|
6643
|
+
keptLineRanges: [
|
|
6644
|
+
{ start: 1, end: firstPartLines },
|
|
6645
|
+
{ start: totalLines - lastPartLines + 1, end: totalLines }
|
|
6646
|
+
],
|
|
6647
|
+
omittedLineRange: { start: omittedStartLine, end: omittedEndLine },
|
|
6648
|
+
language,
|
|
6649
|
+
ratioUsed: ratio
|
|
6650
|
+
},
|
|
6651
|
+
agentGuidance: {
|
|
6652
|
+
whatYouHave: `Lines 1-${firstPartLines} (${Math.round(ratio.top * 100)}% from top) and lines ${totalLines - lastPartLines + 1}-${totalLines} (${Math.round(ratio.bottom * 100)}% from bottom)`,
|
|
6653
|
+
whatIsMissing: `Lines ${omittedStartLine}-${omittedEndLine} (${omittedEndLine - omittedStartLine + 1} lines, ${omittedBytes.toLocaleString()} bytes)`,
|
|
6654
|
+
howToGetMore: [
|
|
6655
|
+
`Call midnight-get-file again with startLine and endLine parameters`,
|
|
6656
|
+
`The omitted content is in the middle of the file`,
|
|
6657
|
+
`You can request it in chunks (e.g., 200 lines at a time) or all at once`
|
|
6658
|
+
],
|
|
6659
|
+
suggestedNextCalls: [
|
|
6660
|
+
{
|
|
6661
|
+
startLine: omittedStartLine,
|
|
6662
|
+
endLine: Math.min(omittedStartLine + 199, omittedEndLine),
|
|
6663
|
+
reason: "First chunk of omitted content"
|
|
6664
|
+
},
|
|
6665
|
+
...omittedEndLine - omittedStartLine > 200 ? [
|
|
6666
|
+
{
|
|
6667
|
+
startLine: Math.max(omittedStartLine, omittedEndLine - 199),
|
|
6668
|
+
endLine: omittedEndLine,
|
|
6669
|
+
reason: "Last chunk of omitted content (may overlap if file is small)"
|
|
6670
|
+
}
|
|
6671
|
+
] : []
|
|
6672
|
+
]
|
|
6673
|
+
}
|
|
6674
|
+
};
|
|
6675
|
+
}
|
|
6528
6676
|
async function getFile(input) {
|
|
6529
|
-
logger.debug("Getting file", {
|
|
6677
|
+
logger.debug("Getting file", {
|
|
6678
|
+
repo: input.repo,
|
|
6679
|
+
path: input.path,
|
|
6680
|
+
startLine: input.startLine,
|
|
6681
|
+
endLine: input.endLine
|
|
6682
|
+
});
|
|
6530
6683
|
const repoInfo = resolveRepo(input.repo);
|
|
6531
6684
|
if (!repoInfo) {
|
|
6532
6685
|
return SelfCorrectionHints.UNKNOWN_REPO(
|
|
@@ -6546,12 +6699,53 @@ async function getFile(input) {
|
|
|
6546
6699
|
`${repoInfo.owner}/${repoInfo.repo}`
|
|
6547
6700
|
);
|
|
6548
6701
|
}
|
|
6702
|
+
let content = file.content;
|
|
6703
|
+
let totalLines = content.split("\n").length;
|
|
6704
|
+
let lineRange;
|
|
6705
|
+
if (input.startLine || input.endLine) {
|
|
6706
|
+
const lines = content.split("\n");
|
|
6707
|
+
const start = Math.max(1, input.startLine || 1);
|
|
6708
|
+
const end = Math.min(lines.length, input.endLine || lines.length);
|
|
6709
|
+
if (start > end) {
|
|
6710
|
+
return {
|
|
6711
|
+
error: `Invalid line range: startLine (${start}) > endLine (${end})`,
|
|
6712
|
+
suggestion: "Ensure startLine is less than or equal to endLine"
|
|
6713
|
+
};
|
|
6714
|
+
}
|
|
6715
|
+
content = lines.slice(start - 1, end).join("\n");
|
|
6716
|
+
lineRange = { start, end };
|
|
6717
|
+
logger.debug("Extracted line range", {
|
|
6718
|
+
start,
|
|
6719
|
+
end,
|
|
6720
|
+
extractedLines: end - start + 1
|
|
6721
|
+
});
|
|
6722
|
+
}
|
|
6723
|
+
const truncateResult = smartTruncate(content, input.path);
|
|
6724
|
+
if (truncateResult.truncated) {
|
|
6725
|
+
logger.info("File content truncated", {
|
|
6726
|
+
repository: `${repoInfo.owner}/${repoInfo.repo}`,
|
|
6727
|
+
path: input.path,
|
|
6728
|
+
language: truncateResult.truncationInfo?.language,
|
|
6729
|
+
originalSize: file.size,
|
|
6730
|
+
contentLength: content.length,
|
|
6731
|
+
omittedLines: truncateResult.truncationInfo?.omittedLineRange
|
|
6732
|
+
});
|
|
6733
|
+
}
|
|
6549
6734
|
return {
|
|
6550
|
-
content:
|
|
6735
|
+
content: truncateResult.content,
|
|
6551
6736
|
path: file.path,
|
|
6552
6737
|
repository: `${repoInfo.owner}/${repoInfo.repo}`,
|
|
6553
6738
|
sha: file.sha,
|
|
6554
6739
|
size: file.size,
|
|
6740
|
+
totalLines,
|
|
6741
|
+
...lineRange && { lineRange },
|
|
6742
|
+
truncated: truncateResult.truncated,
|
|
6743
|
+
...truncateResult.truncationInfo && {
|
|
6744
|
+
truncationInfo: truncateResult.truncationInfo
|
|
6745
|
+
},
|
|
6746
|
+
...truncateResult.agentGuidance && {
|
|
6747
|
+
agentGuidance: truncateResult.agentGuidance
|
|
6748
|
+
},
|
|
6555
6749
|
url: `https://github.com/${repoInfo.owner}/${repoInfo.repo}/blob/${input.ref || "main"}/${file.path}`
|
|
6556
6750
|
};
|
|
6557
6751
|
}
|
|
@@ -6748,11 +6942,29 @@ async function getFileAtVersion(input) {
|
|
|
6748
6942
|
`File not found: ${input.path} at version ${input.version} in ${repoName}`
|
|
6749
6943
|
);
|
|
6750
6944
|
}
|
|
6945
|
+
const truncateResult = smartTruncate(result.content, input.path);
|
|
6946
|
+
if (truncateResult.truncated) {
|
|
6947
|
+
logger.info("File content truncated (versioned)", {
|
|
6948
|
+
repository: `${resolved.owner}/${resolved.repo}`,
|
|
6949
|
+
path: input.path,
|
|
6950
|
+
version: input.version,
|
|
6951
|
+
language: truncateResult.truncationInfo?.language,
|
|
6952
|
+
contentLength: result.content.length,
|
|
6953
|
+
omittedLines: truncateResult.truncationInfo?.omittedLineRange
|
|
6954
|
+
});
|
|
6955
|
+
}
|
|
6751
6956
|
return {
|
|
6752
6957
|
repository: `${resolved.owner}/${resolved.repo}`,
|
|
6753
6958
|
path: input.path,
|
|
6754
6959
|
version: result.version,
|
|
6755
|
-
content:
|
|
6960
|
+
content: truncateResult.content,
|
|
6961
|
+
truncated: truncateResult.truncated,
|
|
6962
|
+
...truncateResult.truncationInfo && {
|
|
6963
|
+
truncationInfo: truncateResult.truncationInfo
|
|
6964
|
+
},
|
|
6965
|
+
...truncateResult.agentGuidance && {
|
|
6966
|
+
agentGuidance: truncateResult.agentGuidance
|
|
6967
|
+
},
|
|
6756
6968
|
note: `This is the exact content at version ${result.version}. Use this as the source of truth for syntax and API at this version.`
|
|
6757
6969
|
};
|
|
6758
6970
|
}
|
|
@@ -6784,14 +6996,38 @@ async function compareSyntax(input) {
|
|
|
6784
6996
|
input.oldVersion,
|
|
6785
6997
|
newVersion
|
|
6786
6998
|
);
|
|
6999
|
+
const truncateForComparison = (content, label) => {
|
|
7000
|
+
if (!content) return { content: null, truncated: false };
|
|
7001
|
+
const result = smartTruncate(content, input.path);
|
|
7002
|
+
if (result.truncated) {
|
|
7003
|
+
logger.info("Comparison content truncated", {
|
|
7004
|
+
repository: `${resolved.owner}/${resolved.repo}`,
|
|
7005
|
+
path: input.path,
|
|
7006
|
+
version: label,
|
|
7007
|
+
language: result.truncationInfo?.language,
|
|
7008
|
+
contentLength: content.length,
|
|
7009
|
+
truncationInfo: result.truncationInfo
|
|
7010
|
+
});
|
|
7011
|
+
}
|
|
7012
|
+
return result;
|
|
7013
|
+
};
|
|
7014
|
+
const old = truncateForComparison(
|
|
7015
|
+
comparison.oldContent,
|
|
7016
|
+
comparison.oldVersion
|
|
7017
|
+
);
|
|
7018
|
+
const newC = truncateForComparison(
|
|
7019
|
+
comparison.newContent,
|
|
7020
|
+
comparison.newVersion
|
|
7021
|
+
);
|
|
6787
7022
|
return {
|
|
6788
7023
|
repository: `${resolved.owner}/${resolved.repo}`,
|
|
6789
7024
|
path: input.path,
|
|
6790
7025
|
oldVersion: comparison.oldVersion,
|
|
6791
7026
|
newVersion: comparison.newVersion,
|
|
6792
7027
|
hasDifferences: comparison.hasDifferences,
|
|
6793
|
-
oldContent:
|
|
6794
|
-
newContent:
|
|
7028
|
+
oldContent: old.content,
|
|
7029
|
+
newContent: newC.content,
|
|
7030
|
+
contentTruncated: old.truncated || newC.truncated,
|
|
6795
7031
|
recommendation: comparison.hasDifferences ? `\u26A0\uFE0F This file has changed between ${comparison.oldVersion} and ${comparison.newVersion}. Review the differences before using code patterns from the old version.` : `\u2705 No changes in this file between versions.`
|
|
6796
7032
|
};
|
|
6797
7033
|
}
|
|
@@ -6989,10 +7225,25 @@ Version: ${COMPACT_VERSION.min}-${COMPACT_VERSION.max} (updated: ${COMPACT_VERSI
|
|
|
6989
7225
|
return {
|
|
6990
7226
|
repository: `${resolved.owner}/${resolved.repo}`,
|
|
6991
7227
|
version: reference.version,
|
|
6992
|
-
syntaxFiles: reference.syntaxFiles.map((f) =>
|
|
6993
|
-
|
|
6994
|
-
|
|
6995
|
-
|
|
7228
|
+
syntaxFiles: reference.syntaxFiles.map((f) => {
|
|
7229
|
+
const result = smartTruncate(f.content, f.path);
|
|
7230
|
+
if (result.truncated) {
|
|
7231
|
+
logger.info("Syntax file truncated", {
|
|
7232
|
+
repository: `${resolved.owner}/${resolved.repo}`,
|
|
7233
|
+
path: f.path,
|
|
7234
|
+
version: reference.version,
|
|
7235
|
+
language: result.truncationInfo?.language,
|
|
7236
|
+
contentLength: f.content.length,
|
|
7237
|
+
truncationInfo: result.truncationInfo
|
|
7238
|
+
});
|
|
7239
|
+
}
|
|
7240
|
+
return {
|
|
7241
|
+
path: f.path,
|
|
7242
|
+
content: result.content,
|
|
7243
|
+
truncated: result.truncated,
|
|
7244
|
+
...result.truncationInfo && { truncationInfo: result.truncationInfo }
|
|
7245
|
+
};
|
|
7246
|
+
}),
|
|
6996
7247
|
note: `This is the authoritative syntax reference at version ${reference.version}. Use this to ensure contracts are compilable.`
|
|
6997
7248
|
};
|
|
6998
7249
|
}
|
|
@@ -7216,7 +7467,9 @@ var repositoryTools = [
|
|
|
7216
7467
|
USAGE GUIDANCE:
|
|
7217
7468
|
\u2022 Use midnight-list-examples first if you're unsure which file to get
|
|
7218
7469
|
\u2022 For searching across files, use midnight-search-* tools instead
|
|
7219
|
-
\u2022 Use 'ref' parameter to get specific versions (branch, tag, or commit)
|
|
7470
|
+
\u2022 Use 'ref' parameter to get specific versions (branch, tag, or commit)
|
|
7471
|
+
\u2022 Use startLine/endLine to request specific sections of large files
|
|
7472
|
+
\u2022 Files >50KB are truncated (first 25KB + last 25KB preserved)`,
|
|
7220
7473
|
inputSchema: {
|
|
7221
7474
|
type: "object",
|
|
7222
7475
|
properties: {
|
|
@@ -7231,6 +7484,14 @@ USAGE GUIDANCE:
|
|
|
7231
7484
|
ref: {
|
|
7232
7485
|
type: "string",
|
|
7233
7486
|
description: "Branch, tag, or commit SHA (default: main)"
|
|
7487
|
+
},
|
|
7488
|
+
startLine: {
|
|
7489
|
+
type: "number",
|
|
7490
|
+
description: "Start line number (1-based, inclusive). Use to request specific sections."
|
|
7491
|
+
},
|
|
7492
|
+
endLine: {
|
|
7493
|
+
type: "number",
|
|
7494
|
+
description: "End line number (1-based, inclusive). Use with startLine for a range."
|
|
7234
7495
|
}
|
|
7235
7496
|
},
|
|
7236
7497
|
required: ["repo", "path"]
|
|
@@ -9315,4 +9576,4 @@ export {
|
|
|
9315
9576
|
startServer,
|
|
9316
9577
|
startHttpServer
|
|
9317
9578
|
};
|
|
9318
|
-
//# sourceMappingURL=chunk-
|
|
9579
|
+
//# sourceMappingURL=chunk-QPQOD3S6.js.map
|
|
@@ -1594,7 +1594,7 @@ async function checkGitHubAPI() {
|
|
|
1594
1594
|
}
|
|
1595
1595
|
async function checkVectorStore() {
|
|
1596
1596
|
try {
|
|
1597
|
-
const { vectorStore: vectorStore2 } = await import("./db-
|
|
1597
|
+
const { vectorStore: vectorStore2 } = await import("./db-7F5YOZB7.js");
|
|
1598
1598
|
if (vectorStore2) {
|
|
1599
1599
|
return {
|
|
1600
1600
|
status: "pass",
|
|
@@ -2069,7 +2069,7 @@ function serialize(data) {
|
|
|
2069
2069
|
}
|
|
2070
2070
|
|
|
2071
2071
|
// src/utils/version.ts
|
|
2072
|
-
var CURRENT_VERSION = "0.2.
|
|
2072
|
+
var CURRENT_VERSION = "0.2.8";
|
|
2073
2073
|
|
|
2074
2074
|
// src/db/vectorStore.ts
|
|
2075
2075
|
var VectorStore = class {
|
|
@@ -2278,4 +2278,4 @@ export {
|
|
|
2278
2278
|
serialize,
|
|
2279
2279
|
CURRENT_VERSION
|
|
2280
2280
|
};
|
|
2281
|
-
//# sourceMappingURL=chunk-
|
|
2281
|
+
//# sourceMappingURL=chunk-VQTI7YUU.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-QPQOD3S6.js";
|
|
13
13
|
import {
|
|
14
14
|
logger
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-VQTI7YUU.js";
|
|
16
16
|
export {
|
|
17
17
|
allResources,
|
|
18
18
|
allTools,
|
package/package.json
CHANGED