@equilateral_ai/mindmeld 3.5.3 → 4.0.2

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 (138) hide show
  1. package/hooks/session-start.js +312 -85
  2. package/package.json +21 -13
  3. package/scripts/init-project.js +9 -23
  4. package/scripts/repo-analyzer.js +118 -2
  5. package/src/client/dbShim.js +16 -0
  6. package/src/core/AuthManager.js +3 -2
  7. package/src/handlers/helpers/dbOperations.js +9 -46
  8. package/src/index.js +2 -217
  9. package/src/utils/piiMask.js +16 -0
  10. package/scripts/inject.js +0 -409
  11. package/scripts/mcp-bridge.js +0 -220
  12. package/scripts/standards.js +0 -285
  13. package/src/collaboration/CollaborationPrompt.js +0 -460
  14. package/src/core/AlertEngine.js +0 -813
  15. package/src/core/AlertNotifier.js +0 -363
  16. package/src/core/CorrelationAnalyzer.js +0 -931
  17. package/src/core/CrossReferenceEngine.js +0 -624
  18. package/src/core/CurationEngine.js +0 -688
  19. package/src/core/DeprecationScheduler.js +0 -183
  20. package/src/core/LoadBearingDetector.js +0 -242
  21. package/src/core/NotificationService.js +0 -1032
  22. package/src/core/RapportOrchestrator.js +0 -632
  23. package/src/core/RelevanceDetector.js +0 -694
  24. package/src/core/StandardLifecycle.js +0 -244
  25. package/src/core/StandardsIngestion.js +0 -991
  26. package/src/core/TeamLoadBearingDetector.js +0 -431
  27. package/src/core/parsers/adrParser.js +0 -479
  28. package/src/core/parsers/cursorRulesParser.js +0 -564
  29. package/src/core/parsers/eslintParser.js +0 -439
  30. package/src/database/dbOperations.js +0 -105
  31. package/src/handlers/activity/activityGetMe.js +0 -98
  32. package/src/handlers/activity/activityGetTeam.js +0 -175
  33. package/src/handlers/admin/adminSetup.js +0 -216
  34. package/src/handlers/alerts/alertsAcknowledge.js +0 -92
  35. package/src/handlers/alerts/alertsGet.js +0 -250
  36. package/src/handlers/analytics/activitySummaryGet.js +0 -234
  37. package/src/handlers/analytics/coachingGet.js +0 -361
  38. package/src/handlers/analytics/convergenceGet.js +0 -236
  39. package/src/handlers/analytics/developerScoreGet.js +0 -137
  40. package/src/handlers/collaborators/collaboratorAdd.js +0 -200
  41. package/src/handlers/collaborators/collaboratorInvite.js +0 -219
  42. package/src/handlers/collaborators/collaboratorList.js +0 -82
  43. package/src/handlers/collaborators/collaboratorRemove.js +0 -128
  44. package/src/handlers/collaborators/inviteAccept.js +0 -122
  45. package/src/handlers/company/companyUsersDelete.js +0 -141
  46. package/src/handlers/company/companyUsersGet.js +0 -90
  47. package/src/handlers/company/companyUsersPost.js +0 -267
  48. package/src/handlers/company/companyUsersPut.js +0 -76
  49. package/src/handlers/context/contextGet.js +0 -57
  50. package/src/handlers/context/invariantsGet.js +0 -74
  51. package/src/handlers/context/loopsGet.js +0 -82
  52. package/src/handlers/context/notesCreate.js +0 -74
  53. package/src/handlers/context/purposeGet.js +0 -78
  54. package/src/handlers/correlations/correlationsDeveloperGet.js +0 -227
  55. package/src/handlers/correlations/correlationsGet.js +0 -93
  56. package/src/handlers/correlations/correlationsProjectGet.js +0 -153
  57. package/src/handlers/enterprise/controlTowerGet.js +0 -224
  58. package/src/handlers/enterprise/enterpriseAuditGet.js +0 -108
  59. package/src/handlers/enterprise/enterpriseContributorsGet.js +0 -85
  60. package/src/handlers/enterprise/enterpriseKnowledgeCategoriesGet.js +0 -53
  61. package/src/handlers/enterprise/enterpriseKnowledgeCreate.js +0 -77
  62. package/src/handlers/enterprise/enterpriseKnowledgeDelete.js +0 -71
  63. package/src/handlers/enterprise/enterpriseKnowledgeGet.js +0 -87
  64. package/src/handlers/enterprise/enterpriseKnowledgeUpdate.js +0 -122
  65. package/src/handlers/enterprise/enterpriseOnboardingComplete.js +0 -77
  66. package/src/handlers/enterprise/enterpriseOnboardingInvite.js +0 -138
  67. package/src/handlers/enterprise/enterpriseOnboardingSetup.js +0 -128
  68. package/src/handlers/enterprise/enterpriseOnboardingStatus.js +0 -88
  69. package/src/handlers/github/githubConnectionStatus.js +0 -49
  70. package/src/handlers/github/githubDiscoverPatterns.js +0 -621
  71. package/src/handlers/github/githubOAuthCallback.js +0 -178
  72. package/src/handlers/github/githubOAuthStart.js +0 -59
  73. package/src/handlers/github/githubPatternsReview.js +0 -76
  74. package/src/handlers/github/githubReposList.js +0 -105
  75. package/src/handlers/health/healthGet.js +0 -55
  76. package/src/handlers/helpers/auditLogger.js +0 -201
  77. package/src/handlers/helpers/checkSuperAdmin.js +0 -84
  78. package/src/handlers/helpers/decisionFrames.js +0 -29
  79. package/src/handlers/helpers/errorHandler.js +0 -49
  80. package/src/handlers/helpers/index.js +0 -138
  81. package/src/handlers/helpers/lambdaWrapper.js +0 -60
  82. package/src/handlers/helpers/mindmeldMcpCore.js +0 -1103
  83. package/src/handlers/helpers/predictiveCache.js +0 -51
  84. package/src/handlers/helpers/projectAccess.js +0 -88
  85. package/src/handlers/helpers/responseUtil.js +0 -55
  86. package/src/handlers/helpers/subscriptionTiers.js +0 -1168
  87. package/src/handlers/mcp/mcpHandler.js +0 -569
  88. package/src/handlers/mcp/mindmeldMcpHandler.js +0 -124
  89. package/src/handlers/mcp/mindmeldMcpStreamHandler.js +0 -342
  90. package/src/handlers/notifications/getPreferences.js +0 -84
  91. package/src/handlers/notifications/sendNotification.js +0 -170
  92. package/src/handlers/notifications/updatePreferences.js +0 -316
  93. package/src/handlers/patterns/patternEvaluatePromotionPost.js +0 -173
  94. package/src/handlers/patterns/patternUsagePost.js +0 -182
  95. package/src/handlers/patterns/patternViolationPost.js +0 -185
  96. package/src/handlers/projects/projectCreate.js +0 -248
  97. package/src/handlers/projects/projectDelete.js +0 -82
  98. package/src/handlers/projects/projectGet.js +0 -95
  99. package/src/handlers/projects/projectUpdate.js +0 -117
  100. package/src/handlers/reports/aiLeverage.js +0 -210
  101. package/src/handlers/reports/engineeringInvestment.js +0 -132
  102. package/src/handlers/reports/riskForecast.js +0 -206
  103. package/src/handlers/reports/standardsRoi.js +0 -254
  104. package/src/handlers/scheduled/analyzeCorrelations.js +0 -178
  105. package/src/handlers/scheduled/analyzeGitHistory.js +0 -510
  106. package/src/handlers/scheduled/generateAlerts.js +0 -135
  107. package/src/handlers/scheduled/maturityUpdateJob.js +0 -166
  108. package/src/handlers/scheduled/refreshActivity.js +0 -21
  109. package/src/handlers/scheduled/scanCompliance.js +0 -334
  110. package/src/handlers/sessions/sessionEndPost.js +0 -180
  111. package/src/handlers/sessions/sessionStandardsPost.js +0 -171
  112. package/src/handlers/standards/catalogGet.js +0 -185
  113. package/src/handlers/standards/catalogSync.js +0 -120
  114. package/src/handlers/standards/discoveriesGet.js +0 -89
  115. package/src/handlers/standards/projectStandardsGet.js +0 -129
  116. package/src/handlers/standards/projectStandardsPut.js +0 -151
  117. package/src/handlers/standards/standardsAuditGet.js +0 -65
  118. package/src/handlers/standards/standardsParseUpload.js +0 -149
  119. package/src/handlers/standards/standardsRelevantPost.js +0 -405
  120. package/src/handlers/standards/standardsTransition.js +0 -161
  121. package/src/handlers/stripe/addonManagePost.js +0 -240
  122. package/src/handlers/stripe/billingPortalPost.js +0 -93
  123. package/src/handlers/stripe/enterpriseCheckoutPost.js +0 -272
  124. package/src/handlers/stripe/seatsUpdatePost.js +0 -185
  125. package/src/handlers/stripe/subscriptionCancelDelete.js +0 -169
  126. package/src/handlers/stripe/subscriptionCreatePost.js +0 -221
  127. package/src/handlers/stripe/subscriptionUpdatePut.js +0 -163
  128. package/src/handlers/stripe/webhookPost.js +0 -482
  129. package/src/handlers/user/apiTokenCreate.js +0 -71
  130. package/src/handlers/user/apiTokenList.js +0 -64
  131. package/src/handlers/user/userSplashAck.js +0 -91
  132. package/src/handlers/user/userSplashGet.js +0 -211
  133. package/src/handlers/users/cognitoPostConfirmation.js +0 -186
  134. package/src/handlers/users/cognitoPreSignUp.js +0 -114
  135. package/src/handlers/users/userEntitlementsGet.js +0 -89
  136. package/src/handlers/users/userGet.js +0 -118
  137. package/src/handlers/users/userProfilePut.js +0 -77
  138. package/src/handlers/webhooks/githubWebhook.js +0 -215
