midnight-mcp 0.1.40 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/README.md +34 -0
  2. package/dist/bin.d.ts +1 -0
  3. package/dist/bin.js +10764 -0
  4. package/dist/index.d.ts +205 -3
  5. package/dist/index.js +10722 -15
  6. package/package.json +16 -6
  7. package/dist/config/compact-version.d.ts +0 -183
  8. package/dist/config/compact-version.js +0 -423
  9. package/dist/db/index.d.ts +0 -3
  10. package/dist/db/index.js +0 -2
  11. package/dist/db/vectorStore.d.ts +0 -69
  12. package/dist/db/vectorStore.js +0 -196
  13. package/dist/pipeline/embeddings.d.ts +0 -25
  14. package/dist/pipeline/embeddings.js +0 -103
  15. package/dist/pipeline/github.d.ts +0 -84
  16. package/dist/pipeline/github.js +0 -399
  17. package/dist/pipeline/index.d.ts +0 -11
  18. package/dist/pipeline/index.js +0 -6
  19. package/dist/pipeline/indexer.d.ts +0 -41
  20. package/dist/pipeline/indexer.js +0 -254
  21. package/dist/pipeline/parser.d.ts +0 -46
  22. package/dist/pipeline/parser.js +0 -436
  23. package/dist/pipeline/releases.d.ts +0 -112
  24. package/dist/pipeline/releases.js +0 -298
  25. package/dist/pipeline/repository.d.ts +0 -372
  26. package/dist/pipeline/repository.js +0 -520
  27. package/dist/prompts/index.d.ts +0 -3
  28. package/dist/prompts/index.js +0 -2
  29. package/dist/prompts/templates.d.ts +0 -26
  30. package/dist/prompts/templates.js +0 -443
  31. package/dist/resources/code.d.ts +0 -15
  32. package/dist/resources/code.js +0 -122
  33. package/dist/resources/content/code-content.d.ts +0 -6
  34. package/dist/resources/content/code-content.js +0 -802
  35. package/dist/resources/content/docs-content.d.ts +0 -14
  36. package/dist/resources/content/docs-content.js +0 -1202
  37. package/dist/resources/content/index.d.ts +0 -6
  38. package/dist/resources/content/index.js +0 -6
  39. package/dist/resources/docs.d.ts +0 -15
  40. package/dist/resources/docs.js +0 -98
  41. package/dist/resources/index.d.ts +0 -6
  42. package/dist/resources/index.js +0 -13
  43. package/dist/resources/schemas.d.ts +0 -16
  44. package/dist/resources/schemas.js +0 -407
  45. package/dist/scripts/index-repos.d.ts +0 -12
  46. package/dist/scripts/index-repos.js +0 -53
  47. package/dist/server.d.ts +0 -43
  48. package/dist/server.js +0 -693
  49. package/dist/services/index.d.ts +0 -6
  50. package/dist/services/index.js +0 -6
  51. package/dist/services/sampling.d.ts +0 -62
  52. package/dist/services/sampling.js +0 -277
  53. package/dist/tools/analyze.d.ts +0 -106
  54. package/dist/tools/analyze.js +0 -431
  55. package/dist/tools/generation.d.ts +0 -9
  56. package/dist/tools/generation.js +0 -285
  57. package/dist/tools/health.d.ts +0 -120
  58. package/dist/tools/health.js +0 -362
  59. package/dist/tools/index.d.ts +0 -14
  60. package/dist/tools/index.js +0 -22
  61. package/dist/tools/meta.d.ts +0 -61
  62. package/dist/tools/meta.js +0 -282
  63. package/dist/tools/repository/constants.d.ts +0 -19
  64. package/dist/tools/repository/constants.js +0 -324
  65. package/dist/tools/repository/handlers.d.ts +0 -373
  66. package/dist/tools/repository/handlers.js +0 -724
  67. package/dist/tools/repository/index.d.ts +0 -9
  68. package/dist/tools/repository/index.js +0 -13
  69. package/dist/tools/repository/schemas.d.ts +0 -153
  70. package/dist/tools/repository/schemas.js +0 -106
  71. package/dist/tools/repository/tools.d.ts +0 -7
  72. package/dist/tools/repository/tools.js +0 -484
  73. package/dist/tools/repository/validation.d.ts +0 -106
  74. package/dist/tools/repository/validation.js +0 -820
  75. package/dist/tools/repository.d.ts +0 -6
  76. package/dist/tools/repository.js +0 -7
  77. package/dist/tools/search.d.ts +0 -76
  78. package/dist/tools/search.js +0 -423
  79. package/dist/types/index.d.ts +0 -2
  80. package/dist/types/index.js +0 -2
  81. package/dist/types/mcp.d.ts +0 -187
  82. package/dist/types/mcp.js +0 -6
  83. package/dist/utils/cache.d.ts +0 -77
  84. package/dist/utils/cache.js +0 -172
  85. package/dist/utils/config.d.ts +0 -70
  86. package/dist/utils/config.js +0 -294
  87. package/dist/utils/errors.d.ts +0 -111
  88. package/dist/utils/errors.js +0 -165
  89. package/dist/utils/health.d.ts +0 -29
  90. package/dist/utils/health.js +0 -132
  91. package/dist/utils/hosted-api.d.ts +0 -67
  92. package/dist/utils/hosted-api.js +0 -119
  93. package/dist/utils/index.d.ts +0 -16
  94. package/dist/utils/index.js +0 -15
  95. package/dist/utils/logger.d.ts +0 -48
  96. package/dist/utils/logger.js +0 -124
  97. package/dist/utils/rate-limit.d.ts +0 -61
  98. package/dist/utils/rate-limit.js +0 -148
  99. package/dist/utils/validation.d.ts +0 -52
  100. package/dist/utils/validation.js +0 -255
