@agntk/agent-harness 0.1.2 → 0.1.3
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/cli/index.js +1 -1
- package/dist/index.js +77 -1
- package/dist/index.js.map +1 -1
- package/dist/{universal-installer-QGS4SJGX.js → universal-installer-EVBDGOWM.js} +79 -2
- package/dist/universal-installer-EVBDGOWM.js.map +1 -0
- package/package.json +1 -1
- package/dist/universal-installer-QGS4SJGX.js.map +0 -1
|
@@ -19,8 +19,79 @@ import "./chunk-ZZJOFKAT.js";
|
|
|
19
19
|
import { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync } from "fs";
|
|
20
20
|
import { join, basename, extname } from "path";
|
|
21
21
|
import { tmpdir } from "os";
|
|
22
|
+
import { createRequire } from "module";
|
|
22
23
|
import matter from "gray-matter";
|
|
23
24
|
import { parse as parseYaml } from "yaml";
|
|
25
|
+
function getHarnessVersion() {
|
|
26
|
+
try {
|
|
27
|
+
const require2 = createRequire(import.meta.url);
|
|
28
|
+
const candidates = [
|
|
29
|
+
"../package.json",
|
|
30
|
+
"../../package.json",
|
|
31
|
+
"../../../package.json"
|
|
32
|
+
];
|
|
33
|
+
for (const candidate of candidates) {
|
|
34
|
+
try {
|
|
35
|
+
const pkg = require2(candidate);
|
|
36
|
+
if (pkg.name === "@agntk/agent-harness" && pkg.version) {
|
|
37
|
+
return pkg.version;
|
|
38
|
+
}
|
|
39
|
+
} catch {
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return "unknown";
|
|
43
|
+
} catch {
|
|
44
|
+
return "unknown";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async function resolveGithubCommitSha(url) {
|
|
48
|
+
const match = url.match(
|
|
49
|
+
/^https?:\/\/raw\.githubusercontent\.com\/([^/]+)\/([^/]+)\/([^/]+)\/(.+)$/
|
|
50
|
+
);
|
|
51
|
+
if (!match) return null;
|
|
52
|
+
const [, owner, repo, ref, path] = match;
|
|
53
|
+
if (/^[0-9a-f]{40}$/i.test(ref)) return ref;
|
|
54
|
+
const apiUrl = `https://api.github.com/repos/${owner}/${repo}/contents/${path}?ref=${ref}`;
|
|
55
|
+
const controller = new AbortController();
|
|
56
|
+
const timeout = setTimeout(() => controller.abort(), 5e3);
|
|
57
|
+
try {
|
|
58
|
+
const response = await fetch(apiUrl, {
|
|
59
|
+
signal: controller.signal,
|
|
60
|
+
headers: { "Accept": "application/vnd.github+json" }
|
|
61
|
+
});
|
|
62
|
+
if (!response.ok) return null;
|
|
63
|
+
const data = await response.json();
|
|
64
|
+
if (typeof data.sha === "string" && /^[0-9a-f]{40}$/i.test(data.sha)) {
|
|
65
|
+
return data.sha;
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
} catch {
|
|
69
|
+
return null;
|
|
70
|
+
} finally {
|
|
71
|
+
clearTimeout(timeout);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async function recordProvenance(content, originalSource) {
|
|
75
|
+
let parsed;
|
|
76
|
+
try {
|
|
77
|
+
parsed = matter(content);
|
|
78
|
+
} catch {
|
|
79
|
+
return content;
|
|
80
|
+
}
|
|
81
|
+
const data = parsed.data;
|
|
82
|
+
if (!data.source) {
|
|
83
|
+
data.source = originalSource;
|
|
84
|
+
}
|
|
85
|
+
if (!data.source_commit) {
|
|
86
|
+
const sha = await resolveGithubCommitSha(originalSource);
|
|
87
|
+
if (sha) {
|
|
88
|
+
data.source_commit = sha;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
data.installed_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
92
|
+
data.installed_by = `agent-harness@${getHarnessVersion()}`;
|
|
93
|
+
return matter.stringify(parsed.content, data);
|
|
94
|
+
}
|
|
24
95
|
var VALID_TYPES = ["rule", "instinct", "skill", "playbook", "workflow", "tool", "agent"];
|
|
25
96
|
var TYPE_DIRS = {
|
|
26
97
|
rule: "rules",
|
|
@@ -427,10 +498,15 @@ async function universalInstall(harnessDir, source, options) {
|
|
|
427
498
|
result.format = detection;
|
|
428
499
|
const normalized = normalizeToHarness(content, filename, detection, options);
|
|
429
500
|
result.fixes.push(...normalized.fixes);
|
|
501
|
+
let finalContent = normalized.content;
|
|
502
|
+
if (source.startsWith("http://") || source.startsWith("https://")) {
|
|
503
|
+
finalContent = await recordProvenance(finalContent, source);
|
|
504
|
+
result.fixes.push("Recorded provenance (source, installed_at, installed_by)");
|
|
505
|
+
}
|
|
430
506
|
const tempDir = join(tmpdir(), "harness-install");
|
|
431
507
|
mkdirSync(tempDir, { recursive: true });
|
|
432
508
|
const tempPath = join(tempDir, normalized.filename);
|
|
433
|
-
writeFileSync(tempPath,
|
|
509
|
+
writeFileSync(tempPath, finalContent, "utf-8");
|
|
434
510
|
if (!options?.skipFix) {
|
|
435
511
|
const fixResult = fixCapability(tempPath);
|
|
436
512
|
result.fixes.push(...fixResult.fixes_applied);
|
|
@@ -572,7 +648,8 @@ export {
|
|
|
572
648
|
installFromFile,
|
|
573
649
|
installFromUrl,
|
|
574
650
|
normalizeToHarness,
|
|
651
|
+
recordProvenance,
|
|
575
652
|
resolveSource,
|
|
576
653
|
universalInstall
|
|
577
654
|
};
|
|
578
|
-
//# sourceMappingURL=universal-installer-
|
|
655
|
+
//# sourceMappingURL=universal-installer-EVBDGOWM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/runtime/universal-installer.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync } from 'fs';\nimport { join, basename, extname } from 'path';\nimport { tmpdir } from 'os';\nimport { createRequire } from 'module';\nimport matter from 'gray-matter';\nimport { parse as parseYaml } from 'yaml';\nimport { fixCapability, installCapability, downloadCapability } from './intake.js';\nimport { autoProcessFile } from './auto-processor.js';\nimport { discoverSources, loadAllSources } from './sources.js';\nimport type { Source, SourceDiscoveryResult } from './sources.js';\nimport { log } from '../core/logger.js';\n\n// ─── Provenance ──────────────────────────────────────────────────────────────\n\n/**\n * Read the harness's own package.json version for the `installed_by` field.\n *\n * Has to handle three possible runtime layouts because tsup bundles flat:\n * - Dev/test: src/runtime/universal-installer.ts → ../../package.json\n * - Built bin: dist/cli/index.js → ../../package.json\n * - Built lib: dist/<bundle>.js → ../package.json\n *\n * Walks up one directory at a time, requires `package.json`, and returns\n * the version of the FIRST one whose name is `@agntk/agent-harness`. Stops\n * after a few levels so a broken environment never causes an infinite loop.\n * Returns \"unknown\" on any failure so an install never blocks on this.\n */\nfunction getHarnessVersion(): string {\n try {\n const require = createRequire(import.meta.url);\n const candidates = [\n '../package.json',\n '../../package.json',\n '../../../package.json',\n ];\n for (const candidate of candidates) {\n try {\n const pkg = require(candidate) as { name?: string; version?: string };\n if (pkg.name === '@agntk/agent-harness' && pkg.version) {\n return pkg.version;\n }\n } catch {\n // Candidate didn't resolve — try the next one.\n }\n }\n return 'unknown';\n } catch {\n return 'unknown';\n }\n}\n\n/**\n * Resolve a commit SHA for a GitHub raw URL by calling the GitHub Contents API.\n *\n * Input URL shape:\n * https://raw.githubusercontent.com/{owner}/{repo}/{ref}/{path}\n * where {ref} is either a 40-char commit SHA or a branch/tag name.\n *\n * Returns the SHA (either the one already in the URL, or the one resolved from\n * a branch name via the Contents API). Returns `null` on any failure — network\n * error, timeout, 404, non-github host, unparseable URL — so the install can\n * proceed without source_commit.\n */\nasync function resolveGithubCommitSha(url: string): Promise<string | null> {\n // Only handle raw.githubusercontent.com URLs\n const match = url.match(\n /^https?:\\/\\/raw\\.githubusercontent\\.com\\/([^/]+)\\/([^/]+)\\/([^/]+)\\/(.+)$/,\n );\n if (!match) return null;\n const [, owner, repo, ref, path] = match;\n\n // If ref is already a 40-char hex SHA, just return it\n if (/^[0-9a-f]{40}$/i.test(ref)) return ref;\n\n // Otherwise resolve via the Contents API\n const apiUrl = `https://api.github.com/repos/${owner}/${repo}/contents/${path}?ref=${ref}`;\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 5000);\n try {\n const response = await fetch(apiUrl, {\n signal: controller.signal,\n headers: { 'Accept': 'application/vnd.github+json' },\n });\n if (!response.ok) return null;\n const data = (await response.json()) as { sha?: string };\n if (typeof data.sha === 'string' && /^[0-9a-f]{40}$/i.test(data.sha)) {\n return data.sha;\n }\n return null;\n } catch {\n return null;\n } finally {\n clearTimeout(timeout);\n }\n}\n\n/**\n * Inject provenance fields into a normalized markdown file's frontmatter.\n *\n * Rules:\n * - `source` and `source_commit` are preserved if already present (idempotent)\n * - `installed_at` and `installed_by` are always updated to reflect the most\n * recent install action\n * - `source_commit` is only written when a SHA could be resolved\n *\n * @param content Normalized markdown content with existing frontmatter\n * @param originalSource The exact URL the user passed to `harness install`\n * @returns The content with provenance fields merged into frontmatter\n */\nexport async function recordProvenance(\n content: string,\n originalSource: string,\n): Promise<string> {\n let parsed: ReturnType<typeof matter>;\n try {\n parsed = matter(content);\n } catch {\n return content;\n }\n\n const data = parsed.data as Record<string, unknown>;\n\n // Preserve existing source — idempotency rule\n if (!data.source) {\n data.source = originalSource;\n }\n\n // Preserve existing source_commit; only resolve if missing AND URL is github raw\n if (!data.source_commit) {\n const sha = await resolveGithubCommitSha(originalSource);\n if (sha) {\n data.source_commit = sha;\n }\n }\n\n // Always update these to reflect the most recent install\n data.installed_at = new Date().toISOString();\n data.installed_by = `agent-harness@${getHarnessVersion()}`;\n\n return matter.stringify(parsed.content, data);\n}\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** Detected source format of a file to be installed. */\nexport type SourceFormat =\n | 'harness' // Already harness convention (frontmatter + L0/L1)\n | 'claude-skill' // Claude Code SKILL.md (plain markdown, no frontmatter)\n | 'faf-yaml' // .faf YAML format\n | 'raw-markdown' // Plain markdown with no harness structure\n | 'bash-hook' // Bash/shell script (hook or workflow)\n | 'mcp-config' // MCP server configuration (JSON/YAML)\n | 'unknown';\n\n/** Result of format detection. */\nexport interface FormatDetection {\n /** Detected format */\n format: SourceFormat;\n /** Inferred primitive type (skill, agent, rule, etc.) */\n primitiveType: string | null;\n /** Confidence score (0-1) */\n confidence: number;\n /** Reasons for the detection */\n reasons: string[];\n}\n\n/** Result of a universal install operation. */\nexport interface UniversalInstallResult {\n /** Whether installation succeeded */\n installed: boolean;\n /** Source reference that was resolved */\n source: string;\n /** Detected format */\n format: FormatDetection;\n /** Path where the file was installed */\n destination: string;\n /** Fixes applied during normalization */\n fixes: string[];\n /** Errors encountered */\n errors: string[];\n /** Suggested dependencies to install */\n suggestedDependencies: string[];\n}\n\n/** Options for the universal installer. */\nexport interface UniversalInstallOptions {\n /** Override the detected primitive type (skill, rule, agent, etc.) */\n type?: string;\n /** Override the generated ID */\n id?: string;\n /** Force install even if validation has warnings */\n force?: boolean;\n /** Skip auto-fix (frontmatter, L0/L1 generation) */\n skipFix?: boolean;\n /** Additional tags to add */\n tags?: string[];\n}\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\nconst VALID_TYPES = ['rule', 'instinct', 'skill', 'playbook', 'workflow', 'tool', 'agent'];\n\nconst TYPE_DIRS: Record<string, string> = {\n rule: 'rules',\n instinct: 'instincts',\n skill: 'skills',\n playbook: 'playbooks',\n workflow: 'workflows',\n tool: 'tools',\n agent: 'agents',\n};\n\n// ─── Format Detection ────────────────────────────────────────────────────────\n\n/**\n * Detect the format of a file based on its content and extension.\n *\n * Detection heuristics:\n * - Has `---` frontmatter with `id:` + `status:` → harness convention\n * - Has `---` frontmatter but missing harness fields → raw-markdown\n * - `.faf` or `.yaml`/`.yml` with `type:` + `content:` keys → faf-yaml\n * - `.sh`/`.bash` or starts with `#!/` → bash-hook\n * - JSON/YAML with `mcpServers` or `servers` → mcp-config\n * - Plain markdown with no frontmatter → claude-skill or raw-markdown\n */\nexport function detectFormat(content: string, filename: string): FormatDetection {\n const ext = extname(filename).toLowerCase();\n const reasons: string[] = [];\n let format: SourceFormat = 'unknown';\n let primitiveType: string | null = null;\n let confidence = 0;\n\n // Check for bash/shell scripts\n if (ext === '.sh' || ext === '.bash' || content.trimStart().startsWith('#!/')) {\n format = 'bash-hook';\n primitiveType = 'workflow';\n confidence = 0.9;\n reasons.push('Shell script detected (shebang or .sh extension)');\n\n // Hooks are typically short scripts with specific patterns\n if (content.includes('hook') || content.includes('pre-commit') || content.includes('post-')) {\n primitiveType = 'workflow';\n reasons.push('Hook pattern detected in content');\n }\n\n return { format, primitiveType, confidence, reasons };\n }\n\n // Check for JSON/YAML MCP configs\n if (ext === '.json') {\n try {\n const parsed = JSON.parse(content) as Record<string, unknown>;\n if (parsed.mcpServers || parsed.servers || parsed.command || parsed.args) {\n format = 'mcp-config';\n primitiveType = 'tool';\n confidence = 0.9;\n reasons.push('MCP configuration JSON detected');\n return { format, primitiveType, confidence, reasons };\n }\n } catch {\n // Not valid JSON, continue\n }\n }\n\n // Check for .faf YAML format\n if (ext === '.faf' || ext === '.yaml' || ext === '.yml') {\n try {\n const parsed = parseYaml(content) as Record<string, unknown>;\n if (parsed.type && parsed.content) {\n format = 'faf-yaml';\n primitiveType = inferTypeFromFafType(String(parsed.type));\n confidence = 0.9;\n reasons.push(`.faf YAML format with type: ${parsed.type}`);\n return { format, primitiveType, confidence, reasons };\n }\n // YAML with mcpServers\n if (parsed.mcpServers || parsed.servers) {\n format = 'mcp-config';\n primitiveType = 'tool';\n confidence = 0.85;\n reasons.push('MCP configuration YAML detected');\n return { format, primitiveType, confidence, reasons };\n }\n } catch {\n // Not valid YAML, continue\n }\n }\n\n // Check for markdown content\n if (ext === '.md' || ext === '' || !ext) {\n // Try to parse frontmatter\n try {\n const parsed = matter(content);\n const data = parsed.data as Record<string, unknown>;\n\n if (data.id && data.status) {\n // Has harness-style frontmatter\n format = 'harness';\n confidence = 0.95;\n reasons.push('Harness frontmatter detected (id + status fields)');\n\n // Detect type from tags\n const tags = Array.isArray(data.tags)\n ? (data.tags as string[]).map((t) => String(t).toLowerCase())\n : [];\n for (const type of VALID_TYPES) {\n if (tags.includes(type)) {\n primitiveType = type;\n break;\n }\n }\n\n return { format, primitiveType, confidence, reasons };\n }\n\n if (Object.keys(data).length > 0) {\n // Has some frontmatter but not harness convention\n format = 'raw-markdown';\n confidence = 0.7;\n reasons.push('Markdown with non-harness frontmatter');\n }\n } catch {\n // No frontmatter or parse error\n }\n\n // Check for Claude Code SKILL.md patterns\n if (format === 'unknown' || format === 'raw-markdown') {\n const isClaudeSkill = detectClaudeSkillPattern(content, filename);\n if (isClaudeSkill) {\n format = 'claude-skill';\n primitiveType = 'skill';\n confidence = 0.8;\n reasons.push('Claude Code SKILL.md pattern detected');\n return { format, primitiveType, confidence, reasons };\n }\n }\n\n // Plain markdown — infer type from content\n if (format === 'unknown') {\n format = 'raw-markdown';\n confidence = 0.5;\n reasons.push('Plain markdown without frontmatter');\n }\n\n // Try to infer type from content/filename\n if (!primitiveType) {\n primitiveType = inferTypeFromContent(content, filename);\n if (primitiveType) {\n reasons.push(`Type inferred from content/filename: ${primitiveType}`);\n }\n }\n\n return { format, primitiveType, confidence, reasons };\n }\n\n return { format, primitiveType, confidence, reasons };\n}\n\n// ─── Format Normalization ────────────────────────────────────────────────────\n\n/**\n * Normalize content from any detected format to harness convention.\n * Returns the normalized markdown content ready for writing.\n */\nexport function normalizeToHarness(\n content: string,\n filename: string,\n detection: FormatDetection,\n options?: UniversalInstallOptions,\n): { content: string; filename: string; fixes: string[] } {\n const fixes: string[] = [];\n const type = options?.type ?? detection.primitiveType;\n\n switch (detection.format) {\n case 'harness':\n // Already in harness format — just pass through\n return { content, filename, fixes: ['Already in harness format'] };\n\n case 'claude-skill':\n return normalizeClaudeSkill(content, filename, type, options, fixes);\n\n case 'faf-yaml':\n return normalizeFafYaml(content, filename, type, options, fixes);\n\n case 'raw-markdown':\n return normalizeRawMarkdown(content, filename, type, options, fixes);\n\n case 'bash-hook':\n return normalizeBashHook(content, filename, type, options, fixes);\n\n case 'mcp-config':\n return normalizeMcpConfig(content, filename, options, fixes);\n\n default:\n return normalizeRawMarkdown(content, filename, type, options, fixes);\n }\n}\n\n/**\n * Convert Claude Code SKILL.md to harness convention.\n * Claude skills are plain markdown — add frontmatter + L0/L1.\n */\nfunction normalizeClaudeSkill(\n content: string,\n filename: string,\n type: string | null,\n options: UniversalInstallOptions | undefined,\n fixes: string[],\n): { content: string; filename: string; fixes: string[] } {\n const id = options?.id ?? deriveId(filename);\n const primitiveType = type ?? 'skill';\n const tags = [primitiveType, ...(options?.tags ?? [])];\n\n // Extract first heading as title\n const headingMatch = content.match(/^#\\s+(.+)$/m);\n const title = headingMatch ? headingMatch[1].trim() : id;\n\n const frontmatter: Record<string, unknown> = {\n id,\n created: new Date().toISOString().split('T')[0],\n author: 'human',\n status: 'active',\n tags,\n };\n\n // Generate L0 from title/first heading\n const l0 = title.length > 120 ? title.slice(0, 117) + '...' : title;\n\n // Generate L1 from first paragraph\n const paragraphs = content.split(/\\n{2,}/).filter((p) => {\n const trimmed = p.trim();\n return trimmed.length > 0 && !trimmed.startsWith('#') && !trimmed.startsWith('<!--');\n });\n const l1 = paragraphs.length > 0\n ? paragraphs[0].replace(/\\n/g, ' ').trim().slice(0, 300)\n : '';\n\n let body = `<!-- L0: ${l0} -->\\n`;\n if (l1) {\n body += `<!-- L1: ${l1} -->\\n`;\n }\n body += '\\n' + content;\n\n const result = matter.stringify(body, frontmatter);\n fixes.push('Added harness frontmatter (id, status, tags)');\n fixes.push(`Generated L0 from heading: \"${l0}\"`);\n if (l1) fixes.push('Generated L1 from first paragraph');\n\n const outFilename = ensureMdExtension(filename);\n return { content: result, filename: outFilename, fixes };\n}\n\n/**\n * Convert .faf YAML format to harness markdown.\n */\nfunction normalizeFafYaml(\n content: string,\n filename: string,\n type: string | null,\n options: UniversalInstallOptions | undefined,\n fixes: string[],\n): { content: string; filename: string; fixes: string[] } {\n let parsed: Record<string, unknown>;\n try {\n parsed = parseYaml(content) as Record<string, unknown>;\n } catch {\n fixes.push('Failed to parse YAML — treating as raw markdown');\n return normalizeRawMarkdown(content, filename, type, options, fixes);\n }\n\n const id = options?.id ?? String(parsed.id ?? deriveId(filename));\n const fafType = String(parsed.type ?? 'skill');\n const primitiveType = type ?? inferTypeFromFafType(fafType) ?? 'skill';\n const title = String(parsed.title ?? parsed.name ?? id);\n const description = String(parsed.description ?? '');\n const fafContent = String(parsed.content ?? '');\n const fafTags = Array.isArray(parsed.tags)\n ? (parsed.tags as string[]).map(String)\n : [];\n\n const tags = [primitiveType, ...fafTags, ...(options?.tags ?? [])];\n\n const frontmatter: Record<string, unknown> = {\n id,\n created: new Date().toISOString().split('T')[0],\n author: 'human',\n status: 'active',\n tags: [...new Set(tags)],\n };\n\n const l0 = title.length > 120 ? title.slice(0, 117) + '...' : title;\n const l1 = description.length > 300 ? description.slice(0, 297) + '...' : description;\n\n let body = `<!-- L0: ${l0} -->\\n`;\n if (l1) body += `<!-- L1: ${l1} -->\\n`;\n body += `\\n# ${title}\\n\\n`;\n if (description) body += `${description}\\n\\n`;\n if (fafContent) body += fafContent + '\\n';\n\n const result = matter.stringify(body, frontmatter);\n fixes.push('Converted .faf YAML to harness markdown');\n fixes.push(`Added frontmatter (id: ${id}, type: ${primitiveType})`);\n\n const outFilename = deriveId(filename) + '.md';\n return { content: result, filename: outFilename, fixes };\n}\n\n/**\n * Normalize raw markdown (no frontmatter or non-harness frontmatter).\n */\nfunction normalizeRawMarkdown(\n content: string,\n filename: string,\n type: string | null,\n options: UniversalInstallOptions | undefined,\n fixes: string[],\n): { content: string; filename: string; fixes: string[] } {\n const id = options?.id ?? deriveId(filename);\n const primitiveType = type ?? 'skill';\n const tags = [primitiveType, ...(options?.tags ?? [])];\n\n // Try to preserve any existing frontmatter\n let parsed: ReturnType<typeof matter>;\n try {\n parsed = matter(content);\n } catch {\n parsed = { data: {}, content, orig: '', excerpt: '', language: '', matter: '', stringify: () => '' } as ReturnType<typeof matter>;\n }\n\n const data = parsed.data as Record<string, unknown>;\n\n // Set required harness fields — options override existing values\n if (options?.id || !data.id) {\n data.id = id;\n fixes.push(`Set id: \"${id}\"`);\n }\n if (!data.status) {\n data.status = 'active';\n fixes.push('Added status: \"active\"');\n }\n if (!data.created) {\n data.created = new Date().toISOString().split('T')[0];\n fixes.push('Added created date');\n }\n if (!data.author || !['human', 'agent', 'infrastructure'].includes(String(data.author))) {\n data.author = 'human';\n fixes.push('Added author: \"human\"');\n }\n if (!Array.isArray(data.tags) || data.tags.length === 0) {\n data.tags = [...new Set(tags)];\n fixes.push(`Added tags: [${(data.tags as string[]).join(', ')}]`);\n }\n\n let body = parsed.content;\n\n // Add L0 if missing\n const l0Regex = /<!--\\s*L0:\\s*(.*?)\\s*-->/;\n if (!l0Regex.test(body)) {\n const headingMatch = body.match(/^#\\s+(.+)$/m);\n const firstLine = body.split('\\n').find((line) => line.trim().length > 0);\n const summary = headingMatch ? headingMatch[1].trim() : (firstLine?.trim() ?? id);\n const l0 = summary.length > 120 ? summary.slice(0, 117) + '...' : summary;\n body = `<!-- L0: ${l0} -->\\n${body}`;\n fixes.push(`Generated L0: \"${l0}\"`);\n }\n\n // Add L1 if missing\n const l1Regex = /<!--\\s*L1:\\s*([\\s\\S]*?)\\s*-->/;\n if (!l1Regex.test(body)) {\n const paragraphs = body.split(/\\n{2,}/).filter((p) => {\n const trimmed = p.trim();\n return trimmed.length > 0 && !trimmed.startsWith('<!--') && !trimmed.startsWith('#');\n });\n if (paragraphs.length > 0) {\n const para = paragraphs[0].replace(/\\n/g, ' ').trim();\n const l1 = para.length > 300 ? para.slice(0, 297) + '...' : para;\n const l0Pos = body.indexOf('-->');\n if (l0Pos !== -1) {\n const insertPos = l0Pos + 3;\n body = body.slice(0, insertPos) + `\\n<!-- L1: ${l1} -->` + body.slice(insertPos);\n } else {\n body = `<!-- L1: ${l1} -->\\n${body}`;\n }\n fixes.push('Generated L1 from first paragraph');\n }\n }\n\n const result = matter.stringify(body, data);\n const outFilename = ensureMdExtension(filename);\n return { content: result, filename: outFilename, fixes };\n}\n\n/**\n * Wrap a bash hook script in harness markdown.\n */\nfunction normalizeBashHook(\n content: string,\n filename: string,\n type: string | null,\n options: UniversalInstallOptions | undefined,\n fixes: string[],\n): { content: string; filename: string; fixes: string[] } {\n const id = options?.id ?? deriveId(filename);\n const primitiveType = type ?? 'workflow';\n const tags = [primitiveType, 'hook', ...(options?.tags ?? [])];\n\n // Extract description from comments at top of script\n const commentLines = content.split('\\n')\n .filter((line) => line.startsWith('#') && !line.startsWith('#!'))\n .map((line) => line.replace(/^#\\s?/, '').trim())\n .filter((line) => line.length > 0);\n\n const description = commentLines.length > 0\n ? commentLines.slice(0, 3).join(' ')\n : `Bash hook: ${id}`;\n\n const frontmatter: Record<string, unknown> = {\n id,\n created: new Date().toISOString().split('T')[0],\n author: 'human',\n status: 'active',\n tags: [...new Set(tags)],\n };\n\n const l0 = description.length > 120 ? description.slice(0, 117) + '...' : description;\n\n let body = `<!-- L0: ${l0} -->\\n\\n`;\n body += `# ${id}\\n\\n`;\n body += `${description}\\n\\n`;\n body += '```bash\\n';\n body += content;\n if (!content.endsWith('\\n')) body += '\\n';\n body += '```\\n';\n\n const result = matter.stringify(body, frontmatter);\n fixes.push('Wrapped bash script in harness markdown');\n fixes.push(`Added frontmatter (id: ${id}, type: ${primitiveType})`);\n\n const outFilename = deriveId(filename) + '.md';\n return { content: result, filename: outFilename, fixes };\n}\n\n/**\n * Convert an MCP config to harness tool documentation.\n */\nfunction normalizeMcpConfig(\n content: string,\n filename: string,\n options: UniversalInstallOptions | undefined,\n fixes: string[],\n): { content: string; filename: string; fixes: string[] } {\n const id = options?.id ?? deriveId(filename);\n const tags = ['tool', 'mcp', ...(options?.tags ?? [])];\n\n // Try to parse config\n let config: Record<string, unknown> = {};\n const ext = extname(filename).toLowerCase();\n try {\n if (ext === '.json') {\n config = JSON.parse(content) as Record<string, unknown>;\n } else {\n config = parseYaml(content) as Record<string, unknown>;\n }\n } catch {\n fixes.push('Failed to parse MCP config');\n }\n\n const serverName = String(config.name ?? config.command ?? id);\n const description = String(config.description ?? `MCP server: ${serverName}`);\n\n const frontmatter: Record<string, unknown> = {\n id,\n created: new Date().toISOString().split('T')[0],\n author: 'human',\n status: 'active',\n tags: [...new Set(tags)],\n };\n\n const l0 = description.length > 120 ? description.slice(0, 117) + '...' : description;\n\n let body = `<!-- L0: ${l0} -->\\n\\n`;\n body += `# MCP Server: ${serverName}\\n\\n`;\n body += `${description}\\n\\n`;\n body += '## Configuration\\n\\n';\n body += '```json\\n';\n body += JSON.stringify(config, null, 2);\n body += '\\n```\\n';\n\n const result = matter.stringify(body, frontmatter);\n fixes.push('Converted MCP config to harness tool documentation');\n fixes.push(`Added frontmatter (id: ${id})`);\n\n const outFilename = deriveId(filename) + '.md';\n return { content: result, filename: outFilename, fixes };\n}\n\n// ─── Source Resolution ───────────────────────────────────────────────────────\n\n/**\n * Resolve a source reference to a local file path.\n *\n * Supports:\n * - Local file paths (absolute or relative)\n * - HTTPS URLs (GitHub raw, any markdown URL)\n * - Source query (searches registered sources)\n *\n * @returns Path to a local file (downloaded if remote)\n */\nexport async function resolveSource(\n source: string,\n harnessDir: string,\n): Promise<{ localPath: string; originalSource: string; error?: string }> {\n // Case 1: Local file path\n if (existsSync(source)) {\n return { localPath: source, originalSource: source };\n }\n\n // Case 2: URL\n if (source.startsWith('https://') || source.startsWith('http://')) {\n // Convert GitHub URL to raw if needed\n const rawUrl = convertToRawUrl(source);\n const result = await downloadCapability(rawUrl);\n if (result.downloaded) {\n return { localPath: result.localPath, originalSource: source };\n }\n return { localPath: '', originalSource: source, error: result.error };\n }\n\n // Case 3: Source registry lookup — search known sources\n const results = discoverSources(harnessDir, source, { maxResults: 1 });\n if (results.length > 0) {\n const hit = results[0];\n // If the source is a GitHub source, construct a raw URL\n if (hit.source.type === 'github') {\n const rawUrl = convertToRawUrl(hit.url);\n const result = await downloadCapability(rawUrl);\n if (result.downloaded) {\n return { localPath: result.localPath, originalSource: source };\n }\n return { localPath: '', originalSource: source, error: result.error };\n }\n return { localPath: '', originalSource: source, error: `Source \"${hit.source.name}\" is type \"${hit.source.type}\" — direct install not yet supported for this type` };\n }\n\n return { localPath: '', originalSource: source, error: `Could not resolve \"${source}\" — not a local file, URL, or known source` };\n}\n\n// ─── Main Install Function ───────────────────────────────────────────────────\n\n/**\n * Universal install: resolve → detect → normalize → fix → install.\n *\n * Accepts a local path, URL, or search query. Detects the format,\n * normalizes to harness convention, applies auto-fixes, and installs\n * to the correct directory.\n *\n * @param harnessDir - Harness directory\n * @param source - File path, URL, or name to install\n * @param options - Installation options\n * @returns Install result with status, fixes, errors, dependency hints\n */\nexport async function universalInstall(\n harnessDir: string,\n source: string,\n options?: UniversalInstallOptions,\n): Promise<UniversalInstallResult> {\n const result: UniversalInstallResult = {\n installed: false,\n source,\n format: { format: 'unknown', primitiveType: null, confidence: 0, reasons: [] },\n destination: '',\n fixes: [],\n errors: [],\n suggestedDependencies: [],\n };\n\n // Step 1: Resolve source to local file\n const resolved = await resolveSource(source, harnessDir);\n if (resolved.error || !resolved.localPath) {\n result.errors.push(resolved.error ?? 'Failed to resolve source');\n return result;\n }\n\n // Step 2: Read content\n let content: string;\n try {\n content = readFileSync(resolved.localPath, 'utf-8');\n } catch (err) {\n result.errors.push(`Failed to read file: ${err instanceof Error ? err.message : String(err)}`);\n return result;\n }\n\n if (content.trim().length === 0) {\n result.errors.push('File is empty');\n return result;\n }\n\n // Step 3: Detect format\n const filename = basename(resolved.localPath);\n const detection = detectFormat(content, filename);\n result.format = detection;\n\n // Step 4: Normalize to harness convention\n const normalized = normalizeToHarness(content, filename, detection, options);\n result.fixes.push(...normalized.fixes);\n\n // Step 4b: Record provenance for URL installs so every installed file is\n // traceable back to its source. Local-path installs are skipped — the path\n // on disk is not a stable identifier.\n let finalContent = normalized.content;\n if (source.startsWith('http://') || source.startsWith('https://')) {\n finalContent = await recordProvenance(finalContent, source);\n result.fixes.push('Recorded provenance (source, installed_at, installed_by)');\n }\n\n // Step 5: Write normalized content to temp file for installation\n const tempDir = join(tmpdir(), 'harness-install');\n mkdirSync(tempDir, { recursive: true });\n const tempPath = join(tempDir, normalized.filename);\n writeFileSync(tempPath, finalContent, 'utf-8');\n\n // Step 6: Apply auto-fix if not skipped\n if (!options?.skipFix) {\n const fixResult = fixCapability(tempPath);\n result.fixes.push(...fixResult.fixes_applied);\n\n if (!fixResult.valid && !options?.force) {\n result.errors.push(...fixResult.errors);\n return result;\n }\n }\n\n // Step 7: Install via existing pipeline\n const installResult = installCapability(harnessDir, tempPath);\n result.installed = installResult.installed;\n result.destination = installResult.destination;\n\n if (!installResult.installed) {\n result.errors.push(...installResult.evalResult.errors);\n // If force mode, try direct copy\n if (options?.force && detection.primitiveType) {\n const targetDir = join(harnessDir, TYPE_DIRS[detection.primitiveType] ?? 'skills');\n if (!existsSync(targetDir)) mkdirSync(targetDir, { recursive: true });\n const dest = join(targetDir, normalized.filename);\n copyFileSync(tempPath, dest);\n result.installed = true;\n result.destination = dest;\n result.fixes.push('Force-installed despite validation errors');\n }\n }\n\n // Step 8: Scan for dependency hints\n result.suggestedDependencies = extractDependencyHints(normalized.content);\n\n return result;\n}\n\n/**\n * Install from a URL (convenience wrapper).\n */\nexport async function installFromUrl(\n harnessDir: string,\n url: string,\n options?: UniversalInstallOptions,\n): Promise<UniversalInstallResult> {\n return universalInstall(harnessDir, url, options);\n}\n\n/**\n * Install from a local file path (convenience wrapper).\n */\nexport async function installFromFile(\n harnessDir: string,\n filePath: string,\n options?: UniversalInstallOptions,\n): Promise<UniversalInstallResult> {\n return universalInstall(harnessDir, filePath, options);\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction deriveId(filename: string): string {\n const base = basename(filename).replace(/\\.(md|faf|yaml|yml|json|sh|bash)$/i, '');\n return base.replace(/[^a-z0-9-]/gi, '-').toLowerCase();\n}\n\nfunction ensureMdExtension(filename: string): string {\n if (filename.endsWith('.md')) return filename;\n return deriveId(filename) + '.md';\n}\n\n/**\n * Convert a GitHub URL to its raw content URL.\n *\n * Handles:\n * - github.com/owner/repo/blob/branch/path → raw.githubusercontent.com/owner/repo/branch/path\n * - Already raw.githubusercontent.com URLs → pass through\n * - Other URLs → pass through\n */\nexport function convertToRawUrl(url: string): string {\n // Already raw\n if (url.includes('raw.githubusercontent.com')) return url;\n\n // GitHub blob URL → raw\n const blobMatch = url.match(\n /^https?:\\/\\/github\\.com\\/([^/]+)\\/([^/]+)\\/blob\\/(.+)$/,\n );\n if (blobMatch) {\n const [, owner, repo, rest] = blobMatch;\n return `https://raw.githubusercontent.com/${owner}/${repo}/${rest}`;\n }\n\n return url;\n}\n\n/**\n * Detect if content matches Claude Code SKILL.md patterns.\n * Claude skills are plain markdown with specific structural patterns.\n */\nfunction detectClaudeSkillPattern(content: string, filename: string): boolean {\n const nameLower = filename.toLowerCase();\n\n // Filename patterns\n if (nameLower === 'skill.md' || nameLower.endsWith('-skill.md') || nameLower.endsWith('_skill.md')) {\n return true;\n }\n\n // Content patterns common in Claude Code skills\n const patterns = [\n /^#\\s+.+skill/im,\n /instructions?\\s+for\\s+/i,\n /when\\s+(the\\s+)?user\\s+(asks?|wants?|needs?|requests?)/i,\n /you\\s+(should|must|will)\\s+/i,\n ];\n\n let matches = 0;\n for (const pattern of patterns) {\n if (pattern.test(content)) matches++;\n }\n\n // Need at least 2 pattern matches to classify as Claude skill\n // (plain markdown + instructional tone)\n return matches >= 2 && !content.startsWith('---');\n}\n\nfunction inferTypeFromFafType(fafType: string): string | null {\n const typeMap: Record<string, string> = {\n skill: 'skill',\n agent: 'agent',\n rule: 'rule',\n playbook: 'playbook',\n workflow: 'workflow',\n tool: 'tool',\n instinct: 'instinct',\n hook: 'workflow',\n template: 'skill',\n plugin: 'skill',\n };\n\n return typeMap[fafType.toLowerCase()] ?? null;\n}\n\nfunction inferTypeFromContent(content: string, filename: string): string | null {\n const lower = content.toLowerCase();\n const nameLower = filename.toLowerCase();\n\n // From filename\n if (nameLower.includes('rule')) return 'rule';\n if (nameLower.includes('agent')) return 'agent';\n if (nameLower.includes('playbook')) return 'playbook';\n if (nameLower.includes('workflow')) return 'workflow';\n if (nameLower.includes('instinct')) return 'instinct';\n if (nameLower.includes('tool')) return 'tool';\n if (nameLower.includes('skill')) return 'skill';\n\n // From content patterns\n if (lower.includes('# rule:') || lower.includes('## rules')) return 'rule';\n if (lower.includes('# agent:') || lower.includes('## agent')) return 'agent';\n if (lower.includes('# playbook:') || lower.includes('## playbook')) return 'playbook';\n if (lower.includes('# skill:') || lower.includes('## skill')) return 'skill';\n if (lower.includes('# workflow:') || lower.includes('## workflow')) return 'workflow';\n if (lower.includes('# tool:') || lower.includes('## tool')) return 'tool';\n\n // Default for markdown without clear type\n return null;\n}\n\n/**\n * Extract dependency hints from content.\n * Looks for references to tools, skills, or other primitives.\n */\nfunction extractDependencyHints(content: string): string[] {\n const hints: string[] = [];\n const seen = new Set<string>();\n\n // Look for \"requires:\" or \"depends:\" in frontmatter\n try {\n const parsed = matter(content);\n const data = parsed.data as Record<string, unknown>;\n if (Array.isArray(data.requires)) {\n for (const dep of data.requires as string[]) {\n if (!seen.has(dep)) {\n hints.push(dep);\n seen.add(dep);\n }\n }\n }\n if (Array.isArray(data.depends)) {\n for (const dep of data.depends as string[]) {\n if (!seen.has(dep)) {\n hints.push(dep);\n seen.add(dep);\n }\n }\n }\n if (Array.isArray(data.related)) {\n for (const dep of data.related as string[]) {\n if (!seen.has(dep)) {\n hints.push(dep);\n seen.add(dep);\n }\n }\n }\n } catch {\n // Ignore parse errors\n }\n\n return hints;\n}\n"],"mappings":"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","names":["require"]}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/runtime/universal-installer.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync } from 'fs';\nimport { join, basename, extname } from 'path';\nimport { tmpdir } from 'os';\nimport matter from 'gray-matter';\nimport { parse as parseYaml } from 'yaml';\nimport { fixCapability, installCapability, downloadCapability } from './intake.js';\nimport { autoProcessFile } from './auto-processor.js';\nimport { discoverSources, loadAllSources } from './sources.js';\nimport type { Source, SourceDiscoveryResult } from './sources.js';\nimport { log } from '../core/logger.js';\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** Detected source format of a file to be installed. */\nexport type SourceFormat =\n | 'harness' // Already harness convention (frontmatter + L0/L1)\n | 'claude-skill' // Claude Code SKILL.md (plain markdown, no frontmatter)\n | 'faf-yaml' // .faf YAML format\n | 'raw-markdown' // Plain markdown with no harness structure\n | 'bash-hook' // Bash/shell script (hook or workflow)\n | 'mcp-config' // MCP server configuration (JSON/YAML)\n | 'unknown';\n\n/** Result of format detection. */\nexport interface FormatDetection {\n /** Detected format */\n format: SourceFormat;\n /** Inferred primitive type (skill, agent, rule, etc.) */\n primitiveType: string | null;\n /** Confidence score (0-1) */\n confidence: number;\n /** Reasons for the detection */\n reasons: string[];\n}\n\n/** Result of a universal install operation. */\nexport interface UniversalInstallResult {\n /** Whether installation succeeded */\n installed: boolean;\n /** Source reference that was resolved */\n source: string;\n /** Detected format */\n format: FormatDetection;\n /** Path where the file was installed */\n destination: string;\n /** Fixes applied during normalization */\n fixes: string[];\n /** Errors encountered */\n errors: string[];\n /** Suggested dependencies to install */\n suggestedDependencies: string[];\n}\n\n/** Options for the universal installer. */\nexport interface UniversalInstallOptions {\n /** Override the detected primitive type (skill, rule, agent, etc.) */\n type?: string;\n /** Override the generated ID */\n id?: string;\n /** Force install even if validation has warnings */\n force?: boolean;\n /** Skip auto-fix (frontmatter, L0/L1 generation) */\n skipFix?: boolean;\n /** Additional tags to add */\n tags?: string[];\n}\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\nconst VALID_TYPES = ['rule', 'instinct', 'skill', 'playbook', 'workflow', 'tool', 'agent'];\n\nconst TYPE_DIRS: Record<string, string> = {\n rule: 'rules',\n instinct: 'instincts',\n skill: 'skills',\n playbook: 'playbooks',\n workflow: 'workflows',\n tool: 'tools',\n agent: 'agents',\n};\n\n// ─── Format Detection ────────────────────────────────────────────────────────\n\n/**\n * Detect the format of a file based on its content and extension.\n *\n * Detection heuristics:\n * - Has `---` frontmatter with `id:` + `status:` → harness convention\n * - Has `---` frontmatter but missing harness fields → raw-markdown\n * - `.faf` or `.yaml`/`.yml` with `type:` + `content:` keys → faf-yaml\n * - `.sh`/`.bash` or starts with `#!/` → bash-hook\n * - JSON/YAML with `mcpServers` or `servers` → mcp-config\n * - Plain markdown with no frontmatter → claude-skill or raw-markdown\n */\nexport function detectFormat(content: string, filename: string): FormatDetection {\n const ext = extname(filename).toLowerCase();\n const reasons: string[] = [];\n let format: SourceFormat = 'unknown';\n let primitiveType: string | null = null;\n let confidence = 0;\n\n // Check for bash/shell scripts\n if (ext === '.sh' || ext === '.bash' || content.trimStart().startsWith('#!/')) {\n format = 'bash-hook';\n primitiveType = 'workflow';\n confidence = 0.9;\n reasons.push('Shell script detected (shebang or .sh extension)');\n\n // Hooks are typically short scripts with specific patterns\n if (content.includes('hook') || content.includes('pre-commit') || content.includes('post-')) {\n primitiveType = 'workflow';\n reasons.push('Hook pattern detected in content');\n }\n\n return { format, primitiveType, confidence, reasons };\n }\n\n // Check for JSON/YAML MCP configs\n if (ext === '.json') {\n try {\n const parsed = JSON.parse(content) as Record<string, unknown>;\n if (parsed.mcpServers || parsed.servers || parsed.command || parsed.args) {\n format = 'mcp-config';\n primitiveType = 'tool';\n confidence = 0.9;\n reasons.push('MCP configuration JSON detected');\n return { format, primitiveType, confidence, reasons };\n }\n } catch {\n // Not valid JSON, continue\n }\n }\n\n // Check for .faf YAML format\n if (ext === '.faf' || ext === '.yaml' || ext === '.yml') {\n try {\n const parsed = parseYaml(content) as Record<string, unknown>;\n if (parsed.type && parsed.content) {\n format = 'faf-yaml';\n primitiveType = inferTypeFromFafType(String(parsed.type));\n confidence = 0.9;\n reasons.push(`.faf YAML format with type: ${parsed.type}`);\n return { format, primitiveType, confidence, reasons };\n }\n // YAML with mcpServers\n if (parsed.mcpServers || parsed.servers) {\n format = 'mcp-config';\n primitiveType = 'tool';\n confidence = 0.85;\n reasons.push('MCP configuration YAML detected');\n return { format, primitiveType, confidence, reasons };\n }\n } catch {\n // Not valid YAML, continue\n }\n }\n\n // Check for markdown content\n if (ext === '.md' || ext === '' || !ext) {\n // Try to parse frontmatter\n try {\n const parsed = matter(content);\n const data = parsed.data as Record<string, unknown>;\n\n if (data.id && data.status) {\n // Has harness-style frontmatter\n format = 'harness';\n confidence = 0.95;\n reasons.push('Harness frontmatter detected (id + status fields)');\n\n // Detect type from tags\n const tags = Array.isArray(data.tags)\n ? (data.tags as string[]).map((t) => String(t).toLowerCase())\n : [];\n for (const type of VALID_TYPES) {\n if (tags.includes(type)) {\n primitiveType = type;\n break;\n }\n }\n\n return { format, primitiveType, confidence, reasons };\n }\n\n if (Object.keys(data).length > 0) {\n // Has some frontmatter but not harness convention\n format = 'raw-markdown';\n confidence = 0.7;\n reasons.push('Markdown with non-harness frontmatter');\n }\n } catch {\n // No frontmatter or parse error\n }\n\n // Check for Claude Code SKILL.md patterns\n if (format === 'unknown' || format === 'raw-markdown') {\n const isClaudeSkill = detectClaudeSkillPattern(content, filename);\n if (isClaudeSkill) {\n format = 'claude-skill';\n primitiveType = 'skill';\n confidence = 0.8;\n reasons.push('Claude Code SKILL.md pattern detected');\n return { format, primitiveType, confidence, reasons };\n }\n }\n\n // Plain markdown — infer type from content\n if (format === 'unknown') {\n format = 'raw-markdown';\n confidence = 0.5;\n reasons.push('Plain markdown without frontmatter');\n }\n\n // Try to infer type from content/filename\n if (!primitiveType) {\n primitiveType = inferTypeFromContent(content, filename);\n if (primitiveType) {\n reasons.push(`Type inferred from content/filename: ${primitiveType}`);\n }\n }\n\n return { format, primitiveType, confidence, reasons };\n }\n\n return { format, primitiveType, confidence, reasons };\n}\n\n// ─── Format Normalization ────────────────────────────────────────────────────\n\n/**\n * Normalize content from any detected format to harness convention.\n * Returns the normalized markdown content ready for writing.\n */\nexport function normalizeToHarness(\n content: string,\n filename: string,\n detection: FormatDetection,\n options?: UniversalInstallOptions,\n): { content: string; filename: string; fixes: string[] } {\n const fixes: string[] = [];\n const type = options?.type ?? detection.primitiveType;\n\n switch (detection.format) {\n case 'harness':\n // Already in harness format — just pass through\n return { content, filename, fixes: ['Already in harness format'] };\n\n case 'claude-skill':\n return normalizeClaudeSkill(content, filename, type, options, fixes);\n\n case 'faf-yaml':\n return normalizeFafYaml(content, filename, type, options, fixes);\n\n case 'raw-markdown':\n return normalizeRawMarkdown(content, filename, type, options, fixes);\n\n case 'bash-hook':\n return normalizeBashHook(content, filename, type, options, fixes);\n\n case 'mcp-config':\n return normalizeMcpConfig(content, filename, options, fixes);\n\n default:\n return normalizeRawMarkdown(content, filename, type, options, fixes);\n }\n}\n\n/**\n * Convert Claude Code SKILL.md to harness convention.\n * Claude skills are plain markdown — add frontmatter + L0/L1.\n */\nfunction normalizeClaudeSkill(\n content: string,\n filename: string,\n type: string | null,\n options: UniversalInstallOptions | undefined,\n fixes: string[],\n): { content: string; filename: string; fixes: string[] } {\n const id = options?.id ?? deriveId(filename);\n const primitiveType = type ?? 'skill';\n const tags = [primitiveType, ...(options?.tags ?? [])];\n\n // Extract first heading as title\n const headingMatch = content.match(/^#\\s+(.+)$/m);\n const title = headingMatch ? headingMatch[1].trim() : id;\n\n const frontmatter: Record<string, unknown> = {\n id,\n created: new Date().toISOString().split('T')[0],\n author: 'human',\n status: 'active',\n tags,\n };\n\n // Generate L0 from title/first heading\n const l0 = title.length > 120 ? title.slice(0, 117) + '...' : title;\n\n // Generate L1 from first paragraph\n const paragraphs = content.split(/\\n{2,}/).filter((p) => {\n const trimmed = p.trim();\n return trimmed.length > 0 && !trimmed.startsWith('#') && !trimmed.startsWith('<!--');\n });\n const l1 = paragraphs.length > 0\n ? paragraphs[0].replace(/\\n/g, ' ').trim().slice(0, 300)\n : '';\n\n let body = `<!-- L0: ${l0} -->\\n`;\n if (l1) {\n body += `<!-- L1: ${l1} -->\\n`;\n }\n body += '\\n' + content;\n\n const result = matter.stringify(body, frontmatter);\n fixes.push('Added harness frontmatter (id, status, tags)');\n fixes.push(`Generated L0 from heading: \"${l0}\"`);\n if (l1) fixes.push('Generated L1 from first paragraph');\n\n const outFilename = ensureMdExtension(filename);\n return { content: result, filename: outFilename, fixes };\n}\n\n/**\n * Convert .faf YAML format to harness markdown.\n */\nfunction normalizeFafYaml(\n content: string,\n filename: string,\n type: string | null,\n options: UniversalInstallOptions | undefined,\n fixes: string[],\n): { content: string; filename: string; fixes: string[] } {\n let parsed: Record<string, unknown>;\n try {\n parsed = parseYaml(content) as Record<string, unknown>;\n } catch {\n fixes.push('Failed to parse YAML — treating as raw markdown');\n return normalizeRawMarkdown(content, filename, type, options, fixes);\n }\n\n const id = options?.id ?? String(parsed.id ?? deriveId(filename));\n const fafType = String(parsed.type ?? 'skill');\n const primitiveType = type ?? inferTypeFromFafType(fafType) ?? 'skill';\n const title = String(parsed.title ?? parsed.name ?? id);\n const description = String(parsed.description ?? '');\n const fafContent = String(parsed.content ?? '');\n const fafTags = Array.isArray(parsed.tags)\n ? (parsed.tags as string[]).map(String)\n : [];\n\n const tags = [primitiveType, ...fafTags, ...(options?.tags ?? [])];\n\n const frontmatter: Record<string, unknown> = {\n id,\n created: new Date().toISOString().split('T')[0],\n author: 'human',\n status: 'active',\n tags: [...new Set(tags)],\n };\n\n const l0 = title.length > 120 ? title.slice(0, 117) + '...' : title;\n const l1 = description.length > 300 ? description.slice(0, 297) + '...' : description;\n\n let body = `<!-- L0: ${l0} -->\\n`;\n if (l1) body += `<!-- L1: ${l1} -->\\n`;\n body += `\\n# ${title}\\n\\n`;\n if (description) body += `${description}\\n\\n`;\n if (fafContent) body += fafContent + '\\n';\n\n const result = matter.stringify(body, frontmatter);\n fixes.push('Converted .faf YAML to harness markdown');\n fixes.push(`Added frontmatter (id: ${id}, type: ${primitiveType})`);\n\n const outFilename = deriveId(filename) + '.md';\n return { content: result, filename: outFilename, fixes };\n}\n\n/**\n * Normalize raw markdown (no frontmatter or non-harness frontmatter).\n */\nfunction normalizeRawMarkdown(\n content: string,\n filename: string,\n type: string | null,\n options: UniversalInstallOptions | undefined,\n fixes: string[],\n): { content: string; filename: string; fixes: string[] } {\n const id = options?.id ?? deriveId(filename);\n const primitiveType = type ?? 'skill';\n const tags = [primitiveType, ...(options?.tags ?? [])];\n\n // Try to preserve any existing frontmatter\n let parsed: ReturnType<typeof matter>;\n try {\n parsed = matter(content);\n } catch {\n parsed = { data: {}, content, orig: '', excerpt: '', language: '', matter: '', stringify: () => '' } as ReturnType<typeof matter>;\n }\n\n const data = parsed.data as Record<string, unknown>;\n\n // Set required harness fields — options override existing values\n if (options?.id || !data.id) {\n data.id = id;\n fixes.push(`Set id: \"${id}\"`);\n }\n if (!data.status) {\n data.status = 'active';\n fixes.push('Added status: \"active\"');\n }\n if (!data.created) {\n data.created = new Date().toISOString().split('T')[0];\n fixes.push('Added created date');\n }\n if (!data.author || !['human', 'agent', 'infrastructure'].includes(String(data.author))) {\n data.author = 'human';\n fixes.push('Added author: \"human\"');\n }\n if (!Array.isArray(data.tags) || data.tags.length === 0) {\n data.tags = [...new Set(tags)];\n fixes.push(`Added tags: [${(data.tags as string[]).join(', ')}]`);\n }\n\n let body = parsed.content;\n\n // Add L0 if missing\n const l0Regex = /<!--\\s*L0:\\s*(.*?)\\s*-->/;\n if (!l0Regex.test(body)) {\n const headingMatch = body.match(/^#\\s+(.+)$/m);\n const firstLine = body.split('\\n').find((line) => line.trim().length > 0);\n const summary = headingMatch ? headingMatch[1].trim() : (firstLine?.trim() ?? id);\n const l0 = summary.length > 120 ? summary.slice(0, 117) + '...' : summary;\n body = `<!-- L0: ${l0} -->\\n${body}`;\n fixes.push(`Generated L0: \"${l0}\"`);\n }\n\n // Add L1 if missing\n const l1Regex = /<!--\\s*L1:\\s*([\\s\\S]*?)\\s*-->/;\n if (!l1Regex.test(body)) {\n const paragraphs = body.split(/\\n{2,}/).filter((p) => {\n const trimmed = p.trim();\n return trimmed.length > 0 && !trimmed.startsWith('<!--') && !trimmed.startsWith('#');\n });\n if (paragraphs.length > 0) {\n const para = paragraphs[0].replace(/\\n/g, ' ').trim();\n const l1 = para.length > 300 ? para.slice(0, 297) + '...' : para;\n const l0Pos = body.indexOf('-->');\n if (l0Pos !== -1) {\n const insertPos = l0Pos + 3;\n body = body.slice(0, insertPos) + `\\n<!-- L1: ${l1} -->` + body.slice(insertPos);\n } else {\n body = `<!-- L1: ${l1} -->\\n${body}`;\n }\n fixes.push('Generated L1 from first paragraph');\n }\n }\n\n const result = matter.stringify(body, data);\n const outFilename = ensureMdExtension(filename);\n return { content: result, filename: outFilename, fixes };\n}\n\n/**\n * Wrap a bash hook script in harness markdown.\n */\nfunction normalizeBashHook(\n content: string,\n filename: string,\n type: string | null,\n options: UniversalInstallOptions | undefined,\n fixes: string[],\n): { content: string; filename: string; fixes: string[] } {\n const id = options?.id ?? deriveId(filename);\n const primitiveType = type ?? 'workflow';\n const tags = [primitiveType, 'hook', ...(options?.tags ?? [])];\n\n // Extract description from comments at top of script\n const commentLines = content.split('\\n')\n .filter((line) => line.startsWith('#') && !line.startsWith('#!'))\n .map((line) => line.replace(/^#\\s?/, '').trim())\n .filter((line) => line.length > 0);\n\n const description = commentLines.length > 0\n ? commentLines.slice(0, 3).join(' ')\n : `Bash hook: ${id}`;\n\n const frontmatter: Record<string, unknown> = {\n id,\n created: new Date().toISOString().split('T')[0],\n author: 'human',\n status: 'active',\n tags: [...new Set(tags)],\n };\n\n const l0 = description.length > 120 ? description.slice(0, 117) + '...' : description;\n\n let body = `<!-- L0: ${l0} -->\\n\\n`;\n body += `# ${id}\\n\\n`;\n body += `${description}\\n\\n`;\n body += '```bash\\n';\n body += content;\n if (!content.endsWith('\\n')) body += '\\n';\n body += '```\\n';\n\n const result = matter.stringify(body, frontmatter);\n fixes.push('Wrapped bash script in harness markdown');\n fixes.push(`Added frontmatter (id: ${id}, type: ${primitiveType})`);\n\n const outFilename = deriveId(filename) + '.md';\n return { content: result, filename: outFilename, fixes };\n}\n\n/**\n * Convert an MCP config to harness tool documentation.\n */\nfunction normalizeMcpConfig(\n content: string,\n filename: string,\n options: UniversalInstallOptions | undefined,\n fixes: string[],\n): { content: string; filename: string; fixes: string[] } {\n const id = options?.id ?? deriveId(filename);\n const tags = ['tool', 'mcp', ...(options?.tags ?? [])];\n\n // Try to parse config\n let config: Record<string, unknown> = {};\n const ext = extname(filename).toLowerCase();\n try {\n if (ext === '.json') {\n config = JSON.parse(content) as Record<string, unknown>;\n } else {\n config = parseYaml(content) as Record<string, unknown>;\n }\n } catch {\n fixes.push('Failed to parse MCP config');\n }\n\n const serverName = String(config.name ?? config.command ?? id);\n const description = String(config.description ?? `MCP server: ${serverName}`);\n\n const frontmatter: Record<string, unknown> = {\n id,\n created: new Date().toISOString().split('T')[0],\n author: 'human',\n status: 'active',\n tags: [...new Set(tags)],\n };\n\n const l0 = description.length > 120 ? description.slice(0, 117) + '...' : description;\n\n let body = `<!-- L0: ${l0} -->\\n\\n`;\n body += `# MCP Server: ${serverName}\\n\\n`;\n body += `${description}\\n\\n`;\n body += '## Configuration\\n\\n';\n body += '```json\\n';\n body += JSON.stringify(config, null, 2);\n body += '\\n```\\n';\n\n const result = matter.stringify(body, frontmatter);\n fixes.push('Converted MCP config to harness tool documentation');\n fixes.push(`Added frontmatter (id: ${id})`);\n\n const outFilename = deriveId(filename) + '.md';\n return { content: result, filename: outFilename, fixes };\n}\n\n// ─── Source Resolution ───────────────────────────────────────────────────────\n\n/**\n * Resolve a source reference to a local file path.\n *\n * Supports:\n * - Local file paths (absolute or relative)\n * - HTTPS URLs (GitHub raw, any markdown URL)\n * - Source query (searches registered sources)\n *\n * @returns Path to a local file (downloaded if remote)\n */\nexport async function resolveSource(\n source: string,\n harnessDir: string,\n): Promise<{ localPath: string; originalSource: string; error?: string }> {\n // Case 1: Local file path\n if (existsSync(source)) {\n return { localPath: source, originalSource: source };\n }\n\n // Case 2: URL\n if (source.startsWith('https://') || source.startsWith('http://')) {\n // Convert GitHub URL to raw if needed\n const rawUrl = convertToRawUrl(source);\n const result = await downloadCapability(rawUrl);\n if (result.downloaded) {\n return { localPath: result.localPath, originalSource: source };\n }\n return { localPath: '', originalSource: source, error: result.error };\n }\n\n // Case 3: Source registry lookup — search known sources\n const results = discoverSources(harnessDir, source, { maxResults: 1 });\n if (results.length > 0) {\n const hit = results[0];\n // If the source is a GitHub source, construct a raw URL\n if (hit.source.type === 'github') {\n const rawUrl = convertToRawUrl(hit.url);\n const result = await downloadCapability(rawUrl);\n if (result.downloaded) {\n return { localPath: result.localPath, originalSource: source };\n }\n return { localPath: '', originalSource: source, error: result.error };\n }\n return { localPath: '', originalSource: source, error: `Source \"${hit.source.name}\" is type \"${hit.source.type}\" — direct install not yet supported for this type` };\n }\n\n return { localPath: '', originalSource: source, error: `Could not resolve \"${source}\" — not a local file, URL, or known source` };\n}\n\n// ─── Main Install Function ───────────────────────────────────────────────────\n\n/**\n * Universal install: resolve → detect → normalize → fix → install.\n *\n * Accepts a local path, URL, or search query. Detects the format,\n * normalizes to harness convention, applies auto-fixes, and installs\n * to the correct directory.\n *\n * @param harnessDir - Harness directory\n * @param source - File path, URL, or name to install\n * @param options - Installation options\n * @returns Install result with status, fixes, errors, dependency hints\n */\nexport async function universalInstall(\n harnessDir: string,\n source: string,\n options?: UniversalInstallOptions,\n): Promise<UniversalInstallResult> {\n const result: UniversalInstallResult = {\n installed: false,\n source,\n format: { format: 'unknown', primitiveType: null, confidence: 0, reasons: [] },\n destination: '',\n fixes: [],\n errors: [],\n suggestedDependencies: [],\n };\n\n // Step 1: Resolve source to local file\n const resolved = await resolveSource(source, harnessDir);\n if (resolved.error || !resolved.localPath) {\n result.errors.push(resolved.error ?? 'Failed to resolve source');\n return result;\n }\n\n // Step 2: Read content\n let content: string;\n try {\n content = readFileSync(resolved.localPath, 'utf-8');\n } catch (err) {\n result.errors.push(`Failed to read file: ${err instanceof Error ? err.message : String(err)}`);\n return result;\n }\n\n if (content.trim().length === 0) {\n result.errors.push('File is empty');\n return result;\n }\n\n // Step 3: Detect format\n const filename = basename(resolved.localPath);\n const detection = detectFormat(content, filename);\n result.format = detection;\n\n // Step 4: Normalize to harness convention\n const normalized = normalizeToHarness(content, filename, detection, options);\n result.fixes.push(...normalized.fixes);\n\n // Step 5: Write normalized content to temp file for installation\n const tempDir = join(tmpdir(), 'harness-install');\n mkdirSync(tempDir, { recursive: true });\n const tempPath = join(tempDir, normalized.filename);\n writeFileSync(tempPath, normalized.content, 'utf-8');\n\n // Step 6: Apply auto-fix if not skipped\n if (!options?.skipFix) {\n const fixResult = fixCapability(tempPath);\n result.fixes.push(...fixResult.fixes_applied);\n\n if (!fixResult.valid && !options?.force) {\n result.errors.push(...fixResult.errors);\n return result;\n }\n }\n\n // Step 7: Install via existing pipeline\n const installResult = installCapability(harnessDir, tempPath);\n result.installed = installResult.installed;\n result.destination = installResult.destination;\n\n if (!installResult.installed) {\n result.errors.push(...installResult.evalResult.errors);\n // If force mode, try direct copy\n if (options?.force && detection.primitiveType) {\n const targetDir = join(harnessDir, TYPE_DIRS[detection.primitiveType] ?? 'skills');\n if (!existsSync(targetDir)) mkdirSync(targetDir, { recursive: true });\n const dest = join(targetDir, normalized.filename);\n copyFileSync(tempPath, dest);\n result.installed = true;\n result.destination = dest;\n result.fixes.push('Force-installed despite validation errors');\n }\n }\n\n // Step 8: Scan for dependency hints\n result.suggestedDependencies = extractDependencyHints(normalized.content);\n\n return result;\n}\n\n/**\n * Install from a URL (convenience wrapper).\n */\nexport async function installFromUrl(\n harnessDir: string,\n url: string,\n options?: UniversalInstallOptions,\n): Promise<UniversalInstallResult> {\n return universalInstall(harnessDir, url, options);\n}\n\n/**\n * Install from a local file path (convenience wrapper).\n */\nexport async function installFromFile(\n harnessDir: string,\n filePath: string,\n options?: UniversalInstallOptions,\n): Promise<UniversalInstallResult> {\n return universalInstall(harnessDir, filePath, options);\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction deriveId(filename: string): string {\n const base = basename(filename).replace(/\\.(md|faf|yaml|yml|json|sh|bash)$/i, '');\n return base.replace(/[^a-z0-9-]/gi, '-').toLowerCase();\n}\n\nfunction ensureMdExtension(filename: string): string {\n if (filename.endsWith('.md')) return filename;\n return deriveId(filename) + '.md';\n}\n\n/**\n * Convert a GitHub URL to its raw content URL.\n *\n * Handles:\n * - github.com/owner/repo/blob/branch/path → raw.githubusercontent.com/owner/repo/branch/path\n * - Already raw.githubusercontent.com URLs → pass through\n * - Other URLs → pass through\n */\nexport function convertToRawUrl(url: string): string {\n // Already raw\n if (url.includes('raw.githubusercontent.com')) return url;\n\n // GitHub blob URL → raw\n const blobMatch = url.match(\n /^https?:\\/\\/github\\.com\\/([^/]+)\\/([^/]+)\\/blob\\/(.+)$/,\n );\n if (blobMatch) {\n const [, owner, repo, rest] = blobMatch;\n return `https://raw.githubusercontent.com/${owner}/${repo}/${rest}`;\n }\n\n return url;\n}\n\n/**\n * Detect if content matches Claude Code SKILL.md patterns.\n * Claude skills are plain markdown with specific structural patterns.\n */\nfunction detectClaudeSkillPattern(content: string, filename: string): boolean {\n const nameLower = filename.toLowerCase();\n\n // Filename patterns\n if (nameLower === 'skill.md' || nameLower.endsWith('-skill.md') || nameLower.endsWith('_skill.md')) {\n return true;\n }\n\n // Content patterns common in Claude Code skills\n const patterns = [\n /^#\\s+.+skill/im,\n /instructions?\\s+for\\s+/i,\n /when\\s+(the\\s+)?user\\s+(asks?|wants?|needs?|requests?)/i,\n /you\\s+(should|must|will)\\s+/i,\n ];\n\n let matches = 0;\n for (const pattern of patterns) {\n if (pattern.test(content)) matches++;\n }\n\n // Need at least 2 pattern matches to classify as Claude skill\n // (plain markdown + instructional tone)\n return matches >= 2 && !content.startsWith('---');\n}\n\nfunction inferTypeFromFafType(fafType: string): string | null {\n const typeMap: Record<string, string> = {\n skill: 'skill',\n agent: 'agent',\n rule: 'rule',\n playbook: 'playbook',\n workflow: 'workflow',\n tool: 'tool',\n instinct: 'instinct',\n hook: 'workflow',\n template: 'skill',\n plugin: 'skill',\n };\n\n return typeMap[fafType.toLowerCase()] ?? null;\n}\n\nfunction inferTypeFromContent(content: string, filename: string): string | null {\n const lower = content.toLowerCase();\n const nameLower = filename.toLowerCase();\n\n // From filename\n if (nameLower.includes('rule')) return 'rule';\n if (nameLower.includes('agent')) return 'agent';\n if (nameLower.includes('playbook')) return 'playbook';\n if (nameLower.includes('workflow')) return 'workflow';\n if (nameLower.includes('instinct')) return 'instinct';\n if (nameLower.includes('tool')) return 'tool';\n if (nameLower.includes('skill')) return 'skill';\n\n // From content patterns\n if (lower.includes('# rule:') || lower.includes('## rules')) return 'rule';\n if (lower.includes('# agent:') || lower.includes('## agent')) return 'agent';\n if (lower.includes('# playbook:') || lower.includes('## playbook')) return 'playbook';\n if (lower.includes('# skill:') || lower.includes('## skill')) return 'skill';\n if (lower.includes('# workflow:') || lower.includes('## workflow')) return 'workflow';\n if (lower.includes('# tool:') || lower.includes('## tool')) return 'tool';\n\n // Default for markdown without clear type\n return null;\n}\n\n/**\n * Extract dependency hints from content.\n * Looks for references to tools, skills, or other primitives.\n */\nfunction extractDependencyHints(content: string): string[] {\n const hints: string[] = [];\n const seen = new Set<string>();\n\n // Look for \"requires:\" or \"depends:\" in frontmatter\n try {\n const parsed = matter(content);\n const data = parsed.data as Record<string, unknown>;\n if (Array.isArray(data.requires)) {\n for (const dep of data.requires as string[]) {\n if (!seen.has(dep)) {\n hints.push(dep);\n seen.add(dep);\n }\n }\n }\n if (Array.isArray(data.depends)) {\n for (const dep of data.depends as string[]) {\n if (!seen.has(dep)) {\n hints.push(dep);\n seen.add(dep);\n }\n }\n }\n if (Array.isArray(data.related)) {\n for (const dep of data.related as string[]) {\n if (!seen.has(dep)) {\n hints.push(dep);\n seen.add(dep);\n }\n }\n }\n } catch {\n // Ignore parse errors\n }\n\n return hints;\n}\n"],"mappings":"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","names":[]}
|