@clarify-labs/cli 0.11.2 → 0.11.4
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/output/cli/mcp/orama-loader.d.ts +3 -2
- package/output/cli.cjs +4 -3
- package/output/cli.cjs.map +1 -1
- package/output/cli.js +4 -3
- package/output/cli.js.map +1 -1
- package/output/{engine-DI8Nd3v0.js → engine-CJmXVTo5.js} +107 -32
- package/output/engine-CJmXVTo5.js.map +1 -0
- package/output/{engine--5unu78V.cjs → engine-Cgc71w13.cjs} +107 -32
- package/output/engine-Cgc71w13.cjs.map +1 -0
- package/output/index.cjs +1 -1
- package/output/index.js +1 -1
- package/output/parsers/markdown/markdown.d.ts +34 -0
- package/output/parsers/markdown/mdx.d.ts +17 -9
- package/output/plugins/mcp-search/orama-index.d.ts +8 -7
- package/package.json +3 -3
- package/output/engine--5unu78V.cjs.map +0 -1
- package/output/engine-DI8Nd3v0.js.map +0 -1
package/output/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","names":[],"sources":["../source/core/runtime/log.ts","../source/core/runtime/vite-config.ts","../source/cli/commands/build.ts","../source/cli/commands/check.ts","../source/cli/commands/dev.ts","../source/cli/spawn.ts","../source/cli/commands/init.ts","../source/cli/mcp/orama-loader.ts","../source/cli/mcp/search-server.ts","../source/cli/commands/mcp.ts","../source/cli/options.ts","../source/cli/program.ts","../source/cli/index.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { readFile, writeFile } from 'node:fs/promises'\nimport { dirname, join } from 'node:path'\n\nconst LOG_FILE_NAME = '.clarify.log'\nconst DEFAULT_LOG_ENTRIES = 50\nconst ENTRY_SEPARATOR = '\\n\\n---\\n\\n'\n\nfunction getMaxLogEntries(): number {\n const envValue = process.env.CLARIFY_LOG_MAX_ENTRIES\n if (!envValue) return DEFAULT_LOG_ENTRIES\n const parsed = Number(envValue)\n return Number.isInteger(parsed) && parsed > 0 ? parsed : DEFAULT_LOG_ENTRIES\n}\n\nfunction normalizeErrorMessage(error: unknown): string {\n if (error === undefined) return 'undefined'\n if (error === null) return 'null'\n if (error instanceof Error) return error.message\n if (typeof error === 'object') {\n if ('message' in error && typeof (error as { message?: unknown }).message === 'string') {\n return (error as { message: string }).message\n }\n try {\n return JSON.stringify(error)\n } catch {\n return String(error)\n }\n }\n return String(error)\n}\n\nfunction normalizeErrorStack(error: unknown): string | undefined {\n if (error instanceof Error) {\n return error.stack\n }\n return undefined\n}\n\nfunction formatLogEntry(root: string, error: unknown): string {\n const timestamp = new Date().toISOString()\n const message = normalizeErrorMessage(error)\n const stack = normalizeErrorStack(error)\n\n return [`=== Clarify build error ===`, `Timestamp: ${timestamp}`, `Project root: ${root}`, `Error: ${message}`, stack ? `Stack:\\n${stack}` : undefined]\n .filter(Boolean)\n .join('\\n')\n}\n\ntype LogEntryReader = (logPath: string) => Promise<string> | string\ntype LogEntryWriter = (logPath: string, content: string) => Promise<void> | void\n\nfunction collectLogEntries(entries: string[], entry: string, max: number): string[] {\n const next = [...entries, entry]\n return next.length > max ? next.slice(-max) : next\n}\n\nfunction readExistingEntries(content: string): string[] {\n return content\n .split(ENTRY_SEPARATOR)\n .map((item) => item.trim())\n .filter(Boolean)\n}\n\nasync function writeLogEntry(root: string, error: unknown, maxEntries: number | undefined, read: LogEntryReader, write: LogEntryWriter): Promise<void> {\n const logPath = join(root, LOG_FILE_NAME)\n const entry = formatLogEntry(root, error)\n const max = maxEntries ?? getMaxLogEntries()\n\n let entries: string[] = []\n if (existsSync(logPath)) {\n try {\n entries = readExistingEntries(await read(logPath))\n } catch {\n entries = []\n }\n }\n\n entries = collectLogEntries(entries, entry, max)\n\n mkdirSync(dirname(logPath), { recursive: true })\n await write(logPath, entries.join(ENTRY_SEPARATOR) + '\\n')\n}\n\nexport async function logBuildError(root: string, error: unknown, maxEntries?: number): Promise<void> {\n await writeLogEntry(root, error, maxEntries, (path) => readFile(path, 'utf8'), (path, content) => writeFile(path, content, 'utf8'))\n}\n\nexport function logBuildErrorSync(root: string, error: unknown, maxEntries?: number): void {\n void writeLogEntry(root, error, maxEntries, (path) => readFileSync(path, 'utf8'), (path, content) => writeFileSync(path, content, 'utf8'))\n}\n","import { existsSync, writeFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\n\nimport { createLogger } from 'vite'\nimport type { ConfigEnv, InlineConfig, Plugin, LogLevel, Logger, LogOptions, LogErrorOptions, LogType } from 'vite'\n\nimport { createViteAdapter } from '../adapters.js'\nimport type { ClarifyEngine } from '../engine/engine.js'\nimport { createClarifyTempDir } from '../project/temp-dir.js'\n\nimport { logBuildErrorSync } from './log.js'\nimport { createClarifyRuntimeAliases } from './runtime-deps.js'\n\nexport type ClarifyViteConfigOptions = {\n root: string\n content: string\n output: string\n host?: string | boolean\n port?: number\n open?: boolean | string\n}\n\nconst DEFAULT_HTML = '<!doctype html><html lang=\"en\"><head><meta charset=\"UTF-8\" /><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" /><title>Clarify</title></head><body><div id=\"root\"></div></body></html>'\n\nfunction ensureHtmlEntry(root: string): string {\n const projectHtmlPath = resolve(root, 'index.html')\n if (existsSync(projectHtmlPath)) return projectHtmlPath\n\n const generatedHtmlPath = resolve(createClarifyTempDir('html'), 'index.html')\n writeFileSync(generatedHtmlPath, DEFAULT_HTML, 'utf-8')\n return generatedHtmlPath\n}\n\nfunction createClarifyLogger(root: string, env: ConfigEnv, level: LogLevel): Logger | undefined {\n if (env.command !== 'build') return undefined\n\n const baseLogger = createLogger(level, { allowClearScreen: true })\n\n return {\n info(msg: string, options?: LogOptions) {\n baseLogger.info(msg, options)\n },\n warn(msg: string, options?: LogOptions) {\n baseLogger.warn(msg, options)\n },\n warnOnce(msg: string, options?: LogOptions) {\n baseLogger.warnOnce(msg, options)\n },\n error(msg: string, options?: LogErrorOptions) {\n baseLogger.error(msg, options)\n if (options?.error) {\n logBuildErrorSync(root, options.error)\n } else {\n logBuildErrorSync(root, typeof msg === 'string' ? new Error(msg) : msg)\n }\n },\n clearScreen(type: LogType) {\n baseLogger.clearScreen(type)\n },\n hasErrorLogged(error: Error | unknown) {\n return baseLogger.hasErrorLogged(error as Error)\n },\n get hasWarned() {\n return baseLogger.hasWarned\n },\n }\n}\n\nfunction createHtmlFallbackPlugin(): Plugin {\n return {\n name: 'clarify:cli-html-fallback',\n configureServer(server) {\n server.middlewares.use(async (req, res, next) => {\n const requestPath = req.url?.split('?')[0] ?? '/'\n const acceptsHtml = req.headers.accept?.includes('text/html') ?? false\n const hasFileExtension = /\\.[^/]+$/.test(requestPath)\n if (!acceptsHtml || hasFileExtension) {\n next()\n return\n }\n\n try {\n const html = await server.transformIndexHtml(requestPath, DEFAULT_HTML)\n res.statusCode = 200\n res.setHeader('Content-Type', 'text/html; charset=utf-8')\n res.end(html)\n } catch (error) {\n next(error)\n }\n })\n },\n }\n}\n\nexport async function createViteConfig(options: ClarifyViteConfigOptions, env: ConfigEnv, engine: ClarifyEngine): Promise<InlineConfig> {\n const entryHtmlPath = ensureHtmlEntry(options.root)\n\n return {\n root: options.root,\n configFile: false,\n appType: 'custom',\n resolve: {\n alias: createClarifyRuntimeAliases(),\n },\n customLogger: createClarifyLogger(options.root, env, 'info'),\n plugins: [\n createViteAdapter(engine),\n createHtmlFallbackPlugin(),\n ],\n server: {\n host: options.host,\n port: options.port,\n open: options.open,\n },\n build: {\n outDir: options.output,\n rolldownOptions: {\n input: {\n index: entryHtmlPath,\n },\n checks: {\n pluginTimings: false,\n },\n output: {\n codeSplitting: {\n groups: [\n {\n name: 'react-vendor',\n test: /node_modules[\\\\/](react|react-dom|react-router|react-router-dom)[\\\\/]/,\n priority: 40,\n },\n {\n name: 'icons-vendor',\n test: /node_modules[\\\\/]lucide-react[\\\\/]/,\n priority: 35,\n },\n {\n name: 'ui-vendor',\n test: /node_modules[\\\\/](@headlessui|framer-motion)[\\\\/]/,\n priority: 30,\n },\n {\n name: 'mermaid-viewer-vendor',\n test: /node_modules[\\\\/]react-zoom-pan-pinch[\\\\/]/,\n priority: 25,\n },\n {\n // Keep mermaid and its heavy diagram/render dependencies out of\n // the eager `vendor` chunk so they stay lazily loaded only on\n // pages that actually render a diagram.\n name: 'mermaid-vendor',\n test: /node_modules[\\\\/](mermaid|@mermaid-js|cytoscape|cytoscape-[^\\\\/]+|dagre-d3-es|@dagrejs|dagre|graphlib|elkjs|katex|d3|d3-[^\\\\/]+|internmap|delaunator|robust-predicates|roughjs|points-on-curve|points-on-path|path-data-parser|@braintree[\\\\/]sanitize-url|dompurify|khroma|ts-dedent|stylis|cose-base|layout-base)[\\\\/]/,\n priority: 20,\n },\n {\n name: 'vendor',\n test: /node_modules[\\\\/]/,\n priority: 10\n },\n ],\n },\n },\n },\n },\n }\n}\n","import { build as viteBuild } from 'vite'\n\nimport { createClarifyEngine } from '../../core/engine/engine.js'\nimport { logBuildError } from '../../core/runtime/log.js'\nimport { createViteConfig } from '../../core/runtime/vite-config.js'\nimport type { ResolvedCliOptions } from '../options.js'\n\nexport async function runBuild(options: ResolvedCliOptions): Promise<void> {\n const env = { command: 'build' as const, mode: 'production' }\n const engine = createClarifyEngine({\n projectRoot: options.root,\n rootDirectory: options.content,\n outputDirectory: options.output,\n })\n try {\n await engine.prepare(env)\n await viteBuild(await createViteConfig(options, env, engine))\n } catch (error) {\n await logBuildError(options.root, error)\n throw error\n }\n}\n","import { lstat, stat } from 'node:fs/promises'\nimport { dirname, extname, isAbsolute, join, normalize, relative, resolve } from 'node:path'\n\nimport { createClarifyEngine } from '../../core/engine/engine.js'\nimport type { ContentRoute } from '../../types.js'\nimport type { CliOptions } from '../options.js'\n\nexport type CheckCommandOptions = CliOptions & {\n strict?: boolean\n format?: 'text' | 'json' | string\n}\n\ntype CheckLevel = 'error' | 'warning'\n\ntype CheckDiagnostic = {\n level: CheckLevel\n code: string\n message: string\n filePath?: string\n routePath?: string\n}\n\ntype CheckResult = {\n errors: CheckDiagnostic[]\n warnings: CheckDiagnostic[]\n}\n\nconst LOCAL_LINK_PATTERN = /(?<!!)(?:\\[[^\\]]*\\]\\(([^)\\s]+)(?:\\s+\"[^\"]*\")?\\)|<a\\s+[^>]*href=[\"']([^\"']+)[\"'])/gi\nconst ROUTE_EXTENSIONS = new Set(['.md', '.mdx'])\nconst IGNORED_SCHEMES = /^[a-z][a-z0-9+.-]*:/i\n\nfunction addDiagnostic(result: CheckResult, diagnostic: CheckDiagnostic): void {\n if (diagnostic.level === 'error') result.errors.push(diagnostic)\n else result.warnings.push(diagnostic)\n}\n\nfunction normalizeRoutePath(path: string): string {\n const [withoutHash] = path.split('#')\n const clean = withoutHash.replace(/\\/index$/, '') || '/'\n return clean.startsWith('/') ? clean : `/${clean}`\n}\n\nfunction routePathCandidates(href: string, route: ContentRoute): string[] {\n const [withoutHashOrQuery] = href.split(/[?#]/)\n if (!withoutHashOrQuery || withoutHashOrQuery.startsWith('#')) return []\n if (withoutHashOrQuery.startsWith('/')) return [normalizeRoutePath(withoutHashOrQuery)]\n\n const routeDir = dirname(route.path)\n const joined = normalize(join(routeDir, withoutHashOrQuery)).replaceAll('\\\\', '/')\n const extension = extname(joined)\n const base = ROUTE_EXTENSIONS.has(extension) ? joined.slice(0, -extension.length) : joined\n return [normalizeRoutePath(base)]\n}\n\nasync function pathExists(filePath: string): Promise<boolean> {\n try {\n await stat(filePath)\n return true\n } catch {\n return false\n }\n}\n\nfunction isLocalHref(href: string): boolean {\n return Boolean(href) && !href.startsWith('#') && !href.startsWith('//') && !IGNORED_SCHEMES.test(href)\n}\n\nasync function resolveLocalFileLink(href: string, route: ContentRoute, contentRoot: string): Promise<boolean> {\n const [withoutHashOrQuery] = href.split(/[?#]/)\n if (!withoutHashOrQuery || withoutHashOrQuery.startsWith('/')) return false\n\n const target = resolve(dirname(route.source.filePath), withoutHashOrQuery)\n const relativeTarget = relative(contentRoot, target)\n if (relativeTarget.startsWith('..') || isAbsolute(relativeTarget)) return false\n if (await pathExists(target)) return true\n\n if (!extname(target)) {\n return pathExists(`${target}.md`) || pathExists(`${target}.mdx`) || pathExists(join(target, 'index.md')) || pathExists(join(target, 'index.mdx'))\n }\n return false\n}\n\nasync function checkContentDirectory(contentRoot: string, result: CheckResult): Promise<void> {\n try {\n const stats = await lstat(contentRoot)\n if (!stats.isDirectory()) {\n addDiagnostic(result, {\n level: 'error',\n code: 'content-not-directory',\n message: `Content path is not a directory: ${contentRoot}`,\n filePath: contentRoot,\n })\n }\n } catch {\n addDiagnostic(result, {\n level: 'error',\n code: 'content-missing',\n message: `Content directory does not exist: ${contentRoot}`,\n filePath: contentRoot,\n })\n }\n}\n\nfunction checkDuplicateRoutes(routes: ContentRoute[], result: CheckResult): void {\n const byPath = new Map<string, ContentRoute[]>()\n for (const route of routes) {\n const key = `${route.locale ?? ''}:${route.path}`\n byPath.set(key, [...(byPath.get(key) ?? []), route])\n }\n\n for (const duplicated of byPath.values()) {\n if (duplicated.length < 2) continue\n for (const route of duplicated) {\n addDiagnostic(result, {\n level: 'error',\n code: 'duplicate-route',\n message: `Route \"${route.path}\" is defined by multiple files: ${duplicated.map(route => relative(process.cwd(), route.source.filePath)).join(', ')}`,\n filePath: route.source.filePath,\n routePath: route.path,\n })\n }\n }\n}\n\nfunction checkFallbackRoutes(routes: ContentRoute[], result: CheckResult): void {\n for (const route of routes) {\n if (!route.isFallback) continue\n addDiagnostic(result, {\n level: 'warning',\n code: 'i18n-fallback-route',\n message: `Route \"${route.path}\" falls back to ${route.locale ?? 'default'} content from ${relative(process.cwd(), route.source.filePath)}`,\n filePath: route.source.filePath,\n routePath: route.path,\n })\n }\n}\n\nasync function checkLocalLinks(routes: ContentRoute[], contentRoot: string, result: CheckResult): Promise<void> {\n const routePaths = new Set(routes.map(route => route.path))\n\n for (const route of routes) {\n if (route.kind !== 'mdx' || !route.source.content) continue\n for (const match of route.source.content.matchAll(LOCAL_LINK_PATTERN)) {\n const href = match[1] ?? match[2]\n if (!href || !isLocalHref(href)) continue\n const candidates = routePathCandidates(href, route)\n if (candidates.some(candidate => routePaths.has(candidate))) continue\n if (await resolveLocalFileLink(href, route, contentRoot)) continue\n\n addDiagnostic(result, {\n level: 'error',\n code: 'broken-link',\n message: `Broken local link \"${href}\" in route \"${route.path}\"`,\n filePath: route.source.filePath,\n routePath: route.path,\n })\n }\n }\n}\n\nfunction printTextResult(result: CheckResult, strict: boolean): void {\n const diagnostics = [...result.errors, ...result.warnings]\n if (diagnostics.length === 0) {\n console.log('✓ Clarify check passed')\n return\n }\n\n for (const diagnostic of diagnostics) {\n const location = diagnostic.filePath ? ` ${relative(process.cwd(), diagnostic.filePath)}` : ''\n const route = diagnostic.routePath ? ` (${diagnostic.routePath})` : ''\n console.log(`${diagnostic.level.toUpperCase()} ${diagnostic.code}${location}${route}`)\n console.log(` ${diagnostic.message}`)\n }\n\n const warningExit = strict && result.warnings.length > 0\n console.log(`\\n${result.errors.length} error(s), ${result.warnings.length} warning(s)${warningExit ? ' (--strict treats warnings as failures)' : ''}`)\n}\n\nexport async function runCheck(options: CheckCommandOptions = {}): Promise<void> {\n const root = resolve(options.root ?? process.cwd())\n const engine = createClarifyEngine({\n projectRoot: root,\n rootDirectory: options.content,\n outputDirectory: options.output,\n })\n await engine.prepare(undefined, undefined, { htmlShell: false, skipModules: true, skipHints: true })\n\n const result: CheckResult = { errors: [], warnings: [] }\n await checkContentDirectory(engine.contentRoot, result)\n checkDuplicateRoutes(engine.routes, result)\n checkFallbackRoutes(engine.routes, result)\n await checkLocalLinks(engine.routes, engine.contentRoot, result)\n\n if (options.format === 'json') {\n console.log(JSON.stringify(result, null, 2))\n } else {\n printTextResult(result, Boolean(options.strict))\n }\n\n if (result.errors.length > 0 || (options.strict && result.warnings.length > 0)) {\n process.exitCode = 1\n }\n}\n","import { createServer } from 'vite'\n\nimport { createClarifyEngine } from '../../core/engine/engine.js'\nimport { createViteConfig } from '../../core/runtime/vite-config.js'\nimport type { ResolvedCliOptions } from '../options.js'\n\nexport async function runDev(options: ResolvedCliOptions): Promise<void> {\n const env = { command: 'serve' as const, mode: 'development' }\n const engine = createClarifyEngine({\n projectRoot: options.root,\n rootDirectory: options.content,\n outputDirectory: options.output,\n })\n await engine.prepare(env)\n const server = await createServer(await createViteConfig(options, env, engine))\n await server.listen()\n server.printUrls()\n server.bindCLIShortcuts({ print: true })\n}\n","import { spawnSync as nodeSpawnSync, SpawnSyncOptions } from 'node:child_process'\n\ntype SpawnOptions = { cwd?: string; stdio?: 'inherit' | 'ignore' | Array<string> }\n\nexport function spawnSync(command: string, args: string[], options: SpawnOptions) {\n return nodeSpawnSync(command, args, options as SpawnSyncOptions)\n}\n","import { existsSync, readFileSync, writeFileSync } from 'node:fs'\nimport { createRequire } from 'node:module'\nimport { dirname, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nimport { copyTemplateDirectory, getTemplateDirectory, resolveTemplate } from '@clarify-labs/templates'\n\nimport type { ResolvedCliOptions } from '../options.js'\nimport { cliPackageVersionWithCaret } from '../package.js'\nimport { spawnSync } from '../spawn.js'\n\nconst require = createRequire(import.meta.url)\n\nfunction findTemplatesPackagePath(): string {\n try {\n return require.resolve('@clarify-labs/templates/package.json')\n } catch {\n const currentDirectory = dirname(fileURLToPath(import.meta.url))\n const workspacePackagePath = resolve(currentDirectory, '../../../../templates/package.json')\n if (existsSync(workspacePackagePath)) return workspacePackagePath\n throw new Error('[clarify] Templates package not found.')\n }\n}\n\nconst templatesPackagePath = findTemplatesPackagePath()\nconst templatesDirectory = dirname(templatesPackagePath)\n\nfunction commandExists(program: string): boolean {\n const result = spawnSync(program, ['--version'], { stdio: 'ignore' })\n return result.status === 0 && result.error === undefined\n}\n\ntype PackageManager = 'pnpm' | 'npm' | 'yarn'\n\nfunction detectPackageManager(): PackageManager {\n if (commandExists('pnpm')) return 'pnpm'\n if (commandExists('npm')) return 'npm'\n if (commandExists('yarn')) return 'yarn'\n return 'npm'\n}\n\nfunction installDependencies(root: string, command: PackageManager): void {\n const args = ['install']\n console.log(`[clarify] Installing dependencies with ${command}...`)\n const result = spawnSync(command, args, { cwd: root, stdio: 'inherit' })\n if (result.status !== 0) {\n throw new Error(`[clarify] Dependency install failed with ${command}`)\n }\n}\n\nfunction getSuggestedInstallCommand(packageManager: PackageManager): string {\n return `${packageManager} install`\n}\n\nfunction getSuggestedRunCommand(packageManager: PackageManager): string {\n if (packageManager === 'pnpm') return 'pnpm dev'\n if (packageManager === 'yarn') return 'yarn dev'\n return 'npm run dev'\n}\n\nfunction updatePackageJson(root: string, force: boolean): boolean {\n const packageJsonPath = resolve(root, 'package.json')\n const packageJson = existsSync(packageJsonPath)\n ? JSON.parse(readFileSync(packageJsonPath, 'utf-8')) as Record<string, unknown>\n : { type: 'module' }\n\n const scripts = typeof packageJson.scripts === 'object' && packageJson.scripts !== null\n ? packageJson.scripts as Record<string, string>\n : {}\n\n if (force || !scripts.dev) scripts.dev = 'clarify dev'\n if (force || !scripts.build) scripts.build = 'clarify build'\n packageJson.scripts = scripts\n\n const devDependencies = typeof packageJson.devDependencies === 'object' && packageJson.devDependencies !== null\n ? packageJson.devDependencies as Record<string, string>\n : {}\n if (!devDependencies['@clarify-labs/cli']) devDependencies['@clarify-labs/cli'] = cliPackageVersionWithCaret\n packageJson.devDependencies = devDependencies\n\n writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\\n`, 'utf-8')\n return true\n}\n\nexport function runInit(options: ResolvedCliOptions, force: boolean, template?: string, install = false): void {\n const selectedTemplate = resolveTemplate(template)\n const templateDirectory = getTemplateDirectory(templatesDirectory, selectedTemplate)\n const { created } = copyTemplateDirectory(templateDirectory, options.root, {\n contentDir: options.content,\n force,\n })\n\n const packageJsonUpdated = updatePackageJson(options.root, force)\n if (packageJsonUpdated) created.push('package.json')\n\n console.log(`[clarify] Project scaffold created using the ${selectedTemplate} template.`)\n if (created.length > 0) {\n console.log(`[clarify] Created or updated ${created.length} ${created.length === 1 ? 'file' : 'files'}: ${created.join(', ')}`)\n }\n\n const packageManager = detectPackageManager()\n if (install) {\n installDependencies(options.root, packageManager)\n const suggestedRun = getSuggestedRunCommand(packageManager)\n console.log('[clarify] Dependencies installed successfully.')\n console.log(`[clarify] You can now run \\`${suggestedRun}\\` to start the local documentation server.`)\n return\n }\n\n const suggestedInstall = getSuggestedInstallCommand(packageManager)\n const suggestedRun = getSuggestedRunCommand(packageManager)\n console.log('[clarify] Next steps:')\n console.log(' 1. Change into your new project directory:')\n console.log(` cd ${options.root}`)\n console.log(' 2. Install dependencies:')\n console.log(` ${suggestedInstall}`)\n console.log(' 3. Start the local documentation server:')\n console.log(` ${suggestedRun}`)\n}\n","import { createHash } from 'node:crypto'\nimport { mkdir, readFile, rm, writeFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nimport type { McpSiteConfig } from '../../plugins/mcp-search/mcp-config.js'\nimport type { McpSearchResult } from '../../plugins/mcp-search/orama-index.js'\nimport { deserializeSearchIndex, searchMcpIndex } from '../../plugins/mcp-search/orama-index.js'\n\n/**\n * A ready-to-search Orama index loaded for the MCP server.\n *\n * The underlying db is fully in-memory after load, so `search` is synchronous\n * to the index. `dispose` drops the reference so the buffer can be GC'd; it's\n * safe to call multiple times.\n */\nexport type LoadedSearchIndex = {\n /** Search the index. Locale filter is optional. */\n search: (params: { query: string; locale?: string; limit?: number }) => McpSearchResult\n /** Release the in-memory index. Safe to call multiple times. */\n dispose: () => void\n}\n\n/** Re-export so callers can name the result type without reaching into orama-index. */\nexport type { McpSearchResult as SearchResult } from '../../plugins/mcp-search/orama-index.js'\n\nexport type OramaLoaderOptions = {\n /**\n * Root directory for the on-disk cache. Defaults to `~/.clarify/mcp-cache`.\n * Each site gets a subdirectory keyed by a stable hash of its origin + path.\n */\n cacheDir?: string\n /**\n * Bypass the cache and always fetch fresh. Implies purging the cached copy\n * for this site on a successful refresh.\n */\n noCache?: boolean\n /** Optional fetch override (testing). */\n fetchImpl?: typeof fetch\n /** Optional logger (testing). Defaults to no-op. */\n log?: (message: string) => void\n}\n\nconst DEFAULT_CACHE_DIR = () => join(homedir(), '.clarify', 'mcp-cache')\nconst FETCH_TIMEOUT_MS = 60_000\n\n/** Stable per-site cache key. Two URLs with the same origin+path share a cache. */\nfunction siteCacheKey(siteUrl: string): string {\n let url: URL\n try {\n url = new URL(siteUrl)\n } catch {\n throw new Error(`[clarify] Invalid site URL: ${siteUrl}`)\n }\n // Origin + pathname, trailing slash normalized, query/hash ignored.\n // Query/hash are irrelevant for \"where does the site live\" and would\n // fragment the cache unnecessarily.\n const normalized = `${url.origin}${url.pathname.replace(/\\/+$/, '')}`\n return createHash('sha256').update(normalized).digest('hex').slice(0, 16)\n}\n\nasync function fetchBufferWithTimeout(url: string, fetchImpl: typeof fetch, log: (m: string) => void): Promise<Uint8Array> {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS)\n try {\n log(`Fetching ${url}`)\n const res = await fetchImpl(url, { signal: controller.signal, redirect: 'follow' })\n if (!res.ok) {\n throw new Error(`HTTP ${res.status} ${res.statusText} fetching ${url}`)\n }\n const buf = await res.arrayBuffer()\n return new Uint8Array(buf)\n } finally {\n clearTimeout(timer)\n }\n}\n\n/**\n * Load the Orama binary index for a remote site and return a ready-to-search\n * handle.\n *\n * The `.msp` index is a single binary file (msgpack-serialized Orama `save()`\n * output). It is cached on disk so repeated MCP starts don't re-download.\n * Cache validity is keyed by `capabilities.search.indexHash` when available.\n * For older sites that do not emit `indexHash`, we fall back to document\n * count + locale fingerprint matching.\n *\n * The caller must supply the same `defaultLocale` recorded in `mcp.json` so\n * the tokenizer matches the one used at build time. A mismatch would not\n * corrupt data but would cause CJK query terms to be tokenized incorrectly.\n */\nexport async function loadSearchIndex(siteUrl: string, config: McpSiteConfig, options: OramaLoaderOptions = {}): Promise<LoadedSearchIndex> {\n const log = options.log ?? (() => {})\n const fetchImpl = options.fetchImpl ?? fetch\n const cacheDir = options.cacheDir ?? DEFAULT_CACHE_DIR()\n const cacheKey = siteCacheKey(siteUrl)\n const siteCacheDir = join(cacheDir, cacheKey)\n const indexCachePath = join(siteCacheDir, 'mcp-search.msp')\n const manifestPath = join(siteCacheDir, 'manifest.json')\n\n const base = new URL(siteUrl).href\n log(`Site base resolved to ${base}`)\n\n // The index path in mcp.json is root-relative (e.g. `/mcp-search.msp` or\n // `/docs/mcp-search.msp`). Resolve it against the site base.\n const search = config.capabilities.search\n if (!search) {\n throw new Error(`[clarify] mcp.json for ${siteUrl} has no search capability.`)\n }\n const indexUrl = new URL(search.indexPath, base).href\n\n // Cache validity: reuse the cached .msp only when the document count and\n // locale fingerprint recorded at last fetch match the caller-provided\n // config. These change whenever the index is rebuilt with different content.\n const fingerprint = localeFingerprint(config)\n const indexHash = search.indexHash\n let useCache = !options.noCache\n if (useCache) {\n try {\n const manifest = JSON.parse(await readFile(manifestPath, 'utf8')) as {\n documentCount?: number\n fingerprint?: string\n indexHash?: string\n }\n if (indexHash) {\n if (manifest.indexHash !== indexHash) {\n log('Cache stale (index hash changed); refetching')\n useCache = false\n }\n } else if (manifest.documentCount !== search.documentCount || manifest.fingerprint !== fingerprint) {\n log('Cache stale (document count or locales changed); refetching')\n useCache = false\n }\n } catch {\n useCache = false\n }\n }\n\n let buffer: Uint8Array | undefined\n if (useCache) {\n try {\n buffer = await readFile(indexCachePath)\n log('Using cached mcp-search.msp')\n } catch {\n // Cache file unreadable; fall through to fetch below.\n }\n }\n\n if (buffer === undefined) {\n const fetched = await fetchBufferWithTimeout(indexUrl, fetchImpl, log)\n buffer = fetched\n // Best-effort persist; failure to cache is non-fatal.\n try {\n await mkdir(siteCacheDir, { recursive: true })\n await writeFile(indexCachePath, fetched)\n await writeFile(\n manifestPath,\n JSON.stringify(\n {\n siteUrl: base,\n fetchedAt: new Date().toISOString(),\n documentCount: search.documentCount,\n fingerprint,\n indexHash,\n },\n null,\n 2,\n ),\n 'utf8',\n )\n log(`Cached mcp-search.msp to ${indexCachePath}`)\n } catch (err) {\n log(`Warning: failed to cache index: ${err instanceof Error ? err.message : String(err)}`)\n }\n }\n\n const defaultLocale = search.defaultLocale\n const db = deserializeSearchIndex(buffer, defaultLocale)\n let disposed = false\n\n return {\n search: ({ query, locale, limit }) => {\n if (disposed) throw new Error('[clarify] Search index already disposed.')\n return searchMcpIndex(db, { query, locale, limit })\n },\n dispose: () => {\n // Orama's in-memory index is plain JS data; dropping the reference is\n // enough for GC. Nothing to flush.\n disposed = true\n },\n }\n}\n\n/**\n * Build a stable fingerprint of the indexed locales so the cache can detect\n * locale-set changes even when the document count happens to stay the same.\n */\nfunction localeFingerprint(config: McpSiteConfig): string {\n return createHash('sha256').update((config.capabilities.search?.locales ?? []).slice().sort().join('|')).digest('hex').slice(0, 16)\n}\n\n/**\n * Remove the on-disk cache for a site. Useful for `--no-cache` cleanup or for\n * tests. No-op if the site has no cache directory.\n */\nexport async function purgeSiteCache(siteUrl: string, cacheDir?: string): Promise<void> {\n const dir = cacheDir ?? DEFAULT_CACHE_DIR()\n const key = siteCacheKey(siteUrl)\n await rm(join(dir, key), { recursive: true, force: true })\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { z } from 'zod'\n\nimport type { McpSiteConfig } from '../../plugins/mcp-search/mcp-config.js'\nimport type { McpSearchHit } from '../../plugins/mcp-search/orama-index.js'\n\nimport type { LoadedSearchIndex } from './orama-loader.js'\n\nexport type SearchServerOptions = {\n /** Optional logger routed to stderr (stdout is the JSON-RPC channel). */\n log?: (message: string) => void\n}\n\n/**\n * A site loaded for the MCP server: its descriptor, ready-to-search index,\n * and the origin URL the index was fetched from (used to resolve relative\n * result paths and to label results by source site).\n */\nexport type LoadedMcpSite = {\n siteUrl: string\n config: McpSiteConfig\n index: LoadedSearchIndex\n}\n\n/** A search hit annotated with the site it came from. */\ntype SourcedHit = McpSearchHit & { site: string }\n\n/**\n * Build the MCP server exposing site search over one or more Clarify sites.\n *\n * Tools registered:\n * - `search_docs`: full-text search across all loaded sites, with each\n * result annotated by its source site.\n *\n * Results are serialized to a compact, LLM-friendly shape: title, URL, site,\n * excerpt, score, and locale. Full page content is intentionally omitted to\n * keep responses within token budgets; clients can fetch the URL themselves.\n */\nexport function createMcpSearchServer(sites: LoadedMcpSite[], options: SearchServerOptions = {}): McpServer {\n const log = options.log ?? (() => {})\n const server = new McpServer({\n name: 'clarify-search',\n version: '1.0.0',\n })\n\n if (sites.length === 0) {\n throw new Error('[clarify] createMcpSearchServer requires at least one loaded site.')\n }\n\n // Aggregate metadata across all loaded sites for the tool description.\n const totalDocs = sites.reduce((sum, site) => sum + (site.config.capabilities.search?.documentCount ?? 0), 0)\n const localeSet = new Set<string>()\n for (const site of sites) {\n for (const locale of site.config.capabilities.search?.locales ?? []) localeSet.add(locale)\n }\n const localeList = [...localeSet]\n const siteTitles = sites\n .map(site => site.config.site.title ?? 'site')\n .filter((title, i, arr) => arr.indexOf(title) === i)\n const siteHint = siteTitles.length === 1\n ? `\"${siteTitles[0]}\"`\n : `${sites.length} sites (${siteTitles.join(', ')})`\n\n const localeHint = localeList.length > 0\n ? ` Available locales: ${localeList.join(', ')}.`\n : ''\n const defaultLocale = sites[0].config.capabilities.search?.defaultLocale\n const defaultLocaleHint = defaultLocale\n ? ` Defaults to \"${defaultLocale}\".`\n : ''\n\n server.registerTool(\n 'search_docs',\n {\n title: 'Search documentation',\n description: [\n `Full-text search over ${siteHint} documentation index.`,\n `Returns ranked results with excerpts, URLs, and source site. The index contains ${totalDocs} pages across ${localeList.length} locale(s).`,\n localeHint,\n defaultLocaleHint,\n 'Pass a `locale` filter to restrict results to a specific language.',\n ].filter(Boolean).join(' '),\n inputSchema: {\n query: z\n .string()\n .min(1)\n .describe('Search query. CJK text is word-segmented automatically; Latin text is split on whitespace/punctuation.'),\n locale: z\n .string()\n .optional()\n .describe(`Filter results to a single locale. One of: ${localeList.join(', ')}.`),\n limit: z\n .number()\n .int()\n .min(1)\n .max(50)\n .optional()\n .describe('Maximum results to return. Default 10, max 50.'),\n },\n },\n async ({ query, locale, limit }) => {\n log(`search_docs query=${JSON.stringify(query)} locale=${JSON.stringify(locale)} limit=${limit ?? 10}`)\n\n // Search every loaded site and merge hits. Each hit is annotated with\n // its source site so the caller can tell results apart when multiple\n // sites are loaded. Results are ranked globally by score.\n const allHits: SourcedHit[] = []\n let errorResult: { text: string } | undefined\n for (const site of sites) {\n try {\n const result = site.index.search({ query, locale, limit })\n for (const hit of result.hits) {\n allHits.push({ ...hit, site: site.siteUrl })\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n log(`search failed for ${site.siteUrl}: ${message}`)\n errorResult = { text: `Search failed for ${site.siteUrl}: ${message}` }\n }\n }\n\n if (allHits.length === 0 && errorResult) {\n return {\n isError: true,\n content: [{ type: 'text', text: errorResult.text }],\n }\n }\n\n allHits.sort((a, b) => b.score - a.score)\n const capped = limit ? allHits.slice(0, limit) : allHits.slice(0, 10)\n\n const summary = [\n `Found ${allHits.length} result(s) across ${totalDocs} indexed pages from ${sites.length} site(s).`,\n `Showing top ${capped.length}.`,\n '',\n ].join('\\n')\n\n const text = [summary, ...capped.map((hit, i) => formatResultText(hit, i))].join('\\n---\\n')\n\n return {\n content: [{ type: 'text', text }],\n }\n },\n )\n\n return server\n}\n\n/**\n * Run the search server over stdio until the client disconnects or the process\n * is signaled. Resolves on clean shutdown.\n */\nexport async function runMcpSearchServer(sites: LoadedMcpSite[], options: SearchServerOptions = {}): Promise<void> {\n const log = options.log ?? (() => {})\n const server = createMcpSearchServer(sites, options)\n const transport = new StdioServerTransport()\n // Dispose every search index when the client disconnects. StdioServerTransport\n // calls onclose after stdin closes.\n transport.onclose = () => {\n log('MCP transport closed; disposing search indices')\n for (const site of sites) site.index.dispose()\n }\n await server.connect(transport)\n log(`MCP search server listening on stdio (${sites.length} site(s))`)\n}\n\nfunction formatResultText(hit: SourcedHit, index: number): string {\n const lines = [\n `## ${index + 1}. ${hit.title}`,\n `URL: ${hit.path}`,\n `Site: ${hit.site}`,\n `Score: ${hit.score}`,\n ]\n if (hit.locale) {\n lines.push(`Locale: ${hit.locale}`)\n }\n if (hit.excerpt) {\n lines.push('', hit.excerpt)\n }\n if (hit.description) {\n lines.push('', `Description: ${hit.description}`)\n }\n if (hit.keywords?.length > 0) {\n lines.push('', `Keywords: ${hit.keywords.join(', ')}`)\n }\n return lines.join('\\n')\n}\n","import type { McpSiteConfig } from '../../plugins/mcp-search/mcp-config.js'\nimport { loadSearchIndex } from '../mcp/orama-loader.js'\nimport type { LoadedMcpSite } from '../mcp/search-server.js'\nimport { runMcpSearchServer } from '../mcp/search-server.js'\n\nexport type McpCliOptions = {\n /** Skip the on-disk index cache; always fetch fresh. */\n noCache?: boolean\n /** Optional logger for diagnostics (defaults to stderr). */\n log?: (message: string) => void\n}\n\n/**\n * Start a local MCP server (stdio transport) that exposes full-text search\n * over one or more deployed Clarify sites' Orama indices.\n *\n * For each site:\n * 1. Fetch `<site>/mcp.json` to learn the index path, default locale, and\n * document count. This is a tiny file and avoids hardcoding any\n * assumptions about where the index lives on the site.\n * 2. Use the descriptor to fetch the binary `.msp` index (cached locally\n * keyed by site origin + document count + locale fingerprint) and\n * deserialize it into an in-memory Orama db with the correct tokenizer.\n *\n * Then register the `search_docs` tool, which searches across all loaded\n * sites and merges results (each hit annotated with its source site), and\n * serve over stdio.\n *\n * All logs go to stderr - stdout is reserved for the JSON-RPC protocol.\n */\nexport async function runMcp(siteUrls: string[], options: McpCliOptions = {}): Promise<void> {\n if (siteUrls.length === 0) {\n throw new Error('[clarify] At least one site URL is required. Usage: clarify mcp <site> [site...]')\n }\n\n const log = options.log ?? stderrLog\n const sites: LoadedMcpSite[] = []\n for (const siteUrl of siteUrls) {\n const config = await fetchMcpConfig(siteUrl, fetch, log)\n const search = config.capabilities.search\n if (!search) {\n throw new Error(`[clarify] mcp.json for ${siteUrl} has no search capability. Run a build with search enabled.`)\n }\n log(`Loaded mcp.json for ${siteUrl}: ${search.documentCount} doc(s), ${search.locales.length} locale(s)`)\n\n const index = await loadSearchIndex(siteUrl, config, {\n noCache: options.noCache,\n fetchImpl: fetch,\n log,\n })\n sites.push({ siteUrl, config, index })\n }\n\n await runMcpSearchServer(sites, { log })\n}\n\nfunction stderrLog(message: string): void {\n process.stderr.write(`[clarify] ${message}\\n`)\n}\n\nexport async function fetchMcpConfig(siteUrl: string, fetchImpl: typeof fetch, log: (m: string) => void): Promise<McpSiteConfig> {\n const configUrl = new URL('mcp.json', new URL(siteUrl).href).href\n log(`Fetching ${configUrl}`)\n const res = await fetchImpl(configUrl, { redirect: 'follow' })\n if (!res.ok) {\n throw new Error(\n `[clarify] Failed to fetch mcp.json from ${configUrl} (HTTP ${res.status}). ` +\n 'Ensure the site was built with a recent version of Clarify that emits mcp.json.',\n )\n }\n const config = (await res.json()) as McpSiteConfig\n if (config.version !== 3) {\n throw new Error(`[clarify] Unsupported mcp.json schema version ${config.version}. Please update the clarify CLI.`)\n }\n const search = config.capabilities.search\n if (!search || search.documentCount === 0) {\n throw new Error(`[clarify] mcp.json at ${configUrl} has no indexed documents. Run a build with search enabled.`)\n }\n if (!search.indexPath) {\n throw new Error(`[clarify] mcp.json at ${configUrl} is missing capabilities.search.indexPath.`)\n }\n if (search.indexHash !== undefined && (typeof search.indexHash !== 'string' || search.indexHash.length === 0)) {\n throw new Error(`[clarify] mcp.json at ${configUrl} has an invalid capabilities.search.indexHash.`)\n }\n return config\n}\n","import { resolve } from 'node:path'\n\nexport type CliOptions = {\n root?: string\n content?: string\n output?: string\n host?: string | boolean\n port?: string | number\n open?: boolean | string\n}\n\nexport type ResolvedCliOptions = {\n root: string\n content: string\n output: string\n host?: string | boolean\n port?: number\n open?: boolean | string\n}\n\nfunction resolvePort(port: CliOptions['port']): number | undefined {\n if (port === undefined) return undefined\n\n const parsedPort = typeof port === 'string' ? Number(port) : port\n if (!Number.isInteger(parsedPort) || parsedPort < 1 || parsedPort > 65535) {\n throw new Error('[clarify] --port must be an integer between 1 and 65535')\n }\n\n return parsedPort\n}\n\nexport function resolveCliOptions(options: CliOptions): ResolvedCliOptions {\n return {\n root: resolve(options.root ?? process.cwd()),\n content: options.content ?? 'source',\n output: options.output ?? 'output',\n host: options.host,\n port: resolvePort(options.port),\n open: options.open,\n }\n}\n","import { cac } from 'cac'\n\nimport { runBuild } from './commands/build.js'\nimport { runCheck, type CheckCommandOptions } from './commands/check.js'\nimport { runDev } from './commands/dev.js'\nimport { runInit } from './commands/init.js'\nimport { runMcp, type McpCliOptions } from './commands/mcp.js'\nimport { resolveCliOptions, type CliOptions } from './options.js'\nimport { cliPackageVersion } from './package.js'\n\ntype InitCommandOptions = CliOptions & {\n force?: boolean\n template?: string\n install?: boolean\n}\n\nfunction withBuildOptions(command: ReturnType<ReturnType<typeof cac>['command']>) {\n return command\n .option('--content <dir>', 'Content directory relative to root')\n}\n\nfunction withSharedOptions(command: ReturnType<ReturnType<typeof cac>['command']>) {\n return command\n .option('--root <dir>', 'Project root directory')\n .option('--content <dir>', 'Content directory relative to root')\n .option('--output <dir>', 'Build output directory relative to root')\n}\n\nfunction createCli() {\n const cli = cac('clarify')\n\n cli\n .version(cliPackageVersion)\n .help()\n\n withSharedOptions(cli.command('dev', 'Start the local documentation server'))\n .option('--host [host]', 'Dev server host')\n .option('--port <port>', 'Dev server port')\n .option('--open [path]', 'Open the dev server in a browser')\n .action(async (options: CliOptions) => {\n await runDev(resolveCliOptions(options))\n })\n\n withSharedOptions(cli.command('build', 'Build the static documentation site'))\n .action(async (options: CliOptions) => {\n await runBuild(resolveCliOptions(options))\n })\n\n withSharedOptions(cli.command('check', 'Validate the documentation project'))\n .option('--strict', 'Treat warnings as failures')\n .option('--format <format>', 'Output format: text or json')\n .action(async (options: CheckCommandOptions) => {\n await runCheck(options)\n })\n\n withBuildOptions(cli.command('init [directory]', 'Create a Clarify project scaffold'))\n .option('--force', 'Overwrite files created by init')\n .option('--template <name>', 'Template to use: minimal, standard, or complete')\n .option('--install', 'Install dependencies after init')\n .action((directory: string | undefined, options: InitCommandOptions) => {\n runInit(resolveCliOptions({ ...options, root: directory }), options.force === true, options.template, options.install === true)\n })\n\n cli\n .command('mcp <...site>', 'Start a local MCP server exposing full-text search over one or more deployed sites')\n .option('--no-cache', 'Skip the local search index cache and always fetch fresh')\n .action(async (sites: string[], options: McpCliOptions) => {\n await runMcp(sites, { noCache: options.noCache === true })\n })\n\n return cli\n}\n\nexport async function main(argv = process.argv): Promise<void> {\n const cli = createCli()\n const args = argv.slice(2)\n cli.parse(argv, { run: false })\n\n if (args.length === 0) {\n cli.outputHelp()\n return\n }\n\n await cli.runMatchedCommand()\n}\n","#!/usr/bin/env node\nimport { main } from './program.js'\n\nmain().catch(error => {\n console.error(error instanceof Error ? error.stack ?? error.message : String(error))\n process.exitCode = 1\n})\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.js","names":[],"sources":["../source/core/runtime/log.ts","../source/core/runtime/vite-config.ts","../source/cli/commands/build.ts","../source/cli/commands/check.ts","../source/cli/commands/dev.ts","../source/cli/spawn.ts","../source/cli/commands/init.ts","../source/cli/mcp/orama-loader.ts","../source/cli/mcp/search-server.ts","../source/cli/commands/mcp.ts","../source/cli/options.ts","../source/cli/program.ts","../source/cli/index.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { readFile, writeFile } from 'node:fs/promises'\nimport { dirname, join } from 'node:path'\n\nconst LOG_FILE_NAME = '.clarify.log'\nconst DEFAULT_LOG_ENTRIES = 50\nconst ENTRY_SEPARATOR = '\\n\\n---\\n\\n'\n\nfunction getMaxLogEntries(): number {\n const envValue = process.env.CLARIFY_LOG_MAX_ENTRIES\n if (!envValue) return DEFAULT_LOG_ENTRIES\n const parsed = Number(envValue)\n return Number.isInteger(parsed) && parsed > 0 ? parsed : DEFAULT_LOG_ENTRIES\n}\n\nfunction normalizeErrorMessage(error: unknown): string {\n if (error === undefined) return 'undefined'\n if (error === null) return 'null'\n if (error instanceof Error) return error.message\n if (typeof error === 'object') {\n if ('message' in error && typeof (error as { message?: unknown }).message === 'string') {\n return (error as { message: string }).message\n }\n try {\n return JSON.stringify(error)\n } catch {\n return String(error)\n }\n }\n return String(error)\n}\n\nfunction normalizeErrorStack(error: unknown): string | undefined {\n if (error instanceof Error) {\n return error.stack\n }\n return undefined\n}\n\nfunction formatLogEntry(root: string, error: unknown): string {\n const timestamp = new Date().toISOString()\n const message = normalizeErrorMessage(error)\n const stack = normalizeErrorStack(error)\n\n return [`=== Clarify build error ===`, `Timestamp: ${timestamp}`, `Project root: ${root}`, `Error: ${message}`, stack ? `Stack:\\n${stack}` : undefined]\n .filter(Boolean)\n .join('\\n')\n}\n\ntype LogEntryReader = (logPath: string) => Promise<string> | string\ntype LogEntryWriter = (logPath: string, content: string) => Promise<void> | void\n\nfunction collectLogEntries(entries: string[], entry: string, max: number): string[] {\n const next = [...entries, entry]\n return next.length > max ? next.slice(-max) : next\n}\n\nfunction readExistingEntries(content: string): string[] {\n return content\n .split(ENTRY_SEPARATOR)\n .map((item) => item.trim())\n .filter(Boolean)\n}\n\nasync function writeLogEntry(root: string, error: unknown, maxEntries: number | undefined, read: LogEntryReader, write: LogEntryWriter): Promise<void> {\n const logPath = join(root, LOG_FILE_NAME)\n const entry = formatLogEntry(root, error)\n const max = maxEntries ?? getMaxLogEntries()\n\n let entries: string[] = []\n if (existsSync(logPath)) {\n try {\n entries = readExistingEntries(await read(logPath))\n } catch {\n entries = []\n }\n }\n\n entries = collectLogEntries(entries, entry, max)\n\n mkdirSync(dirname(logPath), { recursive: true })\n await write(logPath, entries.join(ENTRY_SEPARATOR) + '\\n')\n}\n\nexport async function logBuildError(root: string, error: unknown, maxEntries?: number): Promise<void> {\n await writeLogEntry(root, error, maxEntries, (path) => readFile(path, 'utf8'), (path, content) => writeFile(path, content, 'utf8'))\n}\n\nexport function logBuildErrorSync(root: string, error: unknown, maxEntries?: number): void {\n void writeLogEntry(root, error, maxEntries, (path) => readFileSync(path, 'utf8'), (path, content) => writeFileSync(path, content, 'utf8'))\n}\n","import { existsSync, writeFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\n\nimport { createLogger } from 'vite'\nimport type { ConfigEnv, InlineConfig, Plugin, LogLevel, Logger, LogOptions, LogErrorOptions, LogType } from 'vite'\n\nimport { createViteAdapter } from '../adapters.js'\nimport type { ClarifyEngine } from '../engine/engine.js'\nimport { createClarifyTempDir } from '../project/temp-dir.js'\n\nimport { logBuildErrorSync } from './log.js'\nimport { createClarifyRuntimeAliases } from './runtime-deps.js'\n\nexport type ClarifyViteConfigOptions = {\n root: string\n content: string\n output: string\n host?: string | boolean\n port?: number\n open?: boolean | string\n}\n\nconst DEFAULT_HTML = '<!doctype html><html lang=\"en\"><head><meta charset=\"UTF-8\" /><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" /><title>Clarify</title></head><body><div id=\"root\"></div></body></html>'\n\nfunction ensureHtmlEntry(root: string): string {\n const projectHtmlPath = resolve(root, 'index.html')\n if (existsSync(projectHtmlPath)) return projectHtmlPath\n\n const generatedHtmlPath = resolve(createClarifyTempDir('html'), 'index.html')\n writeFileSync(generatedHtmlPath, DEFAULT_HTML, 'utf-8')\n return generatedHtmlPath\n}\n\nfunction createClarifyLogger(root: string, env: ConfigEnv, level: LogLevel): Logger | undefined {\n if (env.command !== 'build') return undefined\n\n const baseLogger = createLogger(level, { allowClearScreen: true })\n\n return {\n info(msg: string, options?: LogOptions) {\n baseLogger.info(msg, options)\n },\n warn(msg: string, options?: LogOptions) {\n baseLogger.warn(msg, options)\n },\n warnOnce(msg: string, options?: LogOptions) {\n baseLogger.warnOnce(msg, options)\n },\n error(msg: string, options?: LogErrorOptions) {\n baseLogger.error(msg, options)\n if (options?.error) {\n logBuildErrorSync(root, options.error)\n } else {\n logBuildErrorSync(root, typeof msg === 'string' ? new Error(msg) : msg)\n }\n },\n clearScreen(type: LogType) {\n baseLogger.clearScreen(type)\n },\n hasErrorLogged(error: Error | unknown) {\n return baseLogger.hasErrorLogged(error as Error)\n },\n get hasWarned() {\n return baseLogger.hasWarned\n },\n }\n}\n\nfunction createHtmlFallbackPlugin(): Plugin {\n return {\n name: 'clarify:cli-html-fallback',\n configureServer(server) {\n server.middlewares.use(async (req, res, next) => {\n const requestPath = req.url?.split('?')[0] ?? '/'\n const acceptsHtml = req.headers.accept?.includes('text/html') ?? false\n const hasFileExtension = /\\.[^/]+$/.test(requestPath)\n if (!acceptsHtml || hasFileExtension) {\n next()\n return\n }\n\n try {\n const html = await server.transformIndexHtml(requestPath, DEFAULT_HTML)\n res.statusCode = 200\n res.setHeader('Content-Type', 'text/html; charset=utf-8')\n res.end(html)\n } catch (error) {\n next(error)\n }\n })\n },\n }\n}\n\nexport async function createViteConfig(options: ClarifyViteConfigOptions, env: ConfigEnv, engine: ClarifyEngine): Promise<InlineConfig> {\n const entryHtmlPath = ensureHtmlEntry(options.root)\n\n return {\n root: options.root,\n configFile: false,\n appType: 'custom',\n resolve: {\n alias: createClarifyRuntimeAliases(),\n },\n customLogger: createClarifyLogger(options.root, env, 'info'),\n plugins: [\n createViteAdapter(engine),\n createHtmlFallbackPlugin(),\n ],\n server: {\n host: options.host,\n port: options.port,\n open: options.open,\n },\n build: {\n outDir: options.output,\n rolldownOptions: {\n input: {\n index: entryHtmlPath,\n },\n checks: {\n pluginTimings: false,\n },\n output: {\n codeSplitting: {\n groups: [\n {\n name: 'react-vendor',\n test: /node_modules[\\\\/](react|react-dom|react-router|react-router-dom)[\\\\/]/,\n priority: 40,\n },\n {\n name: 'icons-vendor',\n test: /node_modules[\\\\/]lucide-react[\\\\/]/,\n priority: 35,\n },\n {\n name: 'ui-vendor',\n test: /node_modules[\\\\/](@headlessui|framer-motion)[\\\\/]/,\n priority: 30,\n },\n {\n name: 'mermaid-viewer-vendor',\n test: /node_modules[\\\\/]react-zoom-pan-pinch[\\\\/]/,\n priority: 25,\n },\n {\n // Keep mermaid and its heavy diagram/render dependencies out of\n // the eager `vendor` chunk so they stay lazily loaded only on\n // pages that actually render a diagram.\n name: 'mermaid-vendor',\n test: /node_modules[\\\\/](mermaid|@mermaid-js|cytoscape|cytoscape-[^\\\\/]+|dagre-d3-es|@dagrejs|dagre|graphlib|elkjs|katex|d3|d3-[^\\\\/]+|internmap|delaunator|robust-predicates|roughjs|points-on-curve|points-on-path|path-data-parser|@braintree[\\\\/]sanitize-url|dompurify|khroma|ts-dedent|stylis|cose-base|layout-base)[\\\\/]/,\n priority: 20,\n },\n {\n name: 'vendor',\n test: /node_modules[\\\\/]/,\n priority: 10\n },\n ],\n },\n },\n },\n },\n }\n}\n","import { build as viteBuild } from 'vite'\n\nimport { createClarifyEngine } from '../../core/engine/engine.js'\nimport { logBuildError } from '../../core/runtime/log.js'\nimport { createViteConfig } from '../../core/runtime/vite-config.js'\nimport type { ResolvedCliOptions } from '../options.js'\n\nexport async function runBuild(options: ResolvedCliOptions): Promise<void> {\n const env = { command: 'build' as const, mode: 'production' }\n const engine = createClarifyEngine({\n projectRoot: options.root,\n rootDirectory: options.content,\n outputDirectory: options.output,\n })\n try {\n await engine.prepare(env)\n await viteBuild(await createViteConfig(options, env, engine))\n } catch (error) {\n await logBuildError(options.root, error)\n throw error\n }\n}\n","import { lstat, stat } from 'node:fs/promises'\nimport { dirname, extname, isAbsolute, join, normalize, relative, resolve } from 'node:path'\n\nimport { createClarifyEngine } from '../../core/engine/engine.js'\nimport type { ContentRoute } from '../../types.js'\nimport type { CliOptions } from '../options.js'\n\nexport type CheckCommandOptions = CliOptions & {\n strict?: boolean\n format?: 'text' | 'json' | string\n}\n\ntype CheckLevel = 'error' | 'warning'\n\ntype CheckDiagnostic = {\n level: CheckLevel\n code: string\n message: string\n filePath?: string\n routePath?: string\n}\n\ntype CheckResult = {\n errors: CheckDiagnostic[]\n warnings: CheckDiagnostic[]\n}\n\nconst LOCAL_LINK_PATTERN = /(?<!!)(?:\\[[^\\]]*\\]\\(([^)\\s]+)(?:\\s+\"[^\"]*\")?\\)|<a\\s+[^>]*href=[\"']([^\"']+)[\"'])/gi\nconst ROUTE_EXTENSIONS = new Set(['.md', '.mdx'])\nconst IGNORED_SCHEMES = /^[a-z][a-z0-9+.-]*:/i\n\nfunction addDiagnostic(result: CheckResult, diagnostic: CheckDiagnostic): void {\n if (diagnostic.level === 'error') result.errors.push(diagnostic)\n else result.warnings.push(diagnostic)\n}\n\nfunction normalizeRoutePath(path: string): string {\n const [withoutHash] = path.split('#')\n const clean = withoutHash.replace(/\\/index$/, '') || '/'\n return clean.startsWith('/') ? clean : `/${clean}`\n}\n\nfunction routePathCandidates(href: string, route: ContentRoute): string[] {\n const [withoutHashOrQuery] = href.split(/[?#]/)\n if (!withoutHashOrQuery || withoutHashOrQuery.startsWith('#')) return []\n if (withoutHashOrQuery.startsWith('/')) return [normalizeRoutePath(withoutHashOrQuery)]\n\n const routeDir = dirname(route.path)\n const joined = normalize(join(routeDir, withoutHashOrQuery)).replaceAll('\\\\', '/')\n const extension = extname(joined)\n const base = ROUTE_EXTENSIONS.has(extension) ? joined.slice(0, -extension.length) : joined\n return [normalizeRoutePath(base)]\n}\n\nasync function pathExists(filePath: string): Promise<boolean> {\n try {\n await stat(filePath)\n return true\n } catch {\n return false\n }\n}\n\nfunction isLocalHref(href: string): boolean {\n return Boolean(href) && !href.startsWith('#') && !href.startsWith('//') && !IGNORED_SCHEMES.test(href)\n}\n\nasync function resolveLocalFileLink(href: string, route: ContentRoute, contentRoot: string): Promise<boolean> {\n const [withoutHashOrQuery] = href.split(/[?#]/)\n if (!withoutHashOrQuery || withoutHashOrQuery.startsWith('/')) return false\n\n const target = resolve(dirname(route.source.filePath), withoutHashOrQuery)\n const relativeTarget = relative(contentRoot, target)\n if (relativeTarget.startsWith('..') || isAbsolute(relativeTarget)) return false\n if (await pathExists(target)) return true\n\n if (!extname(target)) {\n return pathExists(`${target}.md`) || pathExists(`${target}.mdx`) || pathExists(join(target, 'index.md')) || pathExists(join(target, 'index.mdx'))\n }\n return false\n}\n\nasync function checkContentDirectory(contentRoot: string, result: CheckResult): Promise<void> {\n try {\n const stats = await lstat(contentRoot)\n if (!stats.isDirectory()) {\n addDiagnostic(result, {\n level: 'error',\n code: 'content-not-directory',\n message: `Content path is not a directory: ${contentRoot}`,\n filePath: contentRoot,\n })\n }\n } catch {\n addDiagnostic(result, {\n level: 'error',\n code: 'content-missing',\n message: `Content directory does not exist: ${contentRoot}`,\n filePath: contentRoot,\n })\n }\n}\n\nfunction checkDuplicateRoutes(routes: ContentRoute[], result: CheckResult): void {\n const byPath = new Map<string, ContentRoute[]>()\n for (const route of routes) {\n const key = `${route.locale ?? ''}:${route.path}`\n byPath.set(key, [...(byPath.get(key) ?? []), route])\n }\n\n for (const duplicated of byPath.values()) {\n if (duplicated.length < 2) continue\n for (const route of duplicated) {\n addDiagnostic(result, {\n level: 'error',\n code: 'duplicate-route',\n message: `Route \"${route.path}\" is defined by multiple files: ${duplicated.map(route => relative(process.cwd(), route.source.filePath)).join(', ')}`,\n filePath: route.source.filePath,\n routePath: route.path,\n })\n }\n }\n}\n\nfunction checkFallbackRoutes(routes: ContentRoute[], result: CheckResult): void {\n for (const route of routes) {\n if (!route.isFallback) continue\n addDiagnostic(result, {\n level: 'warning',\n code: 'i18n-fallback-route',\n message: `Route \"${route.path}\" falls back to ${route.locale ?? 'default'} content from ${relative(process.cwd(), route.source.filePath)}`,\n filePath: route.source.filePath,\n routePath: route.path,\n })\n }\n}\n\nasync function checkLocalLinks(routes: ContentRoute[], contentRoot: string, result: CheckResult): Promise<void> {\n const routePaths = new Set(routes.map(route => route.path))\n\n for (const route of routes) {\n if (route.kind !== 'mdx' || !route.source.content) continue\n for (const match of route.source.content.matchAll(LOCAL_LINK_PATTERN)) {\n const href = match[1] ?? match[2]\n if (!href || !isLocalHref(href)) continue\n const candidates = routePathCandidates(href, route)\n if (candidates.some(candidate => routePaths.has(candidate))) continue\n if (await resolveLocalFileLink(href, route, contentRoot)) continue\n\n addDiagnostic(result, {\n level: 'error',\n code: 'broken-link',\n message: `Broken local link \"${href}\" in route \"${route.path}\"`,\n filePath: route.source.filePath,\n routePath: route.path,\n })\n }\n }\n}\n\nfunction printTextResult(result: CheckResult, strict: boolean): void {\n const diagnostics = [...result.errors, ...result.warnings]\n if (diagnostics.length === 0) {\n console.log('✓ Clarify check passed')\n return\n }\n\n for (const diagnostic of diagnostics) {\n const location = diagnostic.filePath ? ` ${relative(process.cwd(), diagnostic.filePath)}` : ''\n const route = diagnostic.routePath ? ` (${diagnostic.routePath})` : ''\n console.log(`${diagnostic.level.toUpperCase()} ${diagnostic.code}${location}${route}`)\n console.log(` ${diagnostic.message}`)\n }\n\n const warningExit = strict && result.warnings.length > 0\n console.log(`\\n${result.errors.length} error(s), ${result.warnings.length} warning(s)${warningExit ? ' (--strict treats warnings as failures)' : ''}`)\n}\n\nexport async function runCheck(options: CheckCommandOptions = {}): Promise<void> {\n const root = resolve(options.root ?? process.cwd())\n const engine = createClarifyEngine({\n projectRoot: root,\n rootDirectory: options.content,\n outputDirectory: options.output,\n })\n await engine.prepare(undefined, undefined, { htmlShell: false, skipModules: true, skipHints: true })\n\n const result: CheckResult = { errors: [], warnings: [] }\n await checkContentDirectory(engine.contentRoot, result)\n checkDuplicateRoutes(engine.routes, result)\n checkFallbackRoutes(engine.routes, result)\n await checkLocalLinks(engine.routes, engine.contentRoot, result)\n\n if (options.format === 'json') {\n console.log(JSON.stringify(result, null, 2))\n } else {\n printTextResult(result, Boolean(options.strict))\n }\n\n if (result.errors.length > 0 || (options.strict && result.warnings.length > 0)) {\n process.exitCode = 1\n }\n}\n","import { createServer } from 'vite'\n\nimport { createClarifyEngine } from '../../core/engine/engine.js'\nimport { createViteConfig } from '../../core/runtime/vite-config.js'\nimport type { ResolvedCliOptions } from '../options.js'\n\nexport async function runDev(options: ResolvedCliOptions): Promise<void> {\n const env = { command: 'serve' as const, mode: 'development' }\n const engine = createClarifyEngine({\n projectRoot: options.root,\n rootDirectory: options.content,\n outputDirectory: options.output,\n })\n await engine.prepare(env)\n const server = await createServer(await createViteConfig(options, env, engine))\n await server.listen()\n server.printUrls()\n server.bindCLIShortcuts({ print: true })\n}\n","import { spawnSync as nodeSpawnSync, SpawnSyncOptions } from 'node:child_process'\n\ntype SpawnOptions = { cwd?: string; stdio?: 'inherit' | 'ignore' | Array<string> }\n\nexport function spawnSync(command: string, args: string[], options: SpawnOptions) {\n return nodeSpawnSync(command, args, options as SpawnSyncOptions)\n}\n","import { existsSync, readFileSync, writeFileSync } from 'node:fs'\nimport { createRequire } from 'node:module'\nimport { dirname, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nimport { copyTemplateDirectory, getTemplateDirectory, resolveTemplate } from '@clarify-labs/templates'\n\nimport type { ResolvedCliOptions } from '../options.js'\nimport { cliPackageVersionWithCaret } from '../package.js'\nimport { spawnSync } from '../spawn.js'\n\nconst require = createRequire(import.meta.url)\n\nfunction findTemplatesPackagePath(): string {\n try {\n return require.resolve('@clarify-labs/templates/package.json')\n } catch {\n const currentDirectory = dirname(fileURLToPath(import.meta.url))\n const workspacePackagePath = resolve(currentDirectory, '../../../../templates/package.json')\n if (existsSync(workspacePackagePath)) return workspacePackagePath\n throw new Error('[clarify] Templates package not found.')\n }\n}\n\nconst templatesPackagePath = findTemplatesPackagePath()\nconst templatesDirectory = dirname(templatesPackagePath)\n\nfunction commandExists(program: string): boolean {\n const result = spawnSync(program, ['--version'], { stdio: 'ignore' })\n return result.status === 0 && result.error === undefined\n}\n\ntype PackageManager = 'pnpm' | 'npm' | 'yarn'\n\nfunction detectPackageManager(): PackageManager {\n if (commandExists('pnpm')) return 'pnpm'\n if (commandExists('npm')) return 'npm'\n if (commandExists('yarn')) return 'yarn'\n return 'npm'\n}\n\nfunction installDependencies(root: string, command: PackageManager): void {\n const args = ['install']\n console.log(`[clarify] Installing dependencies with ${command}...`)\n const result = spawnSync(command, args, { cwd: root, stdio: 'inherit' })\n if (result.status !== 0) {\n throw new Error(`[clarify] Dependency install failed with ${command}`)\n }\n}\n\nfunction getSuggestedInstallCommand(packageManager: PackageManager): string {\n return `${packageManager} install`\n}\n\nfunction getSuggestedRunCommand(packageManager: PackageManager): string {\n if (packageManager === 'pnpm') return 'pnpm dev'\n if (packageManager === 'yarn') return 'yarn dev'\n return 'npm run dev'\n}\n\nfunction updatePackageJson(root: string, force: boolean): boolean {\n const packageJsonPath = resolve(root, 'package.json')\n const packageJson = existsSync(packageJsonPath)\n ? JSON.parse(readFileSync(packageJsonPath, 'utf-8')) as Record<string, unknown>\n : { type: 'module' }\n\n const scripts = typeof packageJson.scripts === 'object' && packageJson.scripts !== null\n ? packageJson.scripts as Record<string, string>\n : {}\n\n if (force || !scripts.dev) scripts.dev = 'clarify dev'\n if (force || !scripts.build) scripts.build = 'clarify build'\n packageJson.scripts = scripts\n\n const devDependencies = typeof packageJson.devDependencies === 'object' && packageJson.devDependencies !== null\n ? packageJson.devDependencies as Record<string, string>\n : {}\n if (!devDependencies['@clarify-labs/cli']) devDependencies['@clarify-labs/cli'] = cliPackageVersionWithCaret\n packageJson.devDependencies = devDependencies\n\n writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\\n`, 'utf-8')\n return true\n}\n\nexport function runInit(options: ResolvedCliOptions, force: boolean, template?: string, install = false): void {\n const selectedTemplate = resolveTemplate(template)\n const templateDirectory = getTemplateDirectory(templatesDirectory, selectedTemplate)\n const { created } = copyTemplateDirectory(templateDirectory, options.root, {\n contentDir: options.content,\n force,\n })\n\n const packageJsonUpdated = updatePackageJson(options.root, force)\n if (packageJsonUpdated) created.push('package.json')\n\n console.log(`[clarify] Project scaffold created using the ${selectedTemplate} template.`)\n if (created.length > 0) {\n console.log(`[clarify] Created or updated ${created.length} ${created.length === 1 ? 'file' : 'files'}: ${created.join(', ')}`)\n }\n\n const packageManager = detectPackageManager()\n if (install) {\n installDependencies(options.root, packageManager)\n const suggestedRun = getSuggestedRunCommand(packageManager)\n console.log('[clarify] Dependencies installed successfully.')\n console.log(`[clarify] You can now run \\`${suggestedRun}\\` to start the local documentation server.`)\n return\n }\n\n const suggestedInstall = getSuggestedInstallCommand(packageManager)\n const suggestedRun = getSuggestedRunCommand(packageManager)\n console.log('[clarify] Next steps:')\n console.log(' 1. Change into your new project directory:')\n console.log(` cd ${options.root}`)\n console.log(' 2. Install dependencies:')\n console.log(` ${suggestedInstall}`)\n console.log(' 3. Start the local documentation server:')\n console.log(` ${suggestedRun}`)\n}\n","import { createHash } from 'node:crypto'\nimport { mkdir, readFile, rm, writeFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nimport type { McpSiteConfig } from '../../plugins/mcp-search/mcp-config.js'\nimport type { McpSearchResult } from '../../plugins/mcp-search/orama-index.js'\nimport { deserializeSearchIndex, searchMcpIndex } from '../../plugins/mcp-search/orama-index.js'\n\n/**\n * A ready-to-search Orama index loaded for the MCP server.\n *\n * The underlying db is fully in-memory after load, so `search` is synchronous\n * to the index. `dispose` drops the reference so the buffer can be GC'd; it's\n * safe to call multiple times.\n */\nexport type LoadedSearchIndex = {\n /** Search the index. Locale filter is optional. */\n search: (params: { query: string; locale?: string; limit?: number }) => McpSearchResult\n /** Release the in-memory index. Safe to call multiple times. */\n dispose: () => void\n}\n\n/** Re-export so callers can name the result type without reaching into orama-index. */\nexport type { McpSearchResult as SearchResult } from '../../plugins/mcp-search/orama-index.js'\n\nexport type OramaLoaderOptions = {\n /**\n * Root directory for the on-disk cache. Defaults to `~/.clarify/mcp-cache`.\n * Each site gets a subdirectory keyed by a stable hash of its origin + path.\n */\n cacheDir?: string\n /**\n * Bypass the cache and always fetch fresh. Implies purging the cached copy\n * for this site on a successful refresh.\n */\n noCache?: boolean\n /** Optional fetch override (testing). */\n fetchImpl?: typeof fetch\n /** Optional logger (testing). Defaults to no-op. */\n log?: (message: string) => void\n}\n\nconst DEFAULT_CACHE_DIR = () => join(homedir(), '.clarify', 'mcp-cache')\nconst FETCH_TIMEOUT_MS = 60_000\n\n/** Stable per-site cache key. Two URLs with the same origin+path share a cache. */\nfunction siteCacheKey(siteUrl: string): string {\n let url: URL\n try {\n url = new URL(siteUrl)\n } catch {\n throw new Error(`[clarify] Invalid site URL: ${siteUrl}`)\n }\n // Origin + pathname, trailing slash normalized, query/hash ignored.\n // Query/hash are irrelevant for \"where does the site live\" and would\n // fragment the cache unnecessarily.\n const normalized = `${url.origin}${url.pathname.replace(/\\/+$/, '')}`\n return createHash('sha256').update(normalized).digest('hex').slice(0, 16)\n}\n\nasync function fetchBufferWithTimeout(url: string, fetchImpl: typeof fetch, log: (m: string) => void): Promise<Uint8Array> {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS)\n try {\n log(`Fetching ${url}`)\n const res = await fetchImpl(url, { signal: controller.signal, redirect: 'follow' })\n if (!res.ok) {\n throw new Error(`HTTP ${res.status} ${res.statusText} fetching ${url}`)\n }\n const buf = await res.arrayBuffer()\n return new Uint8Array(buf)\n } finally {\n clearTimeout(timer)\n }\n}\n\n/**\n * Load the Orama binary index for a remote site and return a ready-to-search\n * handle.\n *\n * The `.msp` index is a single versioned binary file containing a\n * Brotli-compressed, MessagePack-serialized Orama `save()` payload. It is\n * cached on disk so repeated MCP starts don't re-download.\n * Cache validity is keyed by `capabilities.search.indexHash` when available.\n * For older sites that do not emit `indexHash`, we fall back to document\n * count + locale fingerprint matching.\n *\n * The caller must supply the same `defaultLocale` recorded in `mcp.json` so\n * the tokenizer matches the one used at build time. A mismatch would not\n * corrupt data but would cause CJK query terms to be tokenized incorrectly.\n */\nexport async function loadSearchIndex(siteUrl: string, config: McpSiteConfig, options: OramaLoaderOptions = {}): Promise<LoadedSearchIndex> {\n const log = options.log ?? (() => {})\n const fetchImpl = options.fetchImpl ?? fetch\n const cacheDir = options.cacheDir ?? DEFAULT_CACHE_DIR()\n const cacheKey = siteCacheKey(siteUrl)\n const siteCacheDir = join(cacheDir, cacheKey)\n const indexCachePath = join(siteCacheDir, 'mcp-search.msp')\n const manifestPath = join(siteCacheDir, 'manifest.json')\n\n const base = new URL(siteUrl).href\n log(`Site base resolved to ${base}`)\n\n // The index path in mcp.json is root-relative (e.g. `/mcp-search.msp` or\n // `/docs/mcp-search.msp`). Resolve it against the site base.\n const search = config.capabilities.search\n if (!search) {\n throw new Error(`[clarify] mcp.json for ${siteUrl} has no search capability.`)\n }\n const indexUrl = new URL(search.indexPath, base).href\n\n // Cache validity: reuse the cached .msp only when the document count and\n // locale fingerprint recorded at last fetch match the caller-provided\n // config. These change whenever the index is rebuilt with different content.\n const fingerprint = localeFingerprint(config)\n const indexHash = search.indexHash\n let useCache = !options.noCache\n if (useCache) {\n try {\n const manifest = JSON.parse(await readFile(manifestPath, 'utf8')) as {\n documentCount?: number\n fingerprint?: string\n indexHash?: string\n }\n if (indexHash) {\n if (manifest.indexHash !== indexHash) {\n log('Cache stale (index hash changed); refetching')\n useCache = false\n }\n } else if (manifest.documentCount !== search.documentCount || manifest.fingerprint !== fingerprint) {\n log('Cache stale (document count or locales changed); refetching')\n useCache = false\n }\n } catch {\n useCache = false\n }\n }\n\n let buffer: Uint8Array | undefined\n if (useCache) {\n try {\n buffer = await readFile(indexCachePath)\n log('Using cached mcp-search.msp')\n } catch {\n // Cache file unreadable; fall through to fetch below.\n }\n }\n\n if (buffer === undefined) {\n const fetched = await fetchBufferWithTimeout(indexUrl, fetchImpl, log)\n buffer = fetched\n // Best-effort persist; failure to cache is non-fatal.\n try {\n await mkdir(siteCacheDir, { recursive: true })\n await writeFile(indexCachePath, fetched)\n await writeFile(\n manifestPath,\n JSON.stringify(\n {\n siteUrl: base,\n fetchedAt: new Date().toISOString(),\n documentCount: search.documentCount,\n fingerprint,\n indexHash,\n },\n null,\n 2,\n ),\n 'utf8',\n )\n log(`Cached mcp-search.msp to ${indexCachePath}`)\n } catch (err) {\n log(`Warning: failed to cache index: ${err instanceof Error ? err.message : String(err)}`)\n }\n }\n\n const defaultLocale = search.defaultLocale\n const db = deserializeSearchIndex(buffer, defaultLocale)\n let disposed = false\n\n return {\n search: ({ query, locale, limit }) => {\n if (disposed) throw new Error('[clarify] Search index already disposed.')\n return searchMcpIndex(db, { query, locale, limit })\n },\n dispose: () => {\n // Orama's in-memory index is plain JS data; dropping the reference is\n // enough for GC. Nothing to flush.\n disposed = true\n },\n }\n}\n\n/**\n * Build a stable fingerprint of the indexed locales so the cache can detect\n * locale-set changes even when the document count happens to stay the same.\n */\nfunction localeFingerprint(config: McpSiteConfig): string {\n return createHash('sha256').update((config.capabilities.search?.locales ?? []).slice().sort().join('|')).digest('hex').slice(0, 16)\n}\n\n/**\n * Remove the on-disk cache for a site. Useful for `--no-cache` cleanup or for\n * tests. No-op if the site has no cache directory.\n */\nexport async function purgeSiteCache(siteUrl: string, cacheDir?: string): Promise<void> {\n const dir = cacheDir ?? DEFAULT_CACHE_DIR()\n const key = siteCacheKey(siteUrl)\n await rm(join(dir, key), { recursive: true, force: true })\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { z } from 'zod'\n\nimport type { McpSiteConfig } from '../../plugins/mcp-search/mcp-config.js'\nimport type { McpSearchHit } from '../../plugins/mcp-search/orama-index.js'\n\nimport type { LoadedSearchIndex } from './orama-loader.js'\n\nexport type SearchServerOptions = {\n /** Optional logger routed to stderr (stdout is the JSON-RPC channel). */\n log?: (message: string) => void\n}\n\n/**\n * A site loaded for the MCP server: its descriptor, ready-to-search index,\n * and the origin URL the index was fetched from (used to resolve relative\n * result paths and to label results by source site).\n */\nexport type LoadedMcpSite = {\n siteUrl: string\n config: McpSiteConfig\n index: LoadedSearchIndex\n}\n\n/** A search hit annotated with the site it came from. */\ntype SourcedHit = McpSearchHit & { site: string }\n\n/**\n * Build the MCP server exposing site search over one or more Clarify sites.\n *\n * Tools registered:\n * - `search_docs`: full-text search across all loaded sites, with each\n * result annotated by its source site.\n *\n * Results are serialized to a compact, LLM-friendly shape: title, URL, site,\n * excerpt, score, and locale. Full page content is intentionally omitted to\n * keep responses within token budgets; clients can fetch the URL themselves.\n */\nexport function createMcpSearchServer(sites: LoadedMcpSite[], options: SearchServerOptions = {}): McpServer {\n const log = options.log ?? (() => {})\n const server = new McpServer({\n name: 'clarify-search',\n version: '1.0.0',\n })\n\n if (sites.length === 0) {\n throw new Error('[clarify] createMcpSearchServer requires at least one loaded site.')\n }\n\n // Aggregate metadata across all loaded sites for the tool description.\n const totalDocs = sites.reduce((sum, site) => sum + (site.config.capabilities.search?.documentCount ?? 0), 0)\n const localeSet = new Set<string>()\n for (const site of sites) {\n for (const locale of site.config.capabilities.search?.locales ?? []) localeSet.add(locale)\n }\n const localeList = [...localeSet]\n const siteTitles = sites\n .map(site => site.config.site.title ?? 'site')\n .filter((title, i, arr) => arr.indexOf(title) === i)\n const siteHint = siteTitles.length === 1\n ? `\"${siteTitles[0]}\"`\n : `${sites.length} sites (${siteTitles.join(', ')})`\n\n const localeHint = localeList.length > 0\n ? ` Available locales: ${localeList.join(', ')}.`\n : ''\n const defaultLocale = sites[0].config.capabilities.search?.defaultLocale\n const defaultLocaleHint = defaultLocale\n ? ` Defaults to \"${defaultLocale}\".`\n : ''\n\n server.registerTool(\n 'search_docs',\n {\n title: 'Search documentation',\n description: [\n `Full-text search over ${siteHint} documentation index.`,\n `Returns ranked results with excerpts, URLs, and source site. The index contains ${totalDocs} pages across ${localeList.length} locale(s).`,\n localeHint,\n defaultLocaleHint,\n 'Pass a `locale` filter to restrict results to a specific language.',\n ].filter(Boolean).join(' '),\n inputSchema: {\n query: z\n .string()\n .min(1)\n .describe('Search query. CJK text is word-segmented automatically; Latin text is split on whitespace/punctuation.'),\n locale: z\n .string()\n .optional()\n .describe(`Filter results to a single locale. One of: ${localeList.join(', ')}.`),\n limit: z\n .number()\n .int()\n .min(1)\n .max(50)\n .optional()\n .describe('Maximum results to return. Default 10, max 50.'),\n },\n },\n async ({ query, locale, limit }) => {\n log(`search_docs query=${JSON.stringify(query)} locale=${JSON.stringify(locale)} limit=${limit ?? 10}`)\n\n // Search every loaded site and merge hits. Each hit is annotated with\n // its source site so the caller can tell results apart when multiple\n // sites are loaded. Results are ranked globally by score.\n const allHits: SourcedHit[] = []\n let errorResult: { text: string } | undefined\n for (const site of sites) {\n try {\n const result = site.index.search({ query, locale, limit })\n for (const hit of result.hits) {\n allHits.push({ ...hit, site: site.siteUrl })\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n log(`search failed for ${site.siteUrl}: ${message}`)\n errorResult = { text: `Search failed for ${site.siteUrl}: ${message}` }\n }\n }\n\n if (allHits.length === 0 && errorResult) {\n return {\n isError: true,\n content: [{ type: 'text', text: errorResult.text }],\n }\n }\n\n allHits.sort((a, b) => b.score - a.score)\n const capped = limit ? allHits.slice(0, limit) : allHits.slice(0, 10)\n\n const summary = [\n `Found ${allHits.length} result(s) across ${totalDocs} indexed pages from ${sites.length} site(s).`,\n `Showing top ${capped.length}.`,\n '',\n ].join('\\n')\n\n const text = [summary, ...capped.map((hit, i) => formatResultText(hit, i))].join('\\n---\\n')\n\n return {\n content: [{ type: 'text', text }],\n }\n },\n )\n\n return server\n}\n\n/**\n * Run the search server over stdio until the client disconnects or the process\n * is signaled. Resolves on clean shutdown.\n */\nexport async function runMcpSearchServer(sites: LoadedMcpSite[], options: SearchServerOptions = {}): Promise<void> {\n const log = options.log ?? (() => {})\n const server = createMcpSearchServer(sites, options)\n const transport = new StdioServerTransport()\n // Dispose every search index when the client disconnects. StdioServerTransport\n // calls onclose after stdin closes.\n transport.onclose = () => {\n log('MCP transport closed; disposing search indices')\n for (const site of sites) site.index.dispose()\n }\n await server.connect(transport)\n log(`MCP search server listening on stdio (${sites.length} site(s))`)\n}\n\nfunction formatResultText(hit: SourcedHit, index: number): string {\n const lines = [\n `## ${index + 1}. ${hit.title}`,\n `URL: ${hit.path}`,\n `Site: ${hit.site}`,\n `Score: ${hit.score}`,\n ]\n if (hit.locale) {\n lines.push(`Locale: ${hit.locale}`)\n }\n if (hit.excerpt) {\n lines.push('', hit.excerpt)\n }\n if (hit.description) {\n lines.push('', `Description: ${hit.description}`)\n }\n if (hit.keywords?.length > 0) {\n lines.push('', `Keywords: ${hit.keywords.join(', ')}`)\n }\n return lines.join('\\n')\n}\n","import type { McpSiteConfig } from '../../plugins/mcp-search/mcp-config.js'\nimport { loadSearchIndex } from '../mcp/orama-loader.js'\nimport type { LoadedMcpSite } from '../mcp/search-server.js'\nimport { runMcpSearchServer } from '../mcp/search-server.js'\n\nexport type McpCliOptions = {\n /** Skip the on-disk index cache; always fetch fresh. */\n noCache?: boolean\n /** Optional logger for diagnostics (defaults to stderr). */\n log?: (message: string) => void\n}\n\n/**\n * Start a local MCP server (stdio transport) that exposes full-text search\n * over one or more deployed Clarify sites' Orama indices.\n *\n * For each site:\n * 1. Fetch `<site>/mcp.json` to learn the index path, default locale, and\n * document count. This is a tiny file and avoids hardcoding any\n * assumptions about where the index lives on the site.\n * 2. Use the descriptor to fetch the binary `.msp` index (cached locally\n * keyed by site origin + document count + locale fingerprint) and\n * deserialize it into an in-memory Orama db with the correct tokenizer.\n *\n * Then register the `search_docs` tool, which searches across all loaded\n * sites and merges results (each hit annotated with its source site), and\n * serve over stdio.\n *\n * All logs go to stderr - stdout is reserved for the JSON-RPC protocol.\n */\nexport async function runMcp(siteUrls: string[], options: McpCliOptions = {}): Promise<void> {\n if (siteUrls.length === 0) {\n throw new Error('[clarify] At least one site URL is required. Usage: clarify mcp <site> [site...]')\n }\n\n const log = options.log ?? stderrLog\n const sites: LoadedMcpSite[] = []\n for (const siteUrl of siteUrls) {\n const config = await fetchMcpConfig(siteUrl, fetch, log)\n const search = config.capabilities.search\n if (!search) {\n throw new Error(`[clarify] mcp.json for ${siteUrl} has no search capability. Run a build with search enabled.`)\n }\n log(`Loaded mcp.json for ${siteUrl}: ${search.documentCount} doc(s), ${search.locales.length} locale(s)`)\n\n const index = await loadSearchIndex(siteUrl, config, {\n noCache: options.noCache,\n fetchImpl: fetch,\n log,\n })\n sites.push({ siteUrl, config, index })\n }\n\n await runMcpSearchServer(sites, { log })\n}\n\nfunction stderrLog(message: string): void {\n process.stderr.write(`[clarify] ${message}\\n`)\n}\n\nexport async function fetchMcpConfig(siteUrl: string, fetchImpl: typeof fetch, log: (m: string) => void): Promise<McpSiteConfig> {\n const configUrl = new URL('mcp.json', new URL(siteUrl).href).href\n log(`Fetching ${configUrl}`)\n const res = await fetchImpl(configUrl, { redirect: 'follow' })\n if (!res.ok) {\n throw new Error(\n `[clarify] Failed to fetch mcp.json from ${configUrl} (HTTP ${res.status}). ` +\n 'Ensure the site was built with a recent version of Clarify that emits mcp.json.',\n )\n }\n const config = (await res.json()) as McpSiteConfig\n if (config.version !== 3) {\n throw new Error(`[clarify] Unsupported mcp.json schema version ${config.version}. Please update the clarify CLI.`)\n }\n const search = config.capabilities.search\n if (!search || search.documentCount === 0) {\n throw new Error(`[clarify] mcp.json at ${configUrl} has no indexed documents. Run a build with search enabled.`)\n }\n if (!search.indexPath) {\n throw new Error(`[clarify] mcp.json at ${configUrl} is missing capabilities.search.indexPath.`)\n }\n if (search.indexHash !== undefined && (typeof search.indexHash !== 'string' || search.indexHash.length === 0)) {\n throw new Error(`[clarify] mcp.json at ${configUrl} has an invalid capabilities.search.indexHash.`)\n }\n return config\n}\n","import { resolve } from 'node:path'\n\nexport type CliOptions = {\n root?: string\n content?: string\n output?: string\n host?: string | boolean\n port?: string | number\n open?: boolean | string\n}\n\nexport type ResolvedCliOptions = {\n root: string\n content: string\n output: string\n host?: string | boolean\n port?: number\n open?: boolean | string\n}\n\nfunction resolvePort(port: CliOptions['port']): number | undefined {\n if (port === undefined) return undefined\n\n const parsedPort = typeof port === 'string' ? Number(port) : port\n if (!Number.isInteger(parsedPort) || parsedPort < 1 || parsedPort > 65535) {\n throw new Error('[clarify] --port must be an integer between 1 and 65535')\n }\n\n return parsedPort\n}\n\nexport function resolveCliOptions(options: CliOptions): ResolvedCliOptions {\n return {\n root: resolve(options.root ?? process.cwd()),\n content: options.content ?? 'source',\n output: options.output ?? 'output',\n host: options.host,\n port: resolvePort(options.port),\n open: options.open,\n }\n}\n","import { cac } from 'cac'\n\nimport { runBuild } from './commands/build.js'\nimport { runCheck, type CheckCommandOptions } from './commands/check.js'\nimport { runDev } from './commands/dev.js'\nimport { runInit } from './commands/init.js'\nimport { runMcp, type McpCliOptions } from './commands/mcp.js'\nimport { resolveCliOptions, type CliOptions } from './options.js'\nimport { cliPackageVersion } from './package.js'\n\ntype InitCommandOptions = CliOptions & {\n force?: boolean\n template?: string\n install?: boolean\n}\n\nfunction withBuildOptions(command: ReturnType<ReturnType<typeof cac>['command']>) {\n return command\n .option('--content <dir>', 'Content directory relative to root')\n}\n\nfunction withSharedOptions(command: ReturnType<ReturnType<typeof cac>['command']>) {\n return command\n .option('--root <dir>', 'Project root directory')\n .option('--content <dir>', 'Content directory relative to root')\n .option('--output <dir>', 'Build output directory relative to root')\n}\n\nfunction createCli() {\n const cli = cac('clarify')\n\n cli\n .version(cliPackageVersion)\n .help()\n\n withSharedOptions(cli.command('dev', 'Start the local documentation server'))\n .option('--host [host]', 'Dev server host')\n .option('--port <port>', 'Dev server port')\n .option('--open [path]', 'Open the dev server in a browser')\n .action(async (options: CliOptions) => {\n await runDev(resolveCliOptions(options))\n })\n\n withSharedOptions(cli.command('build', 'Build the static documentation site'))\n .action(async (options: CliOptions) => {\n await runBuild(resolveCliOptions(options))\n })\n\n withSharedOptions(cli.command('check', 'Validate the documentation project'))\n .option('--strict', 'Treat warnings as failures')\n .option('--format <format>', 'Output format: text or json')\n .action(async (options: CheckCommandOptions) => {\n await runCheck(options)\n })\n\n withBuildOptions(cli.command('init [directory]', 'Create a Clarify project scaffold'))\n .option('--force', 'Overwrite files created by init')\n .option('--template <name>', 'Template to use: minimal, standard, or complete')\n .option('--install', 'Install dependencies after init')\n .action((directory: string | undefined, options: InitCommandOptions) => {\n runInit(resolveCliOptions({ ...options, root: directory }), options.force === true, options.template, options.install === true)\n })\n\n cli\n .command('mcp <...site>', 'Start a local MCP server exposing full-text search over one or more deployed sites')\n .option('--no-cache', 'Skip the local search index cache and always fetch fresh')\n .action(async (sites: string[], options: McpCliOptions) => {\n await runMcp(sites, { noCache: options.noCache === true })\n })\n\n return cli\n}\n\nexport async function main(argv = process.argv): Promise<void> {\n const cli = createCli()\n const args = argv.slice(2)\n cli.parse(argv, { run: false })\n\n if (args.length === 0) {\n cli.outputHelp()\n return\n }\n\n await cli.runMatchedCommand()\n}\n","#!/usr/bin/env node\nimport { main } from './program.js'\n\nmain().catch(error => {\n console.error(error instanceof Error ? error.stack ?? error.message : String(error))\n process.exitCode = 1\n})\n"],"mappings":"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"}
|
|
@@ -19,6 +19,7 @@ import { build, loadConfigFromFile } from "vite";
|
|
|
19
19
|
import { z } from "zod";
|
|
20
20
|
import { stringify } from "yaml";
|
|
21
21
|
import { createHash } from "node:crypto";
|
|
22
|
+
import { brotliCompressSync, brotliDecompressSync, constants } from "node:zlib";
|
|
22
23
|
import { decode, encode } from "@msgpack/msgpack";
|
|
23
24
|
import { create, insertMultiple, load, save, search } from "@orama/orama";
|
|
24
25
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
@@ -84,7 +85,7 @@ function createContentCompileDiagnostic(options) {
|
|
|
84
85
|
return createContentDiagnostic({
|
|
85
86
|
kind: format,
|
|
86
87
|
title: `${label} ${phase} error`,
|
|
87
|
-
message: phase === "syntax" ?
|
|
88
|
+
message: phase === "syntax" ? `This page could not be compiled. Fix the ${label} syntax or component usage above, then reload the route.` : `This page could not be compiled. Fix the ${label} syntax or plugin error below, then reload the route.`,
|
|
88
89
|
error,
|
|
89
90
|
filePath,
|
|
90
91
|
projectRoot,
|
|
@@ -97,19 +98,24 @@ function createContentCompileDiagnostic(options) {
|
|
|
97
98
|
*
|
|
98
99
|
* `rehypePlugins` includes `rehypeShiki`, which loads grammar/WASM assets and
|
|
99
100
|
* is expensive. The real highlighting happens at Vite build time via the
|
|
100
|
-
* `@mdx-js/rollup`
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
* "不应在 core 中执行代码高亮".
|
|
101
|
+
* `@mdx-js/rollup` plugin (see `createContentCompilerPlugin` in
|
|
102
|
+
* `core/adapters.ts`), which runs the full remark + rehype pipeline.
|
|
103
|
+
* Re-running it here, during route discovery (Phase 3), would compile every
|
|
104
|
+
* `.mdx` file twice and invoke Shiki once per file per `engine.refresh()` -
|
|
105
|
+
* see ARCHITECTURE.md §2.2 which states "不应在 core 中执行代码高亮".
|
|
106
106
|
*
|
|
107
107
|
* The remark pipeline still runs (shared with the Vite plugin via
|
|
108
|
-
* `remarkPlugins`), so MDX/JSX syntax errors
|
|
109
|
-
* diagnostic is meant to surface ahead of the Vite build
|
|
108
|
+
* `remarkPlugins`), so MDX/JSX syntax errors - the only class of error this
|
|
109
|
+
* diagnostic is meant to surface ahead of the Vite build - are caught. The
|
|
110
110
|
* output is discarded; only the thrown error is used.
|
|
111
|
+
*
|
|
112
|
+
* `.md` files are handled by `compileMarkdownContent` in `markdown.ts`, which
|
|
113
|
+
* mirrors the adapter's markdown compiler semantics (`format: 'md'`, raw HTML
|
|
114
|
+
* allowed). Keep the two compilers separate so each format can evolve its own
|
|
115
|
+
* diagnostic rules without contaminating the other.
|
|
111
116
|
*/
|
|
112
|
-
async function compileMdxContent(content,
|
|
117
|
+
async function compileMdxContent(content, options = {}) {
|
|
118
|
+
const { filePath, projectRoot } = options;
|
|
113
119
|
try {
|
|
114
120
|
await compile(content, {
|
|
115
121
|
jsx: true,
|
|
@@ -240,6 +246,54 @@ function createProjectContentProcessor(plugins, ctx) {
|
|
|
240
246
|
return createContentProcessor((input) => runHooks(plugins, "content:transform", input, ctx));
|
|
241
247
|
}
|
|
242
248
|
//#endregion
|
|
249
|
+
//#region source/parsers/markdown/markdown.ts
|
|
250
|
+
/**
|
|
251
|
+
* Validate Markdown content for diagnostics WITHOUT running the build-time
|
|
252
|
+
* rehype pipeline (Shiki highlighting, slug injection, code-block parsing).
|
|
253
|
+
*
|
|
254
|
+
* `rehypePlugins` includes `rehypeShiki`, which loads grammar/WASM assets and
|
|
255
|
+
* is expensive. The real highlighting happens at Vite build time via the
|
|
256
|
+
* `@mdx-js/rollup` plugin (see `createContentCompilerPlugin` in
|
|
257
|
+
* `core/adapters.ts`), which runs the full remark + rehype pipeline.
|
|
258
|
+
* Re-running it here, during route discovery (Phase 3), would compile every
|
|
259
|
+
* `.md` file twice and invoke Shiki once per file per `engine.refresh()` -
|
|
260
|
+
* see ARCHITECTURE.md §2.2 which states "不应在 core 中执行代码高亮".
|
|
261
|
+
*
|
|
262
|
+
* `format: 'md'` mirrors the adapter's markdown compiler semantics (no JSX,
|
|
263
|
+
* raw HTML allowed via `remarkRehypeOptions`), so the same class of syntax
|
|
264
|
+
* errors that would break the Vite build is surfaced as a diagnostic here
|
|
265
|
+
* instead of leaking out as an opaque
|
|
266
|
+
* `Failed to fetch dynamically imported module` at runtime.
|
|
267
|
+
*
|
|
268
|
+
* MDX files are handled by `compileMdxContent` in `mdx.ts`. Keep the two
|
|
269
|
+
* compilers separate so each format can evolve its own diagnostic rules
|
|
270
|
+
* without contaminating the other.
|
|
271
|
+
*/
|
|
272
|
+
async function compileMarkdownContent(content, options = {}) {
|
|
273
|
+
const { filePath, projectRoot } = options;
|
|
274
|
+
try {
|
|
275
|
+
await compile(content, {
|
|
276
|
+
format: "md",
|
|
277
|
+
jsx: true,
|
|
278
|
+
providerImportSource: "@clarify-labs/renderer",
|
|
279
|
+
remarkPlugins,
|
|
280
|
+
remarkRehypeOptions: { allowDangerousHtml: true }
|
|
281
|
+
});
|
|
282
|
+
return { ok: true };
|
|
283
|
+
} catch (error) {
|
|
284
|
+
return {
|
|
285
|
+
ok: false,
|
|
286
|
+
diagnostic: createContentCompileDiagnostic({
|
|
287
|
+
format: "markdown",
|
|
288
|
+
phase: "syntax",
|
|
289
|
+
error,
|
|
290
|
+
filePath,
|
|
291
|
+
projectRoot
|
|
292
|
+
})
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
//#endregion
|
|
243
297
|
//#region source/parsers/routes/routes.ts
|
|
244
298
|
function kebabToTitle(str) {
|
|
245
299
|
return str.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
@@ -248,8 +302,10 @@ function parseMdxTree(content) {
|
|
|
248
302
|
return remark.parse(content);
|
|
249
303
|
}
|
|
250
304
|
async function compileRouteDiagnostic(content, filePath, baseDir) {
|
|
251
|
-
|
|
252
|
-
|
|
305
|
+
const result = await (extname(filePath).toLowerCase() === ".md" ? compileMarkdownContent : compileMdxContent)(content, {
|
|
306
|
+
filePath,
|
|
307
|
+
projectRoot: baseDir
|
|
308
|
+
});
|
|
253
309
|
return result.ok ? void 0 : result.diagnostic;
|
|
254
310
|
}
|
|
255
311
|
/** 从内容中提取第一个 H1 标题 */
|
|
@@ -954,18 +1010,16 @@ var clarifyThemeConfigSchema = z.object({
|
|
|
954
1010
|
tokens: clarifyThemeTokensConfigSchema.optional(),
|
|
955
1011
|
layout: clarifyThemeLayoutConfigSchema.optional()
|
|
956
1012
|
}).strict();
|
|
957
|
-
function featureSchema(shape, defaults) {
|
|
1013
|
+
function featureSchema(shape, defaults, enabledByDefault = true) {
|
|
1014
|
+
const resolvedDefaults = {
|
|
1015
|
+
enabled: enabledByDefault,
|
|
1016
|
+
...defaults
|
|
1017
|
+
};
|
|
958
1018
|
const objectSchema = z.object({
|
|
959
|
-
enabled: z.boolean().default(
|
|
1019
|
+
enabled: z.boolean().default(enabledByDefault),
|
|
960
1020
|
...shape
|
|
961
|
-
}).strict().default(
|
|
962
|
-
|
|
963
|
-
...defaults
|
|
964
|
-
});
|
|
965
|
-
return z.union([z.boolean(), objectSchema]).default({
|
|
966
|
-
enabled: true,
|
|
967
|
-
...defaults
|
|
968
|
-
}).transform((value) => typeof value === "boolean" ? {
|
|
1021
|
+
}).strict().default(resolvedDefaults);
|
|
1022
|
+
return z.union([z.boolean(), objectSchema]).default(resolvedDefaults).transform((value) => typeof value === "boolean" ? {
|
|
969
1023
|
enabled: value,
|
|
970
1024
|
...defaults
|
|
971
1025
|
} : value);
|
|
@@ -973,7 +1027,7 @@ function featureSchema(shape, defaults) {
|
|
|
973
1027
|
var clarifyFeaturesConfigSchema = z.object({
|
|
974
1028
|
search: featureSchema({ mcp: z.boolean().default(true) }, { mcp: true }),
|
|
975
1029
|
repository: featureSchema(clarifyRepositoryConfigSchema.shape, {}),
|
|
976
|
-
themeEditor: featureSchema({}, {}),
|
|
1030
|
+
themeEditor: featureSchema({}, {}, false),
|
|
977
1031
|
openapi: featureSchema({ playground: z.boolean().default(true) }, { playground: true })
|
|
978
1032
|
}).strict();
|
|
979
1033
|
var clarifyProjectConfigSchema = z.object({
|
|
@@ -1557,7 +1611,7 @@ function createViteAdapter(engine) {
|
|
|
1557
1611
|
}
|
|
1558
1612
|
var cliPackageVersion = {
|
|
1559
1613
|
name: "@clarify-labs/cli",
|
|
1560
|
-
version: "0.11.
|
|
1614
|
+
version: "0.11.4",
|
|
1561
1615
|
license: "AGPL-3.0-only",
|
|
1562
1616
|
type: "module",
|
|
1563
1617
|
repository: {
|
|
@@ -1939,6 +1993,22 @@ function createMcpSiteConfig(projectConfig, options) {
|
|
|
1939
1993
|
}
|
|
1940
1994
|
//#endregion
|
|
1941
1995
|
//#region source/plugins/mcp-search/orama-index.ts
|
|
1996
|
+
var MSP_MAGIC = new Uint8Array([
|
|
1997
|
+
67,
|
|
1998
|
+
76,
|
|
1999
|
+
65,
|
|
2000
|
+
82,
|
|
2001
|
+
73,
|
|
2002
|
+
70,
|
|
2003
|
+
89,
|
|
2004
|
+
77,
|
|
2005
|
+
83,
|
|
2006
|
+
80,
|
|
2007
|
+
1
|
|
2008
|
+
]);
|
|
2009
|
+
function hasMspMagic(buffer) {
|
|
2010
|
+
return buffer.byteLength >= MSP_MAGIC.byteLength && MSP_MAGIC.every((byte, index) => buffer[index] === byte);
|
|
2011
|
+
}
|
|
1942
2012
|
/**
|
|
1943
2013
|
* Orama schema for the MCP search index.
|
|
1944
2014
|
*
|
|
@@ -2177,17 +2247,22 @@ function guessTitleFromPath(path) {
|
|
|
2177
2247
|
return segments[segments.length - 1].replace(/\.(md|mdx|html)$/, "").replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
2178
2248
|
}
|
|
2179
2249
|
/**
|
|
2180
|
-
* Serialize an Orama index to a
|
|
2250
|
+
* Serialize an Orama index to a versioned, Brotli-compressed binary buffer.
|
|
2181
2251
|
*
|
|
2182
|
-
* Uses `save()` to extract the raw index data,
|
|
2183
|
-
*
|
|
2184
|
-
*
|
|
2252
|
+
* Uses `save()` to extract the raw index data, MessagePack-encodes it, then
|
|
2253
|
+
* compresses the payload so source documents are not embedded as contiguous
|
|
2254
|
+
* plaintext. The leading magic bytes identify the container and its version.
|
|
2185
2255
|
*/
|
|
2186
2256
|
function serializeSearchIndex(db) {
|
|
2187
|
-
|
|
2257
|
+
const compressed = brotliCompressSync(encode(save(db)), { params: { [constants.BROTLI_PARAM_QUALITY]: 9 } });
|
|
2258
|
+
const buffer = new Uint8Array(MSP_MAGIC.byteLength + compressed.byteLength);
|
|
2259
|
+
buffer.set(MSP_MAGIC);
|
|
2260
|
+
buffer.set(compressed, MSP_MAGIC.byteLength);
|
|
2261
|
+
return buffer;
|
|
2188
2262
|
}
|
|
2189
2263
|
/**
|
|
2190
|
-
* Deserialize a
|
|
2264
|
+
* Deserialize a current compressed container or legacy MessagePack buffer
|
|
2265
|
+
* into a ready-to-search Orama index.
|
|
2191
2266
|
*
|
|
2192
2267
|
* The caller must supply the same `defaultLocale` used when the index was
|
|
2193
2268
|
* built, so the tokenizer matches. A mismatch would not corrupt data but
|
|
@@ -2195,7 +2270,7 @@ function serializeSearchIndex(db) {
|
|
|
2195
2270
|
* as a single token instead of split into "文" + "档").
|
|
2196
2271
|
*/
|
|
2197
2272
|
function deserializeSearchIndex(buffer, defaultLocale) {
|
|
2198
|
-
const raw = decode(buffer);
|
|
2273
|
+
const raw = decode(hasMspMagic(buffer) ? brotliDecompressSync(buffer.subarray(MSP_MAGIC.byteLength)) : buffer);
|
|
2199
2274
|
const db = createMcpSearchIndex(defaultLocale);
|
|
2200
2275
|
load(db, raw);
|
|
2201
2276
|
return db;
|
|
@@ -3766,4 +3841,4 @@ function createClarifyEngine(options = {}) {
|
|
|
3766
3841
|
//#endregion
|
|
3767
3842
|
export { deserializeSearchIndex as a, cliPackageVersionWithCaret as c, createClarifyTempDir as i, createViteAdapter as l, createClarifyEngine as n, searchMcpIndex as o, createClarifyRuntimeAliases as r, cliPackageVersion as s, ClarifyEngine as t, defineConfig as u };
|
|
3768
3843
|
|
|
3769
|
-
//# sourceMappingURL=engine-
|
|
3844
|
+
//# sourceMappingURL=engine-CJmXVTo5.js.map
|