midnight-mcp 0.2.16 → 0.2.18
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 +11 -4
- package/dist/bin.js +3 -3
- package/dist/{chunk-TJ7QA5XT.js → chunk-TSXIIBEH.js} +148 -162
- package/dist/{chunk-P3MTQHP6.js → chunk-WVMAQ2LK.js} +79 -33
- package/dist/db-B4AOK42O.js +7 -0
- package/dist/index.js +2 -2
- package/package.json +7 -2
- package/dist/db-72ZOGII3.js +0 -7
package/README.md
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
|
|
9
9
|
MCP server that gives AI assistants access to Midnight blockchain—search contracts, analyze code, and explore documentation.
|
|
10
10
|
|
|
11
|
+
This project extends the Midnight Network with additional developer tooling.
|
|
12
|
+
|
|
11
13
|
## Requirements
|
|
12
14
|
|
|
13
15
|
- **Node.js 20+** (LTS recommended)
|
|
@@ -124,7 +126,7 @@ All tools are prefixed with `midnight-` (e.g., `midnight-search-compact`).
|
|
|
124
126
|
The `midnight-compile-contract` tool validates Compact code using a hosted compiler service:
|
|
125
127
|
|
|
126
128
|
```
|
|
127
|
-
✅ Compilation successful (Compiler v0.
|
|
129
|
+
✅ Compilation successful (Compiler v0.29.0) in 2841ms
|
|
128
130
|
```
|
|
129
131
|
|
|
130
132
|
- **Fast mode** (`skipZk=true`): Syntax validation in ~1-2 seconds
|
|
@@ -137,7 +139,7 @@ This catches semantic errors that static analysis misses (sealed fields, disclos
|
|
|
137
139
|
|
|
138
140
|
| Capability | Feature |
|
|
139
141
|
| --------------- | ----------------------------------------------- |
|
|
140
|
-
| **Tools** |
|
|
142
|
+
| **Tools** | 29 tools with `listChanged` notifications |
|
|
141
143
|
| **Resources** | 9 embedded resources with subscription support |
|
|
142
144
|
| **Prompts** | 5 workflow prompts |
|
|
143
145
|
| **Logging** | Client-controllable log level |
|
|
@@ -149,7 +151,7 @@ This catches semantic errors that static analysis misses (sealed fields, disclos
|
|
|
149
151
|
|
|
150
152
|
Quick references available offline:
|
|
151
153
|
|
|
152
|
-
- Compact syntax guide (v0.16-0.
|
|
154
|
+
- Compact syntax guide (v0.16-0.21)
|
|
153
155
|
- SDK API reference
|
|
154
156
|
- OpenZeppelin contracts
|
|
155
157
|
- Tokenomics overview
|
|
@@ -164,7 +166,7 @@ Quick references available offline:
|
|
|
164
166
|
| ------------------------- | -------- | ------------------------------------------------------- |
|
|
165
167
|
| `deprecated_ledger_block` | P0 | Catches `ledger { }` → use `export ledger field: Type;` |
|
|
166
168
|
| `invalid_void_type` | P0 | Catches `Void` → use `[]` (empty tuple) |
|
|
167
|
-
| `invalid_pragma_format` | P0 | Catches old pragma → use `>= 0.16 && <= 0.
|
|
169
|
+
| `invalid_pragma_format` | P0 | Catches old pragma → use `>= 0.16 && <= 0.21` |
|
|
168
170
|
| `unexported_enum` | P1 | Enums need `export` for TypeScript access |
|
|
169
171
|
| `module_level_const` | P0 | Use `pure circuit` instead |
|
|
170
172
|
| + 10 more checks | P1-P2 | Overflow, division, assertions, etc. |
|
|
@@ -269,6 +271,11 @@ Add `"GITHUB_TOKEN": "ghp_..."` for higher GitHub API rate limits (60 → 5000 r
|
|
|
269
271
|
```bash
|
|
270
272
|
git clone https://github.com/Olanetsoft/midnight-mcp.git && cd midnight-mcp
|
|
271
273
|
npm install && npm run build && npm test
|
|
274
|
+
|
|
275
|
+
# Lint & format
|
|
276
|
+
npm run lint # ESLint (typescript-eslint)
|
|
277
|
+
npm run lint:fix # Auto-fix lint issues
|
|
278
|
+
npm run format # Prettier
|
|
272
279
|
```
|
|
273
280
|
|
|
274
281
|
The hosted API runs on Cloudflare Workers + Vectorize. See [api/README.md](./api/README.md) for backend details.
|
package/dist/bin.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
startHttpServer,
|
|
4
4
|
startServer
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-TSXIIBEH.js";
|
|
6
6
|
import {
|
|
7
7
|
setOutputFormat
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-WVMAQ2LK.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.18";
|
|
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-WVMAQ2LK.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)",
|
|
@@ -1944,7 +1914,7 @@ import { randomUUID } from "crypto";
|
|
|
1944
1914
|
|
|
1945
1915
|
// src/resources/content/docs-content.ts
|
|
1946
1916
|
var EMBEDDED_DOCS = {
|
|
1947
|
-
"midnight://docs/compact-reference": `# Compact Language Syntax Reference (v0.16 - v0.
|
|
1917
|
+
"midnight://docs/compact-reference": `# Compact Language Syntax Reference (v0.16 - v0.21)
|
|
1948
1918
|
|
|
1949
1919
|
> **CRITICAL**: This reference is derived from **actual compiling contracts** in the Midnight ecosystem.
|
|
1950
1920
|
> Always verify syntax against this reference before generating contracts.
|
|
@@ -1954,7 +1924,7 @@ var EMBEDDED_DOCS = {
|
|
|
1954
1924
|
Use this as a starting point - it compiles successfully:
|
|
1955
1925
|
|
|
1956
1926
|
\`\`\`compact
|
|
1957
|
-
pragma language_version >= 0.16 && <= 0.
|
|
1927
|
+
pragma language_version >= 0.16 && <= 0.21;
|
|
1958
1928
|
|
|
1959
1929
|
import CompactStandardLibrary;
|
|
1960
1930
|
|
|
@@ -1977,13 +1947,13 @@ export circuit increment(): [] {
|
|
|
1977
1947
|
|
|
1978
1948
|
**CORRECT** - use bounded range without patch version:
|
|
1979
1949
|
\`\`\`compact
|
|
1980
|
-
pragma language_version >= 0.16 && <= 0.
|
|
1950
|
+
pragma language_version >= 0.16 && <= 0.21;
|
|
1981
1951
|
\`\`\`
|
|
1982
1952
|
|
|
1983
1953
|
**WRONG** - these will cause parse errors:
|
|
1984
1954
|
\`\`\`compact
|
|
1985
1955
|
pragma language_version >= 0.14.0; // \u274C patch version not needed
|
|
1986
|
-
pragma language_version >= 0.
|
|
1956
|
+
pragma language_version >= 0.20.0 < 0.22.0; // \u274C wrong operator format
|
|
1987
1957
|
\`\`\`
|
|
1988
1958
|
|
|
1989
1959
|
---
|
|
@@ -2231,7 +2201,7 @@ export circuit authenticated_action(): [] {
|
|
|
2231
2201
|
|
|
2232
2202
|
### Commit-Reveal Pattern (COMPLETE, VALIDATED)
|
|
2233
2203
|
\`\`\`compact
|
|
2234
|
-
pragma language_version >= 0.16 && <= 0.
|
|
2204
|
+
pragma language_version >= 0.16 && <= 0.21;
|
|
2235
2205
|
|
|
2236
2206
|
import CompactStandardLibrary;
|
|
2237
2207
|
|
|
@@ -2471,7 +2441,7 @@ assert(disclose(caller == owner), "Not authorized");
|
|
|
2471
2441
|
|---------|---------|
|
|
2472
2442
|
| \`ledger { field: Type; }\` | \`export ledger field: Type;\` |
|
|
2473
2443
|
| \`circuit fn(): Void\` | \`circuit fn(): []\` |
|
|
2474
|
-
| \`pragma >= 0.
|
|
2444
|
+
| \`pragma >= 0.20.0\` | \`pragma >= 0.16 && <= 0.21\` |
|
|
2475
2445
|
| \`enum State { ... }\` | \`export enum State { ... }\` |
|
|
2476
2446
|
| \`if (witness_val == x)\` | \`if (disclose(witness_val == x))\` |
|
|
2477
2447
|
| \`Cell<Field>\` | \`Field\` (Cell is deprecated) |
|
|
@@ -2804,7 +2774,7 @@ npm install @openzeppelin/compact-contracts
|
|
|
2804
2774
|
## Usage Example
|
|
2805
2775
|
|
|
2806
2776
|
\`\`\`compact
|
|
2807
|
-
pragma language_version >= 0.
|
|
2777
|
+
pragma language_version >= 0.16 && <= 0.21;
|
|
2808
2778
|
|
|
2809
2779
|
import CompactStandardLibrary;
|
|
2810
2780
|
import "@openzeppelin/compact-contracts/src/token/FungibleToken"
|
|
@@ -2845,7 +2815,7 @@ The recommended standard for privacy-preserving tokens on Midnight.
|
|
|
2845
2815
|
## Basic Usage
|
|
2846
2816
|
|
|
2847
2817
|
\`\`\`compact
|
|
2848
|
-
pragma language_version >= 0.
|
|
2818
|
+
pragma language_version >= 0.16 && <= 0.21;
|
|
2849
2819
|
|
|
2850
2820
|
import CompactStandardLibrary;
|
|
2851
2821
|
import "@openzeppelin/compact-contracts/src/token/FungibleToken"
|
|
@@ -3436,7 +3406,7 @@ var EMBEDDED_CODE = {
|
|
|
3436
3406
|
"midnight://code/examples/counter": `// Counter Example Contract
|
|
3437
3407
|
// A simple contract demonstrating basic Compact concepts
|
|
3438
3408
|
|
|
3439
|
-
pragma language_version >= 0.16 && <= 0.
|
|
3409
|
+
pragma language_version >= 0.16 && <= 0.21;
|
|
3440
3410
|
|
|
3441
3411
|
import CompactStandardLibrary;
|
|
3442
3412
|
|
|
@@ -3485,7 +3455,7 @@ export circuit isLessThan(threshold: Uint<64>): Boolean {
|
|
|
3485
3455
|
"midnight://code/examples/bboard": `// Bulletin Board Example Contract
|
|
3486
3456
|
// Demonstrates private messaging with selective disclosure
|
|
3487
3457
|
|
|
3488
|
-
pragma language_version >= 0.16 && <= 0.
|
|
3458
|
+
pragma language_version >= 0.16 && <= 0.21;
|
|
3489
3459
|
|
|
3490
3460
|
import CompactStandardLibrary;
|
|
3491
3461
|
|
|
@@ -3534,7 +3504,7 @@ export circuit getMessageCount(): Uint<64> {
|
|
|
3534
3504
|
"midnight://code/patterns/state-management": `// State Management Pattern
|
|
3535
3505
|
// Best practices for managing public and private state
|
|
3536
3506
|
|
|
3537
|
-
pragma language_version >= 0.16 && <= 0.
|
|
3507
|
+
pragma language_version >= 0.16 && <= 0.21;
|
|
3538
3508
|
|
|
3539
3509
|
import CompactStandardLibrary;
|
|
3540
3510
|
|
|
@@ -3585,7 +3555,7 @@ export circuit revealBalance(user: Opaque<"address">): Field {
|
|
|
3585
3555
|
"midnight://code/patterns/access-control": `// Access Control Pattern
|
|
3586
3556
|
// Implementing permissions and authorization
|
|
3587
3557
|
|
|
3588
|
-
pragma language_version >= 0.16 && <= 0.
|
|
3558
|
+
pragma language_version >= 0.16 && <= 0.21;
|
|
3589
3559
|
|
|
3590
3560
|
import CompactStandardLibrary;
|
|
3591
3561
|
|
|
@@ -3640,7 +3610,7 @@ export circuit timeLockedAction(unlockTime: Field): [] {
|
|
|
3640
3610
|
"midnight://code/patterns/privacy-preserving": `// Privacy-Preserving Patterns
|
|
3641
3611
|
// Techniques for maintaining privacy in smart contracts
|
|
3642
3612
|
|
|
3643
|
-
pragma language_version >= 0.16 && <= 0.
|
|
3613
|
+
pragma language_version >= 0.16 && <= 0.21;
|
|
3644
3614
|
|
|
3645
3615
|
import CompactStandardLibrary;
|
|
3646
3616
|
|
|
@@ -3745,7 +3715,7 @@ export circuit proveMembership(
|
|
|
3745
3715
|
"midnight://code/templates/token": `// Privacy-Preserving Token Template
|
|
3746
3716
|
// Starter template for token contracts with privacy features
|
|
3747
3717
|
|
|
3748
|
-
pragma language_version >= 0.16 && <= 0.
|
|
3718
|
+
pragma language_version >= 0.16 && <= 0.21;
|
|
3749
3719
|
|
|
3750
3720
|
import CompactStandardLibrary;
|
|
3751
3721
|
|
|
@@ -3804,7 +3774,7 @@ export circuit mint(to: Opaque<"address">, amount: Uint<64>): Boolean {
|
|
|
3804
3774
|
"midnight://code/templates/voting": `// Private Voting Template
|
|
3805
3775
|
// Starter template for privacy-preserving voting contracts
|
|
3806
3776
|
|
|
3807
|
-
pragma language_version >= 0.16 && <= 0.
|
|
3777
|
+
pragma language_version >= 0.16 && <= 0.21;
|
|
3808
3778
|
|
|
3809
3779
|
import CompactStandardLibrary;
|
|
3810
3780
|
|
|
@@ -3884,7 +3854,7 @@ export circuit addVoter(voter: Opaque<"address">): [] {
|
|
|
3884
3854
|
"midnight://code/examples/nullifier": `// Nullifier Pattern Example
|
|
3885
3855
|
// Demonstrates how to create and use nullifiers to prevent double-spending/actions
|
|
3886
3856
|
|
|
3887
|
-
pragma language_version >= 0.16 && <= 0.
|
|
3857
|
+
pragma language_version >= 0.16 && <= 0.21;
|
|
3888
3858
|
|
|
3889
3859
|
import CompactStandardLibrary;
|
|
3890
3860
|
|
|
@@ -3951,7 +3921,7 @@ export circuit voteWithNullifier(
|
|
|
3951
3921
|
"midnight://code/examples/hash": `// Hash Functions in Compact
|
|
3952
3922
|
// Examples of using hash functions for various purposes
|
|
3953
3923
|
|
|
3954
|
-
pragma language_version >= 0.16 && <= 0.
|
|
3924
|
+
pragma language_version >= 0.16 && <= 0.21;
|
|
3955
3925
|
|
|
3956
3926
|
import CompactStandardLibrary;
|
|
3957
3927
|
|
|
@@ -3998,7 +3968,7 @@ export circuit reveal(value: Field, randomness: Field): Field {
|
|
|
3998
3968
|
"midnight://code/examples/simple-counter": `// Simple Counter Contract
|
|
3999
3969
|
// Minimal example for learning Compact basics
|
|
4000
3970
|
|
|
4001
|
-
pragma language_version >= 0.16 && <= 0.
|
|
3971
|
+
pragma language_version >= 0.16 && <= 0.21;
|
|
4002
3972
|
|
|
4003
3973
|
import CompactStandardLibrary;
|
|
4004
3974
|
|
|
@@ -4036,7 +4006,7 @@ export circuit reset(): [] {
|
|
|
4036
4006
|
"midnight://code/templates/basic": `// Basic Compact Contract Template
|
|
4037
4007
|
// Starting point for new contracts
|
|
4038
4008
|
|
|
4039
|
-
pragma language_version >= 0.16 && <= 0.
|
|
4009
|
+
pragma language_version >= 0.16 && <= 0.21;
|
|
4040
4010
|
|
|
4041
4011
|
import CompactStandardLibrary;
|
|
4042
4012
|
|
|
@@ -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
|
}
|
|
@@ -4826,7 +4796,7 @@ function generateCreateContractPrompt(args) {
|
|
|
4826
4796
|
Call \`midnight-get-latest-syntax\` FIRST to get:
|
|
4827
4797
|
- The \`quickStartTemplate\` (use as your base)
|
|
4828
4798
|
- The \`commonMistakes\` array (avoid these errors)
|
|
4829
|
-
- Current pragma format: \`pragma language_version >= 0.16 && <= 0.
|
|
4799
|
+
- Current pragma format: \`pragma language_version >= 0.16 && <= 0.21;\`
|
|
4830
4800
|
|
|
4831
4801
|
### Step 2: Generate Contract
|
|
4832
4802
|
Based on syntax reference, generate the contract using:
|
|
@@ -4927,7 +4897,7 @@ ${contractCode}
|
|
|
4927
4897
|
Call \`midnight-extract-contract-structure\` with the contract code to check for:
|
|
4928
4898
|
- deprecated_ledger_block (should use \`export ledger field: Type;\`)
|
|
4929
4899
|
- invalid_void_type (should use \`[]\` not \`Void\`)
|
|
4930
|
-
- invalid_pragma_format (should use \`>= 0.16 && <= 0.
|
|
4900
|
+
- invalid_pragma_format (should use \`>= 0.16 && <= 0.21\`)
|
|
4931
4901
|
- unexported_enum (enums need \`export\`)
|
|
4932
4902
|
- deprecated_cell_wrapper
|
|
4933
4903
|
|
|
@@ -5096,7 +5066,7 @@ ${contractCode}
|
|
|
5096
5066
|
Call \`midnight-extract-contract-structure\` FIRST to check for common syntax errors:
|
|
5097
5067
|
- deprecated_ledger_block \u2192 should use \`export ledger field: Type;\`
|
|
5098
5068
|
- invalid_void_type \u2192 should use \`[]\` not \`Void\`
|
|
5099
|
-
- invalid_pragma_format \u2192 should use \`>= 0.16 && <= 0.
|
|
5069
|
+
- invalid_pragma_format \u2192 should use \`>= 0.16 && <= 0.21\`
|
|
5100
5070
|
- unexported_enum \u2192 enums need \`export\` keyword
|
|
5101
5071
|
|
|
5102
5072
|
### Step 2: Get Correct Syntax
|
|
@@ -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;
|
|
@@ -5219,7 +5190,7 @@ Key Compact syntax (REQUIRED):
|
|
|
5219
5190
|
- \`export ledger field: Type;\` - Individual ledger declarations (NOT ledger { } blocks)
|
|
5220
5191
|
- \`export circuit fn(): []\` - Public functions return empty tuple [] (NOT Void)
|
|
5221
5192
|
- \`witness fn(): T;\` - Declaration only, no body
|
|
5222
|
-
- \`pragma language_version >= 0.16 && <= 0.
|
|
5193
|
+
- \`pragma language_version >= 0.16 && <= 0.21;\` - Version pragma
|
|
5223
5194
|
- \`import CompactStandardLibrary;\` - Standard imports
|
|
5224
5195
|
- \`Counter\`, \`Map<K,V>\`, \`Set<T>\` - Built-in collection types
|
|
5225
5196
|
- \`Field\`, \`Boolean\`, \`Uint<N>\`, \`Bytes<N>\` - Primitive types
|
|
@@ -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();
|
|
@@ -6554,9 +6540,9 @@ var COMPACT_VERSION = {
|
|
|
6554
6540
|
/** Minimum supported version */
|
|
6555
6541
|
min: "0.16",
|
|
6556
6542
|
/** Maximum supported version */
|
|
6557
|
-
max: "0.
|
|
6543
|
+
max: "0.21",
|
|
6558
6544
|
/** When this config was last updated */
|
|
6559
|
-
lastUpdated: "
|
|
6545
|
+
lastUpdated: "2026-03-24",
|
|
6560
6546
|
/** Source of truth for syntax patterns */
|
|
6561
6547
|
referenceSource: "https://github.com/piotr-iohk/template-contract"
|
|
6562
6548
|
};
|
|
@@ -7401,7 +7387,7 @@ async function extractContractStructure(input) {
|
|
|
7401
7387
|
type: "invalid_pragma_format",
|
|
7402
7388
|
line: lineNum,
|
|
7403
7389
|
message: `Pragma includes patch version which may cause parse errors`,
|
|
7404
|
-
suggestion: `Use bounded range format: 'pragma language_version >= 0.16 && <= 0.
|
|
7390
|
+
suggestion: `Use bounded range format: 'pragma language_version >= 0.16 && <= 0.21;'`,
|
|
7405
7391
|
severity: "error"
|
|
7406
7392
|
});
|
|
7407
7393
|
}
|
|
@@ -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-TSXIIBEH.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;
|
|
@@ -1088,6 +1091,25 @@ function parseCompactFile(path, content) {
|
|
|
1088
1091
|
});
|
|
1089
1092
|
}
|
|
1090
1093
|
}
|
|
1094
|
+
const newLedgerRegex = /(?:(export)\s+)?ledger\s+(\w+)\s*:\s*([^;]+);/gm;
|
|
1095
|
+
let newLedgerMatch;
|
|
1096
|
+
while ((newLedgerMatch = newLedgerRegex.exec(content)) !== null) {
|
|
1097
|
+
hasLedger = true;
|
|
1098
|
+
const isExport = newLedgerMatch[1] === "export";
|
|
1099
|
+
const fieldName = newLedgerMatch[2];
|
|
1100
|
+
const fieldType = newLedgerMatch[3].trim();
|
|
1101
|
+
const startLine = content.substring(0, newLedgerMatch.index).split("\n").length;
|
|
1102
|
+
codeUnits.push({
|
|
1103
|
+
type: "ledger",
|
|
1104
|
+
name: fieldName,
|
|
1105
|
+
code: newLedgerMatch[0].trim(),
|
|
1106
|
+
startLine,
|
|
1107
|
+
endLine: startLine,
|
|
1108
|
+
isPublic: isExport,
|
|
1109
|
+
isPrivate: !isExport,
|
|
1110
|
+
returnType: fieldType
|
|
1111
|
+
});
|
|
1112
|
+
}
|
|
1091
1113
|
const circuitRegex = /(export\s+)?circuit\s+(\w+)\s*\(([^)]*)\)\s*(?::\s*(\w+))?\s*\{/g;
|
|
1092
1114
|
let circuitMatch;
|
|
1093
1115
|
while ((circuitMatch = circuitRegex.exec(content)) !== null) {
|
|
@@ -1232,9 +1254,18 @@ var EmbeddingGenerator = class {
|
|
|
1232
1254
|
model: this.model,
|
|
1233
1255
|
input: text
|
|
1234
1256
|
});
|
|
1257
|
+
const embedding = response.data[0].embedding;
|
|
1258
|
+
const EXPECTED_DIMENSIONS = 1536;
|
|
1259
|
+
if (!embedding || embedding.length !== EXPECTED_DIMENSIONS) {
|
|
1260
|
+
logger.warn("Unexpected embedding dimensions", {
|
|
1261
|
+
expected: EXPECTED_DIMENSIONS,
|
|
1262
|
+
actual: embedding?.length ?? 0,
|
|
1263
|
+
model: this.model
|
|
1264
|
+
});
|
|
1265
|
+
}
|
|
1235
1266
|
return {
|
|
1236
1267
|
text,
|
|
1237
|
-
embedding
|
|
1268
|
+
embedding,
|
|
1238
1269
|
model: this.model,
|
|
1239
1270
|
tokenCount: response.usage?.total_tokens
|
|
1240
1271
|
};
|
|
@@ -1593,7 +1624,7 @@ var releaseTracker = new ReleaseTracker();
|
|
|
1593
1624
|
|
|
1594
1625
|
// src/utils/health.ts
|
|
1595
1626
|
var startTime = Date.now();
|
|
1596
|
-
var VERSION = "0.2.
|
|
1627
|
+
var VERSION = "0.2.18";
|
|
1597
1628
|
async function checkGitHubAPI() {
|
|
1598
1629
|
const start = Date.now();
|
|
1599
1630
|
try {
|
|
@@ -1621,7 +1652,7 @@ async function checkGitHubAPI() {
|
|
|
1621
1652
|
}
|
|
1622
1653
|
async function checkVectorStore() {
|
|
1623
1654
|
try {
|
|
1624
|
-
const { vectorStore: vectorStore2 } = await import("./db-
|
|
1655
|
+
const { vectorStore: vectorStore2 } = await import("./db-B4AOK42O.js");
|
|
1625
1656
|
if (vectorStore2) {
|
|
1626
1657
|
return {
|
|
1627
1658
|
status: "pass",
|
|
@@ -1806,6 +1837,9 @@ var Cache = class {
|
|
|
1806
1837
|
if (this.cache.size >= this.options.maxSize) {
|
|
1807
1838
|
this.evictOldest();
|
|
1808
1839
|
}
|
|
1840
|
+
if (this.cache.size > 0 && this.cache.size % 100 === 0) {
|
|
1841
|
+
this.prune();
|
|
1842
|
+
}
|
|
1809
1843
|
const now = Date.now();
|
|
1810
1844
|
this.cache.set(key, {
|
|
1811
1845
|
value,
|
|
@@ -1917,12 +1951,6 @@ var metadataCache = new Cache({
|
|
|
1917
1951
|
maxSize: 100,
|
|
1918
1952
|
name: "metadata"
|
|
1919
1953
|
});
|
|
1920
|
-
function pruneAllCaches() {
|
|
1921
|
-
searchCache.prune();
|
|
1922
|
-
fileCache.prune();
|
|
1923
|
-
metadataCache.prune();
|
|
1924
|
-
}
|
|
1925
|
-
setInterval(pruneAllCaches, 5 * 60 * 1e3);
|
|
1926
1954
|
|
|
1927
1955
|
// src/utils/hosted-api.ts
|
|
1928
1956
|
var API_TIMEOUT = 15e3;
|
|
@@ -1991,7 +2019,8 @@ async function makeRequest(url, endpoint, options) {
|
|
|
1991
2019
|
} catch (error) {
|
|
1992
2020
|
if (error instanceof Error && error.name === "AbortError") {
|
|
1993
2021
|
throw new Error(
|
|
1994
|
-
`Request to ${endpoint} timed out after ${API_TIMEOUT / 1e3}s
|
|
2022
|
+
`Request to ${endpoint} timed out after ${API_TIMEOUT / 1e3}s.`,
|
|
2023
|
+
{ cause: error }
|
|
1995
2024
|
);
|
|
1996
2025
|
}
|
|
1997
2026
|
throw error;
|
|
@@ -2065,7 +2094,10 @@ function trackToolCall(tool, success, durationMs, version) {
|
|
|
2065
2094
|
apiRequest("/v1/track/tool", {
|
|
2066
2095
|
method: "POST",
|
|
2067
2096
|
body: JSON.stringify({ tool, success, durationMs, version })
|
|
2068
|
-
}).catch(() => {
|
|
2097
|
+
}).catch((error) => {
|
|
2098
|
+
logger.debug("Tracking call failed (non-blocking)", {
|
|
2099
|
+
error: String(error)
|
|
2100
|
+
});
|
|
2069
2101
|
});
|
|
2070
2102
|
}
|
|
2071
2103
|
|
|
@@ -2096,7 +2128,7 @@ function serialize(data) {
|
|
|
2096
2128
|
}
|
|
2097
2129
|
|
|
2098
2130
|
// src/utils/version.ts
|
|
2099
|
-
var CURRENT_VERSION = "0.2.
|
|
2131
|
+
var CURRENT_VERSION = "0.2.18";
|
|
2100
2132
|
|
|
2101
2133
|
// src/db/vectorStore.ts
|
|
2102
2134
|
var VectorStore = class {
|
|
@@ -2137,9 +2169,23 @@ var VectorStore = class {
|
|
|
2137
2169
|
return;
|
|
2138
2170
|
}
|
|
2139
2171
|
try {
|
|
2140
|
-
const
|
|
2141
|
-
|
|
2142
|
-
|
|
2172
|
+
const validDocuments = documents.filter((d) => {
|
|
2173
|
+
if (!d.embedding || d.embedding.length === 0) {
|
|
2174
|
+
logger.warn("Document missing embedding, skipping", {
|
|
2175
|
+
id: d.id,
|
|
2176
|
+
filePath: d.metadata.filePath
|
|
2177
|
+
});
|
|
2178
|
+
return false;
|
|
2179
|
+
}
|
|
2180
|
+
return true;
|
|
2181
|
+
});
|
|
2182
|
+
if (validDocuments.length === 0) {
|
|
2183
|
+
logger.warn("No documents with valid embeddings to store");
|
|
2184
|
+
return;
|
|
2185
|
+
}
|
|
2186
|
+
const ids = validDocuments.map((d) => d.id);
|
|
2187
|
+
const embeddings = validDocuments.map((d) => d.embedding);
|
|
2188
|
+
const metadatas = validDocuments.map((d) => ({
|
|
2143
2189
|
repository: d.metadata.repository,
|
|
2144
2190
|
filePath: d.metadata.filePath,
|
|
2145
2191
|
language: d.metadata.language,
|
|
@@ -2149,14 +2195,14 @@ var VectorStore = class {
|
|
|
2149
2195
|
codeName: d.metadata.codeName,
|
|
2150
2196
|
isPublic: d.metadata.isPublic
|
|
2151
2197
|
}));
|
|
2152
|
-
const documentContents =
|
|
2198
|
+
const documentContents = validDocuments.map((d) => d.content);
|
|
2153
2199
|
await this.collection.add({
|
|
2154
2200
|
ids,
|
|
2155
2201
|
embeddings,
|
|
2156
2202
|
metadatas,
|
|
2157
2203
|
documents: documentContents
|
|
2158
2204
|
});
|
|
2159
|
-
logger.debug(`Added ${
|
|
2205
|
+
logger.debug(`Added ${validDocuments.length} documents to vector store`);
|
|
2160
2206
|
} catch (error) {
|
|
2161
2207
|
logger.error("Failed to add documents to vector store", {
|
|
2162
2208
|
error: String(error)
|
|
@@ -2305,4 +2351,4 @@ export {
|
|
|
2305
2351
|
serialize,
|
|
2306
2352
|
CURRENT_VERSION
|
|
2307
2353
|
};
|
|
2308
|
-
//# sourceMappingURL=chunk-
|
|
2354
|
+
//# sourceMappingURL=chunk-WVMAQ2LK.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-TSXIIBEH.js";
|
|
13
13
|
import {
|
|
14
14
|
logger
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-WVMAQ2LK.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.18",
|
|
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": {
|