package/scripts/inject.js DELETED
@@ -1,409 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * MindMeld CLI - Inject relevant standards into AI coding tool config
4
- *
5
- * Usage:
6
- * mindmeld inject # stdout (raw markdown)
7
- * mindmeld inject --format cursorrules
8
- * mindmeld inject --format windsurfrules
9
- * mindmeld inject --format aider
10
- * mindmeld inject --format claude # Claude Code hook format
11
- *
12
- * @equilateral_ai/mindmeld v3.0.0
13
- */
14
-
15
- const path = require('path');
16
- const fs = require('fs').promises;
17
-
18
- const FORMATS = {
19
- raw: { file: null, description: 'Raw markdown to stdout' },
20
- cursorrules: { file: '.cursorrules', description: 'Cursor rules file' },
21
- windsurfrules: { file: '.windsurfrules', description: 'Windsurf rules file' },
22
- aider: { file: '.aider.conventions.md', description: 'Aider conventions file' },
23
- claude: { file: null, description: 'Claude Code hook format (stdout)' }
24
- };
25
-
26
- function showInjectHelp() {
27
- console.log(`
28
- MindMeld inject - Generate context-aware standards for any AI coding tool
29
-
30
- Usage:
31
- mindmeld inject [options]
32
-
33
- Options:
34
- --format <type> Output format (default: raw)
35
- --path <dir> Project path (default: current directory)
36
- --help, -h Show this help
37
-
38
- Formats:
39
- raw Plain markdown to stdout (pipe anywhere)
40
- cursorrules Write .cursorrules file
41
- windsurfrules Write .windsurfrules file
42
- aider Write .aider.conventions.md file
43
- claude Claude Code hook format (stdout)
44
-
45
- Examples:
46
- mindmeld inject # Print standards to stdout
47
- mindmeld inject --format cursorrules # Update .cursorrules
48
- mindmeld inject --format aider # Update aider conventions
49
- mindmeld inject | ollama run qwen3-coder # Pipe to local model
50
- mindmeld inject --format raw >> system.txt # Append to system prompt
51
- `);
52
- }
53
-
54
- /**
55
- * Detect project context by scanning files in the working directory
56
- */
57
- async function detectProjectContext(projectPath) {
58
- const context = {
59
- projectName: path.basename(projectPath),
60
- languages: [],
61
- frameworks: [],
62
- files: []
63
- };
64
-
65
- // Check for common project indicators
66
- const checks = [
67
- { file: 'package.json', language: 'javascript', frameworks: ['node'] },
68
- { file: 'tsconfig.json', language: 'typescript', frameworks: ['node'] },
69
- { file: 'template.yaml', language: 'yaml', frameworks: ['aws-sam'] },
70
- { file: 'serverless.yml', language: 'yaml', frameworks: ['serverless'] },
71
- { file: 'Dockerfile', language: 'docker', frameworks: ['docker'] },
72
- { file: 'requirements.txt', language: 'python', frameworks: [] },
73
- { file: 'go.mod', language: 'go', frameworks: [] },
74
- { file: 'Cargo.toml', language: 'rust', frameworks: [] },
75
- { file: '.terraform', language: 'hcl', frameworks: ['terraform'] }
76
- ];
77
-
78
- for (const check of checks) {
79
- try {
80
- await fs.access(path.join(projectPath, check.file));
81
- if (!context.languages.includes(check.language)) {
82
- context.languages.push(check.language);
83
- }
84
- context.frameworks.push(...check.frameworks);
85
- context.files.push(check.file);
86
- } catch (error) {
87
- // Expected: file doesn't exist
88
- if (error.code !== 'ENOENT' && error.code !== 'EACCES') {
89
- console.error(`Unexpected error checking ${check.file}:`, error.message);
90
- }
91
- }
92
- }
93
-
94
- // Check for specific patterns in package.json
95
- try {
96
- const pkg = JSON.parse(await fs.readFile(path.join(projectPath, 'package.json'), 'utf-8'));
97
- const deps = { ...pkg.dependencies, ...pkg.devDependencies };
98
- if (deps['react'] || deps['next']) context.frameworks.push('react');
99
- if (deps['express'] || deps['fastify']) context.frameworks.push('api');
100
- if (deps['@aws-sdk']) context.frameworks.push('aws');
101
- if (deps['pg'] || deps['mysql2'] || deps['mongoose']) context.frameworks.push('database');
102
- } catch (error) {
103
- // Expected: no package.json or invalid JSON
104
- if (error.code !== 'ENOENT' && !(error instanceof SyntaxError)) {
105
- console.error('Unexpected error reading package.json:', error.message);
106
- }
107
- }
108
-
109
- return context;
110
- }
111
-
112
- /**
113
- * Load and score standards from .equilateral-standards
114
- */
115
- async function getRelevantStandards(projectPath, context) {
116
- const standardsDir = path.join(projectPath, '.equilateral-standards');
117
- const standards = [];
118
-
119
- try {
120
- await fs.access(standardsDir);
121
- } catch (error) {
122
- // Expected: standards dir doesn't exist
123
- if (error.code !== 'ENOENT') {
124
- console.error('Unexpected error accessing standards:', error.message);
125
- }
126
- return [];
127
- }
128
-
129
- // Recursively find all .md standard files from community repo
130
- async function scanDir(dir) {
131
- const entries = await fs.readdir(dir, { withFileTypes: true });
132
- for (const entry of entries) {
133
- const fullPath = path.join(dir, entry.name);
134
- if (entry.isDirectory()) {
135
- await scanDir(fullPath);
136
- } else if (entry.name.endsWith('.md') && entry.name !== 'README.md') {
137
- try {
138
- const content = await fs.readFile(fullPath, 'utf-8');
139
- const relativePath = path.relative(standardsDir, fullPath);
140
- const category = path.dirname(relativePath).replace(/\//g, '/');
141
- standards.push({
142
- element: entry.name.replace('.md', '').replace(/_/g, ' '),
143
- category: category === '.' ? 'general' : category,
144
- content: content,
145
- path: relativePath,
146
- score: 0
147
- });
148
- } catch (error) {
149
- // Expected: file not readable
150
- if (error.code !== 'ENOENT' && error.code !== 'EACCES') {
151
- console.error(`Unexpected error reading ${fullPath}:`, error.message);
152
- }
153
- }
154
- }
155
- }
156
- }
157
-
158
- await scanDir(standardsDir);
159
-
160
- // Score relevance based on project context
161
- for (const standard of standards) {
162
- let score = 0;
163
- const contentLower = standard.content.toLowerCase();
164
- const categoryLower = standard.category.toLowerCase();
165
-
166
- // Language match
167
- for (const lang of context.languages) {
168
- if (contentLower.includes(lang) || categoryLower.includes(lang)) {
169
- score += 3;
170
- }
171
- }
172
-
173
- // Framework match
174
- for (const fw of context.frameworks) {
175
- if (contentLower.includes(fw) || categoryLower.includes(fw)) {
176
- score += 5;
177
- }
178
- }
179
-
180
- // Category relevance boost
181
- if (categoryLower.includes('serverless') && context.frameworks.includes('aws-sam')) score += 4;
182
- if (categoryLower.includes('api') && context.frameworks.includes('api')) score += 4;
183
- if (categoryLower.includes('database') && context.frameworks.includes('database')) score += 4;
184
- if (categoryLower.includes('react') && context.frameworks.includes('react')) score += 4;
185
- if (categoryLower.includes('cost') && context.frameworks.includes('aws')) score += 3;
186
-
187
- // Base score for all standards (everyone gets some relevance)
188
- score += 1;
189
-
190
- standard.score = score;
191
- }
192
-
193
- // Sort by relevance, return top 10
194
- standards.sort((a, b) => b.score - a.score);
195
- return standards.slice(0, 10);
196
- }
197
-
198
- /**
199
- * Load team patterns from .mindmeld config
200
- */
201
- async function loadTeamPatterns(projectPath) {
202
- try {
203
- const configPath = path.join(projectPath, '.mindmeld', 'config.json');
204
- const config = JSON.parse(await fs.readFile(configPath, 'utf-8'));
205
- return {
206
- projectName: config.projectName || path.basename(projectPath),
207
- collaborators: config.collaborators || [],
208
- team: config.team || false
209
- };
210
- } catch (error) {
211
- // Expected: config doesn't exist or invalid JSON
212
- if (error.code !== 'ENOENT' && !(error instanceof SyntaxError)) {
213
- console.error('Unexpected error loading team patterns:', error.message);
214
- }
215
- return {
216
- projectName: path.basename(projectPath),
217
- collaborators: [],
218
- team: false
219
- };
220
- }
221
- }
222
-
223
- /**
224
- * Format standards as raw markdown
225
- */
226
- function formatRaw(standards, projectInfo, context) {
227
- const sections = [];
228
-
229
- sections.push(`# Standards for ${projectInfo.projectName}`);
230
- sections.push(`<!-- Generated by MindMeld | ${new Date().toISOString()} -->`);
231
- sections.push(`<!-- Context: ${context.languages.join(', ')} | ${context.frameworks.join(', ')} -->`);
232
- sections.push('');
233
-
234
- if (standards.length === 0) {
235
- sections.push('No standards found. Run `mindmeld init` to set up your project.');
236
- return sections.join('\n');
237
- }
238
-
239
- sections.push(`Injecting ${standards.length} relevant standards (of ${standards.length} scored):`);
240
- sections.push('');
241
-
242
- for (const standard of standards) {
243
- sections.push(`## ${standard.element}`);
244
- sections.push(`**Category**: ${standard.category} | **Relevance**: ${standard.score}`);
245
- sections.push('');
246
- // Truncate content to keep injection lean
247
- const lines = standard.content.split('\n');
248
- const truncated = lines.slice(0, 30).join('\n');
249
- sections.push(truncated);
250
- if (lines.length > 30) {
251
- sections.push('...');
252
- }
253
- sections.push('');
254
- }
255
-
256
- sections.push('---');
257
- sections.push('*Generated by MindMeld - mindmeld.dev*');
258
-
259
- return sections.join('\n');
260
- }
261
-
262
- /**
263
- * Format for .cursorrules / .windsurfrules (compact rules format)
264
- */
265
- function formatRulesFile(standards, projectInfo, context) {
266
- const sections = [];
267
-
268
- sections.push(`# Project Standards - ${projectInfo.projectName}`);
269
- sections.push(`# Auto-generated by MindMeld (mindmeld.dev)`);
270
- sections.push(`# Context: ${context.frameworks.join(', ') || context.languages.join(', ')}`);
271
- sections.push(`# Run \`mindmeld inject --format ${context._format}\` to regenerate`);
272
- sections.push('');
273
-
274
- for (const standard of standards) {
275
- sections.push(`## ${standard.element}`);
276
- // Extract just the key rules, not full prose
277
- const lines = standard.content.split('\n');
278
- const ruleLines = lines.filter(l =>
279
- l.startsWith('- ') || l.startsWith('* ') ||
280
- l.startsWith(' - ') || l.startsWith('> ') ||
281
- l.match(/^#{1,4}\s/) || l.match(/^\*\*[^*]+\*\*:/)
282
- ).slice(0, 10);
283
-
284
- if (ruleLines.length > 0) {
285
- sections.push(ruleLines.join('\n'));
286
- } else {
287
- // Fallback: first meaningful paragraph
288
- const meaningful = lines.filter(l => l.trim().length > 20 && !l.startsWith('#')).slice(0, 3);
289
- sections.push(meaningful.join('\n'));
290
- }
291
- sections.push('');
292
- }
293
-
294
- return sections.join('\n');
295
- }
296
-
297
- /**
298
- * Format for aider conventions
299
- */
300
- function formatAider(standards, projectInfo, context) {
301
- const sections = [];
302
-
303
- sections.push(`# Coding Conventions - ${projectInfo.projectName}`);
304
- sections.push('');
305
- sections.push(`> Auto-generated by MindMeld (mindmeld.dev)`);
306
- sections.push(`> Run \`mindmeld inject --format aider\` to regenerate`);
307
- sections.push('');
308
-
309
- for (const standard of standards) {
310
- sections.push(`## ${standard.element}`);
311
- sections.push('');
312
- // Aider conventions prefer concise bullet points
313
- const lines = standard.content.split('\n');
314
- const bullets = lines.filter(l =>
315
- l.startsWith('- ') || l.startsWith('* ') || l.match(/^\*\*[^*]+\*\*:/)
316
- ).slice(0, 8);
317
-
318
- if (bullets.length > 0) {
319
- sections.push(bullets.join('\n'));
320
- } else {
321
- const meaningful = lines.filter(l => l.trim().length > 10 && !l.startsWith('#')).slice(0, 4);
322
- sections.push(meaningful.join('\n'));
323
- }
324
- sections.push('');
325
- }
326
-
327
- return sections.join('\n');
328
- }
329
-
330
- /**
331
- * Main inject execution
332
- */
333
- async function inject(options = {}) {
334
- const format = options.format || 'raw';
335
- const projectPath = options.path || process.cwd();
336
-
337
- if (!FORMATS[format]) {
338
- console.error(`Unknown format: ${format}`);
339
- console.error(`Available: ${Object.keys(FORMATS).join(', ')}`);
340
- process.exit(1);
341
- }
342
-
343
- // Standalone detection (no database, no prompts, works everywhere)
344
- let standards = [];
345
- let projectInfo = {};
346
- let context = {};
347
-
348
- context = await detectProjectContext(projectPath);
349
- standards = await getRelevantStandards(projectPath, context);
350
- projectInfo = await loadTeamPatterns(projectPath);
351
-
352
- context._format = format;
353
-
354
- // 2. Format output
355
- let output;
356
- switch (format) {
357
- case 'cursorrules':
358
- case 'windsurfrules':
359
- output = formatRulesFile(standards, projectInfo, context);
360
- break;
361
- case 'aider':
362
- output = formatAider(standards, projectInfo, context);
363
- break;
364
- case 'claude':
365
- // Use the session-start formatter with mapped fields
366
- try {
367
- const { formatContextInjection } = require('../hooks/session-start');
368
- const mappedStandards = standards.map(s => ({
369
- element: s.element,
370
- category: s.category,
371
- rule: s.content.split('\n').find(l => l.trim().length > 10 && !l.startsWith('#')) || s.element
372
- }));
373
- output = formatContextInjection({
374
- project: projectInfo.projectName,
375
- relevantStandards: mappedStandards,
376
- teamPatterns: [],
377
- recentLearning: [],
378
- collaborators: projectInfo.collaborators || []
379
- });
380
- } catch (error) {
381
- // Expected: module not found in standalone mode
382
- if (error.code !== 'MODULE_NOT_FOUND') {
383
- console.error('Unexpected error with claude format:', error.message);
384
- }
385
- output = formatRaw(standards, projectInfo, context);
386
- }
387
- break;
388
- case 'raw':
389
- default:
390
- output = formatRaw(standards, projectInfo, context);
391
- break;
392
- }
393
-
394
- // 3. Write to file or stdout
395
- const targetFile = FORMATS[format].file;
396
-
397
- if (targetFile) {
398
- const targetPath = path.join(projectPath, targetFile);
399
- await fs.writeFile(targetPath, output);
400
- console.error(`[MindMeld] Written ${standards.length} standards to ${targetFile}`);
401
- console.error(`[MindMeld] Context: ${context.languages ? context.languages.join(', ') : 'unknown'} | ${context.frameworks ? context.frameworks.join(', ') : ''}`);
402
- console.error(`[MindMeld] Regenerate anytime: mindmeld inject --format ${format}`);
403
- } else {
404
- // Output to stdout (for piping)
405
- console.log(output);
406
- }
407
- }
408
-
409
- module.exports = { inject, showInjectHelp, FORMATS };
@@ -1,220 +0,0 @@
1
- /**
2
- * MindMeld MCP Bridge - Stdio-to-HTTP proxy for MCP clients
3
- *
4
- * Bridges stdio MCP transport to the remote MindMeld MCP server.
5
- * For clients that don't support URL transport natively
6
- * (Cline, Cursor, Windsurf, etc.)
7
- *
8
- * Usage:
9
- * MINDMELD_TOKEN=mm_live_xxx mindmeld mcp
10
- * mindmeld mcp --token mm_live_xxx
11
- */
12
-
13
- const https = require('https');
14
- const os = require('os');
15
- const fs = require('fs');
16
- const path = require('path');
17
-
18
- const MCP_HOST = 'api.mindmeld.dev';
19
- const MCP_PATH = '/api/mcp/mindmeld';
20
- const REQUEST_TIMEOUT = 30000;
21
-
22
- /**
23
- * Resolve API token from env var, CLI arg, or stored file
24
- */
25
- function resolveToken(cliToken) {
26
- if (process.env.MINDMELD_TOKEN) {
27
- return process.env.MINDMELD_TOKEN;
28
- }
29
- if (cliToken) {
30
- return cliToken;
31
- }
32
- try {
33
- const tokenPath = path.join(os.homedir(), '.mindmeld', 'api-token');
34
- return fs.readFileSync(tokenPath, 'utf-8').trim();
35
- } catch (err) {
36
- return null;
37
- }
38
- }
39
-
40
- /**
41
- * Forward a JSON-RPC message to the remote MCP server
42
- */
43
- function forwardToServer(message, token) {
44
- return new Promise((resolve, reject) => {
45
- const body = JSON.stringify(message);
46
- const req = https.request({
47
- method: 'POST',
48
- hostname: MCP_HOST,
49
- path: MCP_PATH,
50
- headers: {
51
- 'Content-Type': 'application/json',
52
- 'Accept': 'application/json',
53
- 'X-MindMeld-Token': token
54
- },
55
- timeout: REQUEST_TIMEOUT
56
- }, (res) => {
57
- let data = '';
58
- res.on('data', chunk => data += chunk);
59
- res.on('end', () => {
60
- if (res.statusCode === 202 || !data.trim()) {
61
- resolve(null);
62
- return;
63
- }
64
- try {
65
- resolve(JSON.parse(data));
66
- } catch (e) {
67
- reject(new Error(`Invalid JSON from server: ${data.substring(0, 200)}`));
68
- }
69
- });
70
- });
71
-
72
- req.on('timeout', () => {
73
- req.destroy();
74
- reject(new Error('Request timed out'));
75
- });
76
-
77
- req.on('error', (e) => {
78
- reject(new Error(`Connection failed: ${e.message}`));
79
- });
80
-
81
- req.write(body);
82
- req.end();
83
- });
84
- }
85
-
86
- /**
87
- * Process a single JSON-RPC message from stdin
88
- */
89
- async function processMessage(line, token) {
90
- let message;
91
- try {
92
- message = JSON.parse(line);
93
- } catch (e) {
94
- process.stdout.write(JSON.stringify({
95
- jsonrpc: '2.0',
96
- error: { code: -32700, message: 'Parse error: invalid JSON' },
97
- id: null
98
- }) + '\n');
99
- return;
100
- }
101
-
102
- const isNotification = !('id' in message);
103
-
104
- try {
105
- const response = await forwardToServer(message, token);
106
-
107
- if (response === null || isNotification) {
108
- return;
109
- }
110
-
111
- process.stdout.write(JSON.stringify(response) + '\n');
112
- } catch (error) {
113
- process.stderr.write(`[MindMeld] ${error.message}\n`);
114
-
115
- if (!isNotification && message.id !== undefined) {
116
- process.stdout.write(JSON.stringify({
117
- jsonrpc: '2.0',
118
- error: { code: -32603, message: error.message },
119
- id: message.id
120
- }) + '\n');
121
- }
122
- }
123
- }
124
-
125
- /**
126
- * Start the stdio bridge — long-lived, runs until stdin closes
127
- */
128
- function startBridge(token) {
129
- process.stderr.write(`[MindMeld] MCP bridge started (pid ${process.pid})\n`);
130
- process.stderr.write(`[MindMeld] Proxying to https://${MCP_HOST}${MCP_PATH}\n`);
131
-
132
- let buffer = '';
133
- let pending = 0;
134
- let stdinClosed = false;
135
-
136
- function maybeExit() {
137
- if (stdinClosed && pending === 0) {
138
- process.stderr.write('[MindMeld] All requests complete, shutting down\n');
139
- process.exit(0);
140
- }
141
- }
142
-
143
- function trackMessage(line) {
144
- pending++;
145
- processMessage(line, token).finally(() => {
146
- pending--;
147
- maybeExit();
148
- });
149
- }
150
-
151
- process.stdin.setEncoding('utf-8');
152
-
153
- process.stdin.on('data', (chunk) => {
154
- buffer += chunk;
155
- const lines = buffer.split('\n');
156
- buffer = lines.pop();
157
-
158
- for (const line of lines) {
159
- const trimmed = line.trim();
160
- if (!trimmed) continue;
161
- trackMessage(trimmed);
162
- }
163
- });
164
-
165
- process.stdin.on('end', () => {
166
- process.stderr.write('[MindMeld] stdin closed\n');
167
- stdinClosed = true;
168
- maybeExit();
169
- });
170
-
171
- process.stdin.on('error', (err) => {
172
- process.stderr.write(`[MindMeld] stdin error: ${err.message}\n`);
173
- process.exit(1);
174
- });
175
- }
176
-
177
- function showMcpHelp() {
178
- console.log(`
179
- MindMeld MCP Bridge - Stdio-to-HTTP proxy for MCP clients
180
-
181
- Usage:
182
- mindmeld mcp [options]
183
-
184
- Options:
185
- --token <token> MindMeld API token (or set MINDMELD_TOKEN env var)
186
- --help, -h Show this help
187
-
188
- Token Resolution (in priority order):
189
- 1. MINDMELD_TOKEN environment variable
190
- 2. --token CLI argument
191
- 3. ~/.mindmeld/api-token file
192
-
193
- Create a token at: https://app.mindmeld.dev/api-tokens
194
-
195
- Client Configuration:
196
- Cline / Cursor / Windsurf:
197
- {
198
- "mcpServers": {
199
- "mindmeld": {
200
- "command": "mindmeld",
201
- "args": ["mcp"],
202
- "env": { "MINDMELD_TOKEN": "mm_live_xxx" }
203
- }
204
- }
205
- }
206
-
207
- Claude Code (use URL transport instead — no bridge needed):
208
- {
209
- "mcpServers": {
210
- "mindmeld": {
211
- "type": "url",
212
- "url": "https://api.mindmeld.dev/api/mcp/mindmeld",
213
- "headers": { "X-MindMeld-Token": "mm_live_xxx" }
214
- }
215
- }
216
- }
217
- `);
218
- }
219
-
220
- module.exports = { startBridge, resolveToken, showMcpHelp };