@@ -1,724 +0,0 @@
1
- /**
2
- * Repository handler functions
3
- * Business logic for repository-related MCP tools
4
- */
5
- import { githubClient } from "../../pipeline/index.js";
6
- import { releaseTracker } from "../../pipeline/releases.js";
7
- import { logger, DEFAULT_REPOSITORIES, SelfCorrectionHints, } from "../../utils/index.js";
8
- import { sendProgressNotification } from "../../server.js";
9
- import { REPO_ALIASES, EXAMPLES } from "./constants.js";
10
- import { EMBEDDED_DOCS } from "../../resources/content/docs-content.js";
11
- import { COMPACT_VERSION, RECOMMENDED_PRAGMA, REFERENCE_CONTRACTS, BUILTIN_FUNCTIONS, TYPE_COMPATIBILITY, LEDGER_TYPE_LIMITS, COMMON_ERRORS, } from "../../config/compact-version.js";
12
- // Re-export validation handlers from validation.ts
13
- export { extractContractStructure } from "./validation.js";
14
- /**
15
- * Resolve repository name alias to owner/repo
16
- */
17
- export function resolveRepo(repoName) {
18
- // Default to compact if not provided
19
- const name = repoName || "compact";
20
- const normalized = name.toLowerCase().replace(/^midnightntwrk\//, "");
21
- const alias = REPO_ALIASES[normalized];
22
- if (alias)
23
- return alias;
24
- // Try to find in configured repos
25
- for (const config of DEFAULT_REPOSITORIES) {
26
- if (config.repo.toLowerCase() === normalized) {
27
- return { owner: config.owner, repo: config.repo };
28
- }
29
- }
30
- // Assume it's a full org/repo name
31
- if (name.includes("/")) {
32
- const [owner, repo] = name.split("/");
33
- return { owner, repo };
34
- }
35
- return null;
36
- }
37
- /**
38
- * Retrieve a specific file from Midnight repositories
39
- */
40
- export async function getFile(input) {
41
- logger.debug("Getting file", { repo: input.repo, path: input.path });
42
- const repoInfo = resolveRepo(input.repo);
43
- if (!repoInfo) {
44
- return SelfCorrectionHints.UNKNOWN_REPO(input.repo, Object.keys(REPO_ALIASES));
45
- }
46
- const file = await githubClient.getFileContent(repoInfo.owner, repoInfo.repo, input.path, input.ref);
47
- if (!file) {
48
- return SelfCorrectionHints.FILE_NOT_FOUND(input.path, `${repoInfo.owner}/${repoInfo.repo}`);
49
- }
50
- return {
51
- content: file.content,
52
- path: file.path,
53
- repository: `${repoInfo.owner}/${repoInfo.repo}`,
54
- sha: file.sha,
55
- size: file.size,
56
- url: `https://github.com/${repoInfo.owner}/${repoInfo.repo}/blob/${input.ref || "main"}/${file.path}`,
57
- };
58
- }
59
- /**
60
- * List available example contracts and DApps
61
- */
62
- export async function listExamples(input) {
63
- logger.debug("Listing examples", { category: input.category });
64
- let filteredExamples = EXAMPLES;
65
- if (input.category && input.category !== "all") {
66
- filteredExamples = EXAMPLES.filter((e) => e.category === input.category);
67
- }
68
- return {
69
- examples: filteredExamples.map((e) => ({
70
- name: e.name,
71
- repository: e.repository,
72
- description: e.description,
73
- complexity: e.complexity,
74
- mainFile: e.mainFile,
75
- features: e.features,
76
- githubUrl: `https://github.com/${e.repository}`,
77
- })),
78
- totalCount: filteredExamples.length,
79
- categories: [...new Set(EXAMPLES.map((e) => e.category))],
80
- };
81
- }
82
- /**
83
- * Retrieve recent changes across Midnight repositories
84
- */
85
- export async function getLatestUpdates(input) {
86
- logger.debug("Getting latest updates", input);
87
- // Default to last 7 days
88
- const since = input.since || new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString();
89
- const repos = input.repos?.map(resolveRepo).filter(Boolean) ||
90
- DEFAULT_REPOSITORIES.map((r) => ({ owner: r.owner, repo: r.repo }));
91
- const updates = [];
92
- for (const repo of repos) {
93
- if (!repo)
94
- continue;
95
- const commits = await githubClient.getRecentCommits(repo.owner, repo.repo, since, 10);
96
- if (commits.length > 0) {
97
- updates.push({
98
- repository: `${repo.owner}/${repo.repo}`,
99
- commits,
100
- });
101
- }
102
- }
103
- // Sort by most recent commit
104
- updates.sort((a, b) => {
105
- const aDate = a.commits[0]?.date || "";
106
- const bDate = b.commits[0]?.date || "";
107
- return bDate.localeCompare(aDate);
108
- });
109
- // Generate summary
110
- const totalCommits = updates.reduce((sum, u) => sum + u.commits.length, 0);
111
- const activeRepos = updates.filter((u) => u.commits.length > 0).length;
112
- return {
113
- summary: {
114
- since,
115
- totalCommits,
116
- activeRepositories: activeRepos,
117
- checkedRepositories: repos.length,
118
- },
119
- updates: updates.map((u) => ({
120
- repository: u.repository,
121
- commitCount: u.commits.length,
122
- latestCommit: u.commits[0]
123
- ? {
124
- message: u.commits[0].message.split("\n")[0], // First line only
125
- date: u.commits[0].date,
126
- author: u.commits[0].author,
127
- url: u.commits[0].url,
128
- }
129
- : null,
130
- recentCommits: u.commits.slice(0, 5).map((c) => ({
131
- message: c.message.split("\n")[0],
132
- date: c.date,
133
- sha: c.sha.substring(0, 7),
134
- })),
135
- })),
136
- };
137
- }
138
- /**
139
- * Get version and release info for a repository
140
- */
141
- export async function getVersionInfo(input) {
142
- // Ensure repo defaults to compact if undefined/empty
143
- const repoName = input?.repo || "compact";
144
- logger.debug("Getting version info", { repo: repoName });
145
- const resolved = resolveRepo(repoName);
146
- if (!resolved) {
147
- throw new Error(`Unknown repository: ${input.repo}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
148
- }
149
- const versionInfo = await releaseTracker.getVersionInfo(resolved.owner, resolved.repo);
150
- return {
151
- repository: `${resolved.owner}/${resolved.repo}`,
152
- latestVersion: versionInfo.latestRelease?.tag || "No releases found",
153
- latestStableVersion: versionInfo.latestStableRelease?.tag || "No stable releases",
154
- publishedAt: versionInfo.latestRelease?.publishedAt || null,
155
- releaseNotes: versionInfo.latestRelease?.body || null,
156
- recentReleases: versionInfo.recentReleases.slice(0, 5).map((r) => ({
157
- version: r.tag,
158
- date: r.publishedAt.split("T")[0],
159
- isPrerelease: r.isPrerelease,
160
- url: r.url,
161
- })),
162
- recentBreakingChanges: versionInfo.changelog
163
- .slice(0, 3)
164
- .flatMap((c) => c.changes.breaking)
165
- .slice(0, 10),
166
- versionContext: releaseTracker.getVersionContext(versionInfo),
167
- };
168
- }
169
- /**
170
- * Check for breaking changes since a specific version
171
- */
172
- export async function checkBreakingChanges(input) {
173
- // Ensure repo defaults to compact if undefined/empty
174
- const repoName = input?.repo || "compact";
175
- logger.debug("Checking breaking changes", {
176
- repo: repoName,
177
- currentVersion: input.currentVersion,
178
- });
179
- const resolved = resolveRepo(repoName);
180
- if (!resolved) {
181
- throw new Error(`Unknown repository: ${repoName}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
182
- }
183
- const outdatedInfo = await releaseTracker.isOutdated(resolved.owner, resolved.repo, input.currentVersion);
184
- const breakingChanges = await releaseTracker.getBreakingChangesSince(resolved.owner, resolved.repo, input.currentVersion);
185
- return {
186
- repository: `${resolved.owner}/${resolved.repo}`,
187
- currentVersion: input.currentVersion,
188
- latestVersion: outdatedInfo.latestVersion,
189
- isOutdated: outdatedInfo.isOutdated,
190
- versionsBehind: outdatedInfo.versionsBehind,
191
- hasBreakingChanges: outdatedInfo.hasBreakingChanges,
192
- breakingChanges: breakingChanges,
193
- recommendation: outdatedInfo.hasBreakingChanges
194
- ? `⚠️ Breaking changes detected! Review the ${breakingChanges.length} breaking change(s) before upgrading.`
195
- : outdatedInfo.isOutdated
196
- ? `✅ Safe to upgrade. No breaking changes detected since ${input.currentVersion}.`
197
- : `✅ You're on the latest version.`,
198
- };
199
- }
200
- /**
201
- * Get migration guide between versions
202
- */
203
- export async function getMigrationGuide(input) {
204
- // Ensure repo defaults to compact if undefined/empty
205
- const repoName = input?.repo || "compact";
206
- logger.debug("Getting migration guide", {
207
- repo: repoName,
208
- fromVersion: input.fromVersion,
209
- toVersion: input.toVersion,
210
- });
211
- const resolved = resolveRepo(repoName);
212
- if (!resolved) {
213
- throw new Error(`Unknown repository: ${repoName}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
214
- }
215
- const guide = await releaseTracker.getMigrationGuide(resolved.owner, resolved.repo, input.fromVersion, input.toVersion);
216
- return {
217
- repository: `${resolved.owner}/${resolved.repo}`,
218
- from: guide.from,
219
- to: guide.to,
220
- summary: {
221
- breakingChangesCount: guide.breakingChanges.length,
222
- deprecationsCount: guide.deprecations.length,
223
- newFeaturesCount: guide.newFeatures.length,
224
- },
225
- breakingChanges: guide.breakingChanges,
226
- deprecations: guide.deprecations,
227
- newFeatures: guide.newFeatures,
228
- migrationSteps: guide.migrationSteps,
229
- migrationDifficulty: guide.breakingChanges.length === 0
230
- ? "Easy - No breaking changes"
231
- : guide.breakingChanges.length <= 3
232
- ? "Moderate - Few breaking changes"
233
- : "Complex - Multiple breaking changes, plan carefully",
234
- };
235
- }
236
- /**
237
- * Get a file at a specific version - critical for version-accurate recommendations
238
- */
239
- export async function getFileAtVersion(input) {
240
- // Ensure repo defaults to compact if undefined/empty
241
- const repoName = input?.repo || "compact";
242
- logger.debug("Getting file at version", {
243
- repo: repoName,
244
- path: input.path,
245
- version: input.version,
246
- });
247
- const resolved = resolveRepo(repoName);
248
- if (!resolved) {
249
- throw new Error(`Unknown repository: ${repoName}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
250
- }
251
- const result = await releaseTracker.getFileAtVersion(resolved.owner, resolved.repo, input.path, input.version);
252
- if (!result) {
253
- throw new Error(`File not found: ${input.path} at version ${input.version} in ${repoName}`);
254
- }
255
- return {
256
- repository: `${resolved.owner}/${resolved.repo}`,
257
- path: input.path,
258
- version: result.version,
259
- content: result.content,
260
- note: `This is the exact content at version ${result.version}. Use this as the source of truth for syntax and API at this version.`,
261
- };
262
- }
263
- /**
264
- * Compare syntax between two versions - shows what changed
265
- */
266
- export async function compareSyntax(input) {
267
- // Ensure repo defaults to compact if undefined/empty
268
- const repoName = input?.repo || "compact";
269
- logger.debug("Comparing syntax between versions", {
270
- repo: repoName,
271
- oldVersion: input.oldVersion,
272
- newVersion: input.newVersion,
273
- });
274
- const resolved = resolveRepo(repoName);
275
- if (!resolved) {
276
- throw new Error(`Unknown repository: ${repoName}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
277
- }
278
- // If no newVersion specified, get latest
279
- let newVersion = input.newVersion;
280
- if (!newVersion) {
281
- const versionInfo = await releaseTracker.getVersionInfo(resolved.owner, resolved.repo);
282
- newVersion =
283
- versionInfo.latestStableRelease?.tag ||
284
- versionInfo.latestRelease?.tag ||
285
- "main";
286
- }
287
- const comparison = await releaseTracker.compareSyntax(resolved.owner, resolved.repo, input.path, input.oldVersion, newVersion);
288
- return {
289
- repository: `${resolved.owner}/${resolved.repo}`,
290
- path: input.path,
291
- oldVersion: comparison.oldVersion,
292
- newVersion: comparison.newVersion,
293
- hasDifferences: comparison.hasDifferences,
294
- oldContent: comparison.oldContent,
295
- newContent: comparison.newContent,
296
- recommendation: comparison.hasDifferences
297
- ? `⚠️ This file has changed between ${comparison.oldVersion} and ${comparison.newVersion}. Review the differences before using code patterns from the old version.`
298
- : `✅ No changes in this file between versions.`,
299
- };
300
- }
301
- /**
302
- * Get the latest syntax reference for Compact language
303
- * This is the source of truth for writing valid, compilable contracts
304
- */
305
- export async function getLatestSyntax(input) {
306
- // Ensure repo defaults to compact if undefined/empty
307
- const repoName = input?.repo || "compact";
308
- logger.debug("Getting latest syntax reference", { repo: repoName });
309
- // For Compact language, always return our curated reference first
310
- // This is more reliable than fetching from GitHub and includes pitfalls/patterns
311
- if (repoName === "compact" || repoName === "midnight-compact") {
312
- const compactReference = EMBEDDED_DOCS["midnight://docs/compact-reference"];
313
- // Check if there's a newer release we might not have documented
314
- // Version config is centralized in src/config/compact-version.ts
315
- let versionWarning;
316
- try {
317
- const versionInfo = await releaseTracker.getVersionInfo("midnightntwrk", "compact");
318
- const latestTag = versionInfo.latestStableRelease?.tag || versionInfo.latestRelease?.tag;
319
- if (latestTag) {
320
- // Extract version number from tag (e.g., "v0.18.0" -> "0.18")
321
- const latestVersion = latestTag
322
- .replace(/^v/, "")
323
- .split(".")
324
- .slice(0, 2)
325
- .join(".");
326
- if (latestVersion !== COMPACT_VERSION.max &&
327
- parseFloat(latestVersion) > parseFloat(COMPACT_VERSION.max)) {
328
- versionWarning = `⚠️ Compact ${latestTag} is available. This reference is based on ${COMPACT_VERSION.max}. Some syntax may have changed - check release notes for breaking changes. See docs/SYNTAX_MAINTENANCE.md for update instructions.`;
329
- }
330
- }
331
- }
332
- catch {
333
- // Ignore version check errors, still return cached docs
334
- }
335
- if (compactReference) {
336
- return {
337
- repository: "midnightntwrk/compact",
338
- version: `${COMPACT_VERSION.min}-${COMPACT_VERSION.max} (current)`,
339
- versionConfig: {
340
- min: COMPACT_VERSION.min,
341
- max: COMPACT_VERSION.max,
342
- lastUpdated: COMPACT_VERSION.lastUpdated,
343
- maintenanceGuide: "See docs/SYNTAX_MAINTENANCE.md for update instructions",
344
- },
345
- ...(versionWarning && { versionWarning }),
346
- // Quick start template - ALWAYS compiles
347
- quickStartTemplate: `${RECOMMENDED_PRAGMA}
348
-
349
- import CompactStandardLibrary;
350
-
351
- export ledger counter: Counter;
352
- export ledger owner: Bytes<32>;
353
-
354
- witness local_secret_key(): Bytes<32>;
355
-
356
- export circuit increment(): [] {
357
- counter.increment(1);
358
- }`,
359
- // Built-in functions vs patterns (CRITICAL knowledge)
360
- builtinFunctions: BUILTIN_FUNCTIONS,
361
- // Type compatibility rules
362
- typeCompatibility: TYPE_COMPATIBILITY,
363
- // Ledger type limitations in circuits
364
- ledgerTypeLimits: LEDGER_TYPE_LIMITS,
365
- // Common compilation errors with fixes
366
- commonErrors: COMMON_ERRORS,
367
- // Common mistakes that cause compilation failures
368
- commonMistakes: [
369
- {
370
- wrong: "ledger { field: Type; }",
371
- correct: "export ledger field: Type;",
372
- error: 'parse error: found "{" looking for an identifier',
373
- },
374
- {
375
- wrong: "circuit fn(): Void",
376
- correct: "circuit fn(): []",
377
- error: 'parse error: found "{" looking for ";"',
378
- },
379
- {
380
- wrong: "pragma language_version >= 0.14.0;",
381
- correct: RECOMMENDED_PRAGMA,
382
- error: "version mismatch or parse error",
383
- },
384
- {
385
- wrong: "enum State { a, b }",
386
- correct: "export enum State { a, b }",
387
- error: "enum not accessible from TypeScript",
388
- },
389
- {
390
- wrong: "if (witness_val == x)",
391
- correct: "if (disclose(witness_val == x))",
392
- error: "implicit disclosure error",
393
- },
394
- {
395
- wrong: "Cell<Field>",
396
- correct: "Field",
397
- error: "unbound identifier Cell (deprecated)",
398
- },
399
- {
400
- wrong: "public_key(sk)",
401
- correct: 'persistentHash<Vector<2, Bytes<32>>>([pad(32, "midnight:pk:"), sk])',
402
- error: 'unbound identifier "public_key"',
403
- },
404
- {
405
- wrong: "counter.value()",
406
- correct: "// Read via witness or TypeScript SDK",
407
- error: 'operation "value" undefined for Counter',
408
- },
409
- {
410
- wrong: "Choice::rock (Rust-style)",
411
- correct: "Choice.rock (dot notation)",
412
- error: 'parse error: found ":" looking for ")"',
413
- },
414
- {
415
- wrong: "witness fn(): T { ... }",
416
- correct: "witness fn(): T; // declaration only, no body",
417
- error: "parse error after witness declaration",
418
- },
419
- {
420
- wrong: "pure function helper(): T",
421
- correct: "pure circuit helper(): T",
422
- error: 'unbound identifier "function"',
423
- },
424
- {
425
- wrong: "amount as Bytes<32> // direct Uint to Bytes",
426
- correct: "(amount as Field) as Bytes<32> // go through Field",
427
- error: "cannot cast from type Uint<64> to type Bytes<32>",
428
- },
429
- {
430
- wrong: "ledger.insert(key, a + b) // arithmetic result",
431
- correct: "ledger.insert(key, (a + b) as Uint<64>) // cast result",
432
- error: "expected type Uint<64> but received Uint<0..N>",
433
- },
434
- {
435
- wrong: "export circuit fn(param: T): [] { ledger.insert(param, v); }",
436
- correct: "export circuit fn(param: T): [] { const d = disclose(param); ledger.insert(d, v); }",
437
- error: "potential witness-value disclosure must be declared",
438
- },
439
- ],
440
- syntaxReference: compactReference,
441
- sections: [
442
- "Quick Start Template",
443
- "Pragma (Version Declaration)",
444
- "Imports",
445
- "Ledger Declarations",
446
- "Data Types",
447
- "Built-in Functions",
448
- "Type Compatibility",
449
- "Ledger Type Limits",
450
- "Circuits",
451
- "Witnesses",
452
- "Constructor",
453
- "Common Patterns",
454
- "Common Operations",
455
- "Assertions",
456
- "Common Mistakes to Avoid",
457
- "Common Errors & Fixes",
458
- "Exports for TypeScript",
459
- "Reference Contracts",
460
- ],
461
- referenceContracts: REFERENCE_CONTRACTS.map((rc) => ({
462
- name: rc.name,
463
- repo: rc.repo,
464
- description: rc.description,
465
- })),
466
- note: `⚠️ CALL THIS TOOL BEFORE generating ANY Compact code!
467
- Use quickStartTemplate as your base. Check commonMistakes BEFORE submitting code.
468
-
469
- KEY RULES:
470
- 1. public_key() is NOT a builtin - use persistentHash pattern
471
- 2. Counter.value() NOT available in circuits - use witnesses
472
- 3. Map.lookup()/Set.member() ARE available in circuits (verified)
473
- 4. Arithmetic results need casting: (a + b) as Uint<64>
474
- 5. Uint→Bytes needs two casts: (amount as Field) as Bytes<32>
475
- 6. Circuit params touching ledger need disclose(): const d = disclose(param);
476
-
477
- Compact is NOT TypeScript - don't guess syntax, use this reference!
478
- Version: ${COMPACT_VERSION.min}-${COMPACT_VERSION.max} (updated: ${COMPACT_VERSION.lastUpdated}).`,
479
- };
480
- }
481
- }
482
- const resolved = resolveRepo(repoName);
483
- if (!resolved) {
484
- throw new Error(`Unknown repository: ${repoName}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
485
- }
486
- const reference = await releaseTracker.getLatestSyntaxReference(resolved.owner, resolved.repo);
487
- if (!reference || reference.syntaxFiles.length === 0) {
488
- // Fallback: get example contracts as syntax reference
489
- const versionInfo = await releaseTracker.getVersionInfo(resolved.owner, resolved.repo);
490
- const version = versionInfo.latestStableRelease?.tag || "main";
491
- return {
492
- repository: `${resolved.owner}/${resolved.repo}`,
493
- version,
494
- warning: "No grammar documentation found. Use example contracts as reference.",
495
- syntaxFiles: [],
496
- examplePaths: ["examples/", "test/", "contracts/"],
497
- };
498
- }
499
- return {
500
- repository: `${resolved.owner}/${resolved.repo}`,
501
- version: reference.version,
502
- syntaxFiles: reference.syntaxFiles.map((f) => ({
503
- path: f.path,
504
- content: f.content,
505
- })),
506
- note: `This is the authoritative syntax reference at version ${reference.version}. Use this to ensure contracts are compilable.`,
507
- };
508
- }
509
- // ============================================================================
510
- // COMPOUND TOOLS - Reduce multiple API calls to single operations
511
- // These tools combine related operations to minimize round-trips and token usage
512
- // ============================================================================
513
- /**
514
- * Compound tool: Full upgrade check
515
- * Combines: getVersionInfo + checkBreakingChanges + getMigrationGuide
516
- * Reduces 3 tool calls to 1, saving ~60% tokens
517
- */
518
- export async function upgradeCheck(input) {
519
- const repoName = input?.repo || "compact";
520
- const currentVersion = input.currentVersion;
521
- const progressToken = input._meta?.progressToken;
522
- logger.debug("Running compound upgrade check", {
523
- repo: repoName,
524
- currentVersion,
525
- });
526
- const resolved = resolveRepo(repoName);
527
- if (!resolved) {
528
- throw new Error(`Unknown repository: ${repoName}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
529
- }
530
- // Send progress: Starting
531
- if (progressToken) {
532
- sendProgressNotification(progressToken, 1, 4, "Fetching version info...");
533
- }
534
- // Fetch all data in parallel
535
- const [versionInfo, outdatedInfo, breakingChanges] = await Promise.all([
536
- releaseTracker.getVersionInfo(resolved.owner, resolved.repo),
537
- releaseTracker.isOutdated(resolved.owner, resolved.repo, currentVersion),
538
- releaseTracker.getBreakingChangesSince(resolved.owner, resolved.repo, currentVersion),
539
- ]);
540
- // Send progress: Fetched version data
541
- if (progressToken) {
542
- sendProgressNotification(progressToken, 2, 4, "Checking breaking changes...");
543
- }
544
- const latestVersion = versionInfo.latestStableRelease?.tag || versionInfo.latestRelease?.tag;
545
- // Only fetch migration guide if there are breaking changes
546
- let migrationGuide = null;
547
- if (breakingChanges.length > 0 && latestVersion) {
548
- // Send progress: Fetching migration guide
549
- if (progressToken) {
550
- sendProgressNotification(progressToken, 3, 4, "Generating migration guide...");
551
- }
552
- migrationGuide = await releaseTracker.getMigrationGuide(resolved.owner, resolved.repo, currentVersion, latestVersion);
553
- }
554
- // Send progress: Complete
555
- if (progressToken) {
556
- sendProgressNotification(progressToken, 4, 4, "Analysis complete");
557
- }
558
- // Compute upgrade urgency
559
- const urgency = computeUpgradeUrgency(outdatedInfo, breakingChanges.length);
560
- return {
561
- repository: `${resolved.owner}/${resolved.repo}`,
562
- currentVersion,
563
- // Version summary
564
- version: {
565
- latest: latestVersion || "No releases",
566
- latestStable: versionInfo.latestStableRelease?.tag || "No stable releases",
567
- publishedAt: versionInfo.latestRelease?.publishedAt || null,
568
- isOutdated: outdatedInfo.isOutdated,
569
- versionsBehind: outdatedInfo.versionsBehind,
570
- },
571
- // Breaking changes summary
572
- breakingChanges: {
573
- count: breakingChanges.length,
574
- hasBreakingChanges: breakingChanges.length > 0,
575
- items: breakingChanges.slice(0, 10), // Limit to avoid token bloat
576
- },
577
- // Migration guide (only if needed)
578
- migration: migrationGuide
579
- ? {
580
- steps: migrationGuide.migrationSteps,
581
- deprecations: migrationGuide.deprecations,
582
- newFeatures: migrationGuide.newFeatures.slice(0, 5),
583
- }
584
- : null,
585
- // Actionable recommendation
586
- urgency,
587
- recommendation: generateUpgradeRecommendation(urgency, breakingChanges.length, outdatedInfo),
588
- };
589
- }
590
- /**
591
- * Compound tool: Full repository context
592
- * Combines: getVersionInfo + getLatestSyntax + listExamples (filtered)
593
- * Provides everything needed to start working with a repo
594
- */
595
- export async function getFullRepoContext(input) {
596
- const repoName = input?.repo || "compact";
597
- const progressToken = input._meta?.progressToken;
598
- logger.debug("Getting full repo context", { repo: repoName });
599
- const resolved = resolveRepo(repoName);
600
- if (!resolved) {
601
- throw new Error(`Unknown repository: ${repoName}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
602
- }
603
- // Send progress: Starting
604
- if (progressToken) {
605
- sendProgressNotification(progressToken, 1, 4, "Fetching version info...");
606
- }
607
- // Fetch version info
608
- const versionInfo = await releaseTracker.getVersionInfo(resolved.owner, resolved.repo);
609
- const version = versionInfo.latestStableRelease?.tag ||
610
- versionInfo.latestRelease?.tag ||
611
- "main";
612
- // Send progress: Fetched version
613
- if (progressToken) {
614
- sendProgressNotification(progressToken, 2, 4, "Loading syntax reference...");
615
- }
616
- // Conditionally fetch syntax reference
617
- let syntaxRef = null;
618
- if (input.includeSyntax !== false) {
619
- syntaxRef = await releaseTracker.getLatestSyntaxReference(resolved.owner, resolved.repo);
620
- }
621
- // Send progress: Loading examples
622
- if (progressToken) {
623
- sendProgressNotification(progressToken, 3, 4, "Gathering examples...");
624
- }
625
- // Get relevant examples for this repo
626
- let examples = [];
627
- if (input.includeExamples !== false) {
628
- // Filter examples relevant to this repo type
629
- const repoType = getRepoType(repoName);
630
- examples = EXAMPLES.filter((ex) => repoType === "all" || ex.category === repoType || repoType === "compact")
631
- .slice(0, 5)
632
- .map((ex) => ({
633
- name: ex.name,
634
- description: ex.description,
635
- complexity: ex.complexity,
636
- }));
637
- }
638
- // Send progress: Complete
639
- if (progressToken) {
640
- sendProgressNotification(progressToken, 4, 4, "Context ready");
641
- }
642
- return {
643
- repository: `${resolved.owner}/${resolved.repo}`,
644
- // Quick start info
645
- quickStart: {
646
- version,
647
- installCommand: getInstallCommand(repoName, version),
648
- docsUrl: `https://github.com/${resolved.owner}/${resolved.repo}`,
649
- },
650
- // Version context
651
- version: {
652
- current: version,
653
- stable: versionInfo.latestStableRelease?.tag || null,
654
- publishedAt: versionInfo.latestRelease?.publishedAt || null,
655
- recentReleases: versionInfo.recentReleases.slice(0, 3).map((r) => ({
656
- tag: r.tag,
657
- date: r.publishedAt.split("T")[0],
658
- })),
659
- },
660
- // Syntax reference (condensed)
661
- syntax: syntaxRef
662
- ? {
663
- version: syntaxRef.version,
664
- files: syntaxRef.syntaxFiles.map((f) => f.path),
665
- // Include first file content as primary reference
666
- primaryReference: syntaxRef.syntaxFiles[0]?.content?.slice(0, 2000) || null,
667
- }
668
- : null,
669
- // Relevant examples
670
- examples,
671
- note: `Use this context to write ${repoName} code at version ${version}. For detailed syntax, use midnight-get-latest-syntax.`,
672
- };
673
- }
674
- // Helper functions for compound tools
675
- function computeUpgradeUrgency(outdatedInfo, breakingCount) {
676
- if (!outdatedInfo.isOutdated)
677
- return "none";
678
- if (breakingCount === 0 && outdatedInfo.versionsBehind <= 2)
679
- return "low";
680
- if (breakingCount <= 2 && outdatedInfo.versionsBehind <= 5)
681
- return "medium";
682
- if (breakingCount <= 5)
683
- return "high";
684
- return "critical";
685
- }
686
- function generateUpgradeRecommendation(urgency, breakingCount, outdatedInfo) {
687
- switch (urgency) {
688
- case "none":
689
- return "✅ You're on the latest version. No action needed.";
690
- case "low":
691
- return `📦 Minor update available (${outdatedInfo.versionsBehind} versions behind). Safe to upgrade at your convenience.`;
692
- case "medium":
693
- return `⚠️ Update recommended. ${breakingCount} breaking change(s) to review. Plan upgrade within 2 weeks.`;
694
- case "high":
695
- return `🔶 Important update. ${breakingCount} breaking changes require attention. Schedule upgrade soon.`;
696
- case "critical":
697
- return `🚨 Critical update needed! ${breakingCount} breaking changes and ${outdatedInfo.versionsBehind} versions behind. Upgrade immediately.`;
698
- default:
699
- return "Check the breaking changes and plan your upgrade.";
700
- }
701
- }
702
- function getRepoType(repoName) {
703
- const name = repoName.toLowerCase();
704
- if (name.includes("counter"))
705
- return "counter";
706
- if (name.includes("bboard"))
707
- return "bboard";
708
- if (name.includes("token") || name.includes("dex"))
709
- return "token";
710
- if (name.includes("voting"))
711
- return "voting";
712
- return "all";
713
- }
714
- function getInstallCommand(repoName, version) {
715
- const name = repoName.toLowerCase();
716
- if (name === "compact" || name.includes("compact")) {
717
- return `npx @aspect-sh/pnpm dlx @midnight-ntwrk/create-midnight-app@${version}`;
718
- }
719
- if (name === "midnight-js" || name.includes("js")) {
720
- return `npm install @midnight-ntwrk/midnight-js@${version}`;
721
- }
722
- return `git clone https://github.com/midnight-ntwrk/${repoName}.git && cd ${repoName} && git checkout ${version}`;
723
- }
724
- //# sourceMappingURL=handlers.js.map