faf-mcp 1.0.0
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/CHANGELOG.md +34 -0
- package/CLAUDE.md +73 -0
- package/LICENSE +22 -0
- package/README.md +165 -0
- package/assets/Project-faf-pckg-json-README.png +0 -0
- package/assets/icons/faf-icon-128.png +0 -0
- package/assets/icons/faf-icon-256.png +0 -0
- package/assets/icons/faf-icon-48.png +0 -0
- package/assets/icons/faf-icon-512.png +0 -0
- package/assets/icons/orange-smiley.svg +6 -0
- package/dist/src/compiler/index.d.ts +7 -0
- package/dist/src/compiler/index.js +24 -0
- package/dist/src/compiler/index.js.map +1 -0
- package/dist/src/compiler/scorer.d.ts +53 -0
- package/dist/src/compiler/scorer.js +189 -0
- package/dist/src/compiler/scorer.js.map +1 -0
- package/dist/src/compiler/slot-validator.d.ts +32 -0
- package/dist/src/compiler/slot-validator.js +293 -0
- package/dist/src/compiler/slot-validator.js.map +1 -0
- package/dist/src/compiler/type-detector.d.ts +62 -0
- package/dist/src/compiler/type-detector.js +388 -0
- package/dist/src/compiler/type-detector.js.map +1 -0
- package/dist/src/config/visibility.d.ts +41 -0
- package/dist/src/config/visibility.js +158 -0
- package/dist/src/config/visibility.js.map +1 -0
- package/dist/src/faf-core/commands/audit.d.ts +21 -0
- package/dist/src/faf-core/commands/audit.js +83 -0
- package/dist/src/faf-core/commands/audit.js.map +1 -0
- package/dist/src/faf-core/commands/auto.d.ts +25 -0
- package/dist/src/faf-core/commands/auto.js +74 -0
- package/dist/src/faf-core/commands/auto.js.map +1 -0
- package/dist/src/faf-core/commands/bi-sync.d.ts +26 -0
- package/dist/src/faf-core/commands/bi-sync.js +157 -0
- package/dist/src/faf-core/commands/bi-sync.js.map +1 -0
- package/dist/src/faf-core/commands/doctor.d.ts +17 -0
- package/dist/src/faf-core/commands/doctor.js +198 -0
- package/dist/src/faf-core/commands/doctor.js.map +1 -0
- package/dist/src/faf-core/commands/enhance.d.ts +46 -0
- package/dist/src/faf-core/commands/enhance.js +360 -0
- package/dist/src/faf-core/commands/enhance.js.map +1 -0
- package/dist/src/faf-core/commands/formats.d.ts +22 -0
- package/dist/src/faf-core/commands/formats.js +117 -0
- package/dist/src/faf-core/commands/formats.js.map +1 -0
- package/dist/src/faf-core/commands/init.d.ts +26 -0
- package/dist/src/faf-core/commands/init.js +114 -0
- package/dist/src/faf-core/commands/init.js.map +1 -0
- package/dist/src/faf-core/commands/innit.d.ts +7 -0
- package/dist/src/faf-core/commands/innit.js +13 -0
- package/dist/src/faf-core/commands/innit.js.map +1 -0
- package/dist/src/faf-core/commands/migrate.d.ts +15 -0
- package/dist/src/faf-core/commands/migrate.js +86 -0
- package/dist/src/faf-core/commands/migrate.js.map +1 -0
- package/dist/src/faf-core/commands/quick.d.ts +16 -0
- package/dist/src/faf-core/commands/quick.js +184 -0
- package/dist/src/faf-core/commands/quick.js.map +1 -0
- package/dist/src/faf-core/commands/score.d.ts +47 -0
- package/dist/src/faf-core/commands/score.js +49 -0
- package/dist/src/faf-core/commands/score.js.map +1 -0
- package/dist/src/faf-core/commands/sync.d.ts +16 -0
- package/dist/src/faf-core/commands/sync.js +210 -0
- package/dist/src/faf-core/commands/sync.js.map +1 -0
- package/dist/src/faf-core/commands/update.d.ts +12 -0
- package/dist/src/faf-core/commands/update.js +46 -0
- package/dist/src/faf-core/commands/update.js.map +1 -0
- package/dist/src/faf-core/commands/validate.d.ts +21 -0
- package/dist/src/faf-core/commands/validate.js +81 -0
- package/dist/src/faf-core/commands/validate.js.map +1 -0
- package/dist/src/faf-core/compiler/faf-compiler.d.ts +138 -0
- package/dist/src/faf-core/compiler/faf-compiler.js +794 -0
- package/dist/src/faf-core/compiler/faf-compiler.js.map +1 -0
- package/dist/src/faf-core/engines/dependency-tsa.d.ts +88 -0
- package/dist/src/faf-core/engines/dependency-tsa.js +361 -0
- package/dist/src/faf-core/engines/dependency-tsa.js.map +1 -0
- package/dist/src/faf-core/engines/fab-formats-processor.d.ts +166 -0
- package/dist/src/faf-core/engines/fab-formats-processor.js +1274 -0
- package/dist/src/faf-core/engines/fab-formats-processor.js.map +1 -0
- package/dist/src/faf-core/engines/faf-dna.d.ts +159 -0
- package/dist/src/faf-core/engines/faf-dna.js +554 -0
- package/dist/src/faf-core/engines/faf-dna.js.map +1 -0
- package/dist/src/faf-core/engines/relentless-context-extractor.d.ts +100 -0
- package/dist/src/faf-core/engines/relentless-context-extractor.js +625 -0
- package/dist/src/faf-core/engines/relentless-context-extractor.js.map +1 -0
- package/dist/src/faf-core/fix-once/colors.d.ts +104 -0
- package/dist/src/faf-core/fix-once/colors.js +236 -0
- package/dist/src/faf-core/fix-once/colors.js.map +1 -0
- package/dist/src/faf-core/fix-once/types.d.ts +257 -0
- package/dist/src/faf-core/fix-once/types.js +26 -0
- package/dist/src/faf-core/fix-once/types.js.map +1 -0
- package/dist/src/faf-core/fix-once/yaml.d.ts +57 -0
- package/dist/src/faf-core/fix-once/yaml.js +172 -0
- package/dist/src/faf-core/fix-once/yaml.js.map +1 -0
- package/dist/src/faf-core/generators/faf-generator-championship.d.ts +16 -0
- package/dist/src/faf-core/generators/faf-generator-championship.js +462 -0
- package/dist/src/faf-core/generators/faf-generator-championship.js.map +1 -0
- package/dist/src/faf-core/utils/balance-visualizer.d.ts +37 -0
- package/dist/src/faf-core/utils/balance-visualizer.js +197 -0
- package/dist/src/faf-core/utils/balance-visualizer.js.map +1 -0
- package/dist/src/faf-core/utils/championship-style.d.ts +109 -0
- package/dist/src/faf-core/utils/championship-style.js +219 -0
- package/dist/src/faf-core/utils/championship-style.js.map +1 -0
- package/dist/src/faf-core/utils/chrome-extension-detector.d.ts +73 -0
- package/dist/src/faf-core/utils/chrome-extension-detector.js +268 -0
- package/dist/src/faf-core/utils/chrome-extension-detector.js.map +1 -0
- package/dist/src/faf-core/utils/fafignore-parser.d.ts +20 -0
- package/dist/src/faf-core/utils/fafignore-parser.js +178 -0
- package/dist/src/faf-core/utils/fafignore-parser.js.map +1 -0
- package/dist/src/faf-core/utils/file-utils.d.ts +112 -0
- package/dist/src/faf-core/utils/file-utils.js +846 -0
- package/dist/src/faf-core/utils/file-utils.js.map +1 -0
- package/dist/src/faf-core/utils/native-file-finder.d.ts +115 -0
- package/dist/src/faf-core/utils/native-file-finder.js +211 -0
- package/dist/src/faf-core/utils/native-file-finder.js.map +1 -0
- package/dist/src/faf-core/utils/platform-detector.d.ts +30 -0
- package/dist/src/faf-core/utils/platform-detector.js +218 -0
- package/dist/src/faf-core/utils/platform-detector.js.map +1 -0
- package/dist/src/faf-core/utils/technical-credit.d.ts +35 -0
- package/dist/src/faf-core/utils/technical-credit.js +286 -0
- package/dist/src/faf-core/utils/technical-credit.js.map +1 -0
- package/dist/src/faf-core/utils/yaml-generator.d.ts +41 -0
- package/dist/src/faf-core/utils/yaml-generator.js +360 -0
- package/dist/src/faf-core/utils/yaml-generator.js.map +1 -0
- package/dist/src/handlers/behavioral-instruction.d.ts +16 -0
- package/dist/src/handlers/behavioral-instruction.js +43 -0
- package/dist/src/handlers/behavioral-instruction.js.map +1 -0
- package/dist/src/handlers/championship-tools.d.ts +113 -0
- package/dist/src/handlers/championship-tools.js +2602 -0
- package/dist/src/handlers/championship-tools.js.map +1 -0
- package/dist/src/handlers/engine-adapter.d.ts +28 -0
- package/dist/src/handlers/engine-adapter.js +603 -0
- package/dist/src/handlers/engine-adapter.js.map +1 -0
- package/dist/src/handlers/fileHandler.d.ts +36 -0
- package/dist/src/handlers/fileHandler.js +246 -0
- package/dist/src/handlers/fileHandler.js.map +1 -0
- package/dist/src/handlers/resources.d.ts +18 -0
- package/dist/src/handlers/resources.js +78 -0
- package/dist/src/handlers/resources.js.map +1 -0
- package/dist/src/handlers/tool-registry.d.ts +23 -0
- package/dist/src/handlers/tool-registry.js +68 -0
- package/dist/src/handlers/tool-registry.js.map +1 -0
- package/dist/src/handlers/tool-types.d.ts +167 -0
- package/dist/src/handlers/tool-types.js +7 -0
- package/dist/src/handlers/tool-types.js.map +1 -0
- package/dist/src/handlers/tools.d.ts +25 -0
- package/dist/src/handlers/tools.js +1168 -0
- package/dist/src/handlers/tools.js.map +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +17 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/server.d.ts +28 -0
- package/dist/src/server.js +179 -0
- package/dist/src/server.js.map +1 -0
- package/dist/src/test-all-functions.d.ts +15 -0
- package/dist/src/test-all-functions.js +163 -0
- package/dist/src/test-all-functions.js.map +1 -0
- package/dist/src/types/mcp-tools.d.ts +53 -0
- package/dist/src/types/mcp-tools.js +77 -0
- package/dist/src/types/mcp-tools.js.map +1 -0
- package/dist/src/types/project-types.d.ts +22 -0
- package/dist/src/types/project-types.js +85 -0
- package/dist/src/types/project-types.js.map +1 -0
- package/dist/src/types/slots.d.ts +39 -0
- package/dist/src/types/slots.js +162 -0
- package/dist/src/types/slots.js.map +1 -0
- package/dist/src/types/tool-visibility.d.ts +36 -0
- package/dist/src/types/tool-visibility.js +510 -0
- package/dist/src/types/tool-visibility.js.map +1 -0
- package/dist/src/utils/auto-path-detection.d.ts +26 -0
- package/dist/src/utils/auto-path-detection.js +198 -0
- package/dist/src/utils/auto-path-detection.js.map +1 -0
- package/dist/src/utils/championship-format.d.ts +30 -0
- package/dist/src/utils/championship-format.js +79 -0
- package/dist/src/utils/championship-format.js.map +1 -0
- package/dist/src/utils/cli-detector.d.ts +20 -0
- package/dist/src/utils/cli-detector.js +230 -0
- package/dist/src/utils/cli-detector.js.map +1 -0
- package/dist/src/utils/display-protocol.d.ts +57 -0
- package/dist/src/utils/display-protocol.js +131 -0
- package/dist/src/utils/display-protocol.js.map +1 -0
- package/dist/src/utils/faf-file-finder.d.ts +59 -0
- package/dist/src/utils/faf-file-finder.js +139 -0
- package/dist/src/utils/faf-file-finder.js.map +1 -0
- package/dist/src/utils/fuzzy-detector.d.ts +56 -0
- package/dist/src/utils/fuzzy-detector.js +221 -0
- package/dist/src/utils/fuzzy-detector.js.map +1 -0
- package/dist/src/utils/path-resolver.d.ts +51 -0
- package/dist/src/utils/path-resolver.js +214 -0
- package/dist/src/utils/path-resolver.js.map +1 -0
- package/dist/src/utils/type-guards.d.ts +9 -0
- package/dist/src/utils/type-guards.js +27 -0
- package/dist/src/utils/type-guards.js.map +1 -0
- package/dist/src/utils/username-detector.d.ts +27 -0
- package/dist/src/utils/username-detector.js +90 -0
- package/dist/src/utils/username-detector.js.map +1 -0
- package/dist/src/utils/visual-style.d.ts +62 -0
- package/dist/src/utils/visual-style.js +164 -0
- package/dist/src/utils/visual-style.js.map +1 -0
- package/dist/src/version.d.ts +9 -0
- package/dist/src/version.js +37 -0
- package/dist/src/version.js.map +1 -0
- package/package.json +114 -0
- package/scripts/discord-sync-curated.js +233 -0
- package/scripts/discord-sync-final.js +218 -0
- package/scripts/discord-sync-simple.js +175 -0
- package/scripts/discord-sync-working.js +187 -0
- package/scripts/discord-sync.js +181 -0
- package/scripts/postinstall.js +46 -0
- package/skill/SKILL.md +385 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Discord Documentation Sync Tool (Simplified)
|
|
5
|
+
* Posts FAF documentation to Discord as messages
|
|
6
|
+
*
|
|
7
|
+
* Usage: node scripts/discord-sync-simple.js <webhook-url>
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const https = require('https');
|
|
13
|
+
|
|
14
|
+
const DOCS_DIR = path.join(__dirname, '../docs');
|
|
15
|
+
|
|
16
|
+
// Documentation files to sync
|
|
17
|
+
const DOCS_TO_SYNC = [
|
|
18
|
+
{
|
|
19
|
+
file: 'QUICK_START.md',
|
|
20
|
+
title: '๐ **Quick Start Guide**',
|
|
21
|
+
url: 'https://faf.one',
|
|
22
|
+
order: 1
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
file: 'FAQ.md',
|
|
26
|
+
title: 'โ **Frequently Asked Questions**',
|
|
27
|
+
url: 'https://faf.one',
|
|
28
|
+
order: 2
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
file: 'USER_GUIDE.md',
|
|
32
|
+
title: '๐ **User Guide**',
|
|
33
|
+
url: 'https://faf.one',
|
|
34
|
+
order: 3
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
file: 'PODIUM-SYSTEM.md',
|
|
38
|
+
title: '๐ **Podium Scoring System**',
|
|
39
|
+
url: 'https://faf.one',
|
|
40
|
+
order: 4
|
|
41
|
+
}
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
function postToDiscord(webhookUrl, content) {
|
|
45
|
+
return new Promise((resolve, reject) => {
|
|
46
|
+
const url = new URL(webhookUrl);
|
|
47
|
+
const payload = JSON.stringify({ content });
|
|
48
|
+
|
|
49
|
+
const options = {
|
|
50
|
+
hostname: url.hostname,
|
|
51
|
+
path: url.pathname + url.search,
|
|
52
|
+
method: 'POST',
|
|
53
|
+
headers: {
|
|
54
|
+
'Content-Type': 'application/json',
|
|
55
|
+
'Content-Length': payload.length
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const req = https.request(options, (res) => {
|
|
60
|
+
if (res.statusCode === 204 || res.statusCode === 200) {
|
|
61
|
+
resolve();
|
|
62
|
+
} else {
|
|
63
|
+
let body = '';
|
|
64
|
+
res.on('data', chunk => body += chunk);
|
|
65
|
+
res.on('end', () => {
|
|
66
|
+
reject(new Error(`Discord returned status ${res.statusCode}: ${body}`));
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
req.on('error', reject);
|
|
72
|
+
req.write(payload);
|
|
73
|
+
req.end();
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function createSummary(content, maxLength = 1500) {
|
|
78
|
+
const lines = content.split('\n');
|
|
79
|
+
let summary = '';
|
|
80
|
+
let lineCount = 0;
|
|
81
|
+
|
|
82
|
+
for (const line of lines) {
|
|
83
|
+
// Skip title lines
|
|
84
|
+
if (line.startsWith('# ')) continue;
|
|
85
|
+
|
|
86
|
+
summary += line + '\n';
|
|
87
|
+
lineCount++;
|
|
88
|
+
|
|
89
|
+
// Stop at reasonable length or after good amount of content
|
|
90
|
+
if (summary.length > maxLength || lineCount > 30) {
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return summary.trim();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async function syncDocs(webhookUrl) {
|
|
99
|
+
console.log('๐ Starting Discord documentation sync...\n');
|
|
100
|
+
|
|
101
|
+
// Post intro message
|
|
102
|
+
const introMessage = `## ๐ FAF Documentation
|
|
103
|
+
|
|
104
|
+
Welcome to the FAF (Foundational AI-context Format) documentation!
|
|
105
|
+
|
|
106
|
+
**๐งก IANA-registered format** ยท \`application/vnd.faf+yaml\`
|
|
107
|
+
**๐ฆ MCP:** 6.1k downloads, 1,231/week
|
|
108
|
+
**โก CLI:** 6.2k downloads, 235/week
|
|
109
|
+
|
|
110
|
+
Full docs available at **https://faf.one**
|
|
111
|
+
|
|
112
|
+
---`;
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
await postToDiscord(webhookUrl, introMessage);
|
|
116
|
+
console.log('โ
Posted intro message');
|
|
117
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
118
|
+
} catch (error) {
|
|
119
|
+
console.error('โ Failed to post intro:', error.message);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Sort docs by order
|
|
123
|
+
const sortedDocs = DOCS_TO_SYNC.sort((a, b) => a.order - b.order);
|
|
124
|
+
|
|
125
|
+
for (const doc of sortedDocs) {
|
|
126
|
+
const filePath = path.join(DOCS_DIR, doc.file);
|
|
127
|
+
|
|
128
|
+
if (!fs.existsSync(filePath)) {
|
|
129
|
+
console.log(`โ ๏ธ Skipping ${doc.file} (not found)`);
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
134
|
+
const summary = createSummary(content);
|
|
135
|
+
|
|
136
|
+
const message = `${doc.title}
|
|
137
|
+
|
|
138
|
+
${summary}
|
|
139
|
+
|
|
140
|
+
**[Read full guide โ](${doc.url})**`;
|
|
141
|
+
|
|
142
|
+
try {
|
|
143
|
+
await postToDiscord(webhookUrl, message);
|
|
144
|
+
console.log(`โ
Posted ${doc.title}`);
|
|
145
|
+
|
|
146
|
+
// Rate limit: Discord allows 5 requests per 2 seconds
|
|
147
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
148
|
+
} catch (error) {
|
|
149
|
+
console.error(`โ Failed to post ${doc.title}:`, error.message);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
console.log('\nโจ Sync complete!');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Main execution
|
|
157
|
+
if (require.main === module) {
|
|
158
|
+
const webhookUrl = process.argv[2];
|
|
159
|
+
|
|
160
|
+
if (!webhookUrl) {
|
|
161
|
+
console.error('Usage: node scripts/discord-sync-simple.js <webhook-url>');
|
|
162
|
+
console.error('\nGet your webhook URL from Discord:');
|
|
163
|
+
console.error('1. Server Settings > Integrations > Webhooks');
|
|
164
|
+
console.error('2. Create New Webhook or use existing');
|
|
165
|
+
console.error('3. Copy Webhook URL');
|
|
166
|
+
process.exit(1);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
syncDocs(webhookUrl).catch((error) => {
|
|
170
|
+
console.error('Fatal error:', error);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
module.exports = { syncDocs };
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Discord Documentation Sync Tool (Working Version)
|
|
5
|
+
* Posts FAF documentation to Discord as properly formatted messages
|
|
6
|
+
*
|
|
7
|
+
* Usage: node scripts/discord-sync-working.js <webhook-url>
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const https = require('https');
|
|
13
|
+
|
|
14
|
+
const DOCS_DIR = path.join(__dirname, '../docs');
|
|
15
|
+
|
|
16
|
+
// Documentation files to sync
|
|
17
|
+
const DOCS_TO_SYNC = [
|
|
18
|
+
{
|
|
19
|
+
file: 'QUICK_START.md',
|
|
20
|
+
title: '๐ Quick Start Guide',
|
|
21
|
+
url: 'https://faf.one',
|
|
22
|
+
order: 1
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
file: 'FAQ.md',
|
|
26
|
+
title: 'โ Frequently Asked Questions',
|
|
27
|
+
url: 'https://faf.one',
|
|
28
|
+
order: 2
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
file: 'USER_GUIDE.md',
|
|
32
|
+
title: '๐ User Guide',
|
|
33
|
+
url: 'https://faf.one',
|
|
34
|
+
order: 3
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
file: 'PODIUM-SYSTEM.md',
|
|
38
|
+
title: '๐ Podium Scoring System',
|
|
39
|
+
url: 'https://faf.one',
|
|
40
|
+
order: 4
|
|
41
|
+
}
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
function postToDiscord(webhookUrl, content) {
|
|
45
|
+
return new Promise((resolve, reject) => {
|
|
46
|
+
const url = new URL(webhookUrl);
|
|
47
|
+
|
|
48
|
+
// Create clean payload - only content field
|
|
49
|
+
const payload = JSON.stringify({
|
|
50
|
+
content: content.substring(0, 2000) // Discord limit is 2000 chars per message
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const options = {
|
|
54
|
+
hostname: url.hostname,
|
|
55
|
+
path: url.pathname + url.search,
|
|
56
|
+
method: 'POST',
|
|
57
|
+
headers: {
|
|
58
|
+
'Content-Type': 'application/json',
|
|
59
|
+
'Content-Length': Buffer.byteLength(payload)
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const req = https.request(options, (res) => {
|
|
64
|
+
let body = '';
|
|
65
|
+
res.on('data', chunk => body += chunk);
|
|
66
|
+
res.on('end', () => {
|
|
67
|
+
if (res.statusCode === 204 || res.statusCode === 200) {
|
|
68
|
+
resolve();
|
|
69
|
+
} else {
|
|
70
|
+
reject(new Error(`Discord returned status ${res.statusCode}: ${body}`));
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
req.on('error', reject);
|
|
76
|
+
req.write(payload);
|
|
77
|
+
req.end();
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function createSummary(content, maxLength = 1800) {
|
|
82
|
+
const lines = content.split('\n');
|
|
83
|
+
let summary = '';
|
|
84
|
+
let lineCount = 0;
|
|
85
|
+
|
|
86
|
+
for (const line of lines) {
|
|
87
|
+
// Skip main title (first # line)
|
|
88
|
+
if (lineCount === 0 && line.startsWith('# ')) {
|
|
89
|
+
lineCount++;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Stop if we're getting too long
|
|
94
|
+
if (summary.length + line.length > maxLength) {
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Stop after reasonable number of lines
|
|
99
|
+
if (lineCount > 40) {
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
summary += line + '\n';
|
|
104
|
+
lineCount++;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return summary.trim();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async function syncDocs(webhookUrl) {
|
|
111
|
+
console.log('๐ Starting Discord documentation sync...\n');
|
|
112
|
+
|
|
113
|
+
// Post intro message
|
|
114
|
+
const introMessage = `**๐ FAF Documentation**
|
|
115
|
+
|
|
116
|
+
Welcome to the FAF (Foundational AI-context Format) documentation!
|
|
117
|
+
|
|
118
|
+
๐งก **IANA-registered format** โข \`application/vnd.faf+yaml\`
|
|
119
|
+
๐ฆ **MCP:** 6.1k downloads, 1,231/week
|
|
120
|
+
โก **CLI:** 6.2k downloads, 235/week
|
|
121
|
+
|
|
122
|
+
Full docs available at **https://faf.one**
|
|
123
|
+
|
|
124
|
+
โโโโโโโโโโโโโโโโโโโโโ`;
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
await postToDiscord(webhookUrl, introMessage);
|
|
128
|
+
console.log('โ
Posted intro message');
|
|
129
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
130
|
+
} catch (error) {
|
|
131
|
+
console.error('โ Failed to post intro:', error.message);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Sort docs by order
|
|
135
|
+
const sortedDocs = DOCS_TO_SYNC.sort((a, b) => a.order - b.order);
|
|
136
|
+
|
|
137
|
+
for (const doc of sortedDocs) {
|
|
138
|
+
const filePath = path.join(DOCS_DIR, doc.file);
|
|
139
|
+
|
|
140
|
+
if (!fs.existsSync(filePath)) {
|
|
141
|
+
console.log(`โ ๏ธ Skipping ${doc.file} (not found)`);
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
146
|
+
const summary = createSummary(content);
|
|
147
|
+
|
|
148
|
+
const message = `**${doc.title}**
|
|
149
|
+
|
|
150
|
+
${summary}
|
|
151
|
+
|
|
152
|
+
**[Read full guide โ](${doc.url})**`;
|
|
153
|
+
|
|
154
|
+
try {
|
|
155
|
+
await postToDiscord(webhookUrl, message);
|
|
156
|
+
console.log(`โ
Posted ${doc.title}`);
|
|
157
|
+
|
|
158
|
+
// Rate limit: Discord allows 5 requests per 2 seconds
|
|
159
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
160
|
+
} catch (error) {
|
|
161
|
+
console.error(`โ Failed to post ${doc.title}:`, error.message);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
console.log('\nโจ Sync complete!');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Main execution
|
|
169
|
+
if (require.main === module) {
|
|
170
|
+
const webhookUrl = process.argv[2];
|
|
171
|
+
|
|
172
|
+
if (!webhookUrl) {
|
|
173
|
+
console.error('Usage: node scripts/discord-sync-working.js <webhook-url>');
|
|
174
|
+
console.error('\nGet your webhook URL from Discord:');
|
|
175
|
+
console.error('1. Server Settings > Integrations > Webhooks');
|
|
176
|
+
console.error('2. Create New Webhook or use existing');
|
|
177
|
+
console.error('3. Copy Webhook URL');
|
|
178
|
+
process.exit(1);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
syncDocs(webhookUrl).catch((error) => {
|
|
182
|
+
console.error('Fatal error:', error);
|
|
183
|
+
process.exit(1);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
module.exports = { syncDocs };
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Discord Documentation Sync Tool
|
|
5
|
+
* Posts FAF documentation to Discord using webhooks
|
|
6
|
+
*
|
|
7
|
+
* Usage: node scripts/discord-sync.js <webhook-url>
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const https = require('https');
|
|
13
|
+
|
|
14
|
+
const DOCS_DIR = path.join(__dirname, '../docs');
|
|
15
|
+
const MAX_EMBED_LENGTH = 4096;
|
|
16
|
+
const CYAN_COLOR = 0x00D4D4; // FAF cyan
|
|
17
|
+
|
|
18
|
+
// Documentation files to sync
|
|
19
|
+
const DOCS_TO_SYNC = [
|
|
20
|
+
{
|
|
21
|
+
file: 'QUICK_START.md',
|
|
22
|
+
title: '๐ Quick Start Guide',
|
|
23
|
+
description: '5-minute setup for claude-faf-mcp',
|
|
24
|
+
order: 1
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
file: 'FAQ.md',
|
|
28
|
+
title: 'โ Frequently Asked Questions',
|
|
29
|
+
description: 'Common questions and answers',
|
|
30
|
+
order: 2
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
file: 'USER_GUIDE.md',
|
|
34
|
+
title: '๐ User Guide',
|
|
35
|
+
description: 'Complete guide to MCP features',
|
|
36
|
+
order: 3
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
file: 'PODIUM-SYSTEM.md',
|
|
40
|
+
title: '๐ Podium Scoring System',
|
|
41
|
+
description: 'F1-inspired scoring tiers',
|
|
42
|
+
order: 4
|
|
43
|
+
}
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
function postToDiscord(webhookUrl, embed) {
|
|
47
|
+
return new Promise((resolve, reject) => {
|
|
48
|
+
const url = new URL(webhookUrl);
|
|
49
|
+
const payload = JSON.stringify({
|
|
50
|
+
embeds: [embed]
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const options = {
|
|
54
|
+
hostname: url.hostname,
|
|
55
|
+
path: url.pathname + url.search,
|
|
56
|
+
method: 'POST',
|
|
57
|
+
headers: {
|
|
58
|
+
'Content-Type': 'application/json',
|
|
59
|
+
'Content-Length': payload.length
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const req = https.request(options, (res) => {
|
|
64
|
+
if (res.statusCode === 204) {
|
|
65
|
+
resolve();
|
|
66
|
+
} else {
|
|
67
|
+
reject(new Error(`Discord returned status ${res.statusCode}`));
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
req.on('error', reject);
|
|
72
|
+
req.write(payload);
|
|
73
|
+
req.end();
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function truncateContent(content, maxLength) {
|
|
78
|
+
if (content.length <= maxLength) {
|
|
79
|
+
return content;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const truncated = content.substring(0, maxLength - 50);
|
|
83
|
+
const lastNewline = truncated.lastIndexOf('\n');
|
|
84
|
+
|
|
85
|
+
return truncated.substring(0, lastNewline > 0 ? lastNewline : maxLength - 50) +
|
|
86
|
+
'\n\n...(view full docs at faf.one)';
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function extractSummary(content) {
|
|
90
|
+
// Extract first few sections only (intro + first topic)
|
|
91
|
+
const lines = content.split('\n');
|
|
92
|
+
let summary = '';
|
|
93
|
+
let sectionCount = 0;
|
|
94
|
+
|
|
95
|
+
for (const line of lines) {
|
|
96
|
+
if (line.startsWith('# ')) {
|
|
97
|
+
// Skip title
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (line.startsWith('## ')) {
|
|
102
|
+
sectionCount++;
|
|
103
|
+
if (sectionCount > 2) break; // Stop after 2 sections
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
summary += line + '\n';
|
|
107
|
+
|
|
108
|
+
if (summary.length > 1500) {
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return summary.trim() + '\n\n**[View full documentation โ](https://faf.one)**';
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function formatMarkdownForDiscord(content) {
|
|
117
|
+
// Extract just a summary instead of full content
|
|
118
|
+
return extractSummary(content);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async function syncDocs(webhookUrl) {
|
|
122
|
+
console.log('๐ Starting Discord documentation sync...\n');
|
|
123
|
+
|
|
124
|
+
// Sort docs by order
|
|
125
|
+
const sortedDocs = DOCS_TO_SYNC.sort((a, b) => a.order - b.order);
|
|
126
|
+
|
|
127
|
+
for (const doc of sortedDocs) {
|
|
128
|
+
const filePath = path.join(DOCS_DIR, doc.file);
|
|
129
|
+
|
|
130
|
+
if (!fs.existsSync(filePath)) {
|
|
131
|
+
console.log(`โ ๏ธ Skipping ${doc.file} (not found)`);
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
136
|
+
const formattedContent = formatMarkdownForDiscord(content);
|
|
137
|
+
|
|
138
|
+
const embed = {
|
|
139
|
+
title: doc.title,
|
|
140
|
+
description: formattedContent,
|
|
141
|
+
color: CYAN_COLOR,
|
|
142
|
+
footer: {
|
|
143
|
+
text: '๐งก faf.one โข IANA-registered AI Context format'
|
|
144
|
+
},
|
|
145
|
+
timestamp: new Date().toISOString()
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
try {
|
|
149
|
+
await postToDiscord(webhookUrl, embed);
|
|
150
|
+
console.log(`โ
Posted ${doc.title}`);
|
|
151
|
+
|
|
152
|
+
// Rate limit: Discord allows 5 requests per 2 seconds
|
|
153
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
154
|
+
} catch (error) {
|
|
155
|
+
console.error(`โ Failed to post ${doc.title}:`, error.message);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
console.log('\nโจ Sync complete!');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Main execution
|
|
163
|
+
if (require.main === module) {
|
|
164
|
+
const webhookUrl = process.argv[2];
|
|
165
|
+
|
|
166
|
+
if (!webhookUrl) {
|
|
167
|
+
console.error('Usage: node scripts/discord-sync.js <webhook-url>');
|
|
168
|
+
console.error('\nGet your webhook URL from Discord:');
|
|
169
|
+
console.error('1. Server Settings > Integrations > Webhooks');
|
|
170
|
+
console.error('2. Create New Webhook or use existing');
|
|
171
|
+
console.error('3. Copy Webhook URL');
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
syncDocs(webhookUrl).catch((error) => {
|
|
176
|
+
console.error('Fatal error:', error);
|
|
177
|
+
process.exit(1);
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
module.exports = { syncDocs, formatMarkdownForDiscord };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Post-install check: Verify faf-cli is installed
|
|
5
|
+
*
|
|
6
|
+
* This script runs after npm install to ensure users installed
|
|
7
|
+
* faf-cli BEFORE claude-faf-mcp (required installation order).
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { execSync } = require('child_process');
|
|
11
|
+
const os = require('os');
|
|
12
|
+
|
|
13
|
+
function checkFafCli() {
|
|
14
|
+
try {
|
|
15
|
+
// Try to find faf CLI
|
|
16
|
+
const command = os.platform() === 'win32' ? 'where faf' : 'which faf';
|
|
17
|
+
execSync(command, { stdio: 'ignore' });
|
|
18
|
+
|
|
19
|
+
// CLI found - success!
|
|
20
|
+
console.log('โ
faf-cli detected - installation order correct');
|
|
21
|
+
return true;
|
|
22
|
+
} catch (error) {
|
|
23
|
+
// CLI not found - warn user
|
|
24
|
+
console.error('');
|
|
25
|
+
console.error('โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ');
|
|
26
|
+
console.error('โ ๏ธ WARNING: faf-cli NOT DETECTED');
|
|
27
|
+
console.error('โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ');
|
|
28
|
+
console.error('');
|
|
29
|
+
console.error('claude-faf-mcp requires faf-cli to be installed FIRST.');
|
|
30
|
+
console.error('');
|
|
31
|
+
console.error('CORRECT INSTALLATION ORDER:');
|
|
32
|
+
console.error(' 1๏ธโฃ npm install -g faf-cli (DO THIS FIRST)');
|
|
33
|
+
console.error(' 2๏ธโฃ npm install -g claude-faf-mcp (ALREADY DONE)');
|
|
34
|
+
console.error('');
|
|
35
|
+
console.error('Please install faf-cli now:');
|
|
36
|
+
console.error(' npm install -g faf-cli');
|
|
37
|
+
console.error('');
|
|
38
|
+
console.error('Then restart Claude Desktop to use all MCP features.');
|
|
39
|
+
console.error('โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ');
|
|
40
|
+
console.error('');
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Run check
|
|
46
|
+
checkFafCli();
|