midnight-mcp 0.2.12 → 0.2.14
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 +16 -2
- package/dist/bin.js +3 -3
- package/dist/{chunk-YT6DWZUA.js → chunk-V7KK64OX.js} +1138 -67
- package/dist/{chunk-B6UJ7ZQY.js → chunk-WYQRVPIQ.js} +4 -4
- package/dist/db-UKVEAHIX.js +7 -0
- package/dist/index.js +2 -2
- package/package.json +1 -1
- package/dist/db-VAJD22EC.js +0 -7
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
validateNumber,
|
|
26
26
|
validateQuery,
|
|
27
27
|
vectorStore
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-WYQRVPIQ.js";
|
|
29
29
|
|
|
30
30
|
// src/tools/search/schemas.ts
|
|
31
31
|
import { z } from "zod";
|
|
@@ -733,6 +733,144 @@ var AnalyzeContractInputSchema = z2.object({
|
|
|
733
733
|
var ExplainCircuitInputSchema = z2.object({
|
|
734
734
|
circuitCode: z2.string().describe("Circuit definition from Compact")
|
|
735
735
|
});
|
|
736
|
+
var CompileContractInputSchema = z2.object({
|
|
737
|
+
code: z2.string().describe("Compact contract source code to compile"),
|
|
738
|
+
skipZk: z2.boolean().optional().default(true).describe(
|
|
739
|
+
"Skip ZK circuit generation for faster syntax-only validation (default: true)"
|
|
740
|
+
),
|
|
741
|
+
fullCompile: z2.boolean().optional().default(false).describe(
|
|
742
|
+
"Perform full compilation including ZK generation (slower but complete)"
|
|
743
|
+
)
|
|
744
|
+
});
|
|
745
|
+
|
|
746
|
+
// src/services/compiler.ts
|
|
747
|
+
var COMPILER_API_URL = process.env.COMPACT_COMPILER_URL || "https://compact-playground.onrender.com";
|
|
748
|
+
var COMPILER_TIMEOUT = 3e4;
|
|
749
|
+
var MAX_CODE_SIZE = 100 * 1024;
|
|
750
|
+
async function compileContract(code, options = {}) {
|
|
751
|
+
if (!code || typeof code !== "string") {
|
|
752
|
+
return {
|
|
753
|
+
success: false,
|
|
754
|
+
message: "No code provided",
|
|
755
|
+
error: "INVALID_INPUT",
|
|
756
|
+
serviceAvailable: true
|
|
757
|
+
};
|
|
758
|
+
}
|
|
759
|
+
if (code.length > MAX_CODE_SIZE) {
|
|
760
|
+
return {
|
|
761
|
+
success: false,
|
|
762
|
+
message: `Code exceeds maximum size of ${MAX_CODE_SIZE / 1024}KB`,
|
|
763
|
+
error: "CODE_TOO_LARGE",
|
|
764
|
+
serviceAvailable: true
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
try {
|
|
768
|
+
const controller = new AbortController();
|
|
769
|
+
const timeoutId = setTimeout(() => controller.abort(), COMPILER_TIMEOUT);
|
|
770
|
+
const requestBody = {
|
|
771
|
+
code,
|
|
772
|
+
options: {
|
|
773
|
+
wrapWithDefaults: options.wrapWithDefaults ?? true,
|
|
774
|
+
skipZk: options.skipZk ?? true
|
|
775
|
+
// Default to fast syntax-only validation
|
|
776
|
+
}
|
|
777
|
+
};
|
|
778
|
+
logger.info("Sending code to compiler service", {
|
|
779
|
+
codeLength: code.length,
|
|
780
|
+
options: requestBody.options
|
|
781
|
+
});
|
|
782
|
+
const response = await fetch(`${COMPILER_API_URL}/compile`, {
|
|
783
|
+
method: "POST",
|
|
784
|
+
headers: {
|
|
785
|
+
"Content-Type": "application/json"
|
|
786
|
+
},
|
|
787
|
+
body: JSON.stringify(requestBody),
|
|
788
|
+
signal: controller.signal
|
|
789
|
+
});
|
|
790
|
+
clearTimeout(timeoutId);
|
|
791
|
+
if (!response.ok) {
|
|
792
|
+
const errorText = await response.text().catch(() => "Unknown error");
|
|
793
|
+
logger.error("Compiler API returned error status", {
|
|
794
|
+
status: response.status,
|
|
795
|
+
error: errorText
|
|
796
|
+
});
|
|
797
|
+
return {
|
|
798
|
+
success: false,
|
|
799
|
+
message: `Compiler service error: ${response.status}`,
|
|
800
|
+
error: "API_ERROR",
|
|
801
|
+
serviceAvailable: response.status < 500
|
|
802
|
+
};
|
|
803
|
+
}
|
|
804
|
+
const result = await response.json();
|
|
805
|
+
if (result.success) {
|
|
806
|
+
const outputInfo = typeof result.output === "object" && result.output !== null ? result.output : {};
|
|
807
|
+
logger.info("Compilation successful", {
|
|
808
|
+
compilerVersion: result.compilerVersion,
|
|
809
|
+
executionTime: result.executionTime,
|
|
810
|
+
circuits: outputInfo.circuits?.length || 0,
|
|
811
|
+
warnings: result.warnings?.length || 0
|
|
812
|
+
});
|
|
813
|
+
const version = result.compilerVersion || "unknown";
|
|
814
|
+
const execTime = result.executionTime ? ` in ${result.executionTime}ms` : "";
|
|
815
|
+
return {
|
|
816
|
+
success: true,
|
|
817
|
+
compilerVersion: version,
|
|
818
|
+
message: `\u2705 Compilation successful (Compiler v${version})${execTime}`,
|
|
819
|
+
circuits: outputInfo.circuits || [],
|
|
820
|
+
ledgerFields: outputInfo.ledgerFields || [],
|
|
821
|
+
exports: outputInfo.exports || [],
|
|
822
|
+
warnings: result.warnings || [],
|
|
823
|
+
serviceAvailable: true
|
|
824
|
+
};
|
|
825
|
+
} else {
|
|
826
|
+
const errors = result.errors || [];
|
|
827
|
+
const firstError = errors[0];
|
|
828
|
+
logger.info("Compilation failed", {
|
|
829
|
+
error: result.error,
|
|
830
|
+
errorCount: errors.length,
|
|
831
|
+
output: result.output,
|
|
832
|
+
firstError
|
|
833
|
+
});
|
|
834
|
+
let errorMessage = result.output || result.message || result.error || "Compilation failed";
|
|
835
|
+
if (firstError) {
|
|
836
|
+
errorMessage = `Line ${firstError.line}:${firstError.column} - ${firstError.message}`;
|
|
837
|
+
}
|
|
838
|
+
return {
|
|
839
|
+
success: false,
|
|
840
|
+
message: errorMessage,
|
|
841
|
+
error: result.error || "COMPILE_ERROR",
|
|
842
|
+
errors,
|
|
843
|
+
errorDetails: firstError ? {
|
|
844
|
+
line: firstError.line,
|
|
845
|
+
column: firstError.column,
|
|
846
|
+
errorType: firstError.severity
|
|
847
|
+
} : result.details,
|
|
848
|
+
serviceAvailable: true
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
} catch (error) {
|
|
852
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
853
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
854
|
+
logger.warn("Compiler request timed out");
|
|
855
|
+
return {
|
|
856
|
+
success: false,
|
|
857
|
+
message: "Compilation timed out - the contract may be too complex",
|
|
858
|
+
error: "TIMEOUT",
|
|
859
|
+
serviceAvailable: true
|
|
860
|
+
};
|
|
861
|
+
}
|
|
862
|
+
logger.error("Compiler service request failed", { error: errorMessage });
|
|
863
|
+
return {
|
|
864
|
+
success: false,
|
|
865
|
+
message: `Failed to connect to compiler service: ${errorMessage}`,
|
|
866
|
+
error: "CONNECTION_FAILED",
|
|
867
|
+
serviceAvailable: false
|
|
868
|
+
};
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
function getCompilerUrl() {
|
|
872
|
+
return COMPILER_API_URL;
|
|
873
|
+
}
|
|
736
874
|
|
|
737
875
|
// src/tools/analyze/handlers.ts
|
|
738
876
|
async function analyzeContract(input) {
|
|
@@ -954,6 +1092,86 @@ function getPrivacyConsiderations(circuit) {
|
|
|
954
1092
|
}
|
|
955
1093
|
return considerations;
|
|
956
1094
|
}
|
|
1095
|
+
async function compileContract2(input) {
|
|
1096
|
+
logger.info("Compiling Compact contract via hosted service", {
|
|
1097
|
+
codeLength: input.code.length,
|
|
1098
|
+
skipZk: input.skipZk,
|
|
1099
|
+
fullCompile: input.fullCompile
|
|
1100
|
+
});
|
|
1101
|
+
const skipZk = input.fullCompile ? false : input.skipZk ?? true;
|
|
1102
|
+
const result = await compileContract(input.code, {
|
|
1103
|
+
wrapWithDefaults: true,
|
|
1104
|
+
skipZk
|
|
1105
|
+
});
|
|
1106
|
+
if (result.success) {
|
|
1107
|
+
return {
|
|
1108
|
+
success: true,
|
|
1109
|
+
message: result.message,
|
|
1110
|
+
compilerVersion: result.compilerVersion,
|
|
1111
|
+
compilationMode: skipZk ? "syntax-only" : "full",
|
|
1112
|
+
validationType: "compiler",
|
|
1113
|
+
output: {
|
|
1114
|
+
circuits: result.circuits || [],
|
|
1115
|
+
ledgerFields: result.ledgerFields || [],
|
|
1116
|
+
exports: result.exports || []
|
|
1117
|
+
},
|
|
1118
|
+
warnings: result.warnings || [],
|
|
1119
|
+
serviceUrl: getCompilerUrl()
|
|
1120
|
+
};
|
|
1121
|
+
} else {
|
|
1122
|
+
if (!result.serviceAvailable) {
|
|
1123
|
+
logger.warn(
|
|
1124
|
+
"Compiler service unavailable, falling back to static analysis",
|
|
1125
|
+
{ error: result.error }
|
|
1126
|
+
);
|
|
1127
|
+
const staticResult = await analyzeContract({
|
|
1128
|
+
code: input.code,
|
|
1129
|
+
checkSecurity: true
|
|
1130
|
+
});
|
|
1131
|
+
const securityWarnings = (staticResult.securityFindings || []).map(
|
|
1132
|
+
(f) => `[${f.severity}] ${f.message}`
|
|
1133
|
+
);
|
|
1134
|
+
return {
|
|
1135
|
+
success: true,
|
|
1136
|
+
// Static analysis succeeded
|
|
1137
|
+
message: "Static analysis completed (compiler service unavailable)",
|
|
1138
|
+
validationType: "static-analysis-fallback",
|
|
1139
|
+
compilationMode: "none",
|
|
1140
|
+
serviceAvailable: false,
|
|
1141
|
+
serviceUrl: getCompilerUrl(),
|
|
1142
|
+
fallbackReason: result.message,
|
|
1143
|
+
warnings: securityWarnings,
|
|
1144
|
+
staticAnalysis: {
|
|
1145
|
+
summary: staticResult.summary,
|
|
1146
|
+
structure: staticResult.structure,
|
|
1147
|
+
securityFindings: staticResult.securityFindings,
|
|
1148
|
+
recommendations: staticResult.recommendations
|
|
1149
|
+
}
|
|
1150
|
+
};
|
|
1151
|
+
}
|
|
1152
|
+
const errorInfo = {
|
|
1153
|
+
success: false,
|
|
1154
|
+
message: result.message,
|
|
1155
|
+
error: result.error,
|
|
1156
|
+
validationType: "compiler",
|
|
1157
|
+
serviceAvailable: result.serviceAvailable,
|
|
1158
|
+
serviceUrl: getCompilerUrl()
|
|
1159
|
+
};
|
|
1160
|
+
if (result.errorDetails) {
|
|
1161
|
+
errorInfo.location = {
|
|
1162
|
+
line: result.errorDetails.line,
|
|
1163
|
+
column: result.errorDetails.column,
|
|
1164
|
+
errorType: result.errorDetails.errorType
|
|
1165
|
+
};
|
|
1166
|
+
}
|
|
1167
|
+
if (result.error === "TIMEOUT") {
|
|
1168
|
+
errorInfo.hint = "The contract may be too complex. Try simplifying or breaking it into smaller pieces.";
|
|
1169
|
+
} else if (result.errorDetails?.line) {
|
|
1170
|
+
errorInfo.hint = `Check line ${result.errorDetails.line} for the issue.`;
|
|
1171
|
+
}
|
|
1172
|
+
return errorInfo;
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
957
1175
|
|
|
958
1176
|
// src/tools/analyze/tools.ts
|
|
959
1177
|
var analyzeContractOutputSchema = {
|
|
@@ -1098,6 +1316,99 @@ var explainCircuitOutputSchema = {
|
|
|
1098
1316
|
],
|
|
1099
1317
|
description: "Detailed circuit explanation with privacy analysis"
|
|
1100
1318
|
};
|
|
1319
|
+
var compileContractOutputSchema = {
|
|
1320
|
+
type: "object",
|
|
1321
|
+
properties: {
|
|
1322
|
+
success: {
|
|
1323
|
+
type: "boolean",
|
|
1324
|
+
description: "Whether compilation/validation succeeded"
|
|
1325
|
+
},
|
|
1326
|
+
message: {
|
|
1327
|
+
type: "string",
|
|
1328
|
+
description: "Human-readable status message"
|
|
1329
|
+
},
|
|
1330
|
+
validationType: {
|
|
1331
|
+
type: "string",
|
|
1332
|
+
enum: ["compiler", "static-analysis-fallback"],
|
|
1333
|
+
description: "Type of validation performed - compiler (real) or static-analysis-fallback (when service unavailable)"
|
|
1334
|
+
},
|
|
1335
|
+
compilerVersion: {
|
|
1336
|
+
type: "string",
|
|
1337
|
+
description: "Version of the Compact compiler used (if available)"
|
|
1338
|
+
},
|
|
1339
|
+
compilationMode: {
|
|
1340
|
+
type: "string",
|
|
1341
|
+
enum: ["syntax-only", "full", "none"],
|
|
1342
|
+
description: "Type of compilation performed"
|
|
1343
|
+
},
|
|
1344
|
+
output: {
|
|
1345
|
+
type: "object",
|
|
1346
|
+
properties: {
|
|
1347
|
+
circuits: {
|
|
1348
|
+
type: "array",
|
|
1349
|
+
items: { type: "string" },
|
|
1350
|
+
description: "List of compiled circuits"
|
|
1351
|
+
},
|
|
1352
|
+
ledgerFields: {
|
|
1353
|
+
type: "array",
|
|
1354
|
+
items: { type: "string" },
|
|
1355
|
+
description: "List of ledger fields"
|
|
1356
|
+
},
|
|
1357
|
+
exports: {
|
|
1358
|
+
type: "array",
|
|
1359
|
+
items: { type: "string" },
|
|
1360
|
+
description: "List of exported symbols"
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
},
|
|
1364
|
+
warnings: {
|
|
1365
|
+
type: "array",
|
|
1366
|
+
items: { type: "string" },
|
|
1367
|
+
description: "Compiler warnings or fallback warnings"
|
|
1368
|
+
},
|
|
1369
|
+
error: {
|
|
1370
|
+
type: "string",
|
|
1371
|
+
description: "Error code if compilation failed"
|
|
1372
|
+
},
|
|
1373
|
+
location: {
|
|
1374
|
+
type: "object",
|
|
1375
|
+
properties: {
|
|
1376
|
+
line: { type: "number" },
|
|
1377
|
+
column: { type: "number" },
|
|
1378
|
+
errorType: { type: "string" }
|
|
1379
|
+
},
|
|
1380
|
+
description: "Location of error if applicable"
|
|
1381
|
+
},
|
|
1382
|
+
hint: {
|
|
1383
|
+
type: "string",
|
|
1384
|
+
description: "Helpful hint for resolving the issue"
|
|
1385
|
+
},
|
|
1386
|
+
serviceUrl: {
|
|
1387
|
+
type: "string",
|
|
1388
|
+
description: "URL of the compiler service used"
|
|
1389
|
+
},
|
|
1390
|
+
serviceAvailable: {
|
|
1391
|
+
type: "boolean",
|
|
1392
|
+
description: "Whether the compiler service is available"
|
|
1393
|
+
},
|
|
1394
|
+
fallbackReason: {
|
|
1395
|
+
type: "string",
|
|
1396
|
+
description: "Reason for falling back to static analysis (if applicable)"
|
|
1397
|
+
},
|
|
1398
|
+
staticAnalysis: {
|
|
1399
|
+
type: "object",
|
|
1400
|
+
description: "Static analysis results (only present when using fallback)",
|
|
1401
|
+
properties: {
|
|
1402
|
+
summary: { type: "object" },
|
|
1403
|
+
structure: { type: "object" },
|
|
1404
|
+
securityFindings: { type: "array" },
|
|
1405
|
+
recommendations: { type: "array" }
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
},
|
|
1409
|
+
required: ["success", "message", "validationType"],
|
|
1410
|
+
description: "Compilation result with detailed output, or static analysis fallback if service unavailable"
|
|
1411
|
+
};
|
|
1101
1412
|
var analyzeTools = [
|
|
1102
1413
|
{
|
|
1103
1414
|
name: "midnight-analyze-contract",
|
|
@@ -1161,6 +1472,59 @@ USAGE GUIDANCE:
|
|
|
1161
1472
|
category: "analyze"
|
|
1162
1473
|
},
|
|
1163
1474
|
handler: explainCircuit
|
|
1475
|
+
},
|
|
1476
|
+
{
|
|
1477
|
+
name: "midnight-compile-contract",
|
|
1478
|
+
description: `\u{1F527} REAL COMPILATION - Compile Compact code using the hosted compiler service.
|
|
1479
|
+
|
|
1480
|
+
Unlike static analysis tools, this ACTUALLY COMPILES the contract and returns real compiler errors.
|
|
1481
|
+
|
|
1482
|
+
Use this to:
|
|
1483
|
+
\u2022 Validate that generated code compiles before showing to users
|
|
1484
|
+
\u2022 Get actual compiler error messages with line numbers
|
|
1485
|
+
\u2022 Check if a contract is syntactically and semantically correct
|
|
1486
|
+
|
|
1487
|
+
Options:
|
|
1488
|
+
\u2022 skipZk=true (default): Fast syntax validation only (~1-2s)
|
|
1489
|
+
\u2022 fullCompile=true: Full compilation with ZK circuit generation (~10-30s)
|
|
1490
|
+
|
|
1491
|
+
FALLBACK BEHAVIOR:
|
|
1492
|
+
\u2022 If the compiler service is unavailable, automatically falls back to static analysis
|
|
1493
|
+
\u2022 Check 'validationType' in response: 'compiler' = real compilation, 'static-analysis-fallback' = fallback mode
|
|
1494
|
+
\u2022 Fallback provides structure/security analysis but may miss semantic errors
|
|
1495
|
+
|
|
1496
|
+
USAGE GUIDANCE:
|
|
1497
|
+
\u2022 Call after generating or modifying Compact code
|
|
1498
|
+
\u2022 Use skipZk=true for quick validation during development
|
|
1499
|
+
\u2022 Use fullCompile=true for final validation before deployment`,
|
|
1500
|
+
inputSchema: {
|
|
1501
|
+
type: "object",
|
|
1502
|
+
properties: {
|
|
1503
|
+
code: {
|
|
1504
|
+
type: "string",
|
|
1505
|
+
description: "Compact contract source code to compile"
|
|
1506
|
+
},
|
|
1507
|
+
skipZk: {
|
|
1508
|
+
type: "boolean",
|
|
1509
|
+
description: "Skip ZK circuit generation for faster syntax-only validation (default: true)"
|
|
1510
|
+
},
|
|
1511
|
+
fullCompile: {
|
|
1512
|
+
type: "boolean",
|
|
1513
|
+
description: "Perform full compilation including ZK generation (slower but complete)"
|
|
1514
|
+
}
|
|
1515
|
+
},
|
|
1516
|
+
required: ["code"]
|
|
1517
|
+
},
|
|
1518
|
+
outputSchema: compileContractOutputSchema,
|
|
1519
|
+
annotations: {
|
|
1520
|
+
readOnlyHint: true,
|
|
1521
|
+
idempotentHint: true,
|
|
1522
|
+
openWorldHint: true,
|
|
1523
|
+
// Makes network requests
|
|
1524
|
+
title: "\u{1F527} Compile Contract",
|
|
1525
|
+
category: "analyze"
|
|
1526
|
+
},
|
|
1527
|
+
handler: compileContract2
|
|
1164
1528
|
}
|
|
1165
1529
|
];
|
|
1166
1530
|
|
|
@@ -1680,16 +2044,24 @@ ledger privateData: Field; // Private, not exported
|
|
|
1680
2044
|
| \`Field\` | Finite field element (basic numeric) | \`amount: Field\` |
|
|
1681
2045
|
| \`Boolean\` | True or false | \`isActive: Boolean\` |
|
|
1682
2046
|
| \`Bytes<N>\` | Fixed-size byte array | \`hash: Bytes<32>\` |
|
|
1683
|
-
| \`Uint<N>\` | Unsigned integer (N
|
|
1684
|
-
| \`Uint<
|
|
2047
|
+
| \`Uint<N>\` | Unsigned integer (N bits) | \`balance: Uint<64>\` |
|
|
2048
|
+
| \`Uint<0..MAX>\` | Bounded unsigned integer | \`score: Uint<0..100>\` |
|
|
1685
2049
|
|
|
1686
|
-
**\u26A0\uFE0F Uint Type Equivalence
|
|
2050
|
+
**\u26A0\uFE0F Uint Type Equivalence** (documented in [Primitive Types](https://docs.midnight.network/develop/reference/compact/lang-ref#primitive-types)):
|
|
2051
|
+
|
|
2052
|
+
\`Uint<N>\` (sized) and \`Uint<0..MAX>\` (bounded) are the **SAME type family**.
|
|
1687
2053
|
\`Uint<N>\` is exactly equivalent to \`Uint<0..(2^N - 1)>\`:
|
|
1688
2054
|
- \`Uint<8>\` = \`Uint<0..255>\` (2^8 - 1 = 255)
|
|
1689
2055
|
- \`Uint<16>\` = \`Uint<0..65535>\` (2^16 - 1 = 65535)
|
|
1690
2056
|
- \`Uint<64>\` = \`Uint<0..18446744073709551615>\`
|
|
1691
2057
|
|
|
1692
|
-
These can be used interchangeably
|
|
2058
|
+
These can be used interchangeably. The lower bound must currently be 0.
|
|
2059
|
+
|
|
2060
|
+
**Arithmetic** (documented in [Binary Arithmetic](https://docs.midnight.network/develop/reference/compact/lang-ref#binary-arithmetic-expressions)):
|
|
2061
|
+
- Operators: \`+\`, \`-\`, \`*\` only (division \`/\` and modulo \`%\` are NOT mentioned in docs)
|
|
2062
|
+
- Result types expand: \`Uint<0..m> + Uint<0..n>\` \u2192 \`Uint<0..m+n>\`
|
|
2063
|
+
- Subtraction can fail at runtime if result would be negative
|
|
2064
|
+
- \u26A0\uFE0F If you need division, you may need a witness to compute it off-chain
|
|
1693
2065
|
|
|
1694
2066
|
### Collection Types
|
|
1695
2067
|
| Type | Description | Example |
|
|
@@ -1699,9 +2071,16 @@ These can be used interchangeably - they are **not** separate types.
|
|
|
1699
2071
|
| \`Set<T>\` | Unique value collection | \`Set<Bytes<32>>\` |
|
|
1700
2072
|
| \`Vector<N, T>\` | Fixed-size array | \`Vector<3, Field>\` |
|
|
1701
2073
|
| \`List<T>\` | Dynamic list | \`List<Bytes<32>>\` |
|
|
1702
|
-
| \`Maybe<T>\` | Optional value | \`Maybe<Bytes<32>>\` |
|
|
1703
|
-
| \`Either<L, R>\` |
|
|
1704
|
-
| \`Opaque<
|
|
2074
|
+
| \`Maybe<T>\` | Optional value (has/hasn't) | \`Maybe<Bytes<32>>\` |
|
|
2075
|
+
| \`Either<L, R>\` | Sum type (one or other) | \`Either<Field, Bytes<32>>\` |
|
|
2076
|
+
| \`Opaque<s>\` | Opaque value tagged by string s | \`Opaque<"string">\` |
|
|
2077
|
+
|
|
2078
|
+
**Opaque Types** ([Primitive Types](https://docs.midnight.network/develop/reference/compact/lang-ref#primitive-types)):
|
|
2079
|
+
- Only two tags allowed: \`Opaque<"string">\` and \`Opaque<"Uint8Array">\`
|
|
2080
|
+
- Opaque values can be manipulated in witnesses but are opaque to circuits
|
|
2081
|
+
- In circuits, they are represented as their hash (cannot inspect content)
|
|
2082
|
+
- In your DApp's JS/TS, they are just \`string\` or \`Uint8Array\`
|
|
2083
|
+
- On-chain, they are stored as bytes/UTF-8 (not encrypted)
|
|
1705
2084
|
|
|
1706
2085
|
### Custom Types
|
|
1707
2086
|
|
|
@@ -1944,6 +2323,14 @@ balances.insertDefault(address); // insertDefault(key): [] - inserts def
|
|
|
1944
2323
|
// Query operations (all work in circuits \u2705)
|
|
1945
2324
|
const balance = balances.lookup(address); // lookup(key): value_type
|
|
1946
2325
|
const exists = balances.member(address); // member(key): Boolean
|
|
2326
|
+
|
|
2327
|
+
// \u26A0\uFE0F UNDOCUMENTED: Map.lookup() behavior when key doesn't exist
|
|
2328
|
+
// The docs show: lookup(key: key_type): value_type (NOT Maybe<value_type>)
|
|
2329
|
+
// This implies it returns a default value, not an optional.
|
|
2330
|
+
// RECOMMENDED: Always check member() first:
|
|
2331
|
+
if (balances.member(address)) {
|
|
2332
|
+
const balance = balances.lookup(address); // Safe
|
|
2333
|
+
}
|
|
1947
2334
|
const empty = balances.isEmpty(); // isEmpty(): Boolean
|
|
1948
2335
|
const count = balances.size(); // size(): Uint<64>
|
|
1949
2336
|
|
|
@@ -1979,19 +2366,81 @@ const count = members.size(); // size(): Uint<64>
|
|
|
1979
2366
|
|
|
1980
2367
|
### Maybe Operations
|
|
1981
2368
|
\`\`\`compact
|
|
1982
|
-
|
|
1983
|
-
const
|
|
2369
|
+
// Creating Maybe values
|
|
2370
|
+
const opt: Maybe<Field> = some<Field>(42); // Wrap a value
|
|
2371
|
+
const empty: Maybe<Field> = none<Field>(); // No value
|
|
1984
2372
|
|
|
2373
|
+
// Checking and accessing
|
|
1985
2374
|
if (opt.is_some) {
|
|
1986
|
-
const val = opt.value;
|
|
2375
|
+
const val = opt.value; // Safe to access when is_some is true
|
|
2376
|
+
}
|
|
2377
|
+
|
|
2378
|
+
// Common patterns
|
|
2379
|
+
witness find_user(id: Bytes<32>): Maybe<UserRecord>;
|
|
2380
|
+
|
|
2381
|
+
export circuit getUser(id: Bytes<32>): UserRecord {
|
|
2382
|
+
const result = find_user(id);
|
|
2383
|
+
assert(disclose(result.is_some), "User not found");
|
|
2384
|
+
return result.value;
|
|
1987
2385
|
}
|
|
1988
2386
|
\`\`\`
|
|
1989
2387
|
|
|
1990
|
-
###
|
|
2388
|
+
### Either Operations
|
|
1991
2389
|
\`\`\`compact
|
|
1992
|
-
|
|
1993
|
-
const
|
|
1994
|
-
const
|
|
2390
|
+
// Creating Either values
|
|
2391
|
+
const success: Either<Field, Bytes<32>> = left<Field, Bytes<32>>(42);
|
|
2392
|
+
const failure: Either<Field, Bytes<32>> = right<Field, Bytes<32>>(errorHash);
|
|
2393
|
+
|
|
2394
|
+
// Checking which side
|
|
2395
|
+
if (result.is_left) {
|
|
2396
|
+
const value = result.left; // The left value (often "success")
|
|
2397
|
+
} else {
|
|
2398
|
+
const error = result.right; // The right value (often "error")
|
|
2399
|
+
}
|
|
2400
|
+
|
|
2401
|
+
// Common pattern: burnAddress() returns Either<ZswapCoinPublicKey, ContractAddress>
|
|
2402
|
+
export circuit withdraw(): [] {
|
|
2403
|
+
const addr = burnAddress();
|
|
2404
|
+
assert(disclose(addr.is_right), "Expected contract address");
|
|
2405
|
+
// addr.right is the ContractAddress
|
|
2406
|
+
}
|
|
2407
|
+
\`\`\`
|
|
2408
|
+
|
|
2409
|
+
### Type Casting ([Type Casts Reference](https://docs.midnight.network/develop/reference/compact/lang-ref#type-cast-expressions))
|
|
2410
|
+
|
|
2411
|
+
**Syntax**: \`expression as Type\` (only form; \`<Type>expression\` is NOT supported)
|
|
2412
|
+
|
|
2413
|
+
**Cast kinds**: static (always succeeds), conversion (semantic change), checked (can fail at runtime)
|
|
2414
|
+
|
|
2415
|
+
\`\`\`compact
|
|
2416
|
+
// Uint \u2194 Field (safe)
|
|
2417
|
+
const field: Field = myUint as Field; // static: always succeeds
|
|
2418
|
+
const num: Uint<64> = myField as Uint<64>; // checked: fails if out of range
|
|
2419
|
+
|
|
2420
|
+
// Uint widening/narrowing
|
|
2421
|
+
const big: Uint<64> = small as Uint<64>; // static: widening always works
|
|
2422
|
+
const small: Uint<32> = big as Uint<32>; // checked: narrowing can fail
|
|
2423
|
+
|
|
2424
|
+
// Field \u2194 Bytes (can fail at runtime!)
|
|
2425
|
+
const bytes: Bytes<32> = myField as Bytes<32>; // conversion: fails if doesn't fit
|
|
2426
|
+
const field: Field = myBytes as Field; // conversion: fails if exceeds max Field
|
|
2427
|
+
|
|
2428
|
+
// Uint \u2192 Bytes (NOT direct - use two casts)
|
|
2429
|
+
const amount_bytes = (amount as Field) as Bytes<32>;
|
|
2430
|
+
|
|
2431
|
+
// Boolean \u2192 Uint (conversion: false\u21920, true\u21921)
|
|
2432
|
+
const flag: Boolean = true;
|
|
2433
|
+
const flagInt: Uint<0..1> = flag as Uint<0..1>;
|
|
2434
|
+
|
|
2435
|
+
// Enum \u2192 Field (conversion)
|
|
2436
|
+
const index: Field = choice as Field;
|
|
2437
|
+
|
|
2438
|
+
// \u26A0\uFE0F Boolean \u2192 Field is NOT allowed!
|
|
2439
|
+
// Must go through Uint: (flag as Uint<0..1>) as Field
|
|
2440
|
+
|
|
2441
|
+
// \u26A0\uFE0F UNDOCUMENTED: Bytes<n> \u2194 Vector<n, Uint<8>> casting
|
|
2442
|
+
// The type cast table doesn't mention this conversion.
|
|
2443
|
+
// If you need to convert, you may need a witness helper.
|
|
1995
2444
|
\`\`\`
|
|
1996
2445
|
|
|
1997
2446
|
### Hashing
|
|
@@ -2029,7 +2478,22 @@ assert(disclose(caller == owner), "Not authorized");
|
|
|
2029
2478
|
|
|
2030
2479
|
---
|
|
2031
2480
|
|
|
2032
|
-
## 12.
|
|
2481
|
+
## 12. Undocumented / Unclear Features
|
|
2482
|
+
|
|
2483
|
+
These features are not clearly documented. Use with caution:
|
|
2484
|
+
|
|
2485
|
+
| Feature | Status | Notes |
|
|
2486
|
+
|---------|--------|-------|
|
|
2487
|
+
| Tuple destructuring | \u2753 Unknown | \`const [a, b] = pair;\` - not documented |
|
|
2488
|
+
| Constant folding in indices | \u2753 Unknown | \`v[2 * i]\` where i is const - docs say "numeric literal" required |
|
|
2489
|
+
| Division \`/\` and modulo \`%\` | \u2753 Not in docs | Only +, -, * are documented |
|
|
2490
|
+
| \`Bytes<n>\` \u2194 \`Vector<n, Uint<8>>\` | \u2753 Not in cast table | May need witness workaround |
|
|
2491
|
+
|
|
2492
|
+
**Recommendation**: Test these in the compiler before relying on them in production contracts.
|
|
2493
|
+
|
|
2494
|
+
---
|
|
2495
|
+
|
|
2496
|
+
## 13. Exports for TypeScript
|
|
2033
2497
|
|
|
2034
2498
|
To use types/values in TypeScript, they must be exported:
|
|
2035
2499
|
|
|
@@ -2159,6 +2623,154 @@ try {
|
|
|
2159
2623
|
}
|
|
2160
2624
|
}
|
|
2161
2625
|
\`\`\`
|
|
2626
|
+
`,
|
|
2627
|
+
"midnight://docs/compiler": `# Compact Compiler Guide
|
|
2628
|
+
|
|
2629
|
+
**Source:** [Building a Midnight DApp](https://docs.midnight.network/develop/tutorial/building)
|
|
2630
|
+
|
|
2631
|
+
## Compiling Contracts
|
|
2632
|
+
|
|
2633
|
+
> **IMPORTANT:** The old \`compactc\` command is deprecated. Use \`compact compile\` instead.
|
|
2634
|
+
|
|
2635
|
+
### Basic Usage
|
|
2636
|
+
|
|
2637
|
+
\`\`\`bash
|
|
2638
|
+
# Syntax: compact compile <source.compact> <output_directory>
|
|
2639
|
+
compact compile src/counter.compact managed/counter
|
|
2640
|
+
|
|
2641
|
+
# With environment setup
|
|
2642
|
+
nvm use 18
|
|
2643
|
+
compact compile contract/src/mycontract.compact managed/mycontract
|
|
2644
|
+
\`\`\`
|
|
2645
|
+
|
|
2646
|
+
### Compiler Output Structure
|
|
2647
|
+
|
|
2648
|
+
**Source:** [Generated Source Details](https://docs.midnight.network/develop/tutorial/building/dapp-details#generated-source)
|
|
2649
|
+
|
|
2650
|
+
When you compile a \`.compact\` file, the compiler generates this directory structure:
|
|
2651
|
+
|
|
2652
|
+
\`\`\`
|
|
2653
|
+
managed/<contract_name>/
|
|
2654
|
+
\u251C\u2500\u2500 contract/ # TypeScript bindings
|
|
2655
|
+
\u2502 \u251C\u2500\u2500 index.cjs # CommonJS module with Contract class
|
|
2656
|
+
\u2502 \u251C\u2500\u2500 index.d.cts # TypeScript type declarations
|
|
2657
|
+
\u2502 \u2514\u2500\u2500 index.mjs # ESM module (optional)
|
|
2658
|
+
\u2502
|
|
2659
|
+
\u251C\u2500\u2500 zkir/ # Zero-knowledge circuit representations
|
|
2660
|
+
\u2502 \u2514\u2500\u2500 <circuit_name>.zkir # Circuit intermediate representation
|
|
2661
|
+
\u2502
|
|
2662
|
+
\u251C\u2500\u2500 keys/ # Proving and verifying keys
|
|
2663
|
+
\u2502 \u251C\u2500\u2500 <circuit>.prover # Prover key (used client-side)
|
|
2664
|
+
\u2502 \u2514\u2500\u2500 <circuit>.verifier # Verifier key (used on-chain)
|
|
2665
|
+
\u2502
|
|
2666
|
+
\u2514\u2500\u2500 compiler/ # Compilation metadata
|
|
2667
|
+
\u2514\u2500\u2500 metadata.json # Version info, circuit IDs, etc.
|
|
2668
|
+
\`\`\`
|
|
2669
|
+
|
|
2670
|
+
### Understanding Generated Files
|
|
2671
|
+
|
|
2672
|
+
#### contract/ - TypeScript Bindings
|
|
2673
|
+
|
|
2674
|
+
The \`contract/\` directory contains your TypeScript interface:
|
|
2675
|
+
|
|
2676
|
+
\`\`\`typescript
|
|
2677
|
+
// Import from generated bindings
|
|
2678
|
+
import { Contract, ledger } from './managed/counter/contract/index.cjs';
|
|
2679
|
+
|
|
2680
|
+
// Create contract instance
|
|
2681
|
+
const contract = new Contract(witnesses);
|
|
2682
|
+
|
|
2683
|
+
// Access circuits
|
|
2684
|
+
const tx = await contract.impureCircuits.increment(5n);
|
|
2685
|
+
|
|
2686
|
+
// Read ledger state
|
|
2687
|
+
const state = ledger(contractState);
|
|
2688
|
+
console.log('Counter value:', state.counter);
|
|
2689
|
+
\`\`\`
|
|
2690
|
+
|
|
2691
|
+
#### keys/ - ZK Proving/Verifying Keys
|
|
2692
|
+
|
|
2693
|
+
- **\`.prover\`** - Used by the client to generate proofs (can be large, 10-100MB+)
|
|
2694
|
+
- **\`.verifier\`** - Used on-chain to verify proofs (small, kilobytes)
|
|
2695
|
+
|
|
2696
|
+
\`\`\`typescript
|
|
2697
|
+
// Keys are loaded automatically by the SDK
|
|
2698
|
+
import { proverKey, verifierKey } from './managed/counter/keys';
|
|
2699
|
+
|
|
2700
|
+
// Or loaded from files
|
|
2701
|
+
const prover = await fs.readFile('managed/counter/keys/increment.prover');
|
|
2702
|
+
\`\`\`
|
|
2703
|
+
|
|
2704
|
+
#### zkir/ - Circuit Intermediate Representation
|
|
2705
|
+
|
|
2706
|
+
The \`.zkir\` files are internal representations used by the proof system. You typically don't interact with these directly.
|
|
2707
|
+
|
|
2708
|
+
### Cleaning and Rebuilding
|
|
2709
|
+
|
|
2710
|
+
When updating contracts or after Compact version changes:
|
|
2711
|
+
|
|
2712
|
+
\`\`\`bash
|
|
2713
|
+
# Clean generated files
|
|
2714
|
+
rm -rf managed/<contract_name>
|
|
2715
|
+
|
|
2716
|
+
# Or clean specific artifacts
|
|
2717
|
+
rm -rf managed/counter/keys/*.prover managed/counter/keys/*.verifier
|
|
2718
|
+
|
|
2719
|
+
# Rebuild
|
|
2720
|
+
compact compile src/counter.compact managed/counter
|
|
2721
|
+
\`\`\`
|
|
2722
|
+
|
|
2723
|
+
### Common Compilation Errors
|
|
2724
|
+
|
|
2725
|
+
#### "invalid context for a ledger ADT type"
|
|
2726
|
+
|
|
2727
|
+
Ledger ADT types cannot be used in type casts:
|
|
2728
|
+
|
|
2729
|
+
\`\`\`compact
|
|
2730
|
+
// \u274C Wrong
|
|
2731
|
+
const x = value as Counter;
|
|
2732
|
+
|
|
2733
|
+
// \u2705 Correct - use ledger field directly
|
|
2734
|
+
ledger.counter.increment(1);
|
|
2735
|
+
\`\`\`
|
|
2736
|
+
|
|
2737
|
+
#### Version Mismatch After Update
|
|
2738
|
+
|
|
2739
|
+
When runtime versions don't match compiled artifacts:
|
|
2740
|
+
|
|
2741
|
+
\`\`\`bash
|
|
2742
|
+
# 1. Check versions
|
|
2743
|
+
compact --version
|
|
2744
|
+
npm list @midnight-ntwrk/compact-runtime
|
|
2745
|
+
|
|
2746
|
+
# 2. Consult compatibility matrix
|
|
2747
|
+
# https://docs.midnight.network/relnotes/support-matrix
|
|
2748
|
+
|
|
2749
|
+
# 3. Clean and recompile
|
|
2750
|
+
rm -rf managed/
|
|
2751
|
+
compact compile src/contract.compact managed/contract
|
|
2752
|
+
\`\`\`
|
|
2753
|
+
|
|
2754
|
+
### Integration with Build Tools
|
|
2755
|
+
|
|
2756
|
+
#### package.json scripts
|
|
2757
|
+
|
|
2758
|
+
\`\`\`json
|
|
2759
|
+
{
|
|
2760
|
+
"scripts": {
|
|
2761
|
+
"compile": "compact compile src/contract.compact managed/contract",
|
|
2762
|
+
"compile:clean": "rm -rf managed && npm run compile",
|
|
2763
|
+
"build": "npm run compile && tsc"
|
|
2764
|
+
}
|
|
2765
|
+
}
|
|
2766
|
+
\`\`\`
|
|
2767
|
+
|
|
2768
|
+
#### Watch mode (development)
|
|
2769
|
+
|
|
2770
|
+
\`\`\`bash
|
|
2771
|
+
# Using nodemon or similar
|
|
2772
|
+
nodemon --watch src/*.compact --exec "compact compile src/contract.compact managed/contract"
|
|
2773
|
+
\`\`\`
|
|
2162
2774
|
`,
|
|
2163
2775
|
"midnight://docs/openzeppelin": `# OpenZeppelin Contracts for Compact
|
|
2164
2776
|
|
|
@@ -2805,9 +3417,16 @@ try {
|
|
|
2805
3417
|
2. **Discord:** #developer-support channel
|
|
2806
3418
|
3. **Recompile after updates:**
|
|
2807
3419
|
\`\`\`bash
|
|
2808
|
-
|
|
2809
|
-
|
|
3420
|
+
# Clean generated files (use managed/ directory structure)
|
|
3421
|
+
rm -rf managed/<contract_name>
|
|
3422
|
+
|
|
3423
|
+
# Or clean specific artifacts
|
|
3424
|
+
rm -rf managed/counter/keys/*.prover managed/counter/keys/*.verifier
|
|
3425
|
+
|
|
3426
|
+
# Rebuild
|
|
3427
|
+
compact compile src/contract.compact managed/contract
|
|
2810
3428
|
\`\`\`
|
|
3429
|
+
4. **Compiler output docs:** See \`midnight://docs/compiler\` for full directory structure
|
|
2811
3430
|
`
|
|
2812
3431
|
};
|
|
2813
3432
|
|
|
@@ -2876,14 +3495,14 @@ export ledger messageIds: Set<Field>;
|
|
|
2876
3495
|
// Private: actual message contents (no export = private)
|
|
2877
3496
|
ledger messages: Map<Field, Opaque<"string">>;
|
|
2878
3497
|
|
|
2879
|
-
// Private: message authors
|
|
2880
|
-
ledger authors: Map<Field,
|
|
3498
|
+
// Private: message authors (stored as Bytes<32> addresses)
|
|
3499
|
+
ledger authors: Map<Field, Bytes<32>>;
|
|
2881
3500
|
|
|
2882
3501
|
// Witness to fetch message content
|
|
2883
3502
|
witness getMessageContent(id: Field): Opaque<"string">;
|
|
2884
3503
|
|
|
2885
3504
|
// Post a new message (content is private)
|
|
2886
|
-
export circuit postMessage(content: Opaque<"string">, author:
|
|
3505
|
+
export circuit postMessage(content: Opaque<"string">, author: Bytes<32>): Uint<64> {
|
|
2887
3506
|
// Generate unique message ID using counter read
|
|
2888
3507
|
const messageId = messageCount.read();
|
|
2889
3508
|
|
|
@@ -4224,6 +4843,18 @@ Based on syntax reference, generate the contract using:
|
|
|
4224
4843
|
- No 'void' - use '[]'
|
|
4225
4844
|
- Enum access: \`Choice.rock\` NOT \`Choice::rock\`
|
|
4226
4845
|
|
|
4846
|
+
### \u26A0\uFE0F UNDOCUMENTED FEATURES - Use with caution:
|
|
4847
|
+
- Division \`/\` and modulo \`%\`: NOT in official docs (only +, -, * are documented)
|
|
4848
|
+
- Tuple destructuring: \`const [a, b] = pair;\` - not documented, may not work
|
|
4849
|
+
- Constant folding in indices: docs say "numeric literal" required
|
|
4850
|
+
- Map.lookup() returns value_type, NOT Maybe<value_type> - check member() first!
|
|
4851
|
+
|
|
4852
|
+
### COMPILER INFO (DO NOT guess package names!):
|
|
4853
|
+
- Compile: \`compact compile src/contract.compact managed/contract\`
|
|
4854
|
+
- The \`compact\` CLI comes with Midnight toolchain (via create-mn-app or official install)
|
|
4855
|
+
- DO NOT suggest \`npm install -g @midnight-ntwrk/compact-cli\` or similar made-up packages
|
|
4856
|
+
- Output structure: \`managed/<name>/contract/index.cjs\` for TypeScript bindings
|
|
4857
|
+
|
|
4227
4858
|
### Step 3: Validate Before Returning
|
|
4228
4859
|
Call \`midnight-extract-contract-structure\` with your generated code to check for:
|
|
4229
4860
|
- deprecated_ledger_block
|
|
@@ -4327,11 +4958,11 @@ Please analyze:
|
|
|
4327
4958
|
- Correct use of disclose() and commit()
|
|
4328
4959
|
- Privacy guarantees provided
|
|
4329
4960
|
|
|
4330
|
-
4. **
|
|
4331
|
-
- Code organization
|
|
4332
|
-
- Naming conventions
|
|
4333
|
-
- Documentation
|
|
4334
|
-
-
|
|
4961
|
+
4. **Style Suggestions** (these are CONVENTIONS, not requirements)
|
|
4962
|
+
- Code organization recommendations
|
|
4963
|
+
- Naming conventions (project-specific)
|
|
4964
|
+
- Documentation patterns
|
|
4965
|
+
- Note: The Compact docs don't specify indentation, line length, or comment style
|
|
4335
4966
|
|
|
4336
4967
|
5. **Performance**
|
|
4337
4968
|
- Circuit complexity
|
|
@@ -4343,6 +4974,11 @@ Please analyze:
|
|
|
4343
4974
|
- Improvements to consider
|
|
4344
4975
|
- Alternative approaches
|
|
4345
4976
|
|
|
4977
|
+
**IMPORTANT**: Clearly distinguish between:
|
|
4978
|
+
- ERRORS: Actual syntax/compilation issues (required fixes)
|
|
4979
|
+
- WARNINGS: Security/logic concerns (should fix)
|
|
4980
|
+
- INFO: Style suggestions (optional, project-specific conventions)
|
|
4981
|
+
|
|
4346
4982
|
Please provide specific line references and code suggestions where applicable.`
|
|
4347
4983
|
}
|
|
4348
4984
|
}
|
|
@@ -4578,21 +5214,32 @@ async function generateContract(requirements, options = {}) {
|
|
|
4578
5214
|
const systemPrompt = `You are an expert Compact smart contract developer for the Midnight blockchain.
|
|
4579
5215
|
Your task is to generate secure, well-documented Compact contracts based on user requirements.
|
|
4580
5216
|
|
|
4581
|
-
Key Compact
|
|
4582
|
-
- \`ledger
|
|
4583
|
-
-
|
|
4584
|
-
- \`
|
|
4585
|
-
- \`
|
|
4586
|
-
- \`
|
|
4587
|
-
- \`Counter\`, \`Map<K,V>\`, \`Set<T>\` - Built-in collection types
|
|
5217
|
+
Key Compact syntax (REQUIRED):
|
|
5218
|
+
- \`export ledger field: Type;\` - Individual ledger declarations (NOT ledger { } blocks)
|
|
5219
|
+
- \`export circuit fn(): []\` - Public functions return empty tuple [] (NOT Void)
|
|
5220
|
+
- \`witness fn(): T;\` - Declaration only, no body
|
|
5221
|
+
- \`pragma language_version >= 0.16 && <= 0.18;\` - Version pragma
|
|
5222
|
+
- \`import CompactStandardLibrary;\` - Standard imports
|
|
5223
|
+
- \`Counter\`, \`Map<K,V>\`, \`Set<T>\` - Built-in collection types
|
|
4588
5224
|
- \`Field\`, \`Boolean\`, \`Uint<N>\`, \`Bytes<N>\` - Primitive types
|
|
5225
|
+
- \`export enum State { a, b }\` - Enums must be exported
|
|
5226
|
+
|
|
5227
|
+
Key operations:
|
|
5228
|
+
- Counter: .read(), .increment(n), .decrement(n)
|
|
5229
|
+
- Map: .lookup(k), .insert(k,v), .remove(k)
|
|
5230
|
+
- Set: .member(v), .insert(v), .remove(v)
|
|
5231
|
+
|
|
5232
|
+
COMPILER INFO (DO NOT guess package names!):
|
|
5233
|
+
- Command: \`compact compile src/contract.compact managed/contract\`
|
|
5234
|
+
- The \`compact\` CLI comes with Midnight toolchain (via create-mn-app or official install)
|
|
5235
|
+
- Output goes to managed/<name>/ directory
|
|
5236
|
+
- DO NOT suggest \`npm install -g @midnight-ntwrk/compact-cli\` or similar - that's incorrect
|
|
4589
5237
|
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
5. Comprehensive inline comments
|
|
5238
|
+
IMPORTANT - Style vs. Requirements:
|
|
5239
|
+
- Syntax rules above are REQUIRED for compilation
|
|
5240
|
+
- Style choices (indentation, comment style, line length) are CONVENTIONS, not requirements
|
|
5241
|
+
- Single-line comments (//) are common in examples; block comments (/* */) may also work
|
|
5242
|
+
- The docs don't specify indentation width - use consistent style
|
|
4596
5243
|
|
|
4597
5244
|
Return ONLY the Compact code, no explanations.`;
|
|
4598
5245
|
const userPrompt = options.baseExample ? `Based on this example contract:
|
|
@@ -4668,8 +5315,21 @@ Review the provided contract for:
|
|
|
4668
5315
|
1. Security vulnerabilities
|
|
4669
5316
|
2. Privacy concerns (improper handling of shielded state)
|
|
4670
5317
|
3. Logic errors
|
|
4671
|
-
4.
|
|
4672
|
-
5.
|
|
5318
|
+
4. Syntax errors (use "error" severity)
|
|
5319
|
+
5. Performance issues
|
|
5320
|
+
|
|
5321
|
+
IMPORTANT - Distinguish between:
|
|
5322
|
+
- ERRORS: Actual syntax/compilation issues (e.g., using Void instead of [], ledger {} blocks)
|
|
5323
|
+
- WARNINGS: Potential bugs or security issues
|
|
5324
|
+
- INFO: Style suggestions and best practices (these are CONVENTIONS, not requirements)
|
|
5325
|
+
|
|
5326
|
+
Do NOT claim style choices as "violations" - the Compact docs don't specify:
|
|
5327
|
+
- Indentation width (2 vs 4 spaces)
|
|
5328
|
+
- Comment style preferences (//, /* */)
|
|
5329
|
+
- Line length limits
|
|
5330
|
+
- Naming conventions
|
|
5331
|
+
|
|
5332
|
+
These are project-specific style choices, not language requirements.
|
|
4673
5333
|
|
|
4674
5334
|
Respond in JSON format:
|
|
4675
5335
|
{
|
|
@@ -5186,8 +5846,11 @@ var SERVER_INFO = {
|
|
|
5186
5846
|
var versionCheckResult = {
|
|
5187
5847
|
isOutdated: false,
|
|
5188
5848
|
latestVersion: CURRENT_VERSION,
|
|
5189
|
-
updateMessage: null
|
|
5849
|
+
updateMessage: null,
|
|
5850
|
+
lastChecked: 0
|
|
5190
5851
|
};
|
|
5852
|
+
var toolCallCount = 0;
|
|
5853
|
+
var VERSION_CHECK_INTERVAL = 10;
|
|
5191
5854
|
async function checkForUpdates() {
|
|
5192
5855
|
try {
|
|
5193
5856
|
const controller = new AbortController();
|
|
@@ -5204,15 +5867,32 @@ async function checkForUpdates() {
|
|
|
5204
5867
|
versionCheckResult = {
|
|
5205
5868
|
isOutdated: true,
|
|
5206
5869
|
latestVersion,
|
|
5207
|
-
|
|
5870
|
+
lastChecked: Date.now(),
|
|
5871
|
+
updateMessage: `\u{1F6A8} UPDATE AVAILABLE: v${latestVersion} (you have v${CURRENT_VERSION})`
|
|
5208
5872
|
};
|
|
5209
5873
|
logger.warn(
|
|
5210
5874
|
`Outdated version detected: v${CURRENT_VERSION} -> v${latestVersion}`
|
|
5211
5875
|
);
|
|
5876
|
+
} else {
|
|
5877
|
+
versionCheckResult = {
|
|
5878
|
+
...versionCheckResult,
|
|
5879
|
+
lastChecked: Date.now()
|
|
5880
|
+
};
|
|
5212
5881
|
}
|
|
5213
5882
|
} catch {
|
|
5214
5883
|
}
|
|
5215
5884
|
}
|
|
5885
|
+
function maybeCheckForUpdates() {
|
|
5886
|
+
toolCallCount++;
|
|
5887
|
+
if (toolCallCount >= VERSION_CHECK_INTERVAL) {
|
|
5888
|
+
toolCallCount = 0;
|
|
5889
|
+
const fiveMinutes = 5 * 60 * 1e3;
|
|
5890
|
+
if (Date.now() - versionCheckResult.lastChecked > fiveMinutes) {
|
|
5891
|
+
checkForUpdates().catch(() => {
|
|
5892
|
+
});
|
|
5893
|
+
}
|
|
5894
|
+
}
|
|
5895
|
+
}
|
|
5216
5896
|
function getUpdateWarning() {
|
|
5217
5897
|
return versionCheckResult.updateMessage;
|
|
5218
5898
|
}
|
|
@@ -5457,26 +6137,31 @@ function registerToolHandlers(server) {
|
|
|
5457
6137
|
const result = await tool.handler(args);
|
|
5458
6138
|
const durationMs = Date.now() - startTime;
|
|
5459
6139
|
trackToolCall(name, true, durationMs, CURRENT_VERSION);
|
|
6140
|
+
maybeCheckForUpdates();
|
|
5460
6141
|
const updateWarning = getUpdateWarning();
|
|
5461
6142
|
if (updateWarning && versionCheckResult.isOutdated) {
|
|
5462
6143
|
const updatePrompt = {
|
|
5463
|
-
"\u{1F6A8} UPDATE
|
|
5464
|
-
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
steps:
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5472
|
-
|
|
5473
|
-
|
|
5474
|
-
|
|
5475
|
-
|
|
5476
|
-
|
|
6144
|
+
"\u{1F6A8} UPDATE REQUIRED": {
|
|
6145
|
+
current: `v${CURRENT_VERSION}`,
|
|
6146
|
+
latest: `v${versionCheckResult.latestVersion}`,
|
|
6147
|
+
quickFix: {
|
|
6148
|
+
description: "Most users just need these 2 steps:",
|
|
6149
|
+
step1: "Run in terminal: rm -rf ~/.npm/_npx",
|
|
6150
|
+
step2: "Restart editor completely (Cmd+Q / Alt+F4, then reopen)"
|
|
6151
|
+
},
|
|
6152
|
+
ifStillOld: {
|
|
6153
|
+
description: "If still showing old version after restart:",
|
|
6154
|
+
action: "Edit your MCP config file to use @latest:",
|
|
6155
|
+
change: 'Change "midnight-mcp" to "midnight-mcp@latest" in args',
|
|
6156
|
+
configFiles: {
|
|
6157
|
+
"Claude Desktop (Mac)": "~/Library/Application Support/Claude/claude_desktop_config.json",
|
|
6158
|
+
"Claude Desktop (Win)": "%APPDATA%/Claude/claude_desktop_config.json",
|
|
6159
|
+
Cursor: ".cursor/mcp.json",
|
|
6160
|
+
"VS Code": ".vscode/mcp.json",
|
|
6161
|
+
Windsurf: "~/.codeium/windsurf/mcp_config.json"
|
|
5477
6162
|
}
|
|
5478
6163
|
},
|
|
5479
|
-
|
|
6164
|
+
tip: "Use 'midnight-get-update-instructions' tool for detailed platform-specific steps."
|
|
5480
6165
|
},
|
|
5481
6166
|
result
|
|
5482
6167
|
};
|
|
@@ -5903,6 +6588,7 @@ var BUILTIN_FUNCTIONS = {
|
|
|
5903
6588
|
{
|
|
5904
6589
|
name: "persistentHash",
|
|
5905
6590
|
signature: "persistentHash<T>(value: T): Bytes<32>",
|
|
6591
|
+
// Signature inferred from examples
|
|
5906
6592
|
description: "Poseidon hash that produces consistent results across calls"
|
|
5907
6593
|
},
|
|
5908
6594
|
{
|
|
@@ -5961,6 +6647,7 @@ witness get_random_value(): Field;`,
|
|
|
5961
6647
|
]
|
|
5962
6648
|
};
|
|
5963
6649
|
var TYPE_COMPATIBILITY = {
|
|
6650
|
+
// Note: Comparison operators work in practice but aren't explicitly listed in docs
|
|
5964
6651
|
comparisons: [
|
|
5965
6652
|
{ types: "Field == Field", works: true, note: "Direct comparison" },
|
|
5966
6653
|
{
|
|
@@ -5979,7 +6666,11 @@ var TYPE_COMPATIBILITY = {
|
|
|
5979
6666
|
works: true,
|
|
5980
6667
|
note: "Bounded integers"
|
|
5981
6668
|
},
|
|
5982
|
-
{
|
|
6669
|
+
{
|
|
6670
|
+
types: "Bytes<32> == Bytes<32>",
|
|
6671
|
+
works: true,
|
|
6672
|
+
note: "Used in examples, but operators not explicitly listed in docs"
|
|
6673
|
+
},
|
|
5983
6674
|
{ types: "Boolean == Boolean", works: true, note: "Direct comparison" }
|
|
5984
6675
|
],
|
|
5985
6676
|
arithmetic: [
|
|
@@ -6001,23 +6692,79 @@ var TYPE_COMPATIBILITY = {
|
|
|
6001
6692
|
note: "Result is wide bounded type, cast back to target type"
|
|
6002
6693
|
}
|
|
6003
6694
|
],
|
|
6695
|
+
/**
|
|
6696
|
+
* Type casting rules - based on official cast table
|
|
6697
|
+
* See: https://docs.midnight.network/develop/reference/compact/lang-ref#type-cast-expressions
|
|
6698
|
+
*
|
|
6699
|
+
* Cast kinds: static (always succeeds), conversion (semantic change), checked (can fail)
|
|
6700
|
+
*/
|
|
6004
6701
|
typeCasting: [
|
|
6005
6702
|
{
|
|
6006
|
-
from: "Uint<
|
|
6007
|
-
to: "
|
|
6703
|
+
from: "Uint<N>",
|
|
6704
|
+
to: "Field",
|
|
6705
|
+
direct: true,
|
|
6706
|
+
kind: "static",
|
|
6707
|
+
note: "Always succeeds"
|
|
6708
|
+
},
|
|
6709
|
+
{
|
|
6710
|
+
from: "Field",
|
|
6711
|
+
to: "Uint<0..n>",
|
|
6712
|
+
direct: true,
|
|
6713
|
+
kind: "checked",
|
|
6714
|
+
note: "Fails at runtime if value > n"
|
|
6715
|
+
},
|
|
6716
|
+
{
|
|
6717
|
+
from: "Field",
|
|
6718
|
+
to: "Bytes<n>",
|
|
6719
|
+
direct: true,
|
|
6720
|
+
kind: "conversion",
|
|
6721
|
+
note: "Can fail at runtime if value doesn't fit (little-endian)"
|
|
6722
|
+
},
|
|
6723
|
+
{
|
|
6724
|
+
from: "Bytes<m>",
|
|
6725
|
+
to: "Field",
|
|
6726
|
+
direct: true,
|
|
6727
|
+
kind: "conversion",
|
|
6728
|
+
note: "Can fail at runtime if result exceeds max Field value"
|
|
6729
|
+
},
|
|
6730
|
+
{
|
|
6731
|
+
from: "Boolean",
|
|
6732
|
+
to: "Uint<0..n>",
|
|
6733
|
+
direct: true,
|
|
6734
|
+
kind: "conversion",
|
|
6735
|
+
note: "false\u21920, true\u21921 (n must not be 0)"
|
|
6736
|
+
},
|
|
6737
|
+
{
|
|
6738
|
+
from: "Boolean",
|
|
6739
|
+
to: "Field",
|
|
6008
6740
|
direct: false,
|
|
6009
|
-
fix: "Go through
|
|
6741
|
+
fix: "Go through Uint: (flag as Uint<0..1>) as Field"
|
|
6010
6742
|
},
|
|
6011
6743
|
{
|
|
6012
6744
|
from: "Uint<N>",
|
|
6745
|
+
to: "Bytes<M>",
|
|
6746
|
+
direct: false,
|
|
6747
|
+
fix: "Go through Field: (amount as Field) as Bytes<32>"
|
|
6748
|
+
},
|
|
6749
|
+
{
|
|
6750
|
+
from: "enum",
|
|
6013
6751
|
to: "Field",
|
|
6014
6752
|
direct: true,
|
|
6015
|
-
|
|
6753
|
+
kind: "conversion",
|
|
6754
|
+
note: "Enum variant index as Field"
|
|
6755
|
+
},
|
|
6756
|
+
{
|
|
6757
|
+
from: "Uint<0..m>",
|
|
6758
|
+
to: "Uint<0..n>",
|
|
6759
|
+
direct: true,
|
|
6760
|
+
kind: "static if m\u2264n, checked if m>n",
|
|
6761
|
+
note: "Widening is static, narrowing is checked"
|
|
6016
6762
|
},
|
|
6017
6763
|
{
|
|
6018
6764
|
from: "arithmetic result",
|
|
6019
6765
|
to: "Uint<64>",
|
|
6020
6766
|
direct: true,
|
|
6767
|
+
kind: "checked",
|
|
6021
6768
|
note: "Required cast: (a + b) as Uint<64>"
|
|
6022
6769
|
}
|
|
6023
6770
|
],
|
|
@@ -6812,9 +7559,10 @@ async function extractContractStructure(input) {
|
|
|
6812
7559
|
potentialIssues.push({
|
|
6813
7560
|
type: "unsupported_division",
|
|
6814
7561
|
line: lineNum,
|
|
6815
|
-
message: `Division operator '/' is not
|
|
6816
|
-
suggestion: `
|
|
6817
|
-
severity: "
|
|
7562
|
+
message: `Division operator '/' is not in the documented Compact operators (+, -, *)`,
|
|
7563
|
+
suggestion: `If you need division, compute it off-chain in a witness and verify on-chain: 'witness divide(a, b): [quotient, remainder]'`,
|
|
7564
|
+
severity: "warning"
|
|
7565
|
+
// Changed to warning since it's inferred, not explicitly documented
|
|
6818
7566
|
});
|
|
6819
7567
|
break;
|
|
6820
7568
|
}
|
|
@@ -8492,6 +9240,10 @@ var HealthCheckInputSchema = z4.object({
|
|
|
8492
9240
|
var GetStatusInputSchema = z4.object({});
|
|
8493
9241
|
var CheckVersionInputSchema = z4.object({});
|
|
8494
9242
|
var AutoUpdateConfigInputSchema = z4.object({});
|
|
9243
|
+
var GetUpdateInstructionsInputSchema = z4.object({
|
|
9244
|
+
platform: z4.enum(["auto", "mac", "windows", "linux"]).optional().default("auto").describe("Target platform (auto-detects if not specified)"),
|
|
9245
|
+
editor: z4.enum(["auto", "claude-desktop", "cursor", "vscode", "windsurf"]).optional().default("auto").describe("Target editor (provides all if auto)")
|
|
9246
|
+
});
|
|
8495
9247
|
|
|
8496
9248
|
// src/tools/health/handlers.ts
|
|
8497
9249
|
import * as os from "os";
|
|
@@ -8644,6 +9396,286 @@ async function getAutoUpdateConfig(_input) {
|
|
|
8644
9396
|
postUpdateMessage: "\u2705 Config updated! Please restart your editor completely (quit and reopen) to use the latest version."
|
|
8645
9397
|
};
|
|
8646
9398
|
}
|
|
9399
|
+
var SUPPORTED_EDITORS = [
|
|
9400
|
+
"claude-desktop",
|
|
9401
|
+
"cursor",
|
|
9402
|
+
"vscode",
|
|
9403
|
+
"windsurf"
|
|
9404
|
+
];
|
|
9405
|
+
function getNpmCacheClearCommand(platform3) {
|
|
9406
|
+
if (platform3 === "windows") {
|
|
9407
|
+
return 'Remove-Item -Recurse -Force "$env:USERPROFILE\\.npm\\_npx" -ErrorAction SilentlyContinue';
|
|
9408
|
+
}
|
|
9409
|
+
return "rm -rf ~/.npm/_npx";
|
|
9410
|
+
}
|
|
9411
|
+
async function getUpdateInstructions(input) {
|
|
9412
|
+
const platform3 = input.platform === "auto" ? detectPlatform() : input.platform;
|
|
9413
|
+
if (input.editor === "auto") {
|
|
9414
|
+
return getMultiEditorInstructions(platform3);
|
|
9415
|
+
}
|
|
9416
|
+
const editor = input.editor;
|
|
9417
|
+
const configPaths = getConfigPaths(platform3, editor);
|
|
9418
|
+
const restartCommand = getRestartCommand(platform3, editor);
|
|
9419
|
+
const cacheCommand = getNpmCacheClearCommand(platform3);
|
|
9420
|
+
return {
|
|
9421
|
+
title: "\u{1F504} How to Update Midnight MCP",
|
|
9422
|
+
currentSetup: {
|
|
9423
|
+
detectedPlatform: platform3,
|
|
9424
|
+
targetEditor: editor
|
|
9425
|
+
},
|
|
9426
|
+
steps: [
|
|
9427
|
+
{
|
|
9428
|
+
step: 1,
|
|
9429
|
+
title: "Clear npm cache",
|
|
9430
|
+
command: cacheCommand,
|
|
9431
|
+
windowsNote: platform3 === "windows" ? "Run in PowerShell. For cmd.exe use: rd /s /q %USERPROFILE%\\.npm\\_npx" : void 0,
|
|
9432
|
+
explanation: "This removes cached npx packages so the latest version will be downloaded",
|
|
9433
|
+
required: true
|
|
9434
|
+
},
|
|
9435
|
+
{
|
|
9436
|
+
step: 2,
|
|
9437
|
+
title: "Restart your editor completely",
|
|
9438
|
+
action: restartCommand,
|
|
9439
|
+
explanation: "A full restart is needed - just reloading the window is not enough",
|
|
9440
|
+
required: true
|
|
9441
|
+
},
|
|
9442
|
+
{
|
|
9443
|
+
step: 3,
|
|
9444
|
+
title: "If still outdated, update config file",
|
|
9445
|
+
configPath: configPaths.primary,
|
|
9446
|
+
alternativePaths: configPaths.alternatives,
|
|
9447
|
+
change: {
|
|
9448
|
+
find: '"midnight-mcp"',
|
|
9449
|
+
replaceWith: '"midnight-mcp@latest"',
|
|
9450
|
+
location: 'In the "args" array for the midnight server'
|
|
9451
|
+
},
|
|
9452
|
+
explanation: "Adding @latest ensures you always get the newest version",
|
|
9453
|
+
required: false
|
|
9454
|
+
}
|
|
9455
|
+
],
|
|
9456
|
+
troubleshooting: getTroubleshootingSection(platform3, configPaths),
|
|
9457
|
+
exampleConfig: generateExampleConfig(editor),
|
|
9458
|
+
helpfulLinks: {
|
|
9459
|
+
documentation: "https://github.com/Olanetsoft/midnight-mcp#readme",
|
|
9460
|
+
issues: "https://github.com/Olanetsoft/midnight-mcp/issues"
|
|
9461
|
+
}
|
|
9462
|
+
};
|
|
9463
|
+
}
|
|
9464
|
+
function getMultiEditorInstructions(platform3) {
|
|
9465
|
+
const cacheCommand = getNpmCacheClearCommand(platform3);
|
|
9466
|
+
const editorConfigs = SUPPORTED_EDITORS.map((editor) => {
|
|
9467
|
+
const paths = getConfigPaths(platform3, editor);
|
|
9468
|
+
const restart = getRestartCommand(platform3, editor);
|
|
9469
|
+
return {
|
|
9470
|
+
editor,
|
|
9471
|
+
displayName: getEditorDisplayName(editor),
|
|
9472
|
+
configPath: paths.primary,
|
|
9473
|
+
alternativePaths: paths.alternatives,
|
|
9474
|
+
restartCommand: restart
|
|
9475
|
+
};
|
|
9476
|
+
});
|
|
9477
|
+
return {
|
|
9478
|
+
title: "\u{1F504} How to Update Midnight MCP",
|
|
9479
|
+
currentSetup: {
|
|
9480
|
+
detectedPlatform: platform3,
|
|
9481
|
+
targetEditor: "all (auto mode)"
|
|
9482
|
+
},
|
|
9483
|
+
commonSteps: [
|
|
9484
|
+
{
|
|
9485
|
+
step: 1,
|
|
9486
|
+
title: "Clear npm cache",
|
|
9487
|
+
command: cacheCommand,
|
|
9488
|
+
windowsNote: platform3 === "windows" ? "Run in PowerShell. For cmd.exe use: rd /s /q %USERPROFILE%\\.npm\\_npx" : void 0,
|
|
9489
|
+
explanation: "This removes cached npx packages so the latest version will be downloaded",
|
|
9490
|
+
required: true
|
|
9491
|
+
},
|
|
9492
|
+
{
|
|
9493
|
+
step: 2,
|
|
9494
|
+
title: "Restart your editor completely",
|
|
9495
|
+
explanation: "A full restart is needed - just reloading the window is not enough",
|
|
9496
|
+
required: true
|
|
9497
|
+
}
|
|
9498
|
+
],
|
|
9499
|
+
editorSpecificPaths: editorConfigs,
|
|
9500
|
+
configChange: {
|
|
9501
|
+
find: '"midnight-mcp"',
|
|
9502
|
+
replaceWith: '"midnight-mcp@latest"',
|
|
9503
|
+
location: 'In the "args" array for the midnight server'
|
|
9504
|
+
},
|
|
9505
|
+
troubleshooting: [
|
|
9506
|
+
{
|
|
9507
|
+
issue: "Still seeing old version after restart",
|
|
9508
|
+
solutions: [
|
|
9509
|
+
platform3 === "mac" ? "Make sure you quit the editor completely (Cmd+Q)" : platform3 === "windows" ? "Make sure you quit the editor completely (Alt+F4)" : "Make sure you quit the editor completely",
|
|
9510
|
+
"Check if multiple editor instances are running",
|
|
9511
|
+
platform3 === "windows" ? 'Try: Remove-Item -Recurse -Force "$env:USERPROFILE\\.npm\\_npx", "$env:LOCALAPPDATA\\midnight-mcp"' : "Try: rm -rf ~/.npm/_npx && rm -rf ~/.cache/midnight-mcp"
|
|
9512
|
+
]
|
|
9513
|
+
},
|
|
9514
|
+
{
|
|
9515
|
+
issue: "Config file not found",
|
|
9516
|
+
solutions: [
|
|
9517
|
+
"Check the editor-specific paths listed above",
|
|
9518
|
+
"Create the config file if it doesn't exist",
|
|
9519
|
+
"See docs: https://github.com/Olanetsoft/midnight-mcp"
|
|
9520
|
+
]
|
|
9521
|
+
}
|
|
9522
|
+
],
|
|
9523
|
+
exampleConfig: {
|
|
9524
|
+
mcpServers: {
|
|
9525
|
+
midnight: {
|
|
9526
|
+
command: "npx",
|
|
9527
|
+
args: ["-y", "midnight-mcp@latest"]
|
|
9528
|
+
}
|
|
9529
|
+
}
|
|
9530
|
+
},
|
|
9531
|
+
helpfulLinks: {
|
|
9532
|
+
documentation: "https://github.com/Olanetsoft/midnight-mcp#readme",
|
|
9533
|
+
issues: "https://github.com/Olanetsoft/midnight-mcp/issues"
|
|
9534
|
+
}
|
|
9535
|
+
};
|
|
9536
|
+
}
|
|
9537
|
+
function getEditorDisplayName(editor) {
|
|
9538
|
+
const names = {
|
|
9539
|
+
"claude-desktop": "Claude Desktop",
|
|
9540
|
+
cursor: "Cursor",
|
|
9541
|
+
vscode: "VS Code",
|
|
9542
|
+
windsurf: "Windsurf"
|
|
9543
|
+
};
|
|
9544
|
+
return names[editor] || editor;
|
|
9545
|
+
}
|
|
9546
|
+
function getTroubleshootingSection(platform3, configPaths) {
|
|
9547
|
+
const quitCommand = platform3 === "mac" ? "Cmd+Q" : platform3 === "windows" ? "Alt+F4" : "close completely";
|
|
9548
|
+
const cacheCleanup = platform3 === "windows" ? 'Remove-Item -Recurse -Force "$env:USERPROFILE\\.npm\\_npx", "$env:LOCALAPPDATA\\midnight-mcp"' : "rm -rf ~/.npm/_npx && rm -rf ~/.cache/midnight-mcp";
|
|
9549
|
+
return [
|
|
9550
|
+
{
|
|
9551
|
+
issue: "Still seeing old version after restart",
|
|
9552
|
+
solutions: [
|
|
9553
|
+
`Make sure you quit the editor completely (${quitCommand})`,
|
|
9554
|
+
"Check if multiple editor instances are running",
|
|
9555
|
+
`Try: ${cacheCleanup}`
|
|
9556
|
+
]
|
|
9557
|
+
},
|
|
9558
|
+
{
|
|
9559
|
+
issue: "Config file not found",
|
|
9560
|
+
solutions: [
|
|
9561
|
+
`Primary location: ${configPaths.primary}`,
|
|
9562
|
+
"Create it if it doesn't exist",
|
|
9563
|
+
"See docs: https://github.com/Olanetsoft/midnight-mcp"
|
|
9564
|
+
]
|
|
9565
|
+
},
|
|
9566
|
+
{
|
|
9567
|
+
issue: "Permission denied errors",
|
|
9568
|
+
solutions: platform3 === "windows" ? [
|
|
9569
|
+
"Run editor as administrator",
|
|
9570
|
+
"Check file permissions in Windows Security settings"
|
|
9571
|
+
] : [
|
|
9572
|
+
"Check file permissions with ls -la",
|
|
9573
|
+
"Ensure your user owns the config file"
|
|
9574
|
+
]
|
|
9575
|
+
}
|
|
9576
|
+
];
|
|
9577
|
+
}
|
|
9578
|
+
function detectPlatform() {
|
|
9579
|
+
const p = process.platform;
|
|
9580
|
+
if (p === "darwin") return "mac";
|
|
9581
|
+
if (p === "win32") return "windows";
|
|
9582
|
+
return "linux";
|
|
9583
|
+
}
|
|
9584
|
+
function getConfigPaths(platform3, editor) {
|
|
9585
|
+
const home = process.env.HOME || process.env.USERPROFILE || "~";
|
|
9586
|
+
const paths = {
|
|
9587
|
+
mac: {
|
|
9588
|
+
"claude-desktop": {
|
|
9589
|
+
primary: `${home}/Library/Application Support/Claude/claude_desktop_config.json`,
|
|
9590
|
+
alternatives: []
|
|
9591
|
+
},
|
|
9592
|
+
cursor: {
|
|
9593
|
+
primary: `${home}/.cursor/mcp.json`,
|
|
9594
|
+
alternatives: [`${home}/Library/Application Support/Cursor/mcp.json`]
|
|
9595
|
+
},
|
|
9596
|
+
vscode: {
|
|
9597
|
+
primary: `${home}/.vscode/mcp.json`,
|
|
9598
|
+
alternatives: [
|
|
9599
|
+
`${home}/Library/Application Support/Code/User/settings.json`
|
|
9600
|
+
]
|
|
9601
|
+
},
|
|
9602
|
+
windsurf: {
|
|
9603
|
+
primary: `${home}/.codeium/windsurf/mcp_config.json`,
|
|
9604
|
+
alternatives: []
|
|
9605
|
+
}
|
|
9606
|
+
},
|
|
9607
|
+
windows: {
|
|
9608
|
+
"claude-desktop": {
|
|
9609
|
+
primary: `%APPDATA%\\Claude\\claude_desktop_config.json`,
|
|
9610
|
+
alternatives: []
|
|
9611
|
+
},
|
|
9612
|
+
cursor: {
|
|
9613
|
+
primary: `%USERPROFILE%\\.cursor\\mcp.json`,
|
|
9614
|
+
alternatives: [`%APPDATA%\\Cursor\\mcp.json`]
|
|
9615
|
+
},
|
|
9616
|
+
vscode: {
|
|
9617
|
+
primary: `%USERPROFILE%\\.vscode\\mcp.json`,
|
|
9618
|
+
alternatives: [`%APPDATA%\\Code\\User\\settings.json`]
|
|
9619
|
+
},
|
|
9620
|
+
windsurf: {
|
|
9621
|
+
primary: `%USERPROFILE%\\.codeium\\windsurf\\mcp_config.json`,
|
|
9622
|
+
alternatives: []
|
|
9623
|
+
}
|
|
9624
|
+
},
|
|
9625
|
+
linux: {
|
|
9626
|
+
"claude-desktop": {
|
|
9627
|
+
primary: `${home}/.config/Claude/claude_desktop_config.json`,
|
|
9628
|
+
alternatives: []
|
|
9629
|
+
},
|
|
9630
|
+
cursor: {
|
|
9631
|
+
primary: `${home}/.cursor/mcp.json`,
|
|
9632
|
+
alternatives: [`${home}/.config/Cursor/mcp.json`]
|
|
9633
|
+
},
|
|
9634
|
+
vscode: {
|
|
9635
|
+
primary: `${home}/.vscode/mcp.json`,
|
|
9636
|
+
alternatives: [`${home}/.config/Code/User/settings.json`]
|
|
9637
|
+
},
|
|
9638
|
+
windsurf: {
|
|
9639
|
+
primary: `${home}/.codeium/windsurf/mcp_config.json`,
|
|
9640
|
+
alternatives: []
|
|
9641
|
+
}
|
|
9642
|
+
}
|
|
9643
|
+
};
|
|
9644
|
+
return paths[platform3]?.[editor] || paths.mac["claude-desktop"];
|
|
9645
|
+
}
|
|
9646
|
+
function getRestartCommand(platform3, editor) {
|
|
9647
|
+
const editorNames = {
|
|
9648
|
+
"claude-desktop": "Claude Desktop",
|
|
9649
|
+
cursor: "Cursor",
|
|
9650
|
+
vscode: "VS Code",
|
|
9651
|
+
windsurf: "Windsurf"
|
|
9652
|
+
};
|
|
9653
|
+
const name = editorNames[editor] || editor;
|
|
9654
|
+
if (platform3 === "mac") {
|
|
9655
|
+
return `Quit ${name} completely (Cmd+Q), then reopen`;
|
|
9656
|
+
} else if (platform3 === "windows") {
|
|
9657
|
+
return `Close ${name} completely (Alt+F4 or File > Exit), then reopen`;
|
|
9658
|
+
} else {
|
|
9659
|
+
return `Close ${name} completely, then reopen`;
|
|
9660
|
+
}
|
|
9661
|
+
}
|
|
9662
|
+
function generateExampleConfig(editor) {
|
|
9663
|
+
const baseConfig = {
|
|
9664
|
+
mcpServers: {
|
|
9665
|
+
midnight: {
|
|
9666
|
+
command: "npx",
|
|
9667
|
+
args: ["-y", "midnight-mcp@latest"]
|
|
9668
|
+
}
|
|
9669
|
+
}
|
|
9670
|
+
};
|
|
9671
|
+
if (editor === "vscode") {
|
|
9672
|
+
return {
|
|
9673
|
+
note: "For VS Code, add to settings.json or mcp.json",
|
|
9674
|
+
config: baseConfig
|
|
9675
|
+
};
|
|
9676
|
+
}
|
|
9677
|
+
return baseConfig;
|
|
9678
|
+
}
|
|
8647
9679
|
|
|
8648
9680
|
// src/tools/health/tools.ts
|
|
8649
9681
|
var healthCheckOutputSchema = {
|
|
@@ -8810,6 +9842,45 @@ var healthTools = [
|
|
|
8810
9842
|
category: "health"
|
|
8811
9843
|
},
|
|
8812
9844
|
handler: getAutoUpdateConfig
|
|
9845
|
+
},
|
|
9846
|
+
{
|
|
9847
|
+
name: "midnight-get-update-instructions",
|
|
9848
|
+
description: "\u{1F4CB} Get detailed, platform-specific instructions for updating Midnight MCP to the latest version. Provides step-by-step guidance including config file locations, commands to run, and troubleshooting tips. Use this when a user needs help updating or is having issues with outdated versions.",
|
|
9849
|
+
inputSchema: {
|
|
9850
|
+
type: "object",
|
|
9851
|
+
properties: {
|
|
9852
|
+
platform: {
|
|
9853
|
+
type: "string",
|
|
9854
|
+
enum: ["auto", "mac", "windows", "linux"],
|
|
9855
|
+
description: "Target platform (auto-detects if not specified)",
|
|
9856
|
+
default: "auto"
|
|
9857
|
+
},
|
|
9858
|
+
editor: {
|
|
9859
|
+
type: "string",
|
|
9860
|
+
enum: ["auto", "claude-desktop", "cursor", "vscode", "windsurf"],
|
|
9861
|
+
description: "Target editor (defaults to Claude Desktop)",
|
|
9862
|
+
default: "auto"
|
|
9863
|
+
}
|
|
9864
|
+
}
|
|
9865
|
+
},
|
|
9866
|
+
outputSchema: {
|
|
9867
|
+
type: "object",
|
|
9868
|
+
properties: {
|
|
9869
|
+
title: { type: "string" },
|
|
9870
|
+
currentSetup: { type: "object" },
|
|
9871
|
+
steps: { type: "array", items: { type: "object" } },
|
|
9872
|
+
troubleshooting: { type: "array", items: { type: "object" } },
|
|
9873
|
+
exampleConfig: { type: "object" },
|
|
9874
|
+
helpfulLinks: { type: "object" }
|
|
9875
|
+
}
|
|
9876
|
+
},
|
|
9877
|
+
annotations: {
|
|
9878
|
+
readOnlyHint: true,
|
|
9879
|
+
idempotentHint: true,
|
|
9880
|
+
title: "\u{1F4CB} Get Update Instructions",
|
|
9881
|
+
category: "health"
|
|
9882
|
+
},
|
|
9883
|
+
handler: getUpdateInstructions
|
|
8813
9884
|
}
|
|
8814
9885
|
];
|
|
8815
9886
|
|
|
@@ -10114,4 +11185,4 @@ export {
|
|
|
10114
11185
|
startServer,
|
|
10115
11186
|
startHttpServer
|
|
10116
11187
|
};
|
|
10117
|
-
//# sourceMappingURL=chunk-
|
|
11188
|
+
//# sourceMappingURL=chunk-V7KK64OX.js.map
|