@clarify-labs/cli 0.11.11 → 0.11.14

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.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 { findRouteConflicts } from '../../core/routing/route-analysis.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 for (const conflict of findRouteConflicts(routes)) {\n for (const route of conflict.routes) {\n addDiagnostic(result, {\n level: 'error',\n code: conflict.kind === 'path' ? 'duplicate-route' : 'duplicate-page-module',\n message: `${conflict.label} is defined by multiple files: ${conflict.routes.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 (!['markdown', 'markdown+jsx'].includes(route.kind) || !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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"}
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'\nimport { printCliVersion } from '../package.js'\n\nexport async function runBuild(options: ResolvedCliOptions): Promise<void> {\n printCliVersion()\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 { findRouteConflicts } from '../../core/routing/route-analysis.js'\nimport type { ContentRoute } from '../../types.js'\nimport type { CliOptions } from '../options.js'\nimport { printCliVersion } from '../package.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 for (const conflict of findRouteConflicts(routes)) {\n for (const route of conflict.routes) {\n addDiagnostic(result, {\n level: 'error',\n code: conflict.kind === 'path' ? 'duplicate-route' : 'duplicate-page-module',\n message: `${conflict.label} is defined by multiple files: ${conflict.routes.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 (!['markdown', 'markdown+jsx'].includes(route.kind) || !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 printCliVersion()\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'\nimport { printCliVersion } from '../package.js'\n\nexport async function runDev(options: ResolvedCliOptions): Promise<void> {\n printCliVersion()\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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"}
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { ClarifyNavbarMenuItem, ClarifyVariableValue } from '../../types.js';
2
+ import { ClarifyNavbarMenuItem, ClarifyPagesGroup, ClarifyVariableValue } from '../../types.js';
3
3
  export declare const clarifyFeaturesConfigSchema: z.ZodObject<{
4
4
  search: z.ZodPipe<z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodDefault<z.ZodObject<{
5
5
  enabled: z.ZodDefault<z.ZodBoolean>;
@@ -130,7 +130,7 @@ export declare const clarifyProjectConfigSchema: z.ZodObject<{
130
130
  tabs: z.ZodOptional<z.ZodArray<z.ZodObject<{
131
131
  tab: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>;
132
132
  icon: z.ZodOptional<z.ZodString>;
133
- pages: z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodType<import('../../types.js').ClarifyPagesGroup, import('../../types.js').ClarifyPagesGroup, z.core.$ZodTypeInternals<import('../../types.js').ClarifyPagesGroup, import('../../types.js').ClarifyPagesGroup>>>, z.ZodLiteral<"FileTree">]>>;
133
+ pages: z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodType<ClarifyPagesGroup, ClarifyPagesGroup, z.core.$ZodTypeInternals<ClarifyPagesGroup, ClarifyPagesGroup>>>, z.ZodLiteral<"FileTree">]>>;
134
134
  }, z.core.$strict>>>;
135
135
  }, z.core.$strict>>;
136
136
  banner: z.ZodOptional<z.ZodObject<{
@@ -742,6 +742,8 @@ function buildNavigationFromConfig(routes, config) {
742
742
  title: resolveLocalizedText(item.group, "", "") ?? "",
743
743
  icon: item.icon,
744
744
  layout: item.layout,
745
+ visible: item.visible,
746
+ searchable: item.searchable,
745
747
  children
746
748
  };
747
749
  }
@@ -771,6 +773,8 @@ function buildNavigationFromConfig(routes, config) {
771
773
  path: children[0]?.path ?? "/",
772
774
  title: resolveLocalizedText(group.group, "", "") ?? "",
773
775
  icon: group.icon,
776
+ visible: group.visible,
777
+ searchable: group.searchable,
774
778
  children
775
779
  };
776
780
  });
@@ -796,6 +800,8 @@ function buildLocalizedNavigationForLocale(routes, config, locale, locales) {
796
800
  title: resolveLocalizedText(item.group, locale, locales.default) ?? "",
797
801
  icon: item.icon,
798
802
  layout: item.layout,
803
+ visible: item.visible,
804
+ searchable: item.searchable,
799
805
  children
800
806
  };
801
807
  }
@@ -816,6 +822,8 @@ function buildLocalizedNavigationForLocale(routes, config, locale, locales) {
816
822
  path: children[0]?.path ?? localizedRoutePath("/", locale, locales),
817
823
  title: resolveLocalizedText(group.group, locale, locales.default) ?? "",
818
824
  icon: group.icon,
825
+ visible: group.visible,
826
+ searchable: group.searchable,
819
827
  children
820
828
  };
821
829
  });
@@ -1110,12 +1118,19 @@ var clarifyPagesItemSchema = z.lazy(() => z.union([
1110
1118
  filter: z.object({ tags: z.array(z.string()).optional() }).strict().optional()
1111
1119
  }).strict()
1112
1120
  ]));
1113
- var clarifyPagesGroupSchema = z.lazy(() => z.object({
1121
+ var clarifyPagesGroupShape = {
1114
1122
  group: clarifyLocalizedTextSchema,
1115
1123
  icon: z.string().optional(),
1124
+ visible: z.enum([
1125
+ "always",
1126
+ "active",
1127
+ "never"
1128
+ ]).optional(),
1129
+ searchable: z.boolean().optional(),
1116
1130
  layout: z.enum(["documentation", "blog"]).optional(),
1117
1131
  pages: z.array(clarifyPagesItemSchema)
1118
- }).strict());
1132
+ };
1133
+ var clarifyPagesGroupSchema = z.lazy(() => z.object(clarifyPagesGroupShape).strict());
1119
1134
  var clarifyPagesConfigSchema = z.union([z.array(clarifyPagesGroupSchema), z.literal("FileTree")]);
1120
1135
  var clarifyTabItemSchema = z.object({
1121
1136
  tab: clarifyLocalizedTextSchema,
@@ -1442,6 +1457,7 @@ function routeToRuntimeManifestEntry(route, component, mode) {
1442
1457
  if (route.locale) entry.locale = route.locale;
1443
1458
  if (route.isFallback) entry.isFallback = true;
1444
1459
  if (route.isBareAlias) entry.isBareAlias = true;
1460
+ if (route.searchable === false) entry.searchable = false;
1445
1461
  if (route.alternates) entry.alternates = route.alternates;
1446
1462
  if (route.meta.description) entry.description = route.meta.description;
1447
1463
  if (route.meta.keywords?.length) entry.keywords = route.meta.keywords;
@@ -1773,7 +1789,7 @@ function createViteAdapter(engine) {
1773
1789
  }
1774
1790
  var cliPackageVersion = {
1775
1791
  name: "@clarify-labs/cli",
1776
- version: "0.11.11",
1792
+ version: "0.11.14",
1777
1793
  license: "AGPL-3.0-only",
1778
1794
  type: "module",
1779
1795
  repository: {
@@ -1849,6 +1865,9 @@ var cliPackageVersion = {
1849
1865
  }
1850
1866
  }.version ?? "0.0.0";
1851
1867
  var cliPackageVersionWithCaret = `^${cliPackageVersion}`;
1868
+ function printCliVersion() {
1869
+ console.error(`[clarify] v${cliPackageVersion}`);
1870
+ }
1852
1871
  //#endregion
1853
1872
  //#region source/core/config/options.ts
1854
1873
  function resolveBuildOptions(options = {}) {
@@ -1896,6 +1915,49 @@ function readRouteArtifactContent(route) {
1896
1915
  const content = readRouteContent(route);
1897
1916
  return shouldUseUtf8Signature(route) ? withUtf8Signature(content) : content;
1898
1917
  }
1918
+ function mergeOpenAPIRecord(target, source, section, filePath) {
1919
+ if (!source) return;
1920
+ for (const [key, value] of Object.entries(source)) {
1921
+ const existing = target[key];
1922
+ if (existing !== void 0 && JSON.stringify(existing) !== JSON.stringify(value)) throw new Error(`[clarify] Cannot aggregate OpenAPI specs: conflicting ${section} entry "${key}" in ${filePath}.`);
1923
+ target[key] = value;
1924
+ }
1925
+ }
1926
+ function createRootOpenAPISpec(routes, projectConfig) {
1927
+ const paths = {};
1928
+ const webhooks = {};
1929
+ const components = {};
1930
+ const tags = /* @__PURE__ */ new Map();
1931
+ const defaultLocale = projectConfig.locales?.default;
1932
+ for (const route of routes) {
1933
+ if (route.kind !== "openapi" || route.diagnostic || !route.source.content || defaultLocale && route.locale && route.locale !== defaultLocale) continue;
1934
+ const filePath = route.source.filePath;
1935
+ const spec = JSON.parse(route.source.content);
1936
+ mergeOpenAPIRecord(paths, spec.paths, "paths", filePath);
1937
+ mergeOpenAPIRecord(webhooks, "webhooks" in spec ? spec.webhooks : void 0, "webhooks", filePath);
1938
+ for (const [section, entries] of Object.entries(spec.components ?? {})) {
1939
+ components[section] ??= {};
1940
+ mergeOpenAPIRecord(components[section], entries, `components.${section}`, filePath);
1941
+ }
1942
+ for (const tag of spec.tags ?? []) {
1943
+ const existing = tags.get(tag.name);
1944
+ if (existing !== void 0 && JSON.stringify(existing) !== JSON.stringify(tag)) throw new Error(`[clarify] Cannot aggregate OpenAPI specs: conflicting tag "${tag.name}" in ${filePath}.`);
1945
+ tags.set(tag.name, tag);
1946
+ }
1947
+ }
1948
+ return {
1949
+ openapi: "3.1.0",
1950
+ info: {
1951
+ title: projectConfig.title,
1952
+ description: projectConfig.description,
1953
+ version: "1.0.0"
1954
+ },
1955
+ paths,
1956
+ ...Object.keys(webhooks).length > 0 ? { webhooks } : {},
1957
+ ...Object.keys(components).length > 0 ? { components } : {},
1958
+ ...tags.size > 0 ? { tags: [...tags.values()] } : {}
1959
+ };
1960
+ }
1899
1961
  function isLlmsTxtRoute(route) {
1900
1962
  return !route.path.split("/").includes("404");
1901
1963
  }
@@ -1995,6 +2057,14 @@ function serveContentArtifacts(req, res, projectConfig, routes) {
1995
2057
  res.end(createLlmsTxtArtifact(routes, projectConfig), "utf8");
1996
2058
  return true;
1997
2059
  }
2060
+ if (contentPath === "/openapi.json" || contentPath === "/openapi.yml") {
2061
+ const spec = createRootOpenAPISpec(routes, projectConfig);
2062
+ const isJson = contentPath.endsWith(".json");
2063
+ res.statusCode = 200;
2064
+ res.setHeader("Content-Type", isJson ? "application/json; charset=utf-8" : "text/yaml; charset=utf-8");
2065
+ res.end(isJson ? JSON.stringify(spec, null, 2) : stringify(spec, { lineWidth: 0 }), "utf8");
2066
+ return true;
2067
+ }
1998
2068
  if (contentPath.endsWith(".openapi.yaml")) {
1999
2069
  const jsonPath = contentPath.replace(/\.yaml$/, ".json");
2000
2070
  const route = routes.find((route) => route.artifacts?.contentArtifactUrl === jsonPath);
@@ -2054,6 +2124,14 @@ function createContentArtifactsPlugin() {
2054
2124
  fileName: "llms.txt",
2055
2125
  source: createLlmsTxtArtifact(ctx.routes, ctx.projectConfig)
2056
2126
  });
2127
+ const rootOpenAPISpec = createRootOpenAPISpec(ctx.routes, ctx.projectConfig);
2128
+ assets.push({
2129
+ fileName: "openapi.json",
2130
+ source: JSON.stringify(rootOpenAPISpec, null, 2)
2131
+ }, {
2132
+ fileName: "openapi.yml",
2133
+ source: stringify(rootOpenAPISpec, { lineWidth: 0 })
2134
+ });
2057
2135
  return assets;
2058
2136
  }
2059
2137
  }
@@ -2281,7 +2359,7 @@ function routeSearchContent(route) {
2281
2359
  * Convert a `ContentRoute` into the document shape stored in the Orama index.
2282
2360
  */
2283
2361
  function routeToSearchDocument(route, defaultLocale) {
2284
- if (route.isBareAlias) return null;
2362
+ if (route.isBareAlias || route.searchable === false) return null;
2285
2363
  const content = routeSearchContent(route);
2286
2364
  if (!content.trim()) return null;
2287
2365
  return {
@@ -2344,7 +2422,7 @@ function collectIndexedLocales(routes, defaultLocale) {
2344
2422
  const seen = /* @__PURE__ */ new Set();
2345
2423
  const locales = [];
2346
2424
  for (const route of routes) {
2347
- if (route.isBareAlias) continue;
2425
+ if (route.isBareAlias || route.searchable === false) continue;
2348
2426
  const code = route.locale ?? defaultLocale ?? "en";
2349
2427
  if (!seen.has(code)) {
2350
2428
  seen.add(code);
@@ -2974,7 +3052,7 @@ async function generateDevSearchIndex(ctx, root, pagefind) {
2974
3052
  try {
2975
3053
  let pageCount = 0;
2976
3054
  for (const route of ctx.routes) {
2977
- if (route.isBareAlias) continue;
3055
+ if (route.isBareAlias || route.searchable === false) continue;
2978
3056
  const content = routeSearchContent(route);
2979
3057
  if (!content.trim()) continue;
2980
3058
  const result = await index.addCustomRecord({
@@ -3434,6 +3512,38 @@ function handleRouteConflicts(routes, development) {
3434
3512
  assertNoRouteConflicts(routes);
3435
3513
  return routes;
3436
3514
  }
3515
+ function unsearchablePaths(navigation) {
3516
+ const paths = /* @__PURE__ */ new Set();
3517
+ const visit = (nodes, inherited = true) => {
3518
+ for (const node of nodes) {
3519
+ const searchable = inherited && node.searchable !== false;
3520
+ if (!searchable) paths.add(node.path);
3521
+ visit(node.children ?? [], searchable);
3522
+ }
3523
+ };
3524
+ switch (navigation.kind) {
3525
+ case "flat":
3526
+ visit(navigation.nodes);
3527
+ break;
3528
+ case "tabbed":
3529
+ navigation.tabs.forEach((tab) => visit(tab.children));
3530
+ break;
3531
+ case "localized":
3532
+ Object.values(navigation.locales).forEach((nodes) => visit(nodes));
3533
+ break;
3534
+ case "localized-tabbed":
3535
+ Object.values(navigation.locales).forEach((locale) => locale.tabs.forEach((tab) => visit(tab.children)));
3536
+ break;
3537
+ }
3538
+ return paths;
3539
+ }
3540
+ function applySearchability(routes, navigation) {
3541
+ const excludedPaths = unsearchablePaths(navigation);
3542
+ return routes.map((route) => excludedPaths.has(route.path) ? {
3543
+ ...route,
3544
+ searchable: false
3545
+ } : route);
3546
+ }
3437
3547
  async function resolveRouteState(routes, plugins, ctx, development) {
3438
3548
  const tabs = ctx.projectConfig.navigation?.tabs;
3439
3549
  const configuredRoutes = applyConfiguredPageRoutePaths(routes, tabs, ctx.projectConfig.locales);
@@ -3441,10 +3551,11 @@ async function resolveRouteState(routes, plugins, ctx, development) {
3441
3551
  routes: configuredRoutes,
3442
3552
  navigation: buildNavigationTree(configuredRoutes, ctx)
3443
3553
  }, ctx);
3444
- const finalRoutes = handleRouteConflicts(resolved.routes, development);
3554
+ const conflictRoutes = handleRouteConflicts(resolved.routes, development);
3555
+ const finalNavigation = conflictRoutes === resolved.routes ? resolved.navigation : buildNavigationTree(conflictRoutes, ctx);
3445
3556
  return {
3446
- routes: finalRoutes,
3447
- navigation: finalRoutes === resolved.routes ? resolved.navigation : buildNavigationTree(finalRoutes, ctx)
3557
+ routes: applySearchability(conflictRoutes, finalNavigation),
3558
+ navigation: finalNavigation
3448
3559
  };
3449
3560
  }
3450
3561
  //#endregion
@@ -3556,7 +3667,7 @@ function injectSSRIntoTemplate(template, appHtml, contextOrConfig, route) {
3556
3667
  html = setNamedMeta(html, "description", route?.meta.description ?? projectConfig.description);
3557
3668
  html = setNamedMeta(html, "keywords", route?.meta.keywords?.join(", "));
3558
3669
  html = injectCanonicalUrl(html, contextOrConfig, route);
3559
- const dataPagefindIgnore = route?.isBareAlias ? " data-pagefind-ignore" : "";
3670
+ const dataPagefindIgnore = route?.isBareAlias || route?.searchable === false ? " data-pagefind-ignore" : "";
3560
3671
  html = html.replace(/<div id="root">([\s\S]*?)<\/div>/, `<div id="root"${dataPagefindIgnore}>${appHtml}</div>`);
3561
3672
  return html;
3562
3673
  }
@@ -4065,7 +4176,7 @@ var ClarifyEngine = class {
4065
4176
  assertNoContentDiagnostics(this.routes);
4066
4177
  const outputDir = this.runtime.outputDirectory ?? this.generateOptions.outputDirectory;
4067
4178
  if (!outputDir) throw new Error("[clarify] outputDirectory is required before SSG runs");
4068
- const ssrOutputDir = join(outputDir, ".ssr");
4179
+ const ssrOutputDir = createClarifyTempDir("ssr-output");
4069
4180
  let tempEntryPath;
4070
4181
  try {
4071
4182
  tempEntryPath = createTempEntryFile(SSR_ENTRY_CODE);
@@ -4081,6 +4192,7 @@ var ClarifyEngine = class {
4081
4192
  console.error("[clarify] SSG failed:", err);
4082
4193
  throw err;
4083
4194
  } finally {
4195
+ removeClarifyTempDir(ssrOutputDir);
4084
4196
  if (tempEntryPath) try {
4085
4197
  rmSync(tempEntryPath, { force: true });
4086
4198
  } catch {}
@@ -4121,6 +4233,6 @@ function createClarifyEngine(options = {}) {
4121
4233
  return new ClarifyEngine(options);
4122
4234
  }
4123
4235
  //#endregion
4124
- export { createClarifyTempDir as a, cliPackageVersion as c, defineConfig as d, findRouteConflicts as i, cliPackageVersionWithCaret as l, createClarifyEngine as n, deserializeSearchIndex as o, createClarifyRuntimeAliases as r, searchMcpIndex as s, ClarifyEngine as t, createViteAdapter as u };
4236
+ export { createClarifyTempDir as a, cliPackageVersion as c, createViteAdapter as d, defineConfig as f, findRouteConflicts as i, cliPackageVersionWithCaret as l, createClarifyEngine as n, deserializeSearchIndex as o, createClarifyRuntimeAliases as r, searchMcpIndex as s, ClarifyEngine as t, printCliVersion as u };
4125
4237
 
4126
- //# sourceMappingURL=engine-DJ8vzo23.js.map
4238
+ //# sourceMappingURL=engine-Cfo7Ncux.js.map