caedora-mcp 0.2.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/README.md +71 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +100 -0
- package/dist/cli.js.map +1 -0
- package/dist/lib/conventions.d.ts +3 -0
- package/dist/lib/conventions.d.ts.map +1 -0
- package/dist/lib/conventions.js +12 -0
- package/dist/lib/conventions.js.map +1 -0
- package/dist/lib/frontmatter.d.ts +23 -0
- package/dist/lib/frontmatter.d.ts.map +1 -0
- package/dist/lib/frontmatter.js +139 -0
- package/dist/lib/frontmatter.js.map +1 -0
- package/dist/lib/okf.d.ts +55 -0
- package/dist/lib/okf.d.ts.map +1 -0
- package/dist/lib/okf.js +276 -0
- package/dist/lib/okf.js.map +1 -0
- package/dist/providers/github.d.ts +26 -0
- package/dist/providers/github.d.ts.map +1 -0
- package/dist/providers/github.js +144 -0
- package/dist/providers/github.js.map +1 -0
- package/dist/providers/local-node.d.ts +25 -0
- package/dist/providers/local-node.d.ts.map +1 -0
- package/dist/providers/local-node.js +112 -0
- package/dist/providers/local-node.js.map +1 -0
- package/dist/providers/types.d.ts +25 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +21 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/server.d.ts +13 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +43 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/operations.d.ts +60 -0
- package/dist/tools/operations.d.ts.map +1 -0
- package/dist/tools/operations.js +48 -0
- package/dist/tools/operations.js.map +1 -0
- package/dist/tools/read.d.ts +49 -0
- package/dist/tools/read.d.ts.map +1 -0
- package/dist/tools/read.js +74 -0
- package/dist/tools/read.js.map +1 -0
- package/dist/tools/search.d.ts +77 -0
- package/dist/tools/search.d.ts.map +1 -0
- package/dist/tools/search.js +107 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/write.d.ts +89 -0
- package/dist/tools/write.d.ts.map +1 -0
- package/dist/tools/write.js +114 -0
- package/dist/tools/write.js.map +1 -0
- package/package.json +59 -0
package/dist/lib/okf.js
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { unified } from 'unified';
|
|
2
|
+
import remarkParse from 'remark-parse';
|
|
3
|
+
import { parseFrontmatter } from './frontmatter.js';
|
|
4
|
+
import { titleFromPath } from './conventions.js';
|
|
5
|
+
import { listFilesRecursive } from '../providers/types.js';
|
|
6
|
+
export const OKF_VERSION = '0.1';
|
|
7
|
+
export const INDEX_FILENAME = 'index.md';
|
|
8
|
+
export const LOG_FILENAME = 'log.md';
|
|
9
|
+
export function isReservedPath(path) {
|
|
10
|
+
const name = path.split('/').pop()?.toLowerCase();
|
|
11
|
+
return name === INDEX_FILENAME || name === LOG_FILENAME;
|
|
12
|
+
}
|
|
13
|
+
export function isConceptPath(path) {
|
|
14
|
+
return path.toLowerCase().endsWith('.md') && !isReservedPath(path);
|
|
15
|
+
}
|
|
16
|
+
export function conceptId(path) {
|
|
17
|
+
return path.replace(/^\/+/, '').replace(/\.md$/i, '');
|
|
18
|
+
}
|
|
19
|
+
export function extractLinks(markdown, sourcePath) {
|
|
20
|
+
const tree = unified().use(remarkParse).parse(markdown);
|
|
21
|
+
const links = [];
|
|
22
|
+
walk(tree, (node) => {
|
|
23
|
+
if (node.type !== 'link' || typeof node.url !== 'string')
|
|
24
|
+
return;
|
|
25
|
+
const targetPath = resolveBundleLink(sourcePath, node.url);
|
|
26
|
+
links.push({
|
|
27
|
+
label: textContent(node),
|
|
28
|
+
href: node.url,
|
|
29
|
+
targetPath,
|
|
30
|
+
targetId: targetPath && isConceptPath(targetPath) ? conceptId(targetPath) : null,
|
|
31
|
+
external: targetPath === null,
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
return links;
|
|
35
|
+
}
|
|
36
|
+
export function resolveBundleLink(sourcePath, href) {
|
|
37
|
+
const value = href.split('#', 1)[0].split('?', 1)[0];
|
|
38
|
+
if (!value || /^[a-z][a-z0-9+.-]*:/i.test(value) || value.startsWith('//'))
|
|
39
|
+
return null;
|
|
40
|
+
const decoded = safeDecode(value);
|
|
41
|
+
const sourceDir = dirname(sourcePath);
|
|
42
|
+
const raw = decoded.startsWith('/') ? decoded.slice(1) : sourceDir ? `${sourceDir}/${decoded}` : decoded;
|
|
43
|
+
const normalized = normalizePath(raw);
|
|
44
|
+
if (!normalized || normalized.startsWith('../'))
|
|
45
|
+
return null;
|
|
46
|
+
return normalized.endsWith('/') ? `${normalized}${INDEX_FILENAME}` : normalized;
|
|
47
|
+
}
|
|
48
|
+
export async function validateBundle(provider) {
|
|
49
|
+
const entries = await listFilesRecursive(provider);
|
|
50
|
+
const markdown = entries.filter((entry) => entry.type === 'file' && entry.path.endsWith('.md'));
|
|
51
|
+
const paths = new Set(markdown.map((entry) => entry.path));
|
|
52
|
+
const issues = [];
|
|
53
|
+
let concepts = 0;
|
|
54
|
+
let links = 0;
|
|
55
|
+
let brokenLinks = 0;
|
|
56
|
+
for (const entry of markdown) {
|
|
57
|
+
const raw = await provider.readFile(entry.path);
|
|
58
|
+
if (isReservedPath(entry.path)) {
|
|
59
|
+
validateReserved(entry.path, raw, issues);
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
concepts++;
|
|
63
|
+
const parsed = parseFrontmatter(raw);
|
|
64
|
+
if (!parsed.hasFrontmatter) {
|
|
65
|
+
issues.push({ path: entry.path, severity: 'error', code: 'missing-frontmatter', message: 'Concept requires YAML frontmatter.' });
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (parsed.error) {
|
|
69
|
+
issues.push({ path: entry.path, severity: 'error', code: 'invalid-frontmatter', message: parsed.error });
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (!parsed.frontmatter.type.trim()) {
|
|
73
|
+
issues.push({ path: entry.path, severity: 'error', code: 'missing-type', message: 'Concept requires a non-empty type.' });
|
|
74
|
+
}
|
|
75
|
+
if (parsed.frontmatter.timestamp && Number.isNaN(Date.parse(parsed.frontmatter.timestamp))) {
|
|
76
|
+
issues.push({ path: entry.path, severity: 'warning', code: 'invalid-timestamp', message: 'timestamp should be ISO 8601.' });
|
|
77
|
+
}
|
|
78
|
+
for (const link of extractLinks(parsed.body, entry.path).filter((item) => !item.external)) {
|
|
79
|
+
links++;
|
|
80
|
+
if (link.targetPath && !paths.has(link.targetPath)) {
|
|
81
|
+
brokenLinks++;
|
|
82
|
+
issues.push({ path: entry.path, severity: 'warning', code: 'broken-link', message: `Missing target ${link.href}` });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
version: OKF_VERSION,
|
|
88
|
+
conformant: !issues.some((issue) => issue.severity === 'error'),
|
|
89
|
+
concepts,
|
|
90
|
+
links,
|
|
91
|
+
brokenLinks,
|
|
92
|
+
issues,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
export async function buildConceptCatalog(provider) {
|
|
96
|
+
const entries = await listFilesRecursive(provider);
|
|
97
|
+
const concepts = [];
|
|
98
|
+
for (const entry of entries.filter((item) => item.type === 'file' && isConceptPath(item.path))) {
|
|
99
|
+
const raw = await provider.readFile(entry.path);
|
|
100
|
+
const parsed = parseFrontmatter(raw);
|
|
101
|
+
concepts.push({
|
|
102
|
+
id: conceptId(entry.path),
|
|
103
|
+
path: entry.path,
|
|
104
|
+
type: parsed.frontmatter.type || 'Unknown',
|
|
105
|
+
title: parsed.frontmatter.title || titleFromPath(entry.path),
|
|
106
|
+
description: parsed.frontmatter.description,
|
|
107
|
+
resource: parsed.frontmatter.resource,
|
|
108
|
+
tags: parsed.frontmatter.tags,
|
|
109
|
+
timestamp: parsed.frontmatter.timestamp,
|
|
110
|
+
links: parsed.error ? [] : extractLinks(parsed.body, entry.path),
|
|
111
|
+
conformant: parsed.hasFrontmatter && !parsed.error && !!parsed.frontmatter.type.trim(),
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
return concepts;
|
|
115
|
+
}
|
|
116
|
+
export async function rebuildIndexes(provider) {
|
|
117
|
+
const entries = await listFilesRecursive(provider);
|
|
118
|
+
const concepts = await buildConceptCatalog(provider);
|
|
119
|
+
const directories = collectDirectories(entries, concepts.map((item) => item.path));
|
|
120
|
+
const changed = [];
|
|
121
|
+
for (const directory of directories) {
|
|
122
|
+
const path = directory ? `${directory}/${INDEX_FILENAME}` : INDEX_FILENAME;
|
|
123
|
+
const content = renderIndex(directory, directories, concepts);
|
|
124
|
+
const current = await provider.readFile(path).catch(() => null);
|
|
125
|
+
if (current === content)
|
|
126
|
+
continue;
|
|
127
|
+
await provider.writeFile(path, content);
|
|
128
|
+
changed.push(path);
|
|
129
|
+
}
|
|
130
|
+
if (changed.length > 0 && !provider.writesAreCommits) {
|
|
131
|
+
await provider.commit('Update bundle indexes', changed);
|
|
132
|
+
}
|
|
133
|
+
return { updated: changed };
|
|
134
|
+
}
|
|
135
|
+
export async function appendLog(provider, action, message) {
|
|
136
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
137
|
+
const entry = `* **${action}**: ${message}`;
|
|
138
|
+
const current = await provider.readFile(LOG_FILENAME).catch(() => '# Bundle Update Log\n');
|
|
139
|
+
const heading = `## ${date}`;
|
|
140
|
+
let next;
|
|
141
|
+
if (current.includes(`${heading}\n`)) {
|
|
142
|
+
const marker = `${heading}\n`;
|
|
143
|
+
const index = current.indexOf(marker) + marker.length;
|
|
144
|
+
next = `${current.slice(0, index)}${entry}\n${current.slice(index).replace(/^\n*/, '')}`;
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
const title = current.match(/^#\s+.+$/m)?.[0] ?? '# Bundle Update Log';
|
|
148
|
+
const rest = current.replace(/^#\s+.+\s*/m, '').trim();
|
|
149
|
+
next = `${title}\n\n${heading}\n${entry}\n${rest ? `\n${rest}\n` : ''}`;
|
|
150
|
+
}
|
|
151
|
+
await provider.writeFile(LOG_FILENAME, next);
|
|
152
|
+
if (!provider.writesAreCommits)
|
|
153
|
+
await provider.commit(`Update ${LOG_FILENAME}`, [LOG_FILENAME]);
|
|
154
|
+
return { path: LOG_FILENAME, action, recorded: true };
|
|
155
|
+
}
|
|
156
|
+
function renderIndex(directory, directories, concepts) {
|
|
157
|
+
const lines = directory
|
|
158
|
+
? [`# ${titleFromPath(directory)} Index`, '']
|
|
159
|
+
: ['---', `okf_version: "${OKF_VERSION}"`, '---', '', '# Knowledge Bundle', '', 'Progressive-disclosure map of this OKF bundle.', ''];
|
|
160
|
+
const children = directories.filter((candidate) => candidate && dirname(candidate) === directory);
|
|
161
|
+
if (children.length > 0) {
|
|
162
|
+
lines.push('# Directories', '');
|
|
163
|
+
for (const child of children.sort()) {
|
|
164
|
+
const name = child.split('/').pop() ?? child;
|
|
165
|
+
lines.push(`* [${titleFromPath(name)}](${encodeURI(`${name}/${INDEX_FILENAME}`)}) - Browse this section.`);
|
|
166
|
+
}
|
|
167
|
+
lines.push('');
|
|
168
|
+
}
|
|
169
|
+
const local = concepts.filter((item) => dirname(item.path) === directory).sort((a, b) => a.title.localeCompare(b.title));
|
|
170
|
+
if (local.length > 0) {
|
|
171
|
+
lines.push('# Concepts', '');
|
|
172
|
+
for (const item of local) {
|
|
173
|
+
const relative = item.path.slice(directory ? directory.length + 1 : 0);
|
|
174
|
+
lines.push(`* [${item.title}](${encodeURI(relative)}) - ${item.description || `${item.type} concept.`}`);
|
|
175
|
+
}
|
|
176
|
+
lines.push('');
|
|
177
|
+
}
|
|
178
|
+
if (children.length === 0 && local.length === 0)
|
|
179
|
+
lines.push('_No concepts in this scope yet._', '');
|
|
180
|
+
return `${lines.join('\n').trimEnd()}\n`;
|
|
181
|
+
}
|
|
182
|
+
function collectDirectories(entries, conceptPaths) {
|
|
183
|
+
const directories = new Set(['']);
|
|
184
|
+
for (const entry of entries) {
|
|
185
|
+
if (entry.type === 'dir')
|
|
186
|
+
addParents(directories, entry.path);
|
|
187
|
+
}
|
|
188
|
+
for (const path of conceptPaths)
|
|
189
|
+
addParents(directories, dirname(path));
|
|
190
|
+
return [...directories];
|
|
191
|
+
}
|
|
192
|
+
function addParents(target, path) {
|
|
193
|
+
if (!path)
|
|
194
|
+
return;
|
|
195
|
+
const parts = path.split('/');
|
|
196
|
+
for (let index = 1; index <= parts.length; index++)
|
|
197
|
+
target.add(parts.slice(0, index).join('/'));
|
|
198
|
+
}
|
|
199
|
+
function validateReserved(path, raw, issues) {
|
|
200
|
+
const name = path.split('/').pop()?.toLowerCase();
|
|
201
|
+
if (name === INDEX_FILENAME) {
|
|
202
|
+
const parsed = parseFrontmatter(raw);
|
|
203
|
+
if (parsed.hasFrontmatter && parsed.error) {
|
|
204
|
+
issues.push({ path, severity: 'error', code: 'invalid-index', message: `Index has invalid YAML frontmatter: ${parsed.error}` });
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (parsed.hasFrontmatter && path.replace(/^\/+/, '') !== INDEX_FILENAME) {
|
|
208
|
+
issues.push({ path, severity: 'error', code: 'invalid-index', message: 'Only the bundle-root index.md may contain frontmatter.' });
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if (parsed.hasFrontmatter) {
|
|
212
|
+
const standardFieldsPresent = parsed.frontmatter.type ||
|
|
213
|
+
parsed.frontmatter.title ||
|
|
214
|
+
parsed.frontmatter.description ||
|
|
215
|
+
parsed.frontmatter.resource ||
|
|
216
|
+
parsed.frontmatter.tags.length > 0 ||
|
|
217
|
+
parsed.frontmatter.timestamp;
|
|
218
|
+
const unsupportedKeys = Object.keys(parsed.frontmatter.extra).filter((key) => key !== 'okf_version');
|
|
219
|
+
if (standardFieldsPresent || unsupportedKeys.length > 0) {
|
|
220
|
+
issues.push({ path, severity: 'error', code: 'invalid-index', message: 'Root index.md frontmatter may only declare okf_version.' });
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
const body = parsed.hasFrontmatter ? parsed.body : raw;
|
|
225
|
+
if (!/^#\s+\S/m.test(body) ||
|
|
226
|
+
(!/\[[^\]]+\]\([^)]+\)/.test(body) && !/_No concepts in this scope yet\._/.test(body))) {
|
|
227
|
+
issues.push({ path, severity: 'error', code: 'invalid-index', message: 'Index requires headings and links.' });
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
if (name === LOG_FILENAME) {
|
|
231
|
+
const dates = [...raw.matchAll(/^##\s+(.+)$/gm)].map((match) => match[1].trim());
|
|
232
|
+
if (!/^#\s+\S/m.test(raw) || dates.some((date) => !/^\d{4}-\d{2}-\d{2}$/.test(date))) {
|
|
233
|
+
issues.push({ path, severity: 'error', code: 'invalid-log', message: 'Log date headings must use YYYY-MM-DD.' });
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
function walk(node, visit) {
|
|
238
|
+
visit(node);
|
|
239
|
+
for (const child of node.children ?? [])
|
|
240
|
+
walk(child, visit);
|
|
241
|
+
}
|
|
242
|
+
function textContent(node) {
|
|
243
|
+
if (node.value)
|
|
244
|
+
return node.value;
|
|
245
|
+
return (node.children ?? []).map(textContent).join('');
|
|
246
|
+
}
|
|
247
|
+
function dirname(path) {
|
|
248
|
+
const parts = path.split('/');
|
|
249
|
+
parts.pop();
|
|
250
|
+
return parts.join('/');
|
|
251
|
+
}
|
|
252
|
+
function safeDecode(value) {
|
|
253
|
+
try {
|
|
254
|
+
return decodeURIComponent(value);
|
|
255
|
+
}
|
|
256
|
+
catch {
|
|
257
|
+
return value;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
function normalizePath(path) {
|
|
261
|
+
const parts = [];
|
|
262
|
+
for (const part of path.replace(/\\/g, '/').split('/')) {
|
|
263
|
+
if (!part || part === '.')
|
|
264
|
+
continue;
|
|
265
|
+
if (part === '..') {
|
|
266
|
+
if (parts.length === 0)
|
|
267
|
+
return '../';
|
|
268
|
+
parts.pop();
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
parts.push(part);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return parts.join('/');
|
|
275
|
+
}
|
|
276
|
+
//# sourceMappingURL=okf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"okf.js","sourceRoot":"","sources":["../../src/lib/okf.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Contents API-backed provider. Functionally equivalent to the web
|
|
3
|
+
* app's `lib/storage/github-provider.ts`, trimmed to the surface the MCP
|
|
4
|
+
* needs (no diff/log helpers).
|
|
5
|
+
*/
|
|
6
|
+
import type { FileEntry, VaultProvider } from './types.js';
|
|
7
|
+
export declare class GitHubNodeProvider implements VaultProvider {
|
|
8
|
+
private token;
|
|
9
|
+
readonly owner: string;
|
|
10
|
+
readonly repo: string;
|
|
11
|
+
readonly type: "github";
|
|
12
|
+
readonly writesAreCommits = true;
|
|
13
|
+
private shaCache;
|
|
14
|
+
constructor(token: string, owner: string, repo: string);
|
|
15
|
+
private get base();
|
|
16
|
+
readFile(path: string): Promise<string>;
|
|
17
|
+
writeFile(path: string, content: string): Promise<void>;
|
|
18
|
+
listFiles(dir?: string): Promise<FileEntry[]>;
|
|
19
|
+
renamePath(from: string, to: string): Promise<void>;
|
|
20
|
+
deletePath(path: string): Promise<void>;
|
|
21
|
+
commit(): Promise<string>;
|
|
22
|
+
private _deleteFile;
|
|
23
|
+
private _fetchSha;
|
|
24
|
+
private _listAllDescendantFiles;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=github.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/providers/github.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAsB1D,qBAAa,kBAAmB,YAAW,aAAa;IAMpD,OAAO,CAAC,KAAK;aACG,KAAK,EAAE,MAAM;aACb,IAAI,EAAE,MAAM;IAP9B,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAS;IACjC,QAAQ,CAAC,gBAAgB,QAAO;IAChC,OAAO,CAAC,QAAQ,CAA4B;gBAGlC,KAAK,EAAE,MAAM,EACL,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM;IAG9B,OAAO,KAAK,IAAI,GAEf;IAEK,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAUvC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBvD,SAAS,CAAC,GAAG,SAAK,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAoBzC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBnD,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWvC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;YAIjB,WAAW;YAWX,SAAS;YAUT,uBAAuB;CAkBtC"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
const API = 'https://api.github.com';
|
|
2
|
+
function apiHeaders(token) {
|
|
3
|
+
return {
|
|
4
|
+
Authorization: `Bearer ${token}`,
|
|
5
|
+
Accept: 'application/vnd.github+json',
|
|
6
|
+
'X-GitHub-Api-Version': '2022-11-28',
|
|
7
|
+
'Content-Type': 'application/json',
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export class GitHubNodeProvider {
|
|
11
|
+
token;
|
|
12
|
+
owner;
|
|
13
|
+
repo;
|
|
14
|
+
type = 'github';
|
|
15
|
+
writesAreCommits = true;
|
|
16
|
+
shaCache = new Map();
|
|
17
|
+
constructor(token, owner, repo) {
|
|
18
|
+
this.token = token;
|
|
19
|
+
this.owner = owner;
|
|
20
|
+
this.repo = repo;
|
|
21
|
+
}
|
|
22
|
+
get base() {
|
|
23
|
+
return `${API}/repos/${this.owner}/${this.repo}`;
|
|
24
|
+
}
|
|
25
|
+
async readFile(path) {
|
|
26
|
+
const res = await fetch(`${this.base}/contents/${encodeURI(path)}`, {
|
|
27
|
+
headers: apiHeaders(this.token),
|
|
28
|
+
});
|
|
29
|
+
if (!res.ok)
|
|
30
|
+
throw new Error(`GitHub: failed to read ${path} (${res.status})`);
|
|
31
|
+
const data = (await res.json());
|
|
32
|
+
this.shaCache.set(path, data.sha);
|
|
33
|
+
return Buffer.from(data.content.replace(/\n/g, ''), 'base64').toString('utf8');
|
|
34
|
+
}
|
|
35
|
+
async writeFile(path, content) {
|
|
36
|
+
const sha = this.shaCache.get(path);
|
|
37
|
+
const body = {
|
|
38
|
+
message: `Update ${path}`,
|
|
39
|
+
content: Buffer.from(content, 'utf8').toString('base64'),
|
|
40
|
+
};
|
|
41
|
+
if (sha)
|
|
42
|
+
body.sha = sha;
|
|
43
|
+
const res = await fetch(`${this.base}/contents/${encodeURI(path)}`, {
|
|
44
|
+
method: 'PUT',
|
|
45
|
+
headers: apiHeaders(this.token),
|
|
46
|
+
body: JSON.stringify(body),
|
|
47
|
+
});
|
|
48
|
+
if (!res.ok)
|
|
49
|
+
throw new Error(`GitHub: failed to write ${path} (${res.status})`);
|
|
50
|
+
const data = (await res.json());
|
|
51
|
+
this.shaCache.set(path, data.content.sha);
|
|
52
|
+
}
|
|
53
|
+
async listFiles(dir = '') {
|
|
54
|
+
const url = dir
|
|
55
|
+
? `${this.base}/contents/${encodeURI(dir)}`
|
|
56
|
+
: `${this.base}/contents`;
|
|
57
|
+
const res = await fetch(url, { headers: apiHeaders(this.token) });
|
|
58
|
+
if (res.status === 404) {
|
|
59
|
+
// Empty folder, or an empty repo ("This repository is empty."). Treat
|
|
60
|
+
// both as no entries rather than erroring.
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
if (!res.ok)
|
|
64
|
+
throw new Error(`GitHub: failed to list ${dir || '/'} (${res.status})`);
|
|
65
|
+
const items = (await res.json());
|
|
66
|
+
return (Array.isArray(items) ? items : [items]).map((item) => ({
|
|
67
|
+
path: item.path,
|
|
68
|
+
name: item.name,
|
|
69
|
+
type: item.type === 'dir' ? 'dir' : 'file',
|
|
70
|
+
size: item.size,
|
|
71
|
+
}));
|
|
72
|
+
}
|
|
73
|
+
async renamePath(from, to) {
|
|
74
|
+
const files = await this._listAllDescendantFiles(from);
|
|
75
|
+
if (files.length === 0) {
|
|
76
|
+
const content = await this.readFile(from);
|
|
77
|
+
await this.writeFile(to, content);
|
|
78
|
+
await this._deleteFile(from);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
for (const filePath of files) {
|
|
82
|
+
const content = await this.readFile(filePath);
|
|
83
|
+
const newPath = `${to}${filePath.slice(from.length)}`;
|
|
84
|
+
await this.writeFile(newPath, content);
|
|
85
|
+
await this._deleteFile(filePath);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
async deletePath(path) {
|
|
89
|
+
const files = await this._listAllDescendantFiles(path);
|
|
90
|
+
if (files.length === 0) {
|
|
91
|
+
await this._deleteFile(path);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
for (const filePath of files) {
|
|
95
|
+
await this._deleteFile(filePath);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async commit() {
|
|
99
|
+
return '';
|
|
100
|
+
}
|
|
101
|
+
async _deleteFile(path) {
|
|
102
|
+
const sha = this.shaCache.get(path) ?? (await this._fetchSha(path));
|
|
103
|
+
const res = await fetch(`${this.base}/contents/${encodeURI(path)}`, {
|
|
104
|
+
method: 'DELETE',
|
|
105
|
+
headers: apiHeaders(this.token),
|
|
106
|
+
body: JSON.stringify({ message: `Delete ${path}`, sha }),
|
|
107
|
+
});
|
|
108
|
+
if (!res.ok)
|
|
109
|
+
throw new Error(`GitHub: failed to delete ${path} (${res.status})`);
|
|
110
|
+
this.shaCache.delete(path);
|
|
111
|
+
}
|
|
112
|
+
async _fetchSha(path) {
|
|
113
|
+
const res = await fetch(`${this.base}/contents/${encodeURI(path)}`, {
|
|
114
|
+
headers: apiHeaders(this.token),
|
|
115
|
+
});
|
|
116
|
+
if (!res.ok)
|
|
117
|
+
throw new Error(`GitHub: failed to get SHA for ${path}`);
|
|
118
|
+
const data = (await res.json());
|
|
119
|
+
this.shaCache.set(path, data.sha);
|
|
120
|
+
return data.sha;
|
|
121
|
+
}
|
|
122
|
+
async _listAllDescendantFiles(path) {
|
|
123
|
+
const out = [];
|
|
124
|
+
const queue = [path];
|
|
125
|
+
while (queue.length > 0) {
|
|
126
|
+
const current = queue.shift();
|
|
127
|
+
let entries;
|
|
128
|
+
try {
|
|
129
|
+
entries = await this.listFiles(current);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
return out;
|
|
133
|
+
}
|
|
134
|
+
for (const e of entries) {
|
|
135
|
+
if (e.type === 'dir')
|
|
136
|
+
queue.push(e.path);
|
|
137
|
+
else
|
|
138
|
+
out.push(e.path);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return out;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=github.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/providers/github.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { FileEntry, VaultProvider } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Node-based VaultProvider that reads and writes an on-disk vault folder.
|
|
4
|
+
* Commits are performed by shelling out to `git` — small, stateless, and
|
|
5
|
+
* avoids pulling in isomorphic-git for Node where real git is already
|
|
6
|
+
* installed.
|
|
7
|
+
*
|
|
8
|
+
* If the folder isn't a git repo, writes still succeed; commits become no-ops
|
|
9
|
+
* (after logging a warning) so the MCP works on folders the user hasn't
|
|
10
|
+
* initialised yet.
|
|
11
|
+
*/
|
|
12
|
+
export declare class LocalNodeProvider implements VaultProvider {
|
|
13
|
+
private readonly root;
|
|
14
|
+
readonly type: "local";
|
|
15
|
+
readonly writesAreCommits = false;
|
|
16
|
+
constructor(root: string);
|
|
17
|
+
private abs;
|
|
18
|
+
readFile(rel: string): Promise<string>;
|
|
19
|
+
writeFile(rel: string, content: string): Promise<void>;
|
|
20
|
+
listFiles(rel?: string): Promise<FileEntry[]>;
|
|
21
|
+
renamePath(from: string, to: string): Promise<void>;
|
|
22
|
+
deletePath(rel: string): Promise<void>;
|
|
23
|
+
commit(message: string, paths: string[]): Promise<string>;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=local-node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-node.d.ts","sourceRoot":"","sources":["../../src/providers/local-node.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAI1D;;;;;;;;;GASG;AACH,qBAAa,iBAAkB,YAAW,aAAa;IAIzC,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAS;IAChC,QAAQ,CAAC,gBAAgB,SAAQ;gBAEJ,IAAI,EAAE,MAAM;IAEzC,OAAO,CAAC,GAAG;IAWL,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAItC,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtD,SAAS,CAAC,GAAG,SAAK,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IA6BzC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOnD,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKtC,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;CA4BhE"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { execFile } from 'node:child_process';
|
|
4
|
+
import { promisify } from 'node:util';
|
|
5
|
+
const execFileAsync = promisify(execFile);
|
|
6
|
+
/**
|
|
7
|
+
* Node-based VaultProvider that reads and writes an on-disk vault folder.
|
|
8
|
+
* Commits are performed by shelling out to `git` — small, stateless, and
|
|
9
|
+
* avoids pulling in isomorphic-git for Node where real git is already
|
|
10
|
+
* installed.
|
|
11
|
+
*
|
|
12
|
+
* If the folder isn't a git repo, writes still succeed; commits become no-ops
|
|
13
|
+
* (after logging a warning) so the MCP works on folders the user hasn't
|
|
14
|
+
* initialised yet.
|
|
15
|
+
*/
|
|
16
|
+
export class LocalNodeProvider {
|
|
17
|
+
root;
|
|
18
|
+
type = 'local';
|
|
19
|
+
writesAreCommits = false;
|
|
20
|
+
constructor(root) {
|
|
21
|
+
this.root = root;
|
|
22
|
+
}
|
|
23
|
+
abs(rel) {
|
|
24
|
+
if (path.isAbsolute(rel)) {
|
|
25
|
+
throw new Error(`Vault paths must be relative: received ${rel}`);
|
|
26
|
+
}
|
|
27
|
+
const resolved = path.resolve(this.root, rel);
|
|
28
|
+
if (!resolved.startsWith(path.resolve(this.root))) {
|
|
29
|
+
throw new Error(`Path escapes vault root: ${rel}`);
|
|
30
|
+
}
|
|
31
|
+
return resolved;
|
|
32
|
+
}
|
|
33
|
+
async readFile(rel) {
|
|
34
|
+
return fs.readFile(this.abs(rel), 'utf8');
|
|
35
|
+
}
|
|
36
|
+
async writeFile(rel, content) {
|
|
37
|
+
const full = this.abs(rel);
|
|
38
|
+
await fs.mkdir(path.dirname(full), { recursive: true });
|
|
39
|
+
await fs.writeFile(full, content, 'utf8');
|
|
40
|
+
}
|
|
41
|
+
async listFiles(rel = '') {
|
|
42
|
+
const dirAbs = this.abs(rel);
|
|
43
|
+
let entries;
|
|
44
|
+
try {
|
|
45
|
+
entries = await fs.readdir(dirAbs, { withFileTypes: true });
|
|
46
|
+
}
|
|
47
|
+
catch (e) {
|
|
48
|
+
if (e.code === 'ENOENT')
|
|
49
|
+
return [];
|
|
50
|
+
throw e;
|
|
51
|
+
}
|
|
52
|
+
const out = [];
|
|
53
|
+
for (const dirent of entries) {
|
|
54
|
+
if (dirent.name === '.git')
|
|
55
|
+
continue;
|
|
56
|
+
const p = rel ? `${rel}/${dirent.name}` : dirent.name;
|
|
57
|
+
if (dirent.isDirectory()) {
|
|
58
|
+
out.push({ path: p, name: dirent.name, type: 'dir' });
|
|
59
|
+
}
|
|
60
|
+
else if (dirent.isFile()) {
|
|
61
|
+
const stat = await fs.stat(path.join(dirAbs, dirent.name));
|
|
62
|
+
out.push({
|
|
63
|
+
path: p,
|
|
64
|
+
name: dirent.name,
|
|
65
|
+
type: 'file',
|
|
66
|
+
size: stat.size,
|
|
67
|
+
lastModified: stat.mtimeMs,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return out;
|
|
72
|
+
}
|
|
73
|
+
async renamePath(from, to) {
|
|
74
|
+
const fromAbs = this.abs(from);
|
|
75
|
+
const toAbs = this.abs(to);
|
|
76
|
+
await fs.mkdir(path.dirname(toAbs), { recursive: true });
|
|
77
|
+
await fs.rename(fromAbs, toAbs);
|
|
78
|
+
}
|
|
79
|
+
async deletePath(rel) {
|
|
80
|
+
const full = this.abs(rel);
|
|
81
|
+
await fs.rm(full, { recursive: true, force: true });
|
|
82
|
+
}
|
|
83
|
+
async commit(message, paths) {
|
|
84
|
+
// If the folder isn't a git repo, silently skip — LocalNodeProvider still
|
|
85
|
+
// functions as a plain filesystem backend in that case.
|
|
86
|
+
try {
|
|
87
|
+
await execFileAsync('git', ['rev-parse', '--git-dir'], { cwd: this.root });
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return '';
|
|
91
|
+
}
|
|
92
|
+
if (paths.length > 0) {
|
|
93
|
+
await execFileAsync('git', ['add', '--', ...paths], { cwd: this.root });
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
await execFileAsync('git', ['add', '-A'], { cwd: this.root });
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
const { stdout } = await execFileAsync('git', ['commit', '-m', message, '--author', 'caedora-mcp <mcp@caedora>'], { cwd: this.root });
|
|
100
|
+
const match = stdout.match(/\[[^\]]*\s([0-9a-f]{7,})\]/);
|
|
101
|
+
return match ? match[1] : '';
|
|
102
|
+
}
|
|
103
|
+
catch (e) {
|
|
104
|
+
const stderr = e.stderr ?? '';
|
|
105
|
+
// Nothing to commit is not an error for our callers.
|
|
106
|
+
if (/nothing to commit/i.test(stderr))
|
|
107
|
+
return '';
|
|
108
|
+
throw e;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=local-node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-node.js","sourceRoot":"","sources":["../../src/providers/local-node.ts"],"names":[],"mappings":"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"}
|