skilld 1.1.0 → 1.1.2
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/dist/_chunks/agent.mjs +13 -1
- package/dist/_chunks/agent.mjs.map +1 -1
- package/dist/_chunks/assemble.mjs +2 -0
- package/dist/_chunks/assemble.mjs.map +1 -1
- package/dist/_chunks/cache.mjs +2 -0
- package/dist/_chunks/cache.mjs.map +1 -1
- package/dist/_chunks/cache2.mjs +3 -1
- package/dist/_chunks/cache2.mjs.map +1 -1
- package/dist/_chunks/chunk.mjs +2 -0
- package/dist/_chunks/config.mjs +4 -0
- package/dist/_chunks/config.mjs.map +1 -1
- package/dist/_chunks/detect.mjs +30 -0
- package/dist/_chunks/detect.mjs.map +1 -1
- package/dist/_chunks/embedding-cache.mjs +6 -6
- package/dist/_chunks/embedding-cache.mjs.map +1 -1
- package/dist/_chunks/formatting.mjs +9 -1
- package/dist/_chunks/formatting.mjs.map +1 -1
- package/dist/_chunks/index2.d.mts.map +1 -1
- package/dist/_chunks/install.mjs +3 -1
- package/dist/_chunks/install.mjs.map +1 -1
- package/dist/_chunks/list.mjs +2 -0
- package/dist/_chunks/list.mjs.map +1 -1
- package/dist/_chunks/markdown.mjs +2 -0
- package/dist/_chunks/markdown.mjs.map +1 -1
- package/dist/_chunks/pool.mjs +2 -0
- package/dist/_chunks/pool.mjs.map +1 -1
- package/dist/_chunks/prompts.mjs +29 -7
- package/dist/_chunks/prompts.mjs.map +1 -1
- package/dist/_chunks/sanitize.mjs +3 -1
- package/dist/_chunks/sanitize.mjs.map +1 -1
- package/dist/_chunks/search-interactive.mjs +3 -1
- package/dist/_chunks/search-interactive.mjs.map +1 -1
- package/dist/_chunks/search.mjs +183 -8
- package/dist/_chunks/search.mjs.map +1 -0
- package/dist/_chunks/shared.mjs +4 -0
- package/dist/_chunks/shared.mjs.map +1 -1
- package/dist/_chunks/skills.mjs +4 -0
- package/dist/_chunks/skills.mjs.map +1 -1
- package/dist/_chunks/sources.mjs +88 -5
- package/dist/_chunks/sources.mjs.map +1 -1
- package/dist/_chunks/sync.mjs +23 -12
- package/dist/_chunks/sync.mjs.map +1 -1
- package/dist/_chunks/uninstall.mjs +3 -1
- package/dist/_chunks/uninstall.mjs.map +1 -1
- package/dist/_chunks/validate.mjs +2 -0
- package/dist/_chunks/validate.mjs.map +1 -1
- package/dist/_chunks/yaml.mjs +2 -0
- package/dist/_chunks/yaml.mjs.map +1 -1
- package/dist/agent/index.d.mts +6 -3
- package/dist/agent/index.d.mts.map +1 -1
- package/dist/cli.mjs +19 -9
- package/dist/cli.mjs.map +1 -1
- package/dist/retriv/index.mjs +5 -3
- package/dist/retriv/index.mjs.map +1 -1
- package/dist/retriv/worker.mjs +2 -0
- package/dist/retriv/worker.mjs.map +1 -1
- package/dist/types.d.mts +0 -1
- package/package.json +10 -10
- package/dist/_chunks/search2.mjs +0 -180
- package/dist/_chunks/search2.mjs.map +0 -1
- package/dist/_chunks/sync2.mjs +0 -15
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatting.mjs","names":["dirname","resolve","agents"],"sources":["../../src/core/config.ts","../../src/version.ts","../../src/cli-helpers.ts","../../src/core/formatting.ts"],"sourcesContent":["import type { OptimizeModel } from '../agent/index.ts'\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { yamlEscape, yamlParseKV, yamlUnescape } from './yaml.ts'\n\nexport interface FeaturesConfig {\n search: boolean\n issues: boolean\n discussions: boolean\n releases: boolean\n}\n\nexport const defaultFeatures: FeaturesConfig = {\n search: true,\n issues: true,\n discussions: true,\n releases: true,\n}\n\nexport interface SkilldConfig {\n model?: OptimizeModel\n agent?: string\n features?: FeaturesConfig\n projects?: string[]\n skipLlm?: boolean\n}\n\nconst CONFIG_DIR = join(homedir(), '.skilld')\nconst CONFIG_PATH = join(CONFIG_DIR, 'config.yaml')\n\nexport function hasConfig(): boolean {\n return existsSync(CONFIG_PATH)\n}\n\n/** Whether the first-run wizard has been completed (not just agent selection) */\nexport function hasCompletedWizard(): boolean {\n if (!existsSync(CONFIG_PATH))\n return false\n const config = readConfig()\n return config.features !== undefined || config.model !== undefined || config.skipLlm !== undefined\n}\n\nexport function readConfig(): SkilldConfig {\n if (!existsSync(CONFIG_PATH))\n return {}\n\n const content = readFileSync(CONFIG_PATH, 'utf-8')\n const config: SkilldConfig = {}\n let inBlock: 'projects' | 'features' | null = null\n const projects: string[] = []\n const features: Partial<FeaturesConfig> = {}\n\n for (const line of content.split('\\n')) {\n if (line.startsWith('projects:')) {\n inBlock = 'projects'\n continue\n }\n if (line.startsWith('features:')) {\n inBlock = 'features'\n continue\n }\n if (inBlock === 'projects') {\n if (line.startsWith(' - ')) {\n projects.push(yamlUnescape(line.slice(4)))\n continue\n }\n inBlock = null\n }\n if (inBlock === 'features') {\n const m = line.match(/^ {2}(\\w+):\\s*(.+)/)\n if (m) {\n const key = m[1] as keyof FeaturesConfig\n if (key in defaultFeatures)\n features[key] = m[2] === 'true'\n continue\n }\n inBlock = null\n }\n const kv = yamlParseKV(line)\n if (!kv)\n continue\n const [key, value] = kv\n if (key === 'model' && value)\n config.model = value as OptimizeModel\n if (key === 'agent' && value)\n config.agent = value\n if (key === 'skipLlm')\n config.skipLlm = value === 'true'\n }\n\n if (projects.length > 0)\n config.projects = projects\n if (Object.keys(features).length > 0)\n config.features = { ...defaultFeatures, ...features }\n return config\n}\n\nexport function writeConfig(config: SkilldConfig): void {\n mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 })\n\n let yaml = ''\n if (config.model)\n yaml += `model: ${config.model}\\n`\n if (config.agent)\n yaml += `agent: ${config.agent}\\n`\n if (config.skipLlm)\n yaml += `skipLlm: true\\n`\n if (config.features) {\n yaml += 'features:\\n'\n for (const [k, v] of Object.entries(config.features)) {\n yaml += ` ${k}: ${v}\\n`\n }\n }\n if (config.projects?.length) {\n yaml += 'projects:\\n'\n for (const p of config.projects) {\n yaml += ` - ${yamlEscape(p)}\\n`\n }\n }\n\n writeFileSync(CONFIG_PATH, yaml, { mode: 0o600 })\n}\n\nexport function updateConfig(updates: Partial<SkilldConfig>): void {\n const config = readConfig()\n writeConfig({ ...config, ...updates })\n}\n\nexport function registerProject(projectPath: string): void {\n const config = readConfig()\n const projects = new Set(config.projects || [])\n projects.add(projectPath)\n writeConfig({ ...config, projects: [...projects] })\n}\n\nexport function unregisterProject(projectPath: string): void {\n const config = readConfig()\n const projects = (config.projects || []).filter(p => p !== projectPath)\n writeConfig({ ...config, projects })\n}\n\nexport function getRegisteredProjects(): string[] {\n return readConfig().projects || []\n}\n","import { readFileSync } from 'node:fs'\nimport { dirname, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\n// Walk up from current file to find package.json (works in both src/ and dist/_chunks/)\nfunction findPackageJson(): string {\n let dir = dirname(fileURLToPath(import.meta.url))\n for (let i = 0; i < 5; i++) {\n const candidate = resolve(dir, 'package.json')\n try {\n const content = readFileSync(candidate, 'utf8')\n if (content)\n return content\n }\n catch {}\n dir = resolve(dir, '..')\n }\n return '{\"version\":\"0.0.0\"}'\n}\n\nexport const version: string = JSON.parse(findPackageJson()).version\n","/**\n * Shared CLI helpers used by subcommand definitions and the main CLI entry.\n * Extracted to avoid circular deps between cli.ts and commands/*.ts.\n */\n\nimport type { AgentType, OptimizeModel } from './agent/index.ts'\nimport type { ProjectState } from './core/skills.ts'\nimport { existsSync, readFileSync } from 'node:fs'\nimport * as p from '@clack/prompts'\nimport { join } from 'pathe'\nimport { detectCurrentAgent } from 'unagent/env'\nimport { agents, detectInstalledAgents, detectTargetAgent, getAgentVersion, getModelName } from './agent/index.ts'\nimport { readConfig, updateConfig } from './core/config.ts'\nimport { version } from './version.ts'\n\nexport type { AgentType, OptimizeModel }\n\nexport interface IntroOptions {\n state: ProjectState\n generators?: Array<{ name: string, version: string }>\n modelId?: string\n}\n\nexport const sharedArgs = {\n global: {\n type: 'boolean' as const,\n alias: 'g',\n description: 'Install globally to ~/.skilld/skills',\n default: false,\n },\n agent: {\n type: 'enum' as const,\n options: Object.keys(agents),\n alias: 'a',\n description: 'Agent where skills are installed',\n },\n model: {\n type: 'string' as const,\n alias: 'm',\n description: 'LLM model for skill generation',\n valueHint: 'id',\n },\n yes: {\n type: 'boolean' as const,\n alias: 'y',\n description: 'Skip prompts, use defaults',\n default: false,\n },\n force: {\n type: 'boolean' as const,\n alias: 'f',\n description: 'Ignore all caches, re-fetch docs and regenerate',\n default: false,\n },\n debug: {\n type: 'boolean' as const,\n description: 'Save raw LLM output to logs/ for each section',\n default: false,\n },\n}\n\n/** Check if the current environment supports interactive prompts */\nexport function isInteractive(): boolean {\n if (detectCurrentAgent())\n return false\n if (process.env.CI)\n return false\n if (!process.stdout.isTTY)\n return false\n return true\n}\n\n/** Exit with error if interactive terminal is required but unavailable */\nexport function requireInteractive(command: string): void {\n if (!isInteractive()) {\n console.error(`Error: \\`skilld ${command}\\` requires an interactive terminal`)\n process.exit(1)\n }\n}\n\n/** Resolve agent from flags/cwd/config. cwd is source of truth over config. */\nexport function resolveAgent(agentFlag?: string): AgentType | 'none' | null {\n if (process.env.SKILLD_NO_AGENT)\n return null\n return (agentFlag as AgentType | undefined)\n ?? detectTargetAgent()\n ?? (readConfig().agent as AgentType | undefined)\n ?? null\n}\n\nlet _warnedNoAgent = false\nfunction warnNoAgent(): void {\n if (_warnedNoAgent)\n return\n _warnedNoAgent = true\n p.log.warn('No coding agent detected — falling back to prompt-only mode.\\n Use --agent <name> to specify, or run `skilld config` to set a default.')\n}\n\n/** Prompt user to pick an agent when auto-detection fails */\nexport async function promptForAgent(): Promise<AgentType | 'none' | null> {\n const noAgent = !!process.env.SKILLD_NO_AGENT\n const installed = noAgent ? [] : detectInstalledAgents()\n\n // Non-interactive: auto-select sole installed agent or fall back to prompt-only\n if (!isInteractive()) {\n if (installed.length === 1) {\n updateConfig({ agent: installed[0] })\n return installed[0]!\n }\n warnNoAgent()\n return 'none'\n }\n\n const options: Array<{ label: string, value: AgentType | 'none', hint?: string }> = (installed.length ? installed : Object.keys(agents) as AgentType[])\n .map(id => ({ label: agents[id].displayName, value: id as AgentType, hint: agents[id].skillsDir }))\n options.push({ label: 'No agent', value: 'none', hint: 'Export portable prompts for any LLM' })\n\n if (!_warnedNoAgent) {\n _warnedNoAgent = true\n const hint = installed.length\n ? `Detected ${installed.map(t => agents[t].displayName).join(', ')} but couldn't determine which to use`\n : 'No agents auto-detected'\n p.log.warn(`Could not detect which coding agent to install skills for.\\n ${hint}`)\n }\n\n const choice = await p.select({\n message: 'Which coding agent should skills be installed for?',\n options,\n })\n\n if (p.isCancel(choice))\n return null\n\n if (choice === 'none')\n return 'none'\n\n // Save as default so they don't get asked again\n updateConfig({ agent: choice })\n p.log.success(`Default agent set to ${agents[choice].displayName}`)\n return choice\n}\n\n/** Get installed LLM generators with working CLIs (verified via --version) */\nexport function getInstalledGenerators(): Array<{ name: string, version: string }> {\n const installed = detectInstalledAgents()\n return installed\n .filter(id => agents[id].cli)\n .map((id) => {\n const ver = getAgentVersion(id)\n return ver ? { name: agents[id].displayName, version: ver } : null\n })\n .filter((a): a is { name: string, version: string } => a !== null)\n}\n\nexport function relativeTime(date: Date): string {\n const now = Date.now()\n const diff = now - date.getTime()\n const mins = Math.floor(diff / 60000)\n const hours = Math.floor(diff / 3600000)\n const days = Math.floor(diff / 86400000)\n if (mins < 1)\n return 'just now'\n if (mins < 60)\n return `${mins}m ago`\n if (hours < 24)\n return `${hours}h ago`\n return `${days}d ago`\n}\n\nexport function getLastSynced(state: ProjectState): string | null {\n let latest: Date | null = null\n for (const skill of state.skills) {\n if (skill.info?.syncedAt) {\n const d = new Date(skill.info.syncedAt)\n if (!latest || d > latest)\n latest = d\n }\n }\n return latest ? relativeTime(latest) : null\n}\n\nexport function introLine({ state, generators, modelId }: IntroOptions): string {\n const name = '\\x1B[1m\\x1B[35mskilld\\x1B[0m'\n const ver = `\\x1B[90mv${version}\\x1B[0m`\n const lastSynced = getLastSynced(state)\n const synced = lastSynced ? ` · \\x1B[90msynced ${lastSynced}\\x1B[0m` : ''\n const modelStr = modelId ? ` · ${getModelName(modelId as any)}` : ''\n const genStr = generators?.length\n ? generators.map(g => `${g.name} v${g.version}`).join(', ')\n : ''\n const genLine = genStr ? `\\n\\x1B[90m↳ ${genStr}${modelStr}\\x1B[0m` : ''\n return `${name} ${ver}${synced}${genLine}`\n}\n\nexport function formatStatus(synced: number, outdated: number): string {\n const parts: string[] = []\n if (synced > 0)\n parts.push(`\\x1B[32m${synced} synced\\x1B[0m`)\n if (outdated > 0)\n parts.push(`\\x1B[33m${outdated} outdated\\x1B[0m`)\n return `Skills: ${parts.join(' · ')}`\n}\n\nexport function getRepoHint(name: string, cwd: string): string | undefined {\n const pkgJsonPath = join(cwd, 'node_modules', name, 'package.json')\n if (!existsSync(pkgJsonPath))\n return undefined\n const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'))\n const url = typeof pkg.repository === 'string'\n ? pkg.repository\n : pkg.repository?.url\n if (!url)\n return undefined\n return url\n .replace(/^git\\+/, '')\n .replace(/\\.git$/, '')\n .replace(/^git:\\/\\//, 'https://')\n .replace(/^ssh:\\/\\/git@github\\.com/, 'https://github.com')\n .replace(/^https?:\\/\\/(www\\.)?github\\.com\\//, '')\n}\n","import type { SearchSnippet } from '../retriv/index.ts'\nimport type { ProjectState } from './skills.ts'\nimport * as p from '@clack/prompts'\n\nexport function timeAgo(iso?: string): string {\n if (!iso)\n return ''\n const diff = Date.now() - new Date(iso).getTime()\n const days = Math.floor(diff / 86400000)\n if (days <= 0)\n return 'today'\n if (days === 1)\n return '1d ago'\n if (days < 7)\n return `${days}d ago`\n if (days < 30)\n return `${Math.floor(days / 7)}w ago`\n return `${Math.floor(days / 30)}mo ago`\n}\n\nexport function formatSource(source?: string): string {\n if (!source)\n return ''\n if (source === 'shipped')\n return 'shipped'\n if (source.includes('llms.txt'))\n return 'llms.txt'\n if (source.includes('github.com'))\n return source.replace(/https?:\\/\\/github\\.com\\//, '')\n return source\n}\n\nexport function formatDuration(ms: number): string {\n if (ms < 1000)\n return `${Math.round(ms)}ms`\n return `${(ms / 1000).toFixed(1)}s`\n}\n\n/** Spinner wrapper that shows elapsed time via built-in timer indicator */\nexport function timedSpinner() {\n const spin = p.spinner({ indicator: 'timer' })\n return {\n start(msg: string) {\n spin.start(msg)\n },\n message(msg: string) {\n spin.message(msg)\n },\n stop(msg: string) {\n spin.stop(msg)\n },\n }\n}\n\nexport function formatSkillStatus(state: ProjectState): void {\n const { missing, outdated, synced } = state\n\n if (synced.length > 0)\n p.log.success(`${synced.length} synced`)\n if (outdated.length > 0)\n p.log.warn(`${outdated.length} outdated: ${outdated.map(s => s.name).join(', ')}`)\n if (missing.length > 0)\n p.log.info(`${missing.length} missing: ${missing.slice(0, 5).join(', ')}${missing.length > 5 ? '...' : ''}`)\n}\n\nexport function highlightTerms(content: string, terms: string[]): string {\n if (terms.length === 0)\n return content\n // Sort by length desc to match longer terms first\n const sorted = [...terms].sort((a, b) => b.length - a.length)\n const pattern = new RegExp(`(${sorted.map(t => t.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')).join('|')})`, 'gi')\n return content.replace(pattern, '\\x1B[33m$1\\x1B[0m')\n}\n\n/** Format a normalized score (0-100) with color */\nexport function scoreLabel(pct: number): string {\n const color = pct >= 70 ? '\\x1B[32m' : pct >= 40 ? '\\x1B[33m' : '\\x1B[90m'\n return `${color}${pct}%\\x1B[0m`\n}\n\n/** Normalize raw cosine similarity scores to 0-100 relative to the best match */\nexport function normalizeScores(results: SearchSnippet[]): Map<SearchSnippet, number> {\n const map = new Map<SearchSnippet, number>()\n const max = results.reduce((m, r) => Math.max(m, r.score), 0)\n for (const r of results)\n map.set(r, max > 0 ? Math.round((r.score / max) * 100) : 0)\n return map\n}\n\nexport function formatSnippet(r: SearchSnippet, versions?: Map<string, string>, pct?: number): string {\n const refPath = `.claude/skills/${r.package}/.skilld/${r.source}`\n const lineRange = r.lineStart === r.lineEnd ? `L${r.lineStart}` : `L${r.lineStart}-${r.lineEnd}`\n const score = pct != null ? scoreLabel(pct) : `\\x1B[90m${r.score.toFixed(2)}\\x1B[0m`\n const version = versions?.get(r.package)\n const pkgLabel = version ? `${r.package}@${version}` : r.package\n\n const scopeStr = r.scope?.length ? `${r.scope.map(e => e.name).join('.')} → ` : ''\n const entityStr = r.entities?.map(e => e.signature || `${e.type} ${e.name}`).join(', ')\n const highlighted = highlightTerms(r.content, r.highlights)\n\n return [\n `${pkgLabel} ${score}${entityStr ? ` \\x1B[36m${scopeStr}${entityStr}\\x1B[0m` : ''}`,\n `\\x1B[90m${refPath}:${lineRange}\\x1B[0m`,\n ` ${highlighted.replace(/\\n/g, '\\n ')}`,\n ].join('\\n')\n}\n\n/** Compact 2-line format for interactive search list */\nexport function formatCompactSnippet(r: SearchSnippet, cols: number): { title: string, path: string, preview: string } {\n const entityStr = r.entities?.length\n ? r.entities.map(e => e.signature || e.name).join(', ')\n : ''\n const scopeStr = r.scope?.length ? `${r.scope.map(e => e.name).join('.')} → ` : ''\n const title = entityStr ? `${scopeStr}${entityStr}` : r.source.split('/').pop() || r.source\n\n const refPath = `.claude/skills/${r.package}/.skilld/${r.source}`\n const lineRange = r.lineStart === r.lineEnd ? `L${r.lineStart}` : `L${r.lineStart}-${r.lineEnd}`\n const path = `${refPath}:${lineRange}`\n\n // First meaningful line as preview (skip empty, frontmatter delimiters, headings-only)\n const maxPreview = cols - 6\n const firstLine = r.content.split('\\n').find(l => l.trim() && l.trim() !== '---' && !/^#+\\s*$/.test(l.trim())) || ''\n const preview = firstLine.length > maxPreview ? `${firstLine.slice(0, maxPreview - 1)}…` : firstLine\n\n return { title, path, preview }\n}\n"],"mappings":";;;;;;;;;;AAaA,MAAa,kBAAkC;CAC7C,QAAQ;CACR,QAAQ;CACR,aAAa;CACb,UAAU;CACX;AAUD,MAAM,aAAa,KAAK,SAAS,EAAE,UAAU;AAC7C,MAAM,cAAc,KAAK,YAAY,cAAc;AAEnD,SAAgB,YAAqB;AACnC,QAAO,WAAW,YAAY;;;AAIhC,SAAgB,qBAA8B;AAC5C,KAAI,CAAC,WAAW,YAAY,CAC1B,QAAO;CACT,MAAM,SAAS,YAAY;AAC3B,QAAO,OAAO,aAAa,KAAA,KAAa,OAAO,UAAU,KAAA,KAAa,OAAO,YAAY,KAAA;;AAG3F,SAAgB,aAA2B;AACzC,KAAI,CAAC,WAAW,YAAY,CAC1B,QAAO,EAAE;CAEX,MAAM,UAAU,aAAa,aAAa,QAAQ;CAClD,MAAM,SAAuB,EAAE;CAC/B,IAAI,UAA0C;CAC9C,MAAM,WAAqB,EAAE;CAC7B,MAAM,WAAoC,EAAE;AAE5C,MAAK,MAAM,QAAQ,QAAQ,MAAM,KAAK,EAAE;AACtC,MAAI,KAAK,WAAW,YAAY,EAAE;AAChC,aAAU;AACV;;AAEF,MAAI,KAAK,WAAW,YAAY,EAAE;AAChC,aAAU;AACV;;AAEF,MAAI,YAAY,YAAY;AAC1B,OAAI,KAAK,WAAW,OAAO,EAAE;AAC3B,aAAS,KAAK,aAAa,KAAK,MAAM,EAAE,CAAC,CAAC;AAC1C;;AAEF,aAAU;;AAEZ,MAAI,YAAY,YAAY;GAC1B,MAAM,IAAI,KAAK,MAAM,qBAAqB;AAC1C,OAAI,GAAG;IACL,MAAM,MAAM,EAAE;AACd,QAAI,OAAO,gBACT,UAAS,OAAO,EAAE,OAAO;AAC3B;;AAEF,aAAU;;EAEZ,MAAM,KAAK,YAAY,KAAK;AAC5B,MAAI,CAAC,GACH;EACF,MAAM,CAAC,KAAK,SAAS;AACrB,MAAI,QAAQ,WAAW,MACrB,QAAO,QAAQ;AACjB,MAAI,QAAQ,WAAW,MACrB,QAAO,QAAQ;AACjB,MAAI,QAAQ,UACV,QAAO,UAAU,UAAU;;AAG/B,KAAI,SAAS,SAAS,EACpB,QAAO,WAAW;AACpB,KAAI,OAAO,KAAK,SAAS,CAAC,SAAS,EACjC,QAAO,WAAW;EAAE,GAAG;EAAiB,GAAG;EAAU;AACvD,QAAO;;AAGT,SAAgB,YAAY,QAA4B;AACtD,WAAU,YAAY;EAAE,WAAW;EAAM,MAAM;EAAO,CAAC;CAEvD,IAAI,OAAO;AACX,KAAI,OAAO,MACT,SAAQ,UAAU,OAAO,MAAM;AACjC,KAAI,OAAO,MACT,SAAQ,UAAU,OAAO,MAAM;AACjC,KAAI,OAAO,QACT,SAAQ;AACV,KAAI,OAAO,UAAU;AACnB,UAAQ;AACR,OAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,OAAO,SAAS,CAClD,SAAQ,KAAK,EAAE,IAAI,EAAE;;AAGzB,KAAI,OAAO,UAAU,QAAQ;AAC3B,UAAQ;AACR,OAAK,MAAM,KAAK,OAAO,SACrB,SAAQ,OAAO,WAAW,EAAE,CAAC;;AAIjC,eAAc,aAAa,MAAM,EAAE,MAAM,KAAO,CAAC;;AAGnD,SAAgB,aAAa,SAAsC;AAEjE,aAAY;EAAE,GADC,YAAY;EACF,GAAG;EAAS,CAAC;;AAGxC,SAAgB,gBAAgB,aAA2B;CACzD,MAAM,SAAS,YAAY;CAC3B,MAAM,WAAW,IAAI,IAAI,OAAO,YAAY,EAAE,CAAC;AAC/C,UAAS,IAAI,YAAY;AACzB,aAAY;EAAE,GAAG;EAAQ,UAAU,CAAC,GAAG,SAAA;EAAW,CAAC;;AAGrD,SAAgB,kBAAkB,aAA2B;CAC3D,MAAM,SAAS,YAAY;CAC3B,MAAM,YAAY,OAAO,YAAY,EAAE,EAAE,QAAO,MAAK,MAAM,YAAY;AACvE,aAAY;EAAE,GAAG;EAAQ;EAAU,CAAC;;AAGtC,SAAgB,wBAAkC;AAChD,QAAO,YAAY,CAAC,YAAY,EAAE;;AC1IpC,SAAS,kBAA0B;CACjC,IAAI,MAAMA,UAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;AACjD,MAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;EAC1B,MAAM,YAAYC,UAAQ,KAAK,eAAe;AAC9C,MAAI;GACF,MAAM,UAAU,aAAa,WAAW,OAAO;AAC/C,OAAI,QACF,QAAO;UAEL;AACN,QAAMA,UAAQ,KAAK,KAAK;;AAE1B,QAAO;;AAGT,MAAa,UAAkB,KAAK,MAAM,iBAAiB,CAAC,CAAC;ACG7D,MAAa,aAAa;CACxB,QAAQ;EACN,MAAM;EACN,OAAO;EACP,aAAa;EACb,SAAS;EACV;CACD,OAAO;EACL,MAAM;EACN,SAAS,OAAO,KAAKC,QAAO;EAC5B,OAAO;EACP,aAAa;EACd;CACD,OAAO;EACL,MAAM;EACN,OAAO;EACP,aAAa;EACb,WAAW;EACZ;CACD,KAAK;EACH,MAAM;EACN,OAAO;EACP,aAAa;EACb,SAAS;EACV;CACD,OAAO;EACL,MAAM;EACN,OAAO;EACP,aAAa;EACb,SAAS;EACV;CACD,OAAO;EACL,MAAM;EACN,aAAa;EACb,SAAS;;CAEZ;;AAGD,SAAgB,gBAAyB;AACvC,KAAI,oBAAoB,CACtB,QAAO;AACT,KAAI,QAAQ,IAAI,GACd,QAAO;AACT,KAAI,CAAC,QAAQ,OAAO,MAClB,QAAO;AACT,QAAO;;;AAIT,SAAgB,mBAAmB,SAAuB;AACxD,KAAI,CAAC,eAAe,EAAE;AACpB,UAAQ,MAAM,mBAAmB,QAAQ,qCAAqC;AAC9E,UAAQ,KAAK,EAAE;;;;AAKnB,SAAgB,aAAa,WAA+C;AAC1E,KAAI,QAAQ,IAAI,gBACd,QAAO;AACT,QAAQ,aACH,mBAAmB,IAClB,YAAY,CAAC,SACd;;AAGP,IAAI,iBAAiB;AACrB,SAAS,cAAoB;AAC3B,KAAI,eACF;AACF,kBAAiB;AACjB,GAAE,IAAI,KAAK,0IAA0I;;;AAIvJ,eAAsB,iBAAqD;CAEzE,MAAM,YADU,CAAC,CAAC,QAAQ,IAAI,kBACF,EAAE,GAAG,uBAAuB;AAGxD,KAAI,CAAC,eAAe,EAAE;AACpB,MAAI,UAAU,WAAW,GAAG;AAC1B,gBAAa,EAAE,OAAO,UAAU,IAAI,CAAC;AACrC,UAAO,UAAU;;AAEnB,eAAa;AACb,SAAO;;CAGT,MAAM,WAA+E,UAAU,SAAS,YAAY,OAAO,KAAKA,QAAO,EACpI,KAAI,QAAO;EAAE,OAAOA,QAAO,IAAI;EAAa,OAAO;EAAiB,MAAMA,QAAO,IAAI;EAAW,EAAE;AACrG,SAAQ,KAAK;EAAE,OAAO;EAAY,OAAO;EAAQ,MAAM;EAAuC,CAAC;AAE/F,KAAI,CAAC,gBAAgB;AACnB,mBAAiB;EACjB,MAAM,OAAO,UAAU,SACnB,YAAY,UAAU,KAAI,MAAKA,QAAO,GAAG,YAAY,CAAC,KAAK,KAAK,CAAC,wCACjE;AACJ,IAAE,IAAI,KAAK,iEAAiE,OAAO;;CAGrF,MAAM,SAAS,MAAM,EAAE,OAAO;EAC5B,SAAS;EACT;EACD,CAAC;AAEF,KAAI,EAAE,SAAS,OAAO,CACpB,QAAO;AAET,KAAI,WAAW,OACb,QAAO;AAGT,cAAa,EAAE,OAAO,QAAQ,CAAC;AAC/B,GAAE,IAAI,QAAQ,wBAAwBA,QAAO,QAAQ,cAAc;AACnE,QAAO;;;AAIT,SAAgB,yBAAmE;AAEjF,QADkB,uBAAuB,CAEtC,QAAO,OAAMA,QAAO,IAAI,IAAI,CAC5B,KAAK,OAAO;EACX,MAAM,MAAM,gBAAgB,GAAG;AAC/B,SAAO,MAAM;GAAE,MAAMA,QAAO,IAAI;GAAa,SAAS;GAAK,GAAG;GAC9D,CACD,QAAQ,MAA8C,MAAM,KAAK;;AAGtE,SAAgB,aAAa,MAAoB;CAE/C,MAAM,OADM,KAAK,KAAK,GACH,KAAK,SAAS;CACjC,MAAM,OAAO,KAAK,MAAM,OAAO,IAAM;CACrC,MAAM,QAAQ,KAAK,MAAM,OAAO,KAAQ;CACxC,MAAM,OAAO,KAAK,MAAM,OAAO,MAAS;AACxC,KAAI,OAAO,EACT,QAAO;AACT,KAAI,OAAO,GACT,QAAO,GAAG,KAAK;AACjB,KAAI,QAAQ,GACV,QAAO,GAAG,MAAM;AAClB,QAAO,GAAG,KAAK;;AAGjB,SAAgB,cAAc,OAAoC;CAChE,IAAI,SAAsB;AAC1B,MAAK,MAAM,SAAS,MAAM,OACxB,KAAI,MAAM,MAAM,UAAU;EACxB,MAAM,IAAI,IAAI,KAAK,MAAM,KAAK,SAAS;AACvC,MAAI,CAAC,UAAU,IAAI,OACjB,UAAS;;AAGf,QAAO,SAAS,aAAa,OAAO,GAAG;;AAGzC,SAAgB,UAAU,EAAE,OAAO,YAAY,WAAiC;CAC9E,MAAM,OAAO;CACb,MAAM,MAAM,YAAY,QAAQ;CAChC,MAAM,aAAa,cAAc,MAAM;CACvC,MAAM,SAAS,aAAa,qBAAqB,WAAW,WAAW;CACvE,MAAM,WAAW,UAAU,MAAM,aAAa,QAAe,KAAK;CAClE,MAAM,SAAS,YAAY,SACvB,WAAW,KAAI,MAAK,GAAG,EAAE,KAAK,IAAI,EAAE,UAAU,CAAC,KAAK,KAAK,GACzD;AAEJ,QAAO,GAAG,KAAK,GAAG,MAAM,SADR,SAAS,eAAe,SAAS,SAAS,WAAW;;AAIvE,SAAgB,aAAa,QAAgB,UAA0B;CACrE,MAAM,QAAkB,EAAE;AAC1B,KAAI,SAAS,EACX,OAAM,KAAK,WAAW,OAAO,gBAAgB;AAC/C,KAAI,WAAW,EACb,OAAM,KAAK,WAAW,SAAS,kBAAkB;AACnD,QAAO,WAAW,MAAM,KAAK,MAAM;;AAGrC,SAAgB,YAAY,MAAc,KAAiC;CACzE,MAAM,cAAc,KAAK,KAAK,gBAAgB,MAAM,eAAe;AACnE,KAAI,CAAC,WAAW,YAAY,CAC1B,QAAO,KAAA;CACT,MAAM,MAAM,KAAK,MAAM,aAAa,aAAa,QAAQ,CAAC;CAC1D,MAAM,MAAM,OAAO,IAAI,eAAe,WAClC,IAAI,aACJ,IAAI,YAAY;AACpB,KAAI,CAAC,IACH,QAAO,KAAA;AACT,QAAO,IACJ,QAAQ,UAAU,GAAG,CACrB,QAAQ,UAAU,GAAG,CACrB,QAAQ,aAAa,WAAW,CAChC,QAAQ,4BAA4B,qBAAqB,CACzD,QAAQ,qCAAqC,GAAG;;ACtNrD,SAAgB,QAAQ,KAAsB;AAC5C,KAAI,CAAC,IACH,QAAO;CACT,MAAM,OAAO,KAAK,KAAK,GAAG,IAAI,KAAK,IAAI,CAAC,SAAS;CACjD,MAAM,OAAO,KAAK,MAAM,OAAO,MAAS;AACxC,KAAI,QAAQ,EACV,QAAO;AACT,KAAI,SAAS,EACX,QAAO;AACT,KAAI,OAAO,EACT,QAAO,GAAG,KAAK;AACjB,KAAI,OAAO,GACT,QAAO,GAAG,KAAK,MAAM,OAAO,EAAE,CAAC;AACjC,QAAO,GAAG,KAAK,MAAM,OAAO,GAAG,CAAC;;AAGlC,SAAgB,aAAa,QAAyB;AACpD,KAAI,CAAC,OACH,QAAO;AACT,KAAI,WAAW,UACb,QAAO;AACT,KAAI,OAAO,SAAS,WAAW,CAC7B,QAAO;AACT,KAAI,OAAO,SAAS,aAAa,CAC/B,QAAO,OAAO,QAAQ,4BAA4B,GAAG;AACvD,QAAO;;AAGT,SAAgB,eAAe,IAAoB;AACjD,KAAI,KAAK,IACP,QAAO,GAAG,KAAK,MAAM,GAAG,CAAC;AAC3B,QAAO,IAAI,KAAK,KAAM,QAAQ,EAAE,CAAC;;;AAInC,SAAgB,eAAe;CAC7B,MAAM,OAAO,EAAE,QAAQ,EAAE,WAAW,SAAS,CAAC;AAC9C,QAAO;EACL,MAAM,KAAa;AACjB,QAAK,MAAM,IAAI;;EAEjB,QAAQ,KAAa;AACnB,QAAK,QAAQ,IAAI;;EAEnB,KAAK,KAAa;AAChB,QAAK,KAAK,IAAI;;EAEjB;;AAcH,SAAgB,eAAe,SAAiB,OAAyB;AACvE,KAAI,MAAM,WAAW,EACnB,QAAO;CAET,MAAM,SAAS,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,SAAS,EAAE,OAAO;CAC7D,MAAM,UAAU,IAAI,OAAO,IAAI,OAAO,KAAI,MAAK,EAAE,QAAQ,uBAAuB,OAAO,CAAC,CAAC,KAAK,IAAI,CAAC,IAAI,KAAK;AAC5G,QAAO,QAAQ,QAAQ,SAAS,oBAAoB;;;AAItD,SAAgB,WAAW,KAAqB;AAE9C,QAAO,GADO,OAAO,KAAK,aAAa,OAAO,KAAK,aAAa,aAC9C,IAAI;;;AAIxB,SAAgB,gBAAgB,SAAsD;CACpF,MAAM,sBAAM,IAAI,KAA4B;CAC5C,MAAM,MAAM,QAAQ,QAAQ,GAAG,MAAM,KAAK,IAAI,GAAG,EAAE,MAAM,EAAE,EAAE;AAC7D,MAAK,MAAM,KAAK,QACd,KAAI,IAAI,GAAG,MAAM,IAAI,KAAK,MAAO,EAAE,QAAQ,MAAO,IAAI,GAAG,EAAE;AAC7D,QAAO;;AAGT,SAAgB,cAAc,GAAkB,UAAgC,KAAsB;CACpG,MAAM,UAAU,kBAAkB,EAAE,QAAQ,WAAW,EAAE;CACzD,MAAM,YAAY,EAAE,cAAc,EAAE,UAAU,IAAI,EAAE,cAAc,IAAI,EAAE,UAAU,GAAG,EAAE;CACvF,MAAM,QAAQ,OAAO,OAAO,WAAW,IAAI,GAAG,WAAW,EAAE,MAAM,QAAQ,EAAE,CAAC;CAC5E,MAAM,UAAU,UAAU,IAAI,EAAE,QAAQ;CACxC,MAAM,WAAW,UAAU,GAAG,EAAE,QAAQ,GAAG,YAAY,EAAE;CAEzD,MAAM,WAAW,EAAE,OAAO,SAAS,GAAG,EAAE,MAAM,KAAI,MAAK,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC,OAAO;CAChF,MAAM,YAAY,EAAE,UAAU,KAAI,MAAK,EAAE,aAAa,GAAG,EAAE,KAAK,GAAG,EAAE,OAAO,CAAC,KAAK,KAAK;CACvF,MAAM,cAAc,eAAe,EAAE,SAAS,EAAE,WAAW;AAE3D,QAAO;EACL,GAAG,SAAS,GAAG,QAAQ,YAAY,aAAa,WAAW,UAAU,WAAW;EAChF,WAAW,QAAQ,GAAG,UAAU;EAChC,KAAK,YAAY,QAAQ,OAAO,OAAO;EACxC,CAAC,KAAK,KAAK;;;AAId,SAAgB,qBAAqB,GAAkB,MAAgE;CACrH,MAAM,YAAY,EAAE,UAAU,SAC1B,EAAE,SAAS,KAAI,MAAK,EAAE,aAAa,EAAE,KAAK,CAAC,KAAK,KAAK,GACrD;CACJ,MAAM,WAAW,EAAE,OAAO,SAAS,GAAG,EAAE,MAAM,KAAI,MAAK,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC,OAAO;CAChF,MAAM,QAAQ,YAAY,GAAG,WAAW,cAAc,EAAE,OAAO,MAAM,IAAI,CAAC,KAAK,IAAI,EAAE;CAIrF,MAAM,OAAO,GAFG,kBAAkB,EAAE,QAAQ,WAAW,EAAE,SAEjC,GADN,EAAE,cAAc,EAAE,UAAU,IAAI,EAAE,cAAc,IAAI,EAAE,UAAU,GAAG,EAAE;CAIvF,MAAM,aAAa,OAAO;CAC1B,MAAM,YAAY,EAAE,QAAQ,MAAM,KAAK,CAAC,MAAK,MAAK,EAAE,MAAM,IAAI,EAAE,MAAM,KAAK,SAAS,CAAC,UAAU,KAAK,EAAE,MAAM,CAAC,CAAC,IAAI;AAGlH,QAAO;EAAE;EAAO;EAAM,SAFN,UAAU,SAAS,aAAa,GAAG,UAAU,MAAM,GAAG,aAAa,EAAE,CAAC,KAAK;EAE5D"}
|
|
1
|
+
{"version":3,"file":"formatting.mjs","names":["dirname","resolve","agents"],"sources":["../../src/core/config.ts","../../src/version.ts","../../src/cli-helpers.ts","../../src/core/formatting.ts"],"sourcesContent":["import type { OptimizeModel } from '../agent/index.ts'\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { yamlEscape, yamlParseKV, yamlUnescape } from './yaml.ts'\n\nexport interface FeaturesConfig {\n search: boolean\n issues: boolean\n discussions: boolean\n releases: boolean\n}\n\nexport const defaultFeatures: FeaturesConfig = {\n search: true,\n issues: true,\n discussions: true,\n releases: true,\n}\n\nexport interface SkilldConfig {\n model?: OptimizeModel\n agent?: string\n features?: FeaturesConfig\n projects?: string[]\n skipLlm?: boolean\n}\n\nconst CONFIG_DIR = join(homedir(), '.skilld')\nconst CONFIG_PATH = join(CONFIG_DIR, 'config.yaml')\n\nexport function hasConfig(): boolean {\n return existsSync(CONFIG_PATH)\n}\n\n/** Whether the first-run wizard has been completed (not just agent selection) */\nexport function hasCompletedWizard(): boolean {\n if (!existsSync(CONFIG_PATH))\n return false\n const config = readConfig()\n return config.features !== undefined || config.model !== undefined || config.skipLlm !== undefined\n}\n\nexport function readConfig(): SkilldConfig {\n if (!existsSync(CONFIG_PATH))\n return {}\n\n const content = readFileSync(CONFIG_PATH, 'utf-8')\n const config: SkilldConfig = {}\n let inBlock: 'projects' | 'features' | null = null\n const projects: string[] = []\n const features: Partial<FeaturesConfig> = {}\n\n for (const line of content.split('\\n')) {\n if (line.startsWith('projects:')) {\n inBlock = 'projects'\n continue\n }\n if (line.startsWith('features:')) {\n inBlock = 'features'\n continue\n }\n if (inBlock === 'projects') {\n if (line.startsWith(' - ')) {\n projects.push(yamlUnescape(line.slice(4)))\n continue\n }\n inBlock = null\n }\n if (inBlock === 'features') {\n const m = line.match(/^ {2}(\\w+):\\s*(.+)/)\n if (m) {\n const key = m[1] as keyof FeaturesConfig\n if (key in defaultFeatures)\n features[key] = m[2] === 'true'\n continue\n }\n inBlock = null\n }\n const kv = yamlParseKV(line)\n if (!kv)\n continue\n const [key, value] = kv\n if (key === 'model' && value)\n config.model = value as OptimizeModel\n if (key === 'agent' && value)\n config.agent = value\n if (key === 'skipLlm')\n config.skipLlm = value === 'true'\n }\n\n if (projects.length > 0)\n config.projects = projects\n if (Object.keys(features).length > 0)\n config.features = { ...defaultFeatures, ...features }\n return config\n}\n\nexport function writeConfig(config: SkilldConfig): void {\n mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 })\n\n let yaml = ''\n if (config.model)\n yaml += `model: ${config.model}\\n`\n if (config.agent)\n yaml += `agent: ${config.agent}\\n`\n if (config.skipLlm)\n yaml += `skipLlm: true\\n`\n if (config.features) {\n yaml += 'features:\\n'\n for (const [k, v] of Object.entries(config.features)) {\n yaml += ` ${k}: ${v}\\n`\n }\n }\n if (config.projects?.length) {\n yaml += 'projects:\\n'\n for (const p of config.projects) {\n yaml += ` - ${yamlEscape(p)}\\n`\n }\n }\n\n writeFileSync(CONFIG_PATH, yaml, { mode: 0o600 })\n}\n\nexport function updateConfig(updates: Partial<SkilldConfig>): void {\n const config = readConfig()\n writeConfig({ ...config, ...updates })\n}\n\nexport function registerProject(projectPath: string): void {\n const config = readConfig()\n const projects = new Set(config.projects || [])\n projects.add(projectPath)\n writeConfig({ ...config, projects: [...projects] })\n}\n\nexport function unregisterProject(projectPath: string): void {\n const config = readConfig()\n const projects = (config.projects || []).filter(p => p !== projectPath)\n writeConfig({ ...config, projects })\n}\n\nexport function getRegisteredProjects(): string[] {\n return readConfig().projects || []\n}\n","import { readFileSync } from 'node:fs'\nimport { dirname, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\n// Walk up from current file to find package.json (works in both src/ and dist/_chunks/)\nfunction findPackageJson(): string {\n let dir = dirname(fileURLToPath(import.meta.url))\n for (let i = 0; i < 5; i++) {\n const candidate = resolve(dir, 'package.json')\n try {\n const content = readFileSync(candidate, 'utf8')\n if (content)\n return content\n }\n catch {}\n dir = resolve(dir, '..')\n }\n return '{\"version\":\"0.0.0\"}'\n}\n\nexport const version: string = JSON.parse(findPackageJson()).version\n","/**\n * Shared CLI helpers used by subcommand definitions and the main CLI entry.\n * Extracted to avoid circular deps between cli.ts and commands/*.ts.\n */\n\nimport type { AgentType, OptimizeModel } from './agent/index.ts'\nimport type { ProjectState } from './core/skills.ts'\nimport { existsSync, readFileSync } from 'node:fs'\nimport * as p from '@clack/prompts'\nimport { join } from 'pathe'\nimport { detectCurrentAgent } from 'unagent/env'\nimport { agents, detectInstalledAgents, detectTargetAgent, getAgentVersion, getModelName } from './agent/index.ts'\nimport { readConfig, updateConfig } from './core/config.ts'\nimport { version } from './version.ts'\n\nexport type { AgentType, OptimizeModel }\n\nexport interface IntroOptions {\n state: ProjectState\n generators?: Array<{ name: string, version: string }>\n modelId?: string\n}\n\nexport const sharedArgs = {\n global: {\n type: 'boolean' as const,\n alias: 'g',\n description: 'Install globally to ~/.skilld/skills',\n default: false,\n },\n agent: {\n type: 'enum' as const,\n options: Object.keys(agents),\n alias: 'a',\n description: 'Agent where skills are installed',\n },\n model: {\n type: 'string' as const,\n alias: 'm',\n description: 'LLM model for skill generation',\n valueHint: 'id',\n },\n yes: {\n type: 'boolean' as const,\n alias: 'y',\n description: 'Skip prompts, use defaults',\n default: false,\n },\n force: {\n type: 'boolean' as const,\n alias: 'f',\n description: 'Ignore all caches, re-fetch docs and regenerate',\n default: false,\n },\n debug: {\n type: 'boolean' as const,\n description: 'Save raw LLM output to logs/ for each section',\n default: false,\n },\n}\n\n/** Check if the current environment supports interactive prompts */\nexport function isInteractive(): boolean {\n if (detectCurrentAgent())\n return false\n if (process.env.CI)\n return false\n if (!process.stdout.isTTY)\n return false\n return true\n}\n\n/** Exit with error if interactive terminal is required but unavailable */\nexport function requireInteractive(command: string): void {\n if (!isInteractive()) {\n console.error(`Error: \\`skilld ${command}\\` requires an interactive terminal`)\n process.exit(1)\n }\n}\n\n/** Resolve agent from flags/cwd/config. cwd is source of truth over config. */\nexport function resolveAgent(agentFlag?: string): AgentType | 'none' | null {\n if (process.env.SKILLD_NO_AGENT)\n return null\n return (agentFlag as AgentType | undefined)\n ?? detectTargetAgent()\n ?? (readConfig().agent as AgentType | undefined)\n ?? null\n}\n\nlet _warnedNoAgent = false\nfunction warnNoAgent(): void {\n if (_warnedNoAgent)\n return\n _warnedNoAgent = true\n p.log.warn('No coding agent detected — falling back to prompt-only mode.\\n Use --agent <name> to specify, or run `skilld config` to set a default.')\n}\n\n/** Prompt user to pick an agent when auto-detection fails */\nexport async function promptForAgent(): Promise<AgentType | 'none' | null> {\n const noAgent = !!process.env.SKILLD_NO_AGENT\n const installed = noAgent ? [] : detectInstalledAgents()\n\n // Non-interactive: auto-select sole installed agent or fall back to prompt-only\n if (!isInteractive()) {\n if (installed.length === 1) {\n updateConfig({ agent: installed[0] })\n return installed[0]!\n }\n warnNoAgent()\n return 'none'\n }\n\n const options: Array<{ label: string, value: AgentType | 'none', hint?: string }> = (installed.length ? installed : Object.keys(agents) as AgentType[])\n .map(id => ({ label: agents[id].displayName, value: id as AgentType, hint: agents[id].skillsDir }))\n options.push({ label: 'No agent', value: 'none', hint: 'Export portable prompts for any LLM' })\n\n if (!_warnedNoAgent) {\n _warnedNoAgent = true\n const hint = installed.length\n ? `Detected ${installed.map(t => agents[t].displayName).join(', ')} but couldn't determine which to use`\n : 'No agents auto-detected'\n p.log.warn(`Could not detect which coding agent to install skills for.\\n ${hint}`)\n }\n\n const choice = await p.select({\n message: 'Which coding agent should skills be installed for?',\n options,\n })\n\n if (p.isCancel(choice))\n return null\n\n if (choice === 'none')\n return 'none'\n\n // Save as default so they don't get asked again\n updateConfig({ agent: choice })\n p.log.success(`Default agent set to ${agents[choice].displayName}`)\n return choice\n}\n\n/** Get installed LLM generators with working CLIs (verified via --version) */\nexport function getInstalledGenerators(): Array<{ name: string, version: string }> {\n const installed = detectInstalledAgents()\n return installed\n .filter(id => agents[id].cli)\n .map((id) => {\n const ver = getAgentVersion(id)\n return ver ? { name: agents[id].displayName, version: ver } : null\n })\n .filter((a): a is { name: string, version: string } => a !== null)\n}\n\nexport function relativeTime(date: Date): string {\n const now = Date.now()\n const diff = now - date.getTime()\n const mins = Math.floor(diff / 60000)\n const hours = Math.floor(diff / 3600000)\n const days = Math.floor(diff / 86400000)\n if (mins < 1)\n return 'just now'\n if (mins < 60)\n return `${mins}m ago`\n if (hours < 24)\n return `${hours}h ago`\n return `${days}d ago`\n}\n\nexport function getLastSynced(state: ProjectState): string | null {\n let latest: Date | null = null\n for (const skill of state.skills) {\n if (skill.info?.syncedAt) {\n const d = new Date(skill.info.syncedAt)\n if (!latest || d > latest)\n latest = d\n }\n }\n return latest ? relativeTime(latest) : null\n}\n\nexport function introLine({ state, generators, modelId }: IntroOptions): string {\n const name = '\\x1B[1m\\x1B[35mskilld\\x1B[0m'\n const ver = `\\x1B[90mv${version}\\x1B[0m`\n const lastSynced = getLastSynced(state)\n const synced = lastSynced ? ` · \\x1B[90msynced ${lastSynced}\\x1B[0m` : ''\n const modelStr = modelId ? ` · ${getModelName(modelId as any)}` : ''\n const genStr = generators?.length\n ? generators.map(g => `${g.name} v${g.version}`).join(', ')\n : ''\n const genLine = genStr ? `\\n\\x1B[90m↳ ${genStr}${modelStr}\\x1B[0m` : ''\n return `${name} ${ver}${synced}${genLine}`\n}\n\nexport function formatStatus(synced: number, outdated: number): string {\n const parts: string[] = []\n if (synced > 0)\n parts.push(`\\x1B[32m${synced} synced\\x1B[0m`)\n if (outdated > 0)\n parts.push(`\\x1B[33m${outdated} outdated\\x1B[0m`)\n return `Skills: ${parts.join(' · ')}`\n}\n\nexport function getRepoHint(name: string, cwd: string): string | undefined {\n const pkgJsonPath = join(cwd, 'node_modules', name, 'package.json')\n if (!existsSync(pkgJsonPath))\n return undefined\n const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'))\n const url = typeof pkg.repository === 'string'\n ? pkg.repository\n : pkg.repository?.url\n if (!url)\n return undefined\n return url\n .replace(/^git\\+/, '')\n .replace(/\\.git$/, '')\n .replace(/^git:\\/\\//, 'https://')\n .replace(/^ssh:\\/\\/git@github\\.com/, 'https://github.com')\n .replace(/^https?:\\/\\/(www\\.)?github\\.com\\//, '')\n}\n","import type { SearchSnippet } from '../retriv/index.ts'\nimport type { ProjectState } from './skills.ts'\nimport * as p from '@clack/prompts'\n\nexport function timeAgo(iso?: string): string {\n if (!iso)\n return ''\n const diff = Date.now() - new Date(iso).getTime()\n const days = Math.floor(diff / 86400000)\n if (days <= 0)\n return 'today'\n if (days === 1)\n return '1d ago'\n if (days < 7)\n return `${days}d ago`\n if (days < 30)\n return `${Math.floor(days / 7)}w ago`\n return `${Math.floor(days / 30)}mo ago`\n}\n\nexport function formatSource(source?: string): string {\n if (!source)\n return ''\n if (source === 'shipped')\n return 'shipped'\n if (source.includes('llms.txt'))\n return 'llms.txt'\n if (source.includes('github.com'))\n return source.replace(/https?:\\/\\/github\\.com\\//, '')\n return source\n}\n\nexport function formatDuration(ms: number): string {\n if (ms < 1000)\n return `${Math.round(ms)}ms`\n return `${(ms / 1000).toFixed(1)}s`\n}\n\n/** Spinner wrapper that shows elapsed time via built-in timer indicator */\nexport function timedSpinner() {\n const spin = p.spinner({ indicator: 'timer' })\n return {\n start(msg: string) {\n spin.start(msg)\n },\n message(msg: string) {\n spin.message(msg)\n },\n stop(msg: string) {\n spin.stop(msg)\n },\n }\n}\n\nexport function formatSkillStatus(state: ProjectState): void {\n const { missing, outdated, synced } = state\n\n if (synced.length > 0)\n p.log.success(`${synced.length} synced`)\n if (outdated.length > 0)\n p.log.warn(`${outdated.length} outdated: ${outdated.map(s => s.name).join(', ')}`)\n if (missing.length > 0)\n p.log.info(`${missing.length} missing: ${missing.slice(0, 5).join(', ')}${missing.length > 5 ? '...' : ''}`)\n}\n\nexport function highlightTerms(content: string, terms: string[]): string {\n if (terms.length === 0)\n return content\n // Sort by length desc to match longer terms first\n const sorted = terms.toSorted((a, b) => b.length - a.length)\n const pattern = new RegExp(`(${sorted.map(t => t.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')).join('|')})`, 'gi')\n return content.replace(pattern, '\\x1B[33m$1\\x1B[0m')\n}\n\n/** Format a normalized score (0-100) with color */\nexport function scoreLabel(pct: number): string {\n const color = pct >= 70 ? '\\x1B[32m' : pct >= 40 ? '\\x1B[33m' : '\\x1B[90m'\n return `${color}${pct}%\\x1B[0m`\n}\n\n/** Normalize raw cosine similarity scores to 0-100 relative to the best match */\nexport function normalizeScores(results: SearchSnippet[]): Map<SearchSnippet, number> {\n const map = new Map<SearchSnippet, number>()\n const max = results.reduce((m, r) => Math.max(m, r.score), 0)\n for (const r of results)\n map.set(r, max > 0 ? Math.round((r.score / max) * 100) : 0)\n return map\n}\n\nexport function formatSnippet(r: SearchSnippet, versions?: Map<string, string>, pct?: number): string {\n const refPath = `.claude/skills/${r.package}/.skilld/${r.source}`\n const lineRange = r.lineStart === r.lineEnd ? `L${r.lineStart}` : `L${r.lineStart}-${r.lineEnd}`\n const score = pct != null ? scoreLabel(pct) : `\\x1B[90m${r.score.toFixed(2)}\\x1B[0m`\n const version = versions?.get(r.package)\n const pkgLabel = version ? `${r.package}@${version}` : r.package\n\n const scopeStr = r.scope?.length ? `${r.scope.map(e => e.name).join('.')} → ` : ''\n const entityStr = r.entities?.map(e => e.signature || `${e.type} ${e.name}`).join(', ')\n const highlighted = highlightTerms(r.content, r.highlights)\n\n return [\n `${pkgLabel} ${score}${entityStr ? ` \\x1B[36m${scopeStr}${entityStr}\\x1B[0m` : ''}`,\n `\\x1B[90m${refPath}:${lineRange}\\x1B[0m`,\n ` ${highlighted.replace(/\\n/g, '\\n ')}`,\n ].join('\\n')\n}\n\n/** Compact 2-line format for interactive search list */\nexport function formatCompactSnippet(r: SearchSnippet, cols: number): { title: string, path: string, preview: string } {\n const entityStr = r.entities?.length\n ? r.entities.map(e => e.signature || e.name).join(', ')\n : ''\n const scopeStr = r.scope?.length ? `${r.scope.map(e => e.name).join('.')} → ` : ''\n const title = entityStr ? `${scopeStr}${entityStr}` : r.source.split('/').pop() || r.source\n\n const refPath = `.claude/skills/${r.package}/.skilld/${r.source}`\n const lineRange = r.lineStart === r.lineEnd ? `L${r.lineStart}` : `L${r.lineStart}-${r.lineEnd}`\n const path = `${refPath}:${lineRange}`\n\n // First meaningful line as preview (skip empty, frontmatter delimiters, headings-only)\n const maxPreview = cols - 6\n const firstLine = r.content.split('\\n').find(l => l.trim() && l.trim() !== '---' && !/^#+\\s*$/.test(l.trim())) || ''\n const preview = firstLine.length > maxPreview ? `${firstLine.slice(0, maxPreview - 1)}…` : firstLine\n\n return { title, path, preview }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index2.d.mts","names":[],"sources":["../../src/sources/blog-releases.ts","../../src/sources/crawl.ts","../../src/sources/discussions.ts","../../src/sources/docs.ts","../../src/sources/entries.ts","../../src/sources/git-skills.ts","../../src/sources/types.ts","../../src/sources/github.ts","../../src/sources/issues.ts","../../src/sources/llms.ts","../../src/sources/npm.ts","../../src/sources/package-registry.ts","../../src/sources/releases.ts","../../src/sources/utils.ts"],"mappings":";;;UAmBU,WAAA;EACR,IAAA;EACA,OAAA;AAAA;;;;;;iBAkFoB,iBAAA,CACpB,WAAA,UACA,gBAAA,WACC,OAAA,CAAQ,WAAA;;;;;;AAzFV;;;;;AAsFD;;;AAtFC,iBCAqB,gBAAA,CACpB,GAAA,UACA,UAAA,IAAc,OAAA,mBACd,QAAA,YACC,OAAA,CAAQ,KAAA;EAAQ,IAAA;EAAc,OAAA;AAAA;;
|
|
1
|
+
{"version":3,"file":"index2.d.mts","names":[],"sources":["../../src/sources/blog-releases.ts","../../src/sources/crawl.ts","../../src/sources/discussions.ts","../../src/sources/docs.ts","../../src/sources/entries.ts","../../src/sources/git-skills.ts","../../src/sources/types.ts","../../src/sources/github.ts","../../src/sources/issues.ts","../../src/sources/llms.ts","../../src/sources/npm.ts","../../src/sources/package-registry.ts","../../src/sources/releases.ts","../../src/sources/utils.ts"],"mappings":"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"}
|
package/dist/_chunks/install.mjs
CHANGED
|
@@ -12,12 +12,13 @@ import { a as getModelLabel, r as createToolProgress, s as optimizeDocs } from "
|
|
|
12
12
|
import { T as readConfig, h as promptForAgent, l as timedSpinner, v as resolveAgent, x as defaultFeatures, y as sharedArgs } from "./formatting.mjs";
|
|
13
13
|
import { a as mergeLocks, l as syncLockfilesToDirs, o as parsePackages, s as readLock, u as writeLock } from "./skills.mjs";
|
|
14
14
|
import { n as shutdownWorker } from "./pool.mjs";
|
|
15
|
-
import {
|
|
15
|
+
import { a as selectLlmConfig, i as indexResources, o as writePromptFiles, r as classifyCachedDoc } from "./sync.mjs";
|
|
16
16
|
import { homedir } from "node:os";
|
|
17
17
|
import { dirname, join } from "pathe";
|
|
18
18
|
import { copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
|
|
19
19
|
import * as p from "@clack/prompts";
|
|
20
20
|
import { defineCommand } from "citty";
|
|
21
|
+
//#region src/commands/install.ts
|
|
21
22
|
async function installCommand(opts) {
|
|
22
23
|
const cwd = process.cwd();
|
|
23
24
|
const agent = targets[opts.agent];
|
|
@@ -560,6 +561,7 @@ function hasStaleReferences(referencesPath, pkgName, version, features) {
|
|
|
560
561
|
for (const [name, shouldExist] of expected) if (shouldExist && !existsSync(join(referencesPath, name))) return true;
|
|
561
562
|
return false;
|
|
562
563
|
}
|
|
564
|
+
//#endregion
|
|
563
565
|
export { installCommandDef };
|
|
564
566
|
|
|
565
567
|
//# sourceMappingURL=install.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.mjs","names":["agents","checkShippedDocs"],"sources":["../../src/commands/install.ts"],"sourcesContent":["/**\n * Install command - restore .skilld/ and SKILL.md from lockfile\n *\n * After cloning a repo, the .skilld/ symlinks are missing (gitignored).\n * If SKILL.md was deleted, a base version is regenerated from local metadata.\n * This command recreates them from the lockfile:\n * .claude/skills/<skill>/.skilld/pkg -> node_modules/<pkg> (always)\n * .claude/skills/<skill>/.skilld/docs -> ~/.skilld/references/<pkg>@<version>/docs (if external)\n * .claude/skills/<skill>/SKILL.md -> regenerated from package.json + cache state\n */\n\nimport type { AgentType, CustomPrompt, SkillSection } from '../agent/index.ts'\nimport type { FeaturesConfig } from '../core/config.ts'\nimport type { SkillInfo } from '../core/lockfile.ts'\nimport { copyFileSync, existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, symlinkSync, unlinkSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport * as p from '@clack/prompts'\nimport { defineCommand } from 'citty'\nimport { dirname, join } from 'pathe'\nimport { agents, createToolProgress, getModelLabel, linkSkillToAgents, optimizeDocs } from '../agent/index.ts'\nimport { generateSkillMd } from '../agent/prompts/skill.ts'\nimport {\n hasShippedDocs as checkShippedDocs,\n ensureCacheDir,\n getCacheDir,\n getPackageDbPath,\n getPkgKeyFiles,\n getRepoCacheDir,\n getShippedSkills,\n isCached,\n linkPkgNamed,\n linkShippedSkill,\n listReferenceFiles,\n readCachedDocs,\n resolvePkgDir,\n writeToCache,\n} from '../cache/index.ts'\nimport { promptForAgent, resolveAgent, sharedArgs } from '../cli-helpers.ts'\nimport { defaultFeatures, readConfig } from '../core/config.ts'\nimport { timedSpinner } from '../core/formatting.ts'\nimport { mergeLocks, parsePackages, readLock, syncLockfilesToDirs, writeLock } from '../core/lockfile.ts'\nimport { sanitizeMarkdown } from '../core/sanitize.ts'\nimport { getSharedSkillsDir } from '../core/shared.ts'\nimport { createIndex, SearchDepsUnavailableError } from '../retriv/index.ts'\nimport { shutdownWorker } from '../retriv/pool.ts'\nimport { fetchGitSkills } from '../sources/git-skills.ts'\nimport {\n $fetch,\n downloadLlmsDocs,\n fetchGitDocs,\n fetchLlmsTxt,\n fetchReadmeContent,\n filterFrameworkDocs,\n isShallowGitDocs,\n normalizeLlmsLinks,\n parseGitHubUrl,\n resolveEntryFiles,\n resolvePackageDocs,\n} from '../sources/index.ts'\nimport { classifyCachedDoc, indexResources } from './sync-shared.ts'\nimport { selectLlmConfig, writePromptFiles } from './sync.ts'\n\nexport interface InstallOptions {\n global: boolean\n agent: AgentType\n}\n\nexport async function installCommand(opts: InstallOptions): Promise<void> {\n const cwd = process.cwd()\n const agent = agents[opts.agent]\n const shared = !opts.global && getSharedSkillsDir(cwd)\n const skillsDir = opts.global\n ? join(homedir(), '.skilld', 'skills')\n : shared || join(cwd, agent.skillsDir)\n\n // Collect lockfiles from all agent skill dirs and merge\n // In shared mode, read from .skills/ only\n const allSkillsDirs = shared\n ? [shared]\n : Object.values(agents).map(t =>\n opts.global ? t.globalSkillsDir : join(cwd, t.skillsDir),\n )\n const allLocks = allSkillsDirs\n .map(dir => readLock(dir))\n .filter((l): l is NonNullable<typeof l> => !!l && Object.keys(l.skills).length > 0)\n\n if (allLocks.length === 0) {\n p.log.warn('No skilld-lock.yaml found. Run `skilld` to sync skills first.')\n return\n }\n\n const lock = mergeLocks(allLocks)\n\n const skills = Object.entries(lock.skills)\n const toRestore: Array<{ name: string, info: SkillInfo }> = []\n const features = readConfig().features ?? defaultFeatures\n\n // Find skills with missing/broken references symlinks\n for (const [name, info] of skills) {\n if (!info.version)\n continue\n\n // Shipped skills: the skill dir IS the symlink, no references/ subdir\n if (info.source === 'shipped') {\n const skillDir = join(skillsDir, name)\n if (!existsSync(skillDir)) {\n toRestore.push({ name, info })\n }\n continue\n }\n\n const skillDir = join(skillsDir, name)\n const referencesPath = join(skillDir, '.skilld')\n const skillMdPath = join(skillDir, 'SKILL.md')\n\n // Check skill dir, SKILL.md, and all internal .skilld/ references\n const needsRestore = !existsSync(skillDir)\n || !existsSync(skillMdPath)\n || !existsSync(referencesPath)\n || hasStaleReferences(referencesPath, info.packageName || name, info.version!, features)\n\n if (needsRestore) {\n toRestore.push({ name, info })\n }\n }\n\n if (toRestore.length === 0) {\n p.log.success('All up to date')\n return\n }\n\n p.log.info(`Restoring ${toRestore.length} references`)\n ensureCacheDir()\n\n const allSkillNames = skills.map(([, info]) => info.packageName || '').filter(Boolean)\n const regenerated: Array<{ name: string, pkgName: string, version: string, skillDir: string, packages?: string }> = []\n\n for (const { name, info } of toRestore) {\n const version = info.version!\n const pkgName = info.packageName || unsanitizeName(name, info.source)\n\n // Shipped skills: re-link from node_modules or cached dist\n if (info.source === 'shipped') {\n const shipped = getShippedSkills(pkgName, cwd, version)\n const match = shipped.find(s => s.skillName === name)\n if (match) {\n linkShippedSkill(skillsDir, name, match.skillDir)\n p.log.success(`Linked ${name}`)\n }\n else {\n p.log.warn(`${name}: package ${pkgName} no longer ships this skill`)\n }\n continue\n }\n\n // Git-sourced skills: re-fetch from remote\n if (info.source === 'github' || info.source === 'gitlab' || info.source === 'local') {\n const source = {\n type: info.source as 'github' | 'gitlab' | 'local',\n ...(info.repo?.includes('/') ? { owner: info.repo.split('/')[0], repo: info.repo.split('/')[1] } : {}),\n skillPath: info.path,\n ref: info.ref,\n ...(info.source === 'local' ? { localPath: info.repo } : {}),\n }\n const result = await fetchGitSkills(source)\n const match = result.skills.find(s => s.name === name)\n if (match) {\n const skillDir = join(skillsDir, name)\n mkdirSync(skillDir, { recursive: true })\n writeFileSync(join(skillDir, 'SKILL.md'), sanitizeMarkdown(match.content))\n for (const f of match.files) {\n const filePath = join(skillDir, f.path)\n mkdirSync(dirname(filePath), { recursive: true })\n writeFileSync(filePath, f.content)\n }\n p.log.success(`Restored ${name} from ${info.repo}`)\n }\n else {\n p.log.warn(`${name}: skill not found in ${info.repo}`)\n }\n continue\n }\n\n const skillDir = join(skillsDir, name)\n const referencesPath = join(skillDir, '.skilld')\n const globalCachePath = getCacheDir(pkgName, version)\n const spin = timedSpinner()\n\n // Check if already in global cache - just create symlinks\n if (isCached(pkgName, version)) {\n spin.start(`Linking ${name}`)\n mkdirSync(skillDir, { recursive: true })\n mkdirSync(referencesPath, { recursive: true })\n linkPkgSymlink(referencesPath, pkgName, cwd, version)\n // Restore named symlinks for all tracked packages\n for (const pkg of parsePackages(info.packages))\n linkPkgNamed(skillDir, pkg.name, cwd, pkg.version)\n // Only link external docs if package doesn't ship its own and has more than just README\n if (!pkgHasShippedDocs(pkgName, cwd, version) && !isReadmeOnly(globalCachePath)) {\n const docsLink = join(referencesPath, 'docs')\n const cachedDocs = join(globalCachePath, 'docs')\n if (existsSync(docsLink))\n unlinkSync(docsLink)\n if (existsSync(cachedDocs))\n symlinkSync(cachedDocs, docsLink, 'junction')\n }\n // Link issues, discussions, and releases (try repo cache first, fall back to package cache)\n const repoGh = info.repo ? parseGitHubUrl(`https://github.com/${info.repo}`) : null\n const repoCachePath = repoGh ? getRepoCacheDir(repoGh.owner, repoGh.repo) : null\n if (features.issues) {\n const issuesLink = join(referencesPath, 'issues')\n const repoIssues = repoCachePath ? join(repoCachePath, 'issues') : null\n const cachedIssues = (repoIssues && existsSync(repoIssues)) ? repoIssues : join(globalCachePath, 'issues')\n if (existsSync(issuesLink))\n unlinkSync(issuesLink)\n if (existsSync(cachedIssues))\n symlinkSync(cachedIssues, issuesLink, 'junction')\n }\n if (features.discussions) {\n const discussionsLink = join(referencesPath, 'discussions')\n const repoDiscussions = repoCachePath ? join(repoCachePath, 'discussions') : null\n const cachedDiscussions = (repoDiscussions && existsSync(repoDiscussions)) ? repoDiscussions : join(globalCachePath, 'discussions')\n if (existsSync(discussionsLink))\n unlinkSync(discussionsLink)\n if (existsSync(cachedDiscussions))\n symlinkSync(cachedDiscussions, discussionsLink, 'junction')\n }\n if (features.releases) {\n const releasesLink = join(referencesPath, 'releases')\n const repoReleases = repoCachePath ? join(repoCachePath, 'releases') : null\n const cachedReleases = (repoReleases && existsSync(repoReleases)) ? repoReleases : join(globalCachePath, 'releases')\n if (existsSync(releasesLink))\n unlinkSync(releasesLink)\n if (existsSync(cachedReleases))\n symlinkSync(cachedReleases, releasesLink, 'junction')\n }\n const sectionsLink = join(referencesPath, 'sections')\n const cachedSections = join(globalCachePath, 'sections')\n if (existsSync(sectionsLink))\n unlinkSync(sectionsLink)\n if (existsSync(cachedSections))\n symlinkSync(cachedSections, sectionsLink, 'junction')\n // Create search index from cached docs if missing\n if (features.search && !existsSync(getPackageDbPath(pkgName, version))) {\n spin.message(`Indexing ${name}`)\n const cached = readCachedDocs(pkgName, version)\n const docsToIndex = cached.map(d => ({\n id: d.path,\n content: d.content,\n metadata: { package: pkgName, source: d.path, type: classifyCachedDoc(d.path).type },\n }))\n await indexResources({ packageName: pkgName, version, cwd, docsToIndex, features, onProgress: msg => spin.message(msg) })\n }\n if (!copyFromExistingAgent(skillDir, name, allSkillsDirs)) {\n if (regenerateBaseSkillMd(skillDir, pkgName, version, cwd, allSkillNames, info.source, info.packages))\n regenerated.push({ name, pkgName, version, skillDir, packages: info.packages })\n }\n spin.stop(`Linked ${name}`)\n continue\n }\n\n // Need to download to global cache first\n spin.start(`Downloading ${name}@${version}`)\n\n const resolved = await resolvePackageDocs(pkgName, { version })\n\n if (!resolved) {\n spin.stop(`Could not resolve: ${name}`)\n continue\n }\n\n const cachedDocs: Array<{ path: string, content: string }> = []\n const docsToIndex: Array<{ id: string, content: string, metadata: Record<string, any> }> = []\n const isFrameworkDoc = (path: string) => filterFrameworkDocs([path], pkgName).length > 0\n\n // Try git docs first\n if (resolved.gitDocsUrl && resolved.repoUrl) {\n const gh = parseGitHubUrl(resolved.repoUrl)\n if (gh) {\n const gitDocs = await fetchGitDocs(gh.owner, gh.repo, version, pkgName)\n if (gitDocs?.files.length) {\n const BATCH_SIZE = 20\n for (let i = 0; i < gitDocs.files.length; i += BATCH_SIZE) {\n const batch = gitDocs.files.slice(i, i + BATCH_SIZE)\n const results = await Promise.all(\n batch.map(async (file) => {\n const url = `${gitDocs.baseUrl}/${file}`\n const content = await $fetch(url, { responseType: 'text' }).catch(() => null)\n if (!content)\n return null\n return { file, content }\n }),\n )\n for (const r of results) {\n if (r) {\n const cachePath = gitDocs.docsPrefix ? r.file.replace(gitDocs.docsPrefix, '') : r.file\n cachedDocs.push({ path: cachePath, content: r.content })\n docsToIndex.push({ id: cachePath, content: r.content, metadata: { package: pkgName, source: cachePath, type: 'doc' } })\n }\n }\n }\n\n // Shallow git-docs: if < threshold and llms.txt exists, discard and fall through\n if (isShallowGitDocs(cachedDocs.length) && resolved.llmsUrl) {\n cachedDocs.length = 0\n docsToIndex.length = 0\n }\n else if (cachedDocs.length > 0 && resolved.llmsUrl) {\n // Always cache llms.txt alongside good git-docs as supplementary reference\n const llmsContent = await fetchLlmsTxt(resolved.llmsUrl)\n if (llmsContent) {\n const baseUrl = resolved.docsUrl || new URL(resolved.llmsUrl).origin\n cachedDocs.push({ path: 'llms.txt', content: normalizeLlmsLinks(llmsContent.raw) })\n if (llmsContent.links.length > 0) {\n const docs = await downloadLlmsDocs(llmsContent, baseUrl)\n for (const doc of docs) {\n if (!isFrameworkDoc(doc.url))\n continue\n const localPath = doc.url.startsWith('/') ? doc.url.slice(1) : doc.url\n cachedDocs.push({ path: join('llms-docs', ...localPath.split('/')), content: doc.content })\n }\n }\n }\n }\n }\n }\n }\n\n // Try llms.txt\n if (resolved.llmsUrl && cachedDocs.length === 0) {\n const llmsContent = await fetchLlmsTxt(resolved.llmsUrl)\n if (llmsContent) {\n cachedDocs.push({ path: 'llms.txt', content: normalizeLlmsLinks(llmsContent.raw) })\n if (llmsContent.links.length > 0) {\n const baseUrl = resolved.docsUrl || new URL(resolved.llmsUrl).origin\n const docs = await downloadLlmsDocs(llmsContent, baseUrl)\n for (const doc of docs) {\n if (!isFrameworkDoc(doc.url))\n continue\n const localPath = doc.url.startsWith('/') ? doc.url.slice(1) : doc.url\n const cachePath = join('docs', ...localPath.split('/'))\n cachedDocs.push({ path: cachePath, content: doc.content })\n docsToIndex.push({ id: doc.url, content: doc.content, metadata: { package: pkgName, source: cachePath, type: 'doc' } })\n }\n }\n }\n }\n\n // Fallback to README\n if (resolved.readmeUrl && cachedDocs.length === 0) {\n const content = await fetchReadmeContent(resolved.readmeUrl)\n if (content) {\n cachedDocs.push({ path: 'docs/README.md', content })\n docsToIndex.push({ id: 'README.md', content, metadata: { package: pkgName, source: 'docs/README.md', type: 'doc' } })\n }\n }\n\n if (cachedDocs.length > 0) {\n writeToCache(pkgName, version, cachedDocs)\n\n mkdirSync(referencesPath, { recursive: true })\n linkPkgSymlink(referencesPath, pkgName, cwd, version)\n // Restore named symlinks for all tracked packages\n for (const pkg of parsePackages(info.packages))\n linkPkgNamed(skillDir, pkg.name, cwd, pkg.version)\n // Link fetched docs unless it's just a README (already in pkg/)\n if (!isReadmeOnly(globalCachePath)) {\n const docsLink = join(referencesPath, 'docs')\n const cachedDocsDir = join(globalCachePath, 'docs')\n if (existsSync(docsLink))\n unlinkSync(docsLink)\n if (existsSync(cachedDocsDir))\n symlinkSync(cachedDocsDir, docsLink, 'junction')\n }\n\n if (features.search) {\n try {\n if (docsToIndex.length > 0) {\n await createIndex(docsToIndex, { dbPath: getPackageDbPath(pkgName, version) })\n }\n\n // Index package entry files (.d.ts / .js)\n const pkgDir = resolvePkgDir(pkgName, cwd, version)\n const entryFiles = pkgDir ? await resolveEntryFiles(pkgDir) : []\n if (entryFiles.length > 0) {\n await createIndex(entryFiles.map(e => ({\n id: e.path,\n content: e.content,\n metadata: { package: pkgName, source: `pkg/${e.path}`, type: e.type },\n })), { dbPath: getPackageDbPath(pkgName, version) })\n }\n }\n catch (err) {\n if (!(err instanceof SearchDepsUnavailableError))\n throw err\n }\n }\n\n if (!copyFromExistingAgent(skillDir, name, allSkillsDirs)) {\n if (regenerateBaseSkillMd(skillDir, pkgName, version, cwd, allSkillNames, info.source, info.packages))\n regenerated.push({ name, pkgName, version, skillDir, packages: info.packages })\n }\n spin.stop(`Downloaded and linked ${name}`)\n }\n else {\n spin.stop(`No docs found for ${name}`)\n }\n }\n\n // Offer LLM enhancement for regenerated SKILL.md files\n if (regenerated.length > 0 && !readConfig().skipLlm) {\n const names = regenerated.map(r => r.name).join(', ')\n const llmConfig = await selectLlmConfig(undefined, `Enhance SKILL.md for ${names}`)\n if (llmConfig?.promptOnly) {\n const features = readConfig().features ?? defaultFeatures\n for (const { pkgName, version, skillDir } of regenerated) {\n const globalCachePath = getCacheDir(pkgName, version)\n writePromptFiles({\n packageName: pkgName,\n skillDir,\n version,\n hasIssues: existsSync(join(globalCachePath, 'issues')),\n hasDiscussions: existsSync(join(globalCachePath, 'discussions')),\n hasReleases: existsSync(join(globalCachePath, 'releases')),\n hasChangelog: false,\n docsType: 'docs',\n hasShippedDocs: false,\n pkgFiles: getPkgKeyFiles(pkgName, process.cwd(), version),\n sections: llmConfig.sections,\n customPrompt: llmConfig.customPrompt,\n features,\n })\n }\n }\n else if (llmConfig) {\n p.log.step(getModelLabel(llmConfig.model))\n for (const { pkgName, version, skillDir, packages: pkgPackages } of regenerated) {\n await enhanceRegenerated(pkgName, version, skillDir, llmConfig.model, llmConfig.sections, llmConfig.customPrompt, pkgPackages)\n }\n }\n }\n\n // Write merged lockfile to target dir and sync to all other existing lockfiles\n for (const [name, info] of Object.entries(lock.skills))\n writeLock(skillsDir, name, info)\n\n // In shared mode: recreate per-agent symlinks, skip per-agent lockfile sync\n if (shared) {\n for (const [name] of skills)\n linkSkillToAgents(name, shared, cwd, opts.agent)\n }\n else {\n syncLockfilesToDirs(lock, allSkillsDirs.filter(d => d !== skillsDir))\n }\n\n await shutdownWorker()\n\n p.outro('Install complete')\n}\n\n/** Copy SKILL.md from another agent's skill dir if one exists */\nfunction copyFromExistingAgent(skillDir: string, name: string, allSkillsDirs: string[]): boolean {\n const targetMd = join(skillDir, 'SKILL.md')\n if (existsSync(targetMd))\n return false\n for (const dir of allSkillsDirs) {\n if (dir === skillDir)\n continue\n const candidateMd = join(dir, name, 'SKILL.md')\n if (existsSync(candidateMd) && !lstatSync(candidateMd).isSymbolicLink()) {\n mkdirSync(skillDir, { recursive: true })\n copyFileSync(candidateMd, targetMd)\n return true\n }\n }\n return false\n}\n\n/** Try to recover original package name from sanitized name + source */\nfunction unsanitizeName(sanitized: string, source?: string): string {\n if (source?.includes('ungh://')) {\n const match = source.match(/ungh:\\/\\/([^/]+)\\/(.+)/)\n if (match)\n return `@${match[1]}/${match[2]}`\n }\n\n if (sanitized.startsWith('antfu-'))\n return `@antfu/${sanitized.slice(6)}`\n if (sanitized.startsWith('clack-'))\n return `@clack/${sanitized.slice(6)}`\n if (sanitized.startsWith('nuxt-'))\n return `@nuxt/${sanitized.slice(5)}`\n if (sanitized.startsWith('vue-'))\n return `@vue/${sanitized.slice(4)}`\n if (sanitized.startsWith('vueuse-'))\n return `@vueuse/${sanitized.slice(7)}`\n\n return sanitized\n}\n\n/** Create pkg symlink inside references dir (links to entire package or cached dist) */\nfunction linkPkgSymlink(referencesDir: string, name: string, cwd: string, version?: string): void {\n const pkgPath = resolvePkgDir(name, cwd, version)\n if (!pkgPath)\n return\n\n const pkgLink = join(referencesDir, 'pkg')\n if (existsSync(pkgLink))\n unlinkSync(pkgLink)\n symlinkSync(pkgPath, pkgLink, 'junction')\n}\n\n/** Check if cache only has docs/README.md (pkg/ already has this) */\nfunction isReadmeOnly(cacheDir: string): boolean {\n const docsDir = join(cacheDir, 'docs')\n if (!existsSync(docsDir))\n return false\n const files = readdirSync(docsDir)\n return files.length === 1 && files[0] === 'README.md'\n}\n\n/** Check if package ships its own docs folder */\nfunction pkgHasShippedDocs(name: string, cwd: string, version?: string): boolean {\n const pkgPath = resolvePkgDir(name, cwd, version)\n if (!pkgPath)\n return false\n\n const docsCandidates = ['docs', 'documentation', 'doc']\n for (const candidate of docsCandidates) {\n const docsPath = join(pkgPath, candidate)\n if (existsSync(docsPath))\n return true\n }\n return false\n}\n\n/** Run LLM enhancement on a regenerated SKILL.md */\nasync function enhanceRegenerated(\n pkgName: string,\n version: string,\n skillDir: string,\n model: Parameters<typeof optimizeDocs>[0]['model'],\n sections: SkillSection[],\n customPrompt?: CustomPrompt,\n packages?: string,\n): Promise<void> {\n const llmLog = p.taskLog({ title: `Agent exploring ${pkgName}` })\n\n const docFiles = listReferenceFiles(skillDir)\n const globalCachePath = getCacheDir(pkgName, version)\n const hasIssues = existsSync(join(globalCachePath, 'issues'))\n const hasDiscussions = existsSync(join(globalCachePath, 'discussions'))\n const hasGithub = hasIssues || hasDiscussions\n const hasReleases = existsSync(join(globalCachePath, 'releases'))\n\n const features = readConfig().features ?? defaultFeatures\n const { optimized, wasOptimized } = await optimizeDocs({\n packageName: pkgName,\n skillDir,\n model,\n version,\n hasGithub,\n hasReleases,\n docFiles,\n sections,\n customPrompt,\n features,\n pkgFiles: getPkgKeyFiles(pkgName, process.cwd(), version),\n onProgress: createToolProgress(llmLog),\n })\n\n if (wasOptimized) {\n llmLog.success('Generated best practices')\n // Re-read local metadata for the enhanced version\n const cwd = process.cwd()\n const pkgPath = resolvePkgDir(pkgName, cwd, version)\n let description: string | undefined\n let dependencies: Record<string, string> | undefined\n if (pkgPath) {\n const pkgJsonPath = join(pkgPath, 'package.json')\n if (existsSync(pkgJsonPath)) {\n const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'))\n description = pkg.description\n dependencies = pkg.dependencies\n }\n }\n\n let docsType: 'llms.txt' | 'readme' | 'docs' = 'docs'\n if (existsSync(join(globalCachePath, 'docs', 'llms.txt')))\n docsType = 'llms.txt'\n else if (isReadmeOnly(globalCachePath))\n docsType = 'readme'\n\n // Derive dirName from the skill directory name\n const dirName = skillDir.split('/').pop()\n\n const allPackages = parsePackages(packages).map(p => ({ name: p.name }))\n const skillMd = generateSkillMd({\n name: pkgName,\n version,\n description,\n dependencies,\n body: optimized,\n relatedSkills: [],\n hasIssues,\n hasDiscussions,\n hasReleases,\n docsType,\n hasShippedDocs: checkShippedDocs(pkgName, cwd, version),\n pkgFiles: getPkgKeyFiles(pkgName, cwd, version),\n dirName,\n packages: allPackages.length > 1 ? allPackages : undefined,\n features,\n })\n writeFileSync(join(skillDir, 'SKILL.md'), skillMd)\n }\n else {\n llmLog.error('LLM optimization skipped')\n }\n}\n\nexport const installCommandDef = defineCommand({\n meta: { name: 'install', description: 'Restore references from lockfile' },\n args: {\n global: sharedArgs.global,\n agent: sharedArgs.agent,\n },\n async run({ args }) {\n let agent = resolveAgent(args.agent)\n if (!agent || agent === 'none') {\n if (agent === 'none')\n return\n const picked = await promptForAgent()\n if (!picked || picked === 'none')\n return\n agent = picked\n }\n\n p.intro(`\\x1B[1m\\x1B[35mskilld\\x1B[0m install`)\n return installCommand({ global: args.global, agent })\n },\n})\n\n/** Regenerate base SKILL.md from local metadata if missing */\nfunction regenerateBaseSkillMd(\n skillDir: string,\n pkgName: string,\n version: string,\n cwd: string,\n allSkillNames: string[],\n source?: string,\n packages?: string,\n): boolean {\n const skillMdPath = join(skillDir, 'SKILL.md')\n if (existsSync(skillMdPath))\n return false\n\n // Read description + deps from local package.json\n const pkgPath = resolvePkgDir(pkgName, cwd, version)\n let description: string | undefined\n let dependencies: Record<string, string> | undefined\n if (pkgPath) {\n const pkgJsonPath = join(pkgPath, 'package.json')\n if (existsSync(pkgJsonPath)) {\n const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'))\n description = pkg.description\n dependencies = pkg.dependencies\n }\n }\n\n // Infer docsType from source or cache\n const globalCachePath = getCacheDir(pkgName, version)\n let docsType: 'llms.txt' | 'readme' | 'docs' = 'docs'\n if (source?.includes('llms.txt') || existsSync(join(globalCachePath, 'docs', 'llms.txt')))\n docsType = 'llms.txt'\n else if (isReadmeOnly(globalCachePath))\n docsType = 'readme'\n\n // Check cache dirs for issues/discussions/releases (only if feature enabled)\n const feat = readConfig().features ?? defaultFeatures\n const hasIssues = feat.issues && existsSync(join(globalCachePath, 'issues'))\n const hasDiscussions = feat.discussions && existsSync(join(globalCachePath, 'discussions'))\n const hasReleases = feat.releases && existsSync(join(globalCachePath, 'releases'))\n\n // Related skills from other lockfile entries\n const relatedSkills = allSkillNames.filter(n => n !== pkgName)\n\n // Derive dirName from the skill directory name (lockfile key)\n const dirName = skillDir.split('/').pop()\n\n // Build multi-package list from lockfile packages field\n const allPackages = parsePackages(packages).map(p => ({ name: p.name }))\n\n const content = generateSkillMd({\n name: pkgName,\n version,\n description,\n dependencies,\n relatedSkills,\n hasIssues,\n hasDiscussions,\n hasReleases,\n docsType,\n hasShippedDocs: checkShippedDocs(pkgName, cwd, version),\n pkgFiles: getPkgKeyFiles(pkgName, cwd, version),\n dirName,\n packages: allPackages.length > 1 ? allPackages : undefined,\n features: readConfig().features ?? defaultFeatures,\n })\n\n mkdirSync(skillDir, { recursive: true })\n writeFileSync(skillMdPath, content)\n return true\n}\n\n/** Check if .skilld/ has broken symlinks or is missing expected references from global cache */\nfunction hasStaleReferences(referencesPath: string, pkgName: string, version: string, features: FeaturesConfig): boolean {\n // Scan existing entries for broken symlinks\n for (const entry of readdirSync(referencesPath)) {\n const entryPath = join(referencesPath, entry)\n if (lstatSync(entryPath).isSymbolicLink() && !existsSync(entryPath))\n return true\n }\n\n // Check pkg link always expected\n if (!existsSync(join(referencesPath, 'pkg')))\n return true\n\n // Check expected links against global cache\n const globalCachePath = getCacheDir(pkgName, version)\n const expected: Array<[string, boolean]> = [\n ['docs', existsSync(join(globalCachePath, 'docs'))],\n ['issues', features.issues && existsSync(join(globalCachePath, 'issues'))],\n ['discussions', features.discussions && existsSync(join(globalCachePath, 'discussions'))],\n ['releases', features.releases && existsSync(join(globalCachePath, 'releases'))],\n ['sections', existsSync(join(globalCachePath, 'sections'))],\n ]\n\n for (const [name, shouldExist] of expected) {\n if (shouldExist && !existsSync(join(referencesPath, name)))\n return true\n }\n\n return false\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"install.mjs","names":["agents","checkShippedDocs"],"sources":["../../src/commands/install.ts"],"sourcesContent":["/**\n * Install command - restore .skilld/ and SKILL.md from lockfile\n *\n * After cloning a repo, the .skilld/ symlinks are missing (gitignored).\n * If SKILL.md was deleted, a base version is regenerated from local metadata.\n * This command recreates them from the lockfile:\n * .claude/skills/<skill>/.skilld/pkg -> node_modules/<pkg> (always)\n * .claude/skills/<skill>/.skilld/docs -> ~/.skilld/references/<pkg>@<version>/docs (if external)\n * .claude/skills/<skill>/SKILL.md -> regenerated from package.json + cache state\n */\n\nimport type { AgentType, CustomPrompt, SkillSection } from '../agent/index.ts'\nimport type { FeaturesConfig } from '../core/config.ts'\nimport type { SkillInfo } from '../core/lockfile.ts'\nimport { copyFileSync, existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, symlinkSync, unlinkSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport * as p from '@clack/prompts'\nimport { defineCommand } from 'citty'\nimport { dirname, join } from 'pathe'\nimport { agents, createToolProgress, getModelLabel, linkSkillToAgents, optimizeDocs } from '../agent/index.ts'\nimport { generateSkillMd } from '../agent/prompts/skill.ts'\nimport {\n hasShippedDocs as checkShippedDocs,\n ensureCacheDir,\n getCacheDir,\n getPackageDbPath,\n getPkgKeyFiles,\n getRepoCacheDir,\n getShippedSkills,\n isCached,\n linkPkgNamed,\n linkShippedSkill,\n listReferenceFiles,\n readCachedDocs,\n resolvePkgDir,\n writeToCache,\n} from '../cache/index.ts'\nimport { promptForAgent, resolveAgent, sharedArgs } from '../cli-helpers.ts'\nimport { defaultFeatures, readConfig } from '../core/config.ts'\nimport { timedSpinner } from '../core/formatting.ts'\nimport { mergeLocks, parsePackages, readLock, syncLockfilesToDirs, writeLock } from '../core/lockfile.ts'\nimport { sanitizeMarkdown } from '../core/sanitize.ts'\nimport { getSharedSkillsDir } from '../core/shared.ts'\nimport { createIndex, SearchDepsUnavailableError } from '../retriv/index.ts'\nimport { shutdownWorker } from '../retriv/pool.ts'\nimport { fetchGitSkills } from '../sources/git-skills.ts'\nimport {\n $fetch,\n downloadLlmsDocs,\n fetchGitDocs,\n fetchLlmsTxt,\n fetchReadmeContent,\n filterFrameworkDocs,\n isShallowGitDocs,\n normalizeLlmsLinks,\n parseGitHubUrl,\n resolveEntryFiles,\n resolvePackageDocs,\n} from '../sources/index.ts'\nimport { classifyCachedDoc, indexResources } from './sync-shared.ts'\nimport { selectLlmConfig, writePromptFiles } from './sync.ts'\n\nexport interface InstallOptions {\n global: boolean\n agent: AgentType\n}\n\nexport async function installCommand(opts: InstallOptions): Promise<void> {\n const cwd = process.cwd()\n const agent = agents[opts.agent]\n const shared = !opts.global && getSharedSkillsDir(cwd)\n const skillsDir = opts.global\n ? join(homedir(), '.skilld', 'skills')\n : shared || join(cwd, agent.skillsDir)\n\n // Collect lockfiles from all agent skill dirs and merge\n // In shared mode, read from .skills/ only\n const allSkillsDirs = shared\n ? [shared]\n : Object.values(agents).map(t =>\n opts.global ? t.globalSkillsDir : join(cwd, t.skillsDir),\n )\n const allLocks = allSkillsDirs\n .map(dir => readLock(dir))\n .filter((l): l is NonNullable<typeof l> => !!l && Object.keys(l.skills).length > 0)\n\n if (allLocks.length === 0) {\n p.log.warn('No skilld-lock.yaml found. Run `skilld` to sync skills first.')\n return\n }\n\n const lock = mergeLocks(allLocks)\n\n const skills = Object.entries(lock.skills)\n const toRestore: Array<{ name: string, info: SkillInfo }> = []\n const features = readConfig().features ?? defaultFeatures\n\n // Find skills with missing/broken references symlinks\n for (const [name, info] of skills) {\n if (!info.version)\n continue\n\n // Shipped skills: the skill dir IS the symlink, no references/ subdir\n if (info.source === 'shipped') {\n const skillDir = join(skillsDir, name)\n if (!existsSync(skillDir)) {\n toRestore.push({ name, info })\n }\n continue\n }\n\n const skillDir = join(skillsDir, name)\n const referencesPath = join(skillDir, '.skilld')\n const skillMdPath = join(skillDir, 'SKILL.md')\n\n // Check skill dir, SKILL.md, and all internal .skilld/ references\n const needsRestore = !existsSync(skillDir)\n || !existsSync(skillMdPath)\n || !existsSync(referencesPath)\n || hasStaleReferences(referencesPath, info.packageName || name, info.version!, features)\n\n if (needsRestore) {\n toRestore.push({ name, info })\n }\n }\n\n if (toRestore.length === 0) {\n p.log.success('All up to date')\n return\n }\n\n p.log.info(`Restoring ${toRestore.length} references`)\n ensureCacheDir()\n\n const allSkillNames = skills.map(([, info]) => info.packageName || '').filter(Boolean)\n const regenerated: Array<{ name: string, pkgName: string, version: string, skillDir: string, packages?: string }> = []\n\n for (const { name, info } of toRestore) {\n const version = info.version!\n const pkgName = info.packageName || unsanitizeName(name, info.source)\n\n // Shipped skills: re-link from node_modules or cached dist\n if (info.source === 'shipped') {\n const shipped = getShippedSkills(pkgName, cwd, version)\n const match = shipped.find(s => s.skillName === name)\n if (match) {\n linkShippedSkill(skillsDir, name, match.skillDir)\n p.log.success(`Linked ${name}`)\n }\n else {\n p.log.warn(`${name}: package ${pkgName} no longer ships this skill`)\n }\n continue\n }\n\n // Git-sourced skills: re-fetch from remote\n if (info.source === 'github' || info.source === 'gitlab' || info.source === 'local') {\n const source = {\n type: info.source as 'github' | 'gitlab' | 'local',\n ...(info.repo?.includes('/') ? { owner: info.repo.split('/')[0], repo: info.repo.split('/')[1] } : {}),\n skillPath: info.path,\n ref: info.ref,\n ...(info.source === 'local' ? { localPath: info.repo } : {}),\n }\n const result = await fetchGitSkills(source)\n const match = result.skills.find(s => s.name === name)\n if (match) {\n const skillDir = join(skillsDir, name)\n mkdirSync(skillDir, { recursive: true })\n writeFileSync(join(skillDir, 'SKILL.md'), sanitizeMarkdown(match.content))\n for (const f of match.files) {\n const filePath = join(skillDir, f.path)\n mkdirSync(dirname(filePath), { recursive: true })\n writeFileSync(filePath, f.content)\n }\n p.log.success(`Restored ${name} from ${info.repo}`)\n }\n else {\n p.log.warn(`${name}: skill not found in ${info.repo}`)\n }\n continue\n }\n\n const skillDir = join(skillsDir, name)\n const referencesPath = join(skillDir, '.skilld')\n const globalCachePath = getCacheDir(pkgName, version)\n const spin = timedSpinner()\n\n // Check if already in global cache - just create symlinks\n if (isCached(pkgName, version)) {\n spin.start(`Linking ${name}`)\n mkdirSync(skillDir, { recursive: true })\n mkdirSync(referencesPath, { recursive: true })\n linkPkgSymlink(referencesPath, pkgName, cwd, version)\n // Restore named symlinks for all tracked packages\n for (const pkg of parsePackages(info.packages))\n linkPkgNamed(skillDir, pkg.name, cwd, pkg.version)\n // Only link external docs if package doesn't ship its own and has more than just README\n if (!pkgHasShippedDocs(pkgName, cwd, version) && !isReadmeOnly(globalCachePath)) {\n const docsLink = join(referencesPath, 'docs')\n const cachedDocs = join(globalCachePath, 'docs')\n if (existsSync(docsLink))\n unlinkSync(docsLink)\n if (existsSync(cachedDocs))\n symlinkSync(cachedDocs, docsLink, 'junction')\n }\n // Link issues, discussions, and releases (try repo cache first, fall back to package cache)\n const repoGh = info.repo ? parseGitHubUrl(`https://github.com/${info.repo}`) : null\n const repoCachePath = repoGh ? getRepoCacheDir(repoGh.owner, repoGh.repo) : null\n if (features.issues) {\n const issuesLink = join(referencesPath, 'issues')\n const repoIssues = repoCachePath ? join(repoCachePath, 'issues') : null\n const cachedIssues = (repoIssues && existsSync(repoIssues)) ? repoIssues : join(globalCachePath, 'issues')\n if (existsSync(issuesLink))\n unlinkSync(issuesLink)\n if (existsSync(cachedIssues))\n symlinkSync(cachedIssues, issuesLink, 'junction')\n }\n if (features.discussions) {\n const discussionsLink = join(referencesPath, 'discussions')\n const repoDiscussions = repoCachePath ? join(repoCachePath, 'discussions') : null\n const cachedDiscussions = (repoDiscussions && existsSync(repoDiscussions)) ? repoDiscussions : join(globalCachePath, 'discussions')\n if (existsSync(discussionsLink))\n unlinkSync(discussionsLink)\n if (existsSync(cachedDiscussions))\n symlinkSync(cachedDiscussions, discussionsLink, 'junction')\n }\n if (features.releases) {\n const releasesLink = join(referencesPath, 'releases')\n const repoReleases = repoCachePath ? join(repoCachePath, 'releases') : null\n const cachedReleases = (repoReleases && existsSync(repoReleases)) ? repoReleases : join(globalCachePath, 'releases')\n if (existsSync(releasesLink))\n unlinkSync(releasesLink)\n if (existsSync(cachedReleases))\n symlinkSync(cachedReleases, releasesLink, 'junction')\n }\n const sectionsLink = join(referencesPath, 'sections')\n const cachedSections = join(globalCachePath, 'sections')\n if (existsSync(sectionsLink))\n unlinkSync(sectionsLink)\n if (existsSync(cachedSections))\n symlinkSync(cachedSections, sectionsLink, 'junction')\n // Create search index from cached docs if missing\n if (features.search && !existsSync(getPackageDbPath(pkgName, version))) {\n spin.message(`Indexing ${name}`)\n const cached = readCachedDocs(pkgName, version)\n const docsToIndex = cached.map(d => ({\n id: d.path,\n content: d.content,\n metadata: { package: pkgName, source: d.path, type: classifyCachedDoc(d.path).type },\n }))\n await indexResources({ packageName: pkgName, version, cwd, docsToIndex, features, onProgress: msg => spin.message(msg) })\n }\n if (!copyFromExistingAgent(skillDir, name, allSkillsDirs)) {\n if (regenerateBaseSkillMd(skillDir, pkgName, version, cwd, allSkillNames, info.source, info.packages))\n regenerated.push({ name, pkgName, version, skillDir, packages: info.packages })\n }\n spin.stop(`Linked ${name}`)\n continue\n }\n\n // Need to download to global cache first\n spin.start(`Downloading ${name}@${version}`)\n\n const resolved = await resolvePackageDocs(pkgName, { version })\n\n if (!resolved) {\n spin.stop(`Could not resolve: ${name}`)\n continue\n }\n\n const cachedDocs: Array<{ path: string, content: string }> = []\n const docsToIndex: Array<{ id: string, content: string, metadata: Record<string, any> }> = []\n const isFrameworkDoc = (path: string) => filterFrameworkDocs([path], pkgName).length > 0\n\n // Try git docs first\n if (resolved.gitDocsUrl && resolved.repoUrl) {\n const gh = parseGitHubUrl(resolved.repoUrl)\n if (gh) {\n const gitDocs = await fetchGitDocs(gh.owner, gh.repo, version, pkgName)\n if (gitDocs?.files.length) {\n const BATCH_SIZE = 20\n for (let i = 0; i < gitDocs.files.length; i += BATCH_SIZE) {\n const batch = gitDocs.files.slice(i, i + BATCH_SIZE)\n const results = await Promise.all(\n batch.map(async (file) => {\n const url = `${gitDocs.baseUrl}/${file}`\n const content = await $fetch(url, { responseType: 'text' }).catch(() => null)\n if (!content)\n return null\n return { file, content }\n }),\n )\n for (const r of results) {\n if (r) {\n const cachePath = gitDocs.docsPrefix ? r.file.replace(gitDocs.docsPrefix, '') : r.file\n cachedDocs.push({ path: cachePath, content: r.content })\n docsToIndex.push({ id: cachePath, content: r.content, metadata: { package: pkgName, source: cachePath, type: 'doc' } })\n }\n }\n }\n\n // Shallow git-docs: if < threshold and llms.txt exists, discard and fall through\n if (isShallowGitDocs(cachedDocs.length) && resolved.llmsUrl) {\n cachedDocs.length = 0\n docsToIndex.length = 0\n }\n else if (cachedDocs.length > 0 && resolved.llmsUrl) {\n // Always cache llms.txt alongside good git-docs as supplementary reference\n const llmsContent = await fetchLlmsTxt(resolved.llmsUrl)\n if (llmsContent) {\n const baseUrl = resolved.docsUrl || new URL(resolved.llmsUrl).origin\n cachedDocs.push({ path: 'llms.txt', content: normalizeLlmsLinks(llmsContent.raw) })\n if (llmsContent.links.length > 0) {\n const docs = await downloadLlmsDocs(llmsContent, baseUrl)\n for (const doc of docs) {\n if (!isFrameworkDoc(doc.url))\n continue\n const localPath = doc.url.startsWith('/') ? doc.url.slice(1) : doc.url\n cachedDocs.push({ path: join('llms-docs', ...localPath.split('/')), content: doc.content })\n }\n }\n }\n }\n }\n }\n }\n\n // Try llms.txt\n if (resolved.llmsUrl && cachedDocs.length === 0) {\n const llmsContent = await fetchLlmsTxt(resolved.llmsUrl)\n if (llmsContent) {\n cachedDocs.push({ path: 'llms.txt', content: normalizeLlmsLinks(llmsContent.raw) })\n if (llmsContent.links.length > 0) {\n const baseUrl = resolved.docsUrl || new URL(resolved.llmsUrl).origin\n const docs = await downloadLlmsDocs(llmsContent, baseUrl)\n for (const doc of docs) {\n if (!isFrameworkDoc(doc.url))\n continue\n const localPath = doc.url.startsWith('/') ? doc.url.slice(1) : doc.url\n const cachePath = join('docs', ...localPath.split('/'))\n cachedDocs.push({ path: cachePath, content: doc.content })\n docsToIndex.push({ id: doc.url, content: doc.content, metadata: { package: pkgName, source: cachePath, type: 'doc' } })\n }\n }\n }\n }\n\n // Fallback to README\n if (resolved.readmeUrl && cachedDocs.length === 0) {\n const content = await fetchReadmeContent(resolved.readmeUrl)\n if (content) {\n cachedDocs.push({ path: 'docs/README.md', content })\n docsToIndex.push({ id: 'README.md', content, metadata: { package: pkgName, source: 'docs/README.md', type: 'doc' } })\n }\n }\n\n if (cachedDocs.length > 0) {\n writeToCache(pkgName, version, cachedDocs)\n\n mkdirSync(referencesPath, { recursive: true })\n linkPkgSymlink(referencesPath, pkgName, cwd, version)\n // Restore named symlinks for all tracked packages\n for (const pkg of parsePackages(info.packages))\n linkPkgNamed(skillDir, pkg.name, cwd, pkg.version)\n // Link fetched docs unless it's just a README (already in pkg/)\n if (!isReadmeOnly(globalCachePath)) {\n const docsLink = join(referencesPath, 'docs')\n const cachedDocsDir = join(globalCachePath, 'docs')\n if (existsSync(docsLink))\n unlinkSync(docsLink)\n if (existsSync(cachedDocsDir))\n symlinkSync(cachedDocsDir, docsLink, 'junction')\n }\n\n if (features.search) {\n try {\n if (docsToIndex.length > 0) {\n await createIndex(docsToIndex, { dbPath: getPackageDbPath(pkgName, version) })\n }\n\n // Index package entry files (.d.ts / .js)\n const pkgDir = resolvePkgDir(pkgName, cwd, version)\n const entryFiles = pkgDir ? await resolveEntryFiles(pkgDir) : []\n if (entryFiles.length > 0) {\n await createIndex(entryFiles.map(e => ({\n id: e.path,\n content: e.content,\n metadata: { package: pkgName, source: `pkg/${e.path}`, type: e.type },\n })), { dbPath: getPackageDbPath(pkgName, version) })\n }\n }\n catch (err) {\n if (!(err instanceof SearchDepsUnavailableError))\n throw err\n }\n }\n\n if (!copyFromExistingAgent(skillDir, name, allSkillsDirs)) {\n if (regenerateBaseSkillMd(skillDir, pkgName, version, cwd, allSkillNames, info.source, info.packages))\n regenerated.push({ name, pkgName, version, skillDir, packages: info.packages })\n }\n spin.stop(`Downloaded and linked ${name}`)\n }\n else {\n spin.stop(`No docs found for ${name}`)\n }\n }\n\n // Offer LLM enhancement for regenerated SKILL.md files\n if (regenerated.length > 0 && !readConfig().skipLlm) {\n const names = regenerated.map(r => r.name).join(', ')\n const llmConfig = await selectLlmConfig(undefined, `Enhance SKILL.md for ${names}`)\n if (llmConfig?.promptOnly) {\n const features = readConfig().features ?? defaultFeatures\n for (const { pkgName, version, skillDir } of regenerated) {\n const globalCachePath = getCacheDir(pkgName, version)\n writePromptFiles({\n packageName: pkgName,\n skillDir,\n version,\n hasIssues: existsSync(join(globalCachePath, 'issues')),\n hasDiscussions: existsSync(join(globalCachePath, 'discussions')),\n hasReleases: existsSync(join(globalCachePath, 'releases')),\n hasChangelog: false,\n docsType: 'docs',\n hasShippedDocs: false,\n pkgFiles: getPkgKeyFiles(pkgName, process.cwd(), version),\n sections: llmConfig.sections,\n customPrompt: llmConfig.customPrompt,\n features,\n })\n }\n }\n else if (llmConfig) {\n p.log.step(getModelLabel(llmConfig.model))\n for (const { pkgName, version, skillDir, packages: pkgPackages } of regenerated) {\n await enhanceRegenerated(pkgName, version, skillDir, llmConfig.model, llmConfig.sections, llmConfig.customPrompt, pkgPackages)\n }\n }\n }\n\n // Write merged lockfile to target dir and sync to all other existing lockfiles\n for (const [name, info] of Object.entries(lock.skills))\n writeLock(skillsDir, name, info)\n\n // In shared mode: recreate per-agent symlinks, skip per-agent lockfile sync\n if (shared) {\n for (const [name] of skills)\n linkSkillToAgents(name, shared, cwd, opts.agent)\n }\n else {\n syncLockfilesToDirs(lock, allSkillsDirs.filter(d => d !== skillsDir))\n }\n\n await shutdownWorker()\n\n p.outro('Install complete')\n}\n\n/** Copy SKILL.md from another agent's skill dir if one exists */\nfunction copyFromExistingAgent(skillDir: string, name: string, allSkillsDirs: string[]): boolean {\n const targetMd = join(skillDir, 'SKILL.md')\n if (existsSync(targetMd))\n return false\n for (const dir of allSkillsDirs) {\n if (dir === skillDir)\n continue\n const candidateMd = join(dir, name, 'SKILL.md')\n if (existsSync(candidateMd) && !lstatSync(candidateMd).isSymbolicLink()) {\n mkdirSync(skillDir, { recursive: true })\n copyFileSync(candidateMd, targetMd)\n return true\n }\n }\n return false\n}\n\n/** Try to recover original package name from sanitized name + source */\nfunction unsanitizeName(sanitized: string, source?: string): string {\n if (source?.includes('ungh://')) {\n const match = source.match(/ungh:\\/\\/([^/]+)\\/(.+)/)\n if (match)\n return `@${match[1]}/${match[2]}`\n }\n\n if (sanitized.startsWith('antfu-'))\n return `@antfu/${sanitized.slice(6)}`\n if (sanitized.startsWith('clack-'))\n return `@clack/${sanitized.slice(6)}`\n if (sanitized.startsWith('nuxt-'))\n return `@nuxt/${sanitized.slice(5)}`\n if (sanitized.startsWith('vue-'))\n return `@vue/${sanitized.slice(4)}`\n if (sanitized.startsWith('vueuse-'))\n return `@vueuse/${sanitized.slice(7)}`\n\n return sanitized\n}\n\n/** Create pkg symlink inside references dir (links to entire package or cached dist) */\nfunction linkPkgSymlink(referencesDir: string, name: string, cwd: string, version?: string): void {\n const pkgPath = resolvePkgDir(name, cwd, version)\n if (!pkgPath)\n return\n\n const pkgLink = join(referencesDir, 'pkg')\n if (existsSync(pkgLink))\n unlinkSync(pkgLink)\n symlinkSync(pkgPath, pkgLink, 'junction')\n}\n\n/** Check if cache only has docs/README.md (pkg/ already has this) */\nfunction isReadmeOnly(cacheDir: string): boolean {\n const docsDir = join(cacheDir, 'docs')\n if (!existsSync(docsDir))\n return false\n const files = readdirSync(docsDir)\n return files.length === 1 && files[0] === 'README.md'\n}\n\n/** Check if package ships its own docs folder */\nfunction pkgHasShippedDocs(name: string, cwd: string, version?: string): boolean {\n const pkgPath = resolvePkgDir(name, cwd, version)\n if (!pkgPath)\n return false\n\n const docsCandidates = ['docs', 'documentation', 'doc']\n for (const candidate of docsCandidates) {\n const docsPath = join(pkgPath, candidate)\n if (existsSync(docsPath))\n return true\n }\n return false\n}\n\n/** Run LLM enhancement on a regenerated SKILL.md */\nasync function enhanceRegenerated(\n pkgName: string,\n version: string,\n skillDir: string,\n model: Parameters<typeof optimizeDocs>[0]['model'],\n sections: SkillSection[],\n customPrompt?: CustomPrompt,\n packages?: string,\n): Promise<void> {\n const llmLog = p.taskLog({ title: `Agent exploring ${pkgName}` })\n\n const docFiles = listReferenceFiles(skillDir)\n const globalCachePath = getCacheDir(pkgName, version)\n const hasIssues = existsSync(join(globalCachePath, 'issues'))\n const hasDiscussions = existsSync(join(globalCachePath, 'discussions'))\n const hasGithub = hasIssues || hasDiscussions\n const hasReleases = existsSync(join(globalCachePath, 'releases'))\n\n const features = readConfig().features ?? defaultFeatures\n const { optimized, wasOptimized } = await optimizeDocs({\n packageName: pkgName,\n skillDir,\n model,\n version,\n hasGithub,\n hasReleases,\n docFiles,\n sections,\n customPrompt,\n features,\n pkgFiles: getPkgKeyFiles(pkgName, process.cwd(), version),\n onProgress: createToolProgress(llmLog),\n })\n\n if (wasOptimized) {\n llmLog.success('Generated best practices')\n // Re-read local metadata for the enhanced version\n const cwd = process.cwd()\n const pkgPath = resolvePkgDir(pkgName, cwd, version)\n let description: string | undefined\n let dependencies: Record<string, string> | undefined\n if (pkgPath) {\n const pkgJsonPath = join(pkgPath, 'package.json')\n if (existsSync(pkgJsonPath)) {\n const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'))\n description = pkg.description\n dependencies = pkg.dependencies\n }\n }\n\n let docsType: 'llms.txt' | 'readme' | 'docs' = 'docs'\n if (existsSync(join(globalCachePath, 'docs', 'llms.txt')))\n docsType = 'llms.txt'\n else if (isReadmeOnly(globalCachePath))\n docsType = 'readme'\n\n // Derive dirName from the skill directory name\n const dirName = skillDir.split('/').pop()\n\n const allPackages = parsePackages(packages).map(p => ({ name: p.name }))\n const skillMd = generateSkillMd({\n name: pkgName,\n version,\n description,\n dependencies,\n body: optimized,\n relatedSkills: [],\n hasIssues,\n hasDiscussions,\n hasReleases,\n docsType,\n hasShippedDocs: checkShippedDocs(pkgName, cwd, version),\n pkgFiles: getPkgKeyFiles(pkgName, cwd, version),\n dirName,\n packages: allPackages.length > 1 ? allPackages : undefined,\n features,\n })\n writeFileSync(join(skillDir, 'SKILL.md'), skillMd)\n }\n else {\n llmLog.error('LLM optimization skipped')\n }\n}\n\nexport const installCommandDef = defineCommand({\n meta: { name: 'install', description: 'Restore references from lockfile' },\n args: {\n global: sharedArgs.global,\n agent: sharedArgs.agent,\n },\n async run({ args }) {\n let agent = resolveAgent(args.agent)\n if (!agent || agent === 'none') {\n if (agent === 'none')\n return\n const picked = await promptForAgent()\n if (!picked || picked === 'none')\n return\n agent = picked\n }\n\n p.intro(`\\x1B[1m\\x1B[35mskilld\\x1B[0m install`)\n return installCommand({ global: args.global, agent })\n },\n})\n\n/** Regenerate base SKILL.md from local metadata if missing */\nfunction regenerateBaseSkillMd(\n skillDir: string,\n pkgName: string,\n version: string,\n cwd: string,\n allSkillNames: string[],\n source?: string,\n packages?: string,\n): boolean {\n const skillMdPath = join(skillDir, 'SKILL.md')\n if (existsSync(skillMdPath))\n return false\n\n // Read description + deps from local package.json\n const pkgPath = resolvePkgDir(pkgName, cwd, version)\n let description: string | undefined\n let dependencies: Record<string, string> | undefined\n if (pkgPath) {\n const pkgJsonPath = join(pkgPath, 'package.json')\n if (existsSync(pkgJsonPath)) {\n const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'))\n description = pkg.description\n dependencies = pkg.dependencies\n }\n }\n\n // Infer docsType from source or cache\n const globalCachePath = getCacheDir(pkgName, version)\n let docsType: 'llms.txt' | 'readme' | 'docs' = 'docs'\n if (source?.includes('llms.txt') || existsSync(join(globalCachePath, 'docs', 'llms.txt')))\n docsType = 'llms.txt'\n else if (isReadmeOnly(globalCachePath))\n docsType = 'readme'\n\n // Check cache dirs for issues/discussions/releases (only if feature enabled)\n const feat = readConfig().features ?? defaultFeatures\n const hasIssues = feat.issues && existsSync(join(globalCachePath, 'issues'))\n const hasDiscussions = feat.discussions && existsSync(join(globalCachePath, 'discussions'))\n const hasReleases = feat.releases && existsSync(join(globalCachePath, 'releases'))\n\n // Related skills from other lockfile entries\n const relatedSkills = allSkillNames.filter(n => n !== pkgName)\n\n // Derive dirName from the skill directory name (lockfile key)\n const dirName = skillDir.split('/').pop()\n\n // Build multi-package list from lockfile packages field\n const allPackages = parsePackages(packages).map(p => ({ name: p.name }))\n\n const content = generateSkillMd({\n name: pkgName,\n version,\n description,\n dependencies,\n relatedSkills,\n hasIssues,\n hasDiscussions,\n hasReleases,\n docsType,\n hasShippedDocs: checkShippedDocs(pkgName, cwd, version),\n pkgFiles: getPkgKeyFiles(pkgName, cwd, version),\n dirName,\n packages: allPackages.length > 1 ? allPackages : undefined,\n features: readConfig().features ?? defaultFeatures,\n })\n\n mkdirSync(skillDir, { recursive: true })\n writeFileSync(skillMdPath, content)\n return true\n}\n\n/** Check if .skilld/ has broken symlinks or is missing expected references from global cache */\nfunction hasStaleReferences(referencesPath: string, pkgName: string, version: string, features: FeaturesConfig): boolean {\n // Scan existing entries for broken symlinks\n for (const entry of readdirSync(referencesPath)) {\n const entryPath = join(referencesPath, entry)\n if (lstatSync(entryPath).isSymbolicLink() && !existsSync(entryPath))\n return true\n }\n\n // Check pkg link always expected\n if (!existsSync(join(referencesPath, 'pkg')))\n return true\n\n // Check expected links against global cache\n const globalCachePath = getCacheDir(pkgName, version)\n const expected: Array<[string, boolean]> = [\n ['docs', existsSync(join(globalCachePath, 'docs'))],\n ['issues', features.issues && existsSync(join(globalCachePath, 'issues'))],\n ['discussions', features.discussions && existsSync(join(globalCachePath, 'discussions'))],\n ['releases', features.releases && existsSync(join(globalCachePath, 'releases'))],\n ['sections', existsSync(join(globalCachePath, 'sections'))],\n ]\n\n for (const [name, shouldExist] of expected) {\n if (shouldExist && !existsSync(join(referencesPath, name)))\n return true\n }\n\n return false\n}\n"],"mappings":"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"}
|
package/dist/_chunks/list.mjs
CHANGED
|
@@ -11,6 +11,7 @@ import "./agent.mjs";
|
|
|
11
11
|
import { c as timeAgo, i as formatSource, y as sharedArgs } from "./formatting.mjs";
|
|
12
12
|
import { i as iterateSkills } from "./skills.mjs";
|
|
13
13
|
import { defineCommand } from "citty";
|
|
14
|
+
//#region src/commands/list.ts
|
|
14
15
|
function listCommand(opts = {}) {
|
|
15
16
|
const skills = [...iterateSkills({ scope: opts.global ? "global" : "all" })];
|
|
16
17
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -67,6 +68,7 @@ const listCommandDef = defineCommand({
|
|
|
67
68
|
});
|
|
68
69
|
}
|
|
69
70
|
});
|
|
71
|
+
//#endregion
|
|
70
72
|
export { listCommandDef };
|
|
71
73
|
|
|
72
74
|
//# sourceMappingURL=list.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list.mjs","names":[],"sources":["../../src/commands/list.ts"],"sourcesContent":["import { defineCommand } from 'citty'\nimport { sharedArgs } from '../cli-helpers.ts'\nimport { formatSource, timeAgo } from '../core/formatting.ts'\nimport { iterateSkills } from '../core/skills.ts'\n\nexport interface ListOptions {\n global?: boolean\n json?: boolean\n}\n\ninterface ListEntry {\n name: string\n version: string\n source: string\n synced: string\n}\n\nexport function listCommand(opts: ListOptions = {}): void {\n const scope = opts.global ? 'global' : 'all'\n const skills = [...iterateSkills({ scope })]\n\n // Deduplicate by package identity\n const seen = new Set<string>()\n const entries: ListEntry[] = []\n\n for (const skill of skills) {\n const key = skill.info?.packageName || skill.name\n if (seen.has(key))\n continue\n seen.add(key)\n entries.push({\n name: skill.name,\n version: skill.info?.version || '',\n source: formatSource(skill.info?.source),\n synced: timeAgo(skill.info?.syncedAt),\n })\n }\n\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(entries)}\\n`)\n return\n }\n\n if (entries.length === 0) {\n process.stdout.write('No skills installed\\n')\n return\n }\n\n // Column widths\n const nameW = Math.max(...entries.map(e => e.name.length))\n const verW = Math.max(...entries.map(e => e.version.length))\n const srcW = Math.max(...entries.map(e => e.source.length))\n\n for (const e of entries) {\n const line = [\n e.name.padEnd(nameW),\n e.version.padEnd(verW),\n e.source.padEnd(srcW),\n e.synced,\n ].join(' ')\n process.stdout.write(`${line}\\n`)\n }\n}\n\nexport const listCommandDef = defineCommand({\n meta: { name: 'list', description: 'List installed skills' },\n args: {\n global: sharedArgs.global,\n json: {\n type: 'boolean' as const,\n description: 'Output as JSON',\n default: false,\n },\n },\n run({ args }) {\n return listCommand({ global: args.global, json: args.json })\n },\n})\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"list.mjs","names":[],"sources":["../../src/commands/list.ts"],"sourcesContent":["import { defineCommand } from 'citty'\nimport { sharedArgs } from '../cli-helpers.ts'\nimport { formatSource, timeAgo } from '../core/formatting.ts'\nimport { iterateSkills } from '../core/skills.ts'\n\nexport interface ListOptions {\n global?: boolean\n json?: boolean\n}\n\ninterface ListEntry {\n name: string\n version: string\n source: string\n synced: string\n}\n\nexport function listCommand(opts: ListOptions = {}): void {\n const scope = opts.global ? 'global' : 'all'\n const skills = [...iterateSkills({ scope })]\n\n // Deduplicate by package identity\n const seen = new Set<string>()\n const entries: ListEntry[] = []\n\n for (const skill of skills) {\n const key = skill.info?.packageName || skill.name\n if (seen.has(key))\n continue\n seen.add(key)\n entries.push({\n name: skill.name,\n version: skill.info?.version || '',\n source: formatSource(skill.info?.source),\n synced: timeAgo(skill.info?.syncedAt),\n })\n }\n\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(entries)}\\n`)\n return\n }\n\n if (entries.length === 0) {\n process.stdout.write('No skills installed\\n')\n return\n }\n\n // Column widths\n const nameW = Math.max(...entries.map(e => e.name.length))\n const verW = Math.max(...entries.map(e => e.version.length))\n const srcW = Math.max(...entries.map(e => e.source.length))\n\n for (const e of entries) {\n const line = [\n e.name.padEnd(nameW),\n e.version.padEnd(verW),\n e.source.padEnd(srcW),\n e.synced,\n ].join(' ')\n process.stdout.write(`${line}\\n`)\n }\n}\n\nexport const listCommandDef = defineCommand({\n meta: { name: 'list', description: 'List installed skills' },\n args: {\n global: sharedArgs.global,\n json: {\n type: 'boolean' as const,\n description: 'Output as JSON',\n default: false,\n },\n },\n run({ args }) {\n return listCommand({ global: args.global, json: args.json })\n },\n})\n"],"mappings":";;;;;;;;;;;;;;AAiBA,SAAgB,YAAY,OAAoB,EAAE,EAAQ;CAExD,MAAM,SAAS,CAAC,GAAG,cAAc,EAAE,OADrB,KAAK,SAAS,WAAW,OACG,CAAC,CAAC;CAG5C,MAAM,uBAAO,IAAI,KAAa;CAC9B,MAAM,UAAuB,EAAE;AAE/B,MAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,MAAM,MAAM,MAAM,eAAe,MAAM;AAC7C,MAAI,KAAK,IAAI,IAAI,CACf;AACF,OAAK,IAAI,IAAI;AACb,UAAQ,KAAK;GACX,MAAM,MAAM;GACZ,SAAS,MAAM,MAAM,WAAW;GAChC,QAAQ,aAAa,MAAM,MAAM,OAAO;GACxC,QAAQ,QAAQ,MAAM,MAAM,SAAA;GAC7B,CAAC;;AAGJ,KAAI,KAAK,MAAM;AACb,UAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,QAAQ,CAAC,IAAI;AACpD;;AAGF,KAAI,QAAQ,WAAW,GAAG;AACxB,UAAQ,OAAO,MAAM,wBAAwB;AAC7C;;CAIF,MAAM,QAAQ,KAAK,IAAI,GAAG,QAAQ,KAAI,MAAK,EAAE,KAAK,OAAO,CAAC;CAC1D,MAAM,OAAO,KAAK,IAAI,GAAG,QAAQ,KAAI,MAAK,EAAE,QAAQ,OAAO,CAAC;CAC5D,MAAM,OAAO,KAAK,IAAI,GAAG,QAAQ,KAAI,MAAK,EAAE,OAAO,OAAO,CAAC;AAE3D,MAAK,MAAM,KAAK,SAAS;EACvB,MAAM,OAAO;GACX,EAAE,KAAK,OAAO,MAAM;GACpB,EAAE,QAAQ,OAAO,KAAK;GACtB,EAAE,OAAO,OAAO,KAAK;GACrB,EAAE;GACH,CAAC,KAAK,KAAK;AACZ,UAAQ,OAAO,MAAM,GAAG,KAAK,IAAI;;;AAIrC,MAAa,iBAAiB,cAAc;CAC1C,MAAM;EAAE,MAAM;EAAQ,aAAa;EAAyB;CAC5D,MAAM;EACJ,QAAQ,WAAW;EACnB,MAAM;GACJ,MAAM;GACN,aAAa;GACb,SAAS;;EAEZ;CACD,IAAI,EAAE,QAAQ;AACZ,SAAO,YAAY;GAAE,QAAQ,KAAK;GAAQ,MAAM,KAAK;GAAM,CAAC;;CAE/D,CAAC"}
|
|
@@ -4,6 +4,7 @@ import { frontmatterFromMarkdown } from "mdast-util-frontmatter";
|
|
|
4
4
|
import { toString } from "mdast-util-to-string";
|
|
5
5
|
import { frontmatter } from "micromark-extension-frontmatter";
|
|
6
6
|
import { visit } from "unist-util-visit";
|
|
7
|
+
//#region src/core/markdown.ts
|
|
7
8
|
/** Parse markdown string to AST + frontmatter key-values */
|
|
8
9
|
function parseMd(content) {
|
|
9
10
|
const tree = fromMarkdown(content, {
|
|
@@ -78,6 +79,7 @@ function stripFrontmatter(content) {
|
|
|
78
79
|
const match = content.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n/);
|
|
79
80
|
return match ? content.slice(match[0].length).trim() : content;
|
|
80
81
|
}
|
|
82
|
+
//#endregion
|
|
81
83
|
export { stripFrontmatter as a, parseFrontmatter as i, extractLinks as n, extractTitle as r, extractDescription as t };
|
|
82
84
|
|
|
83
85
|
//# sourceMappingURL=markdown.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.mjs","names":[],"sources":["../../src/core/markdown.ts"],"sourcesContent":["/**\n * AST-based markdown parsing using mdast/micromark.\n * Replaces scattered regex-based frontmatter/heading/link extraction.\n */\n\nimport type { Nodes, Root } from 'mdast'\nimport { fromMarkdown } from 'mdast-util-from-markdown'\nimport { frontmatterFromMarkdown } from 'mdast-util-frontmatter'\nimport { toString } from 'mdast-util-to-string'\nimport { frontmatter } from 'micromark-extension-frontmatter'\nimport { visit } from 'unist-util-visit'\nimport { yamlParseKV } from './yaml.ts'\n\nexport interface MdHeading {\n depth: number\n text: string\n}\n\nexport interface MdLink {\n title: string\n url: string\n}\n\nexport interface ParsedMd {\n tree: Root\n frontmatter: Record<string, string>\n}\n\n/** Parse markdown string to AST + frontmatter key-values */\nexport function parseMd(content: string): ParsedMd {\n const tree = fromMarkdown(content, {\n extensions: [frontmatter(['yaml'])],\n mdastExtensions: [frontmatterFromMarkdown(['yaml'])],\n })\n\n const fm: Record<string, string> = {}\n visit(tree, 'yaml', (node: Nodes) => {\n if (node.type === 'yaml') {\n for (const line of (node as any).value.split('\\n')) {\n const kv = yamlParseKV(line)\n if (kv)\n fm[kv[0]] = kv[1]\n }\n }\n })\n\n return { tree, frontmatter: fm }\n}\n\n/** Extract frontmatter key-value pairs only */\nexport function parseFrontmatter(content: string): Record<string, string> {\n return parseMd(content).frontmatter\n}\n\n/** Strip custom heading anchors like {#some-id} */\nfunction stripHeadingAnchors(text: string): string {\n return text.replace(/\\s*\\{#[^}]+\\}\\s*$/, '').trim()\n}\n\n/** Extract title: frontmatter title > first h1 > null */\nexport function extractTitle(content: string): string | null {\n const { tree, frontmatter: fm } = parseMd(content)\n if (fm.title)\n return fm.title\n\n let title: string | null = null\n visit(tree, 'heading', (node) => {\n if (node.depth === 1 && !title) {\n // Strip {#id} anchors and leading backslash escapes (e.g. `# \\`)\n const text = stripHeadingAnchors(toString(node)).replace(/^\\\\+\\s*/, '').trim()\n if (text.length > 0)\n title = text\n }\n })\n\n return title\n}\n\n/** Extract first paragraph text, 150 char max */\nexport function extractDescription(content: string): string | null {\n const { tree } = parseMd(content)\n\n let desc: string | null = null\n visit(tree, 'paragraph', (node, _index, parent) => {\n // Only top-level paragraphs (skip blockquote children, list items, etc.)\n if (desc || parent?.type !== 'root')\n return\n\n const text = toString(node).trim()\n if (text.length === 0)\n return\n\n // Strip markdown link syntax remnants and formatting chars\n let clean = text.replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, '$1').replace(/[`*_~]/g, '')\n if (clean.length > 150)\n clean = `${clean.slice(0, 147)}...`\n desc = clean\n })\n\n return desc\n}\n\n/** Extract all headings with depth and text */\nexport function extractHeadings(content: string): MdHeading[] {\n const { tree } = parseMd(content)\n const headings: MdHeading[] = []\n\n visit(tree, 'heading', (node) => {\n headings.push({ depth: node.depth, text: stripHeadingAnchors(toString(node)) })\n })\n\n return headings\n}\n\n/** Extract all links (deduped by url) */\nexport function extractLinks(content: string): MdLink[] {\n const { tree } = parseMd(content)\n const links: MdLink[] = []\n const seen = new Set<string>()\n\n visit(tree, 'link', (node) => {\n if (!seen.has(node.url)) {\n seen.add(node.url)\n links.push({ title: toString(node), url: node.url })\n }\n })\n\n return links\n}\n\n/** Strip frontmatter block, return body only */\nexport function stripFrontmatter(content: string): string {\n const match = content.match(/^---\\r?\\n[\\s\\S]*?\\r?\\n---\\r?\\n/)\n return match ? content.slice(match[0].length).trim() : content\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"markdown.mjs","names":[],"sources":["../../src/core/markdown.ts"],"sourcesContent":["/**\n * AST-based markdown parsing using mdast/micromark.\n * Replaces scattered regex-based frontmatter/heading/link extraction.\n */\n\nimport type { Nodes, Root } from 'mdast'\nimport { fromMarkdown } from 'mdast-util-from-markdown'\nimport { frontmatterFromMarkdown } from 'mdast-util-frontmatter'\nimport { toString } from 'mdast-util-to-string'\nimport { frontmatter } from 'micromark-extension-frontmatter'\nimport { visit } from 'unist-util-visit'\nimport { yamlParseKV } from './yaml.ts'\n\nexport interface MdHeading {\n depth: number\n text: string\n}\n\nexport interface MdLink {\n title: string\n url: string\n}\n\nexport interface ParsedMd {\n tree: Root\n frontmatter: Record<string, string>\n}\n\n/** Parse markdown string to AST + frontmatter key-values */\nexport function parseMd(content: string): ParsedMd {\n const tree = fromMarkdown(content, {\n extensions: [frontmatter(['yaml'])],\n mdastExtensions: [frontmatterFromMarkdown(['yaml'])],\n })\n\n const fm: Record<string, string> = {}\n visit(tree, 'yaml', (node: Nodes) => {\n if (node.type === 'yaml') {\n for (const line of (node as any).value.split('\\n')) {\n const kv = yamlParseKV(line)\n if (kv)\n fm[kv[0]] = kv[1]\n }\n }\n })\n\n return { tree, frontmatter: fm }\n}\n\n/** Extract frontmatter key-value pairs only */\nexport function parseFrontmatter(content: string): Record<string, string> {\n return parseMd(content).frontmatter\n}\n\n/** Strip custom heading anchors like {#some-id} */\nfunction stripHeadingAnchors(text: string): string {\n return text.replace(/\\s*\\{#[^}]+\\}\\s*$/, '').trim()\n}\n\n/** Extract title: frontmatter title > first h1 > null */\nexport function extractTitle(content: string): string | null {\n const { tree, frontmatter: fm } = parseMd(content)\n if (fm.title)\n return fm.title\n\n let title: string | null = null\n visit(tree, 'heading', (node) => {\n if (node.depth === 1 && !title) {\n // Strip {#id} anchors and leading backslash escapes (e.g. `# \\`)\n const text = stripHeadingAnchors(toString(node)).replace(/^\\\\+\\s*/, '').trim()\n if (text.length > 0)\n title = text\n }\n })\n\n return title\n}\n\n/** Extract first paragraph text, 150 char max */\nexport function extractDescription(content: string): string | null {\n const { tree } = parseMd(content)\n\n let desc: string | null = null\n visit(tree, 'paragraph', (node, _index, parent) => {\n // Only top-level paragraphs (skip blockquote children, list items, etc.)\n if (desc || parent?.type !== 'root')\n return\n\n const text = toString(node).trim()\n if (text.length === 0)\n return\n\n // Strip markdown link syntax remnants and formatting chars\n let clean = text.replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, '$1').replace(/[`*_~]/g, '')\n if (clean.length > 150)\n clean = `${clean.slice(0, 147)}...`\n desc = clean\n })\n\n return desc\n}\n\n/** Extract all headings with depth and text */\nexport function extractHeadings(content: string): MdHeading[] {\n const { tree } = parseMd(content)\n const headings: MdHeading[] = []\n\n visit(tree, 'heading', (node) => {\n headings.push({ depth: node.depth, text: stripHeadingAnchors(toString(node)) })\n })\n\n return headings\n}\n\n/** Extract all links (deduped by url) */\nexport function extractLinks(content: string): MdLink[] {\n const { tree } = parseMd(content)\n const links: MdLink[] = []\n const seen = new Set<string>()\n\n visit(tree, 'link', (node) => {\n if (!seen.has(node.url)) {\n seen.add(node.url)\n links.push({ title: toString(node), url: node.url })\n }\n })\n\n return links\n}\n\n/** Strip frontmatter block, return body only */\nexport function stripFrontmatter(content: string): string {\n const match = content.match(/^---\\r?\\n[\\s\\S]*?\\r?\\n---\\r?\\n/)\n return match ? content.slice(match[0].length).trim() : content\n}\n"],"mappings":";;;;;;;;AA6BA,SAAgB,QAAQ,SAA2B;CACjD,MAAM,OAAO,aAAa,SAAS;EACjC,YAAY,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;EACnC,iBAAiB,CAAC,wBAAwB,CAAC,OAAO,CAAC,CAAA;EACpD,CAAC;CAEF,MAAM,KAA6B,EAAE;AACrC,OAAM,MAAM,SAAS,SAAgB;AACnC,MAAI,KAAK,SAAS,OAChB,MAAK,MAAM,QAAS,KAAa,MAAM,MAAM,KAAK,EAAE;GAClD,MAAM,KAAK,YAAY,KAAK;AAC5B,OAAI,GACF,IAAG,GAAG,MAAM,GAAG;;GAGrB;AAEF,QAAO;EAAE;EAAM,aAAa;EAAI;;;AAIlC,SAAgB,iBAAiB,SAAyC;AACxE,QAAO,QAAQ,QAAQ,CAAC;;;AAI1B,SAAS,oBAAoB,MAAsB;AACjD,QAAO,KAAK,QAAQ,qBAAqB,GAAG,CAAC,MAAM;;;AAIrD,SAAgB,aAAa,SAAgC;CAC3D,MAAM,EAAE,MAAM,aAAa,OAAO,QAAQ,QAAQ;AAClD,KAAI,GAAG,MACL,QAAO,GAAG;CAEZ,IAAI,QAAuB;AAC3B,OAAM,MAAM,YAAY,SAAS;AAC/B,MAAI,KAAK,UAAU,KAAK,CAAC,OAAO;GAE9B,MAAM,OAAO,oBAAoB,SAAS,KAAK,CAAC,CAAC,QAAQ,WAAW,GAAG,CAAC,MAAM;AAC9E,OAAI,KAAK,SAAS,EAChB,SAAQ;;GAEZ;AAEF,QAAO;;;AAIT,SAAgB,mBAAmB,SAAgC;CACjE,MAAM,EAAE,SAAS,QAAQ,QAAQ;CAEjC,IAAI,OAAsB;AAC1B,OAAM,MAAM,cAAc,MAAM,QAAQ,WAAW;AAEjD,MAAI,QAAQ,QAAQ,SAAS,OAC3B;EAEF,MAAM,OAAO,SAAS,KAAK,CAAC,MAAM;AAClC,MAAI,KAAK,WAAW,EAClB;EAGF,IAAI,QAAQ,KAAK,QAAQ,0BAA0B,KAAK,CAAC,QAAQ,WAAW,GAAG;AAC/E,MAAI,MAAM,SAAS,IACjB,SAAQ,GAAG,MAAM,MAAM,GAAG,IAAI,CAAC;AACjC,SAAO;GACP;AAEF,QAAO;;;AAgBT,SAAgB,aAAa,SAA2B;CACtD,MAAM,EAAE,SAAS,QAAQ,QAAQ;CACjC,MAAM,QAAkB,EAAE;CAC1B,MAAM,uBAAO,IAAI,KAAa;AAE9B,OAAM,MAAM,SAAS,SAAS;AAC5B,MAAI,CAAC,KAAK,IAAI,KAAK,IAAI,EAAE;AACvB,QAAK,IAAI,KAAK,IAAI;AAClB,SAAM,KAAK;IAAE,OAAO,SAAS,KAAK;IAAE,KAAK,KAAK;IAAK,CAAC;;GAEtD;AAEF,QAAO;;;AAIT,SAAgB,iBAAiB,SAAyB;CACxD,MAAM,QAAQ,QAAQ,MAAM,iCAAiC;AAC7D,QAAO,QAAQ,QAAQ,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG"}
|
package/dist/_chunks/pool.mjs
CHANGED
|
@@ -3,6 +3,7 @@ import { dirname, join } from "pathe";
|
|
|
3
3
|
import { existsSync } from "node:fs";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { Worker } from "node:worker_threads";
|
|
6
|
+
//#region src/retriv/pool.ts
|
|
6
7
|
var pool_exports = /* @__PURE__ */ __exportAll({
|
|
7
8
|
createIndexInWorker: () => createIndexInWorker,
|
|
8
9
|
shutdownWorker: () => shutdownWorker
|
|
@@ -115,6 +116,7 @@ async function shutdownWorker() {
|
|
|
115
116
|
w.postMessage({ type: "shutdown" });
|
|
116
117
|
});
|
|
117
118
|
}
|
|
119
|
+
//#endregion
|
|
118
120
|
export { shutdownWorker as n, pool_exports as t };
|
|
119
121
|
|
|
120
122
|
//# sourceMappingURL=pool.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pool.mjs","names":[],"sources":["../../src/retriv/pool.ts"],"sourcesContent":["import type { IndexConfig, Document as RetrivDocument } from './types.ts'\nimport type { WorkerMessage, WorkerResponse } from './worker.ts'\nimport { existsSync } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { Worker } from 'node:worker_threads'\nimport { dirname, join } from 'pathe'\n\ninterface PendingTask {\n id: number\n resolve: () => void\n reject: (err: Error) => void\n onProgress?: IndexConfig['onProgress']\n}\n\nlet worker: Worker | null = null\nlet taskId = 0\nconst pending = new Map<number, PendingTask>()\nconst queue: Array<() => void> = []\nlet running = false\n\nfunction resolveWorkerPath(): { path: string, execArgv?: string[] } {\n const dir = dirname(fileURLToPath(import.meta.url))\n\n // Bundled: dist/retriv/worker.mjs (resolve from package root, not chunk dir)\n for (const candidate of [join(dir, 'worker.mjs'), join(dir, '..', 'retriv', 'worker.mjs')]) {\n if (existsSync(candidate))\n return { path: candidate }\n }\n\n // Dev stub: src/retriv/pool.ts → src/retriv/worker.ts\n return { path: join(dir, 'worker.ts'), execArgv: ['--experimental-strip-types'] }\n}\n\nfunction ensureWorker(): Worker {\n if (worker)\n return worker\n\n const config = resolveWorkerPath()\n const w = new Worker(config.path, {\n execArgv: config.execArgv,\n })\n\n w.on('message', (msg: WorkerResponse) => {\n const task = pending.get(msg.id)\n if (!task)\n return\n\n if (msg.type === 'progress') {\n task.onProgress?.({ phase: msg.phase as any, current: msg.current, total: msg.total })\n }\n else if (msg.type === 'done') {\n pending.delete(msg.id)\n task.resolve()\n }\n else if (msg.type === 'error') {\n pending.delete(msg.id)\n task.reject(new Error(msg.message))\n }\n })\n\n w.on('error', (err: Error) => {\n for (const task of pending.values())\n task.reject(err)\n pending.clear()\n worker = null\n })\n\n w.on('exit', (code) => {\n if (pending.size > 0) {\n const err = new Error(`Worker exited (code ${code}) with ${pending.size} pending tasks`)\n for (const task of pending.values())\n task.reject(err)\n pending.clear()\n }\n worker = null\n })\n\n worker = w\n return w\n}\n\nfunction drainQueue() {\n if (running || queue.length === 0)\n return\n const next = queue.shift()!\n next()\n}\n\nexport async function createIndexInWorker(\n documents: RetrivDocument[],\n config: IndexConfig,\n): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const run = () => {\n running = true\n const id = ++taskId\n\n let w: Worker\n try {\n w = ensureWorker()\n }\n catch (err) {\n running = false\n drainQueue()\n reject(err instanceof Error ? err : new Error(String(err)))\n return\n }\n\n pending.set(id, {\n id,\n resolve: () => {\n running = false\n drainQueue()\n resolve()\n },\n reject: (err) => {\n running = false\n drainQueue()\n reject(err)\n },\n onProgress: config.onProgress,\n })\n\n const msg: WorkerMessage = {\n type: 'index',\n id,\n documents,\n dbPath: config.dbPath,\n }\n\n w.postMessage(msg)\n }\n\n if (running) {\n queue.push(run)\n }\n else {\n run()\n }\n })\n}\n\nexport async function shutdownWorker(): Promise<void> {\n if (!worker)\n return\n\n const w = worker\n worker = null\n\n return new Promise<void>((resolve) => {\n const timeout = setTimeout(() => {\n w.terminate().then(() => resolve(), () => resolve())\n }, 5000)\n\n w.once('exit', () => {\n clearTimeout(timeout)\n resolve()\n })\n\n w.postMessage({ type: 'shutdown' } satisfies WorkerMessage)\n })\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"pool.mjs","names":[],"sources":["../../src/retriv/pool.ts"],"sourcesContent":["import type { IndexConfig, Document as RetrivDocument } from './types.ts'\nimport type { WorkerMessage, WorkerResponse } from './worker.ts'\nimport { existsSync } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { Worker } from 'node:worker_threads'\nimport { dirname, join } from 'pathe'\n\ninterface PendingTask {\n id: number\n resolve: () => void\n reject: (err: Error) => void\n onProgress?: IndexConfig['onProgress']\n}\n\nlet worker: Worker | null = null\nlet taskId = 0\nconst pending = new Map<number, PendingTask>()\nconst queue: Array<() => void> = []\nlet running = false\n\nfunction resolveWorkerPath(): { path: string, execArgv?: string[] } {\n const dir = dirname(fileURLToPath(import.meta.url))\n\n // Bundled: dist/retriv/worker.mjs (resolve from package root, not chunk dir)\n for (const candidate of [join(dir, 'worker.mjs'), join(dir, '..', 'retriv', 'worker.mjs')]) {\n if (existsSync(candidate))\n return { path: candidate }\n }\n\n // Dev stub: src/retriv/pool.ts → src/retriv/worker.ts\n return { path: join(dir, 'worker.ts'), execArgv: ['--experimental-strip-types'] }\n}\n\nfunction ensureWorker(): Worker {\n if (worker)\n return worker\n\n const config = resolveWorkerPath()\n const w = new Worker(config.path, {\n execArgv: config.execArgv,\n })\n\n w.on('message', (msg: WorkerResponse) => {\n const task = pending.get(msg.id)\n if (!task)\n return\n\n if (msg.type === 'progress') {\n task.onProgress?.({ phase: msg.phase as any, current: msg.current, total: msg.total })\n }\n else if (msg.type === 'done') {\n pending.delete(msg.id)\n task.resolve()\n }\n else if (msg.type === 'error') {\n pending.delete(msg.id)\n task.reject(new Error(msg.message))\n }\n })\n\n w.on('error', (err: Error) => {\n for (const task of pending.values())\n task.reject(err)\n pending.clear()\n worker = null\n })\n\n w.on('exit', (code) => {\n if (pending.size > 0) {\n const err = new Error(`Worker exited (code ${code}) with ${pending.size} pending tasks`)\n for (const task of pending.values())\n task.reject(err)\n pending.clear()\n }\n worker = null\n })\n\n worker = w\n return w\n}\n\nfunction drainQueue() {\n if (running || queue.length === 0)\n return\n const next = queue.shift()!\n next()\n}\n\nexport async function createIndexInWorker(\n documents: RetrivDocument[],\n config: IndexConfig,\n): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const run = () => {\n running = true\n const id = ++taskId\n\n let w: Worker\n try {\n w = ensureWorker()\n }\n catch (err) {\n running = false\n drainQueue()\n reject(err instanceof Error ? err : new Error(String(err)))\n return\n }\n\n pending.set(id, {\n id,\n resolve: () => {\n running = false\n drainQueue()\n resolve()\n },\n reject: (err) => {\n running = false\n drainQueue()\n reject(err)\n },\n onProgress: config.onProgress,\n })\n\n const msg: WorkerMessage = {\n type: 'index',\n id,\n documents,\n dbPath: config.dbPath,\n }\n\n w.postMessage(msg)\n }\n\n if (running) {\n queue.push(run)\n }\n else {\n run()\n }\n })\n}\n\nexport async function shutdownWorker(): Promise<void> {\n if (!worker)\n return\n\n const w = worker\n worker = null\n\n return new Promise<void>((resolve) => {\n const timeout = setTimeout(() => {\n w.terminate().then(() => resolve(), () => resolve())\n }, 5000)\n\n w.once('exit', () => {\n clearTimeout(timeout)\n resolve()\n })\n\n w.postMessage({ type: 'shutdown' } satisfies WorkerMessage)\n })\n}\n"],"mappings":";;;;;;;;;;AAcA,IAAI,SAAwB;AAC5B,IAAI,SAAS;AACb,MAAM,0BAAU,IAAI,KAA0B;AAC9C,MAAM,QAA2B,EAAE;AACnC,IAAI,UAAU;AAEd,SAAS,oBAA2D;CAClE,MAAM,MAAM,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;AAGnD,MAAK,MAAM,aAAa,CAAC,KAAK,KAAK,aAAa,EAAE,KAAK,KAAK,MAAM,UAAU,aAAa,CAAC,CACxF,KAAI,WAAW,UAAU,CACvB,QAAO,EAAE,MAAM,WAAW;AAI9B,QAAO;EAAE,MAAM,KAAK,KAAK,YAAY;EAAE,UAAU,CAAC,6BAAA;EAA+B;;AAGnF,SAAS,eAAuB;AAC9B,KAAI,OACF,QAAO;CAET,MAAM,SAAS,mBAAmB;CAClC,MAAM,IAAI,IAAI,OAAO,OAAO,MAAM,EAChC,UAAU,OAAO,UAClB,CAAC;AAEF,GAAE,GAAG,YAAY,QAAwB;EACvC,MAAM,OAAO,QAAQ,IAAI,IAAI,GAAG;AAChC,MAAI,CAAC,KACH;AAEF,MAAI,IAAI,SAAS,WACf,MAAK,aAAa;GAAE,OAAO,IAAI;GAAc,SAAS,IAAI;GAAS,OAAO,IAAI;GAAO,CAAC;WAE/E,IAAI,SAAS,QAAQ;AAC5B,WAAQ,OAAO,IAAI,GAAG;AACtB,QAAK,SAAS;aAEP,IAAI,SAAS,SAAS;AAC7B,WAAQ,OAAO,IAAI,GAAG;AACtB,QAAK,OAAO,IAAI,MAAM,IAAI,QAAQ,CAAC;;GAErC;AAEF,GAAE,GAAG,UAAU,QAAe;AAC5B,OAAK,MAAM,QAAQ,QAAQ,QAAQ,CACjC,MAAK,OAAO,IAAI;AAClB,UAAQ,OAAO;AACf,WAAS;GACT;AAEF,GAAE,GAAG,SAAS,SAAS;AACrB,MAAI,QAAQ,OAAO,GAAG;GACpB,MAAM,sBAAM,IAAI,MAAM,uBAAuB,KAAK,SAAS,QAAQ,KAAK,gBAAgB;AACxF,QAAK,MAAM,QAAQ,QAAQ,QAAQ,CACjC,MAAK,OAAO,IAAI;AAClB,WAAQ,OAAO;;AAEjB,WAAS;GACT;AAEF,UAAS;AACT,QAAO;;AAGT,SAAS,aAAa;AACpB,KAAI,WAAW,MAAM,WAAW,EAC9B;AACW,OAAM,OAAO,EACpB;;AAGR,eAAsB,oBACpB,WACA,QACe;AACf,QAAO,IAAI,SAAe,SAAS,WAAW;EAC5C,MAAM,YAAY;AAChB,aAAU;GACV,MAAM,KAAK,EAAE;GAEb,IAAI;AACJ,OAAI;AACF,QAAI,cAAc;YAEb,KAAK;AACV,cAAU;AACV,gBAAY;AACZ,WAAO,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC,CAAC;AAC3D;;AAGF,WAAQ,IAAI,IAAI;IACd;IACA,eAAe;AACb,eAAU;AACV,iBAAY;AACZ,cAAS;;IAEX,SAAS,QAAQ;AACf,eAAU;AACV,iBAAY;AACZ,YAAO,IAAI;;IAEb,YAAY,OAAO;IACpB,CAAC;GAEF,MAAM,MAAqB;IACzB,MAAM;IACN;IACA;IACA,QAAQ,OAAO;IAChB;AAED,KAAE,YAAY,IAAI;;AAGpB,MAAI,QACF,OAAM,KAAK,IAAI;MAGf,MAAK;GAEP;;AAGJ,eAAsB,iBAAgC;AACpD,KAAI,CAAC,OACH;CAEF,MAAM,IAAI;AACV,UAAS;AAET,QAAO,IAAI,SAAe,YAAY;EACpC,MAAM,UAAU,iBAAiB;AAC/B,KAAE,WAAW,CAAC,WAAW,SAAS,QAAQ,SAAS,CAAC;KACnD,IAAK;AAER,IAAE,KAAK,cAAc;AACnB,gBAAa,QAAQ;AACrB,YAAS;IACT;AAEF,IAAE,YAAY,EAAE,MAAM,YAAY,CAAyB;GAC3D"}
|