feat(lib): bundle MCP servers from .common/lib into factory/lib/
Copies source (no node_modules, dist, .tasks, .wiki, __pycache__) for: - projects-meta-mcp v2.25.0 (TypeScript/Node) - wiki-graph v0.3.1 (TypeScript/Node) - interns-mcp v0.3.3 (Python/FastMCP) .gitignore: exclude lib build artefacts (node_modules, dist, .venv, __pycache__, *.pyc) bootstrap.ps1: add MCP build step — npm install+build for TS servers, venv+pip for Python Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
59
lib/wiki-graph/src/corpus.ts
Normal file
59
lib/wiki-graph/src/corpus.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { readdirSync, statSync, readFileSync } from 'node:fs';
|
||||
import { join, dirname, basename } from 'node:path';
|
||||
|
||||
export interface PageFile {
|
||||
/** Page basename without `.md`, original case. */
|
||||
slug: string;
|
||||
/** Directory relative to corpus root, '' for root-level pages. POSIX-ish, using OS sep. */
|
||||
dir: string;
|
||||
/** Absolute path on disk. */
|
||||
path: string;
|
||||
/** Last-modified time in ms (for cache revalidation). */
|
||||
mtimeMs: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Top-level dirs excluded from the graph by default. In the Karpathy wiki schema
|
||||
* `raw/` (verbatim ingested docs) and `sources/` (provenance summaries) are NOT
|
||||
* graph pages — they share basenames with canonical concept/entity pages and would
|
||||
* collapse into them (false collisions) and inject provenance edges. `assets/` is
|
||||
* binary. The graph models the canonical concept/entity network only.
|
||||
*/
|
||||
export const DEFAULT_EXCLUDE: readonly string[] = ['raw', 'sources', 'assets'];
|
||||
|
||||
export interface ListOptions {
|
||||
/** Top-level dir names to skip. Defaults to {@link DEFAULT_EXCLUDE}; pass `[]` to index everything. */
|
||||
exclude?: readonly string[];
|
||||
}
|
||||
|
||||
function firstSegment(dir: string): string {
|
||||
if (dir === '') return '';
|
||||
return dir.split(/[\\/]/)[0];
|
||||
}
|
||||
|
||||
/** List every `.md` file under `corpusDir` (recursive, minus excluded dirs), with mtime. */
|
||||
export function listPages(corpusDir: string, opts: ListOptions = {}): PageFile[] {
|
||||
const exclude = new Set(opts.exclude ?? DEFAULT_EXCLUDE);
|
||||
const entries = readdirSync(corpusDir, { recursive: true }) as string[];
|
||||
const pages: PageFile[] = [];
|
||||
for (const rel of entries) {
|
||||
if (!rel.endsWith('.md')) continue;
|
||||
const dirRaw = dirname(rel);
|
||||
const dir = dirRaw === '.' ? '' : dirRaw;
|
||||
if (exclude.has(firstSegment(dir))) continue;
|
||||
const abs = join(corpusDir, rel);
|
||||
const st = statSync(abs);
|
||||
if (!st.isFile()) continue;
|
||||
pages.push({
|
||||
slug: basename(rel, '.md'),
|
||||
dir,
|
||||
path: abs,
|
||||
mtimeMs: st.mtimeMs,
|
||||
});
|
||||
}
|
||||
return pages;
|
||||
}
|
||||
|
||||
export function readPageContent(page: PageFile): string {
|
||||
return readFileSync(page.path, 'utf8');
|
||||
}
|
||||
Reference in New Issue
Block a user