@modexagents/core 0.3.1
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/LICENSE +21 -0
- package/README.md +26 -0
- package/dist/index.d.ts +1230 -0
- package/dist/index.js +1979 -0
- package/dist/index.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/schema.ts","../src/serialize.ts","../src/extract.ts","../src/prompt.ts","../src/sources/index.ts","../src/sources/epub.ts","../src/sources/types.ts","../src/sources/pdf.ts","../src/sources/text.ts","../src/sources/web.ts","../src/glob.ts","../src/parseSkills.ts","../src/merge.ts","../src/canonicalJson.ts","../src/fileLock.ts","../src/operations/feed.ts","../src/agent.ts","../src/provenance.ts","../src/tokenEstimate.ts","../src/operations/agents.ts","../src/credentials.ts","../src/registry/types.ts","../src/registry/client.ts","../src/operations/login.ts","../src/operations/bind.ts","../src/registryState.ts","../src/operations/aspirations.ts","../src/operations/index.ts"],"sourcesContent":["import { z } from 'zod';\n\nexport const SCHEMA_VERSION = 0;\n\nconst SLUG_PATTERN = /^[a-z0-9]+(-[a-z0-9]+)*$/;\n\nexport const SkillSchema = z.object({\n slug: z\n .string()\n .min(1)\n .max(64)\n .regex(SLUG_PATTERN, 'slug must be kebab-case [a-z0-9-]'),\n name: z.string().min(1).max(120),\n description: z.string().min(1).max(2000),\n tags: z\n .array(z.string().regex(SLUG_PATTERN, 'tag must be kebab-case [a-z0-9-]').max(40))\n .min(1)\n .max(6),\n source: z.string().min(1).max(255),\n});\n\nexport type Skill = z.infer<typeof SkillSchema>;\n\nexport const SkillsDocSchema = z.object({\n schema_version: z.literal(SCHEMA_VERSION),\n skills: z.array(SkillSchema),\n});\n\nexport type SkillsDoc = z.infer<typeof SkillsDocSchema>;\n\n// What the model emits via the tool call — same shape as Skill but without `source`,\n// which the caller attaches from the input file basename.\nexport const ExtractedSkillSchema = SkillSchema.omit({ source: true });\nexport type ExtractedSkill = z.infer<typeof ExtractedSkillSchema>;\n\nexport const ExtractionResultSchema = z.object({\n skills: z.array(ExtractedSkillSchema),\n});\n\nexport type ExtractionResult = z.infer<typeof ExtractionResultSchema>;\n","import { SCHEMA_VERSION, type Skill, type SkillsDoc } from './schema.js';\n\n// Lexicographic by UTF-16 code unit. Stable across Node versions and locales,\n// unlike localeCompare. Hashing in later phases depends on this being stable.\nfunction compareCodepoints(a: string, b: string): number {\n if (a < b) return -1;\n if (a > b) return 1;\n return 0;\n}\n\nfunction normalizeSkill(skill: Skill): Skill {\n return {\n slug: skill.slug,\n name: skill.name.trim(),\n description: skill.description.trim(),\n tags: [...skill.tags].sort(compareCodepoints),\n source: skill.source,\n };\n}\n\nfunction renderSkill(skill: Skill): string {\n return [\n `## ${skill.slug}`,\n '',\n `**Name:** ${skill.name}`,\n '',\n `**Description:** ${skill.description}`,\n '',\n `**Tags:** ${skill.tags.join(', ')}`,\n '',\n `**Source:** ${skill.source}`,\n '',\n '---',\n ].join('\\n');\n}\n\n/**\n * Serialize a SkillsDoc to canonical SKILLS.md.\n *\n * Stability rules (load-bearing — later phases hash this output):\n * - LF line endings, single trailing newline\n * - Skills sorted ascending by slug (UTF-16 code units)\n * - Tags sorted ascending, joined by \", \"\n * - Field order fixed: Name, Description, Tags, Source\n * - Frontmatter limited to schema_version\n */\nexport function serialize(doc: SkillsDoc): string {\n const skills = doc.skills.map(normalizeSkill).sort((a, b) => compareCodepoints(a.slug, b.slug));\n\n const frontmatter = ['---', `schema_version: ${SCHEMA_VERSION}`, '---'].join('\\n');\n\n if (skills.length === 0) {\n return `${frontmatter}\\n`;\n }\n\n const body = skills.map(renderSkill).join('\\n\\n');\n return `${frontmatter}\\n\\n${body}\\n`;\n}\n\nexport function buildDoc(skills: Skill[]): SkillsDoc {\n return { schema_version: SCHEMA_VERSION, skills };\n}\n","import Anthropic from '@anthropic-ai/sdk';\n\nimport { ExtractionResultSchema, type Skill } from './schema.js';\nimport { EMIT_SKILLS_TOOL, MODEL_ID, SYSTEM_PROMPT } from './prompt.js';\n\n// Phase A guard. Real chunking arrives in Phase C.\nconst MAX_CORPUS_BYTES = 500_000;\n\nexport class ExtractionError extends Error {\n override readonly cause?: unknown;\n\n constructor(message: string, cause?: unknown) {\n super(message);\n this.name = 'ExtractionError';\n this.cause = cause;\n }\n}\n\nexport interface ExtractOptions {\n source: string;\n apiKey?: string;\n model?: string;\n maxTokens?: number;\n client?: Anthropic;\n}\n\nexport async function extractSkills(\n corpus: string,\n opts: ExtractOptions,\n): Promise<Skill[]> {\n const bytes = Buffer.byteLength(corpus, 'utf8');\n if (bytes > MAX_CORPUS_BYTES) {\n throw new ExtractionError(\n `Corpus is ${bytes} bytes, which exceeds the Phase A limit of ${MAX_CORPUS_BYTES}. Chunking arrives in Phase C.`,\n );\n }\n if (corpus.trim().length === 0) {\n throw new ExtractionError('Corpus is empty.');\n }\n\n const apiKey = opts.apiKey ?? process.env['ANTHROPIC_API_KEY'];\n if (!opts.client && !apiKey) {\n throw new ExtractionError(\n 'ANTHROPIC_API_KEY is not set. Export it in your environment, or copy .env.example to .env.',\n );\n }\n\n const client = opts.client ?? new Anthropic({ apiKey });\n const model = opts.model ?? MODEL_ID;\n\n let response;\n try {\n response = await client.messages.create({\n model,\n max_tokens: opts.maxTokens ?? 4096,\n system: [\n {\n type: 'text',\n text: SYSTEM_PROMPT,\n cache_control: { type: 'ephemeral' },\n },\n ],\n tools: [EMIT_SKILLS_TOOL],\n tool_choice: { type: 'tool', name: 'emit_skills' },\n messages: [\n {\n role: 'user',\n content: corpus,\n },\n ],\n });\n } catch (err) {\n throw new ExtractionError('Anthropic API call failed', err);\n }\n\n const toolUse = response.content.find(\n (b) => b.type === 'tool_use' && b.name === 'emit_skills',\n );\n if (!toolUse || toolUse.type !== 'tool_use') {\n throw new ExtractionError(\n `Model did not emit the emit_skills tool call (stop_reason=${response.stop_reason}).`,\n );\n }\n\n const parsed = ExtractionResultSchema.safeParse(toolUse.input);\n if (!parsed.success) {\n const detail = parsed.error.issues\n .map((i) => `${i.path.join('.') || '<root>'}: ${i.message}`)\n .join('; ');\n throw new ExtractionError(`Model output failed validation: ${detail}`);\n }\n\n return parsed.data.skills.map((s) => ({ ...s, source: opts.source }));\n}\n","export const MODEL_ID = 'claude-haiku-4-5-20251001';\n\nexport const EMIT_SKILLS_TOOL = {\n name: 'emit_skills',\n description:\n 'Emit the structured set of skills extracted from the user-provided corpus.',\n input_schema: {\n type: 'object' as const,\n properties: {\n skills: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n slug: {\n type: 'string',\n pattern: '^[a-z0-9]+(-[a-z0-9]+)*$',\n maxLength: 64,\n description:\n 'Kebab-case identifier, unique within this output. No underscores, spaces, or capitals.',\n },\n name: {\n type: 'string',\n minLength: 1,\n maxLength: 120,\n description: 'Short human-readable title (3-8 words).',\n },\n description: {\n type: 'string',\n minLength: 1,\n maxLength: 2000,\n description:\n 'One paragraph (1-4 sentences), self-contained, written so a reader who has not seen the corpus can apply it.',\n },\n tags: {\n type: 'array',\n minItems: 1,\n maxItems: 6,\n items: {\n type: 'string',\n pattern: '^[a-z0-9]+(-[a-z0-9]+)*$',\n maxLength: 40,\n },\n description: '1-6 kebab-case topical labels.',\n },\n },\n required: ['slug', 'name', 'description', 'tags'],\n additionalProperties: false,\n },\n },\n },\n required: ['skills'],\n additionalProperties: false,\n },\n};\n\nexport const SYSTEM_PROMPT = `You are an extraction engine that reads a corpus and produces a structured set of distinct skills.\n\nA \"skill\" is a transferable, reusable practice or technique that a person could apply across contexts — not a fact, definition, story, or one-off opinion.\n\nFor every skill you identify, emit:\n- slug: kebab-case identifier matching ^[a-z0-9]+(-[a-z0-9]+)*$, unique within this output\n- name: short human-readable title (3-8 words; Title Case acceptable)\n- description: one paragraph (1-4 sentences), self-contained, written as a directly applicable instruction\n- tags: 1-6 kebab-case topical labels matching ^[a-z0-9]+(-[a-z0-9]+)*$\n\nQuality rules:\n- Only emit skills that are clearly supported by the corpus.\n- Do not invent skills to pad the list. Returning fewer high-quality skills is preferred to many vague ones.\n- Avoid near-duplicates. If two passages describe the same underlying technique, emit one skill.\n- Do not include source citations, page numbers, or quotes in the description.\n- The description must stand on its own; a reader who has not seen the corpus must be able to apply the skill.\n\nAlways respond by calling the emit_skills tool exactly once with the full result. Do not include any text outside the tool call.`;\n","import { extname } from 'node:path';\n\nimport { loadEpubSource } from './epub.js';\nimport { loadPdfSource } from './pdf.js';\nimport { loadTextSource } from './text.js';\nimport type { LoadedSource } from './types.js';\nimport { SourceError } from './types.js';\nimport { loadWebSource } from './web.js';\n\nexport type { LoadedSource, SourceKind } from './types.js';\nexport { SourceError } from './types.js';\n\nexport function isWebUrl(target: string): boolean {\n return target.startsWith('http://') || target.startsWith('https://');\n}\n\nconst EXT_LOADERS: Record<string, (path: string) => Promise<LoadedSource>> = {\n '.txt': loadTextSource,\n '.md': loadTextSource,\n '.pdf': loadPdfSource,\n '.epub': loadEpubSource,\n};\n\n// Dispatch a feed target (file path or URL) to the right loader. Returns the\n// extracted plaintext along with provenance metadata (source name, URL, kind).\nexport async function readSource(target: string): Promise<LoadedSource> {\n if (isWebUrl(target)) {\n return loadWebSource(target);\n }\n const ext = extname(target).toLowerCase();\n const loader = EXT_LOADERS[ext];\n if (loader === undefined) {\n const shown = ext || '(no extension)';\n throw new SourceError(\n `Unsupported source type: ${shown}. Supported: .txt, .md, .pdf, .epub, http(s)://… URLs.`,\n );\n }\n return loader(target);\n}\n","import { basename } from 'node:path';\n\nimport type { LoadedSource } from './types.js';\nimport { SourceError } from './types.js';\n\n// Strip HTML to plaintext: drop tags, decode the few entities that matter.\n// epub2 hands us small, well-formed XHTML chapters, so we don't need a full\n// DOM walk like Readability does for arbitrary web pages.\nfunction htmlToText(html: string): string {\n return html\n .replace(/<\\/(p|div|h[1-6]|li|br|tr|hr)>/gi, '\\n')\n .replace(/<br\\s*\\/?>/gi, '\\n')\n .replace(/<[^>]+>/g, '')\n .replace(/ /g, ' ')\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/[ \\t]+\\n/g, '\\n')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim();\n}\n\nexport async function loadEpubSource(path: string): Promise<LoadedSource> {\n const { EPub } = await import('epub2');\n\n let book: InstanceType<typeof EPub>;\n try {\n book = await EPub.createAsync(path);\n } catch (err) {\n throw new SourceError(`Could not open EPUB ${path}: ${(err as Error).message}`);\n }\n\n const chapters: string[] = [];\n for (const item of book.flow) {\n if (!item.id) continue;\n let html: string;\n try {\n html = await book.getChapterAsync(item.id);\n } catch (err) {\n throw new SourceError(\n `Could not read chapter '${item.id}' from ${path}: ${(err as Error).message}`,\n );\n }\n const text = htmlToText(html);\n if (text.length > 0) chapters.push(text);\n }\n\n const content = chapters.join('\\n\\n');\n if (content.trim().length === 0) {\n throw new SourceError(`EPUB ${path} extracted to empty text (no readable chapters).`);\n }\n\n return {\n source: basename(path),\n source_url: null,\n source_kind: 'epub',\n content,\n };\n}\n","import type { SourceKind } from '../provenance.js';\n\nexport type { SourceKind };\n\n// What every source loader returns. The fields land directly on the\n// provenance feed entry's `input` block (plus source_sha256 / source_bytes,\n// which are computed from `content` by the caller).\nexport interface LoadedSource {\n source: string; // basename for files, normalized URL for web\n source_url: string | null; // null for local files\n source_kind: SourceKind;\n content: string; // extracted plaintext\n}\n\nexport class SourceError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'SourceError';\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport { basename } from 'node:path';\n\nimport type { LoadedSource } from './types.js';\nimport { SourceError } from './types.js';\n\nexport async function loadPdfSource(path: string): Promise<LoadedSource> {\n let bytes: Buffer;\n try {\n bytes = await readFile(path);\n } catch (err) {\n throw new SourceError(`Could not read ${path}: ${(err as Error).message}`);\n }\n\n // unpdf is heavy and pulls a WASM-ish runtime; import it lazily so users who\n // never feed a PDF don't pay the startup cost.\n const { extractText } = await import('unpdf');\n\n let result: { totalPages: number; text: string | string[] };\n try {\n result = await extractText(new Uint8Array(bytes), { mergePages: true });\n } catch (err) {\n throw new SourceError(`Could not parse PDF ${path}: ${(err as Error).message}`);\n }\n\n const text = Array.isArray(result.text) ? result.text.join('\\n') : result.text;\n if (text.trim().length === 0) {\n throw new SourceError(\n `PDF ${path} extracted to empty text (${result.totalPages} pages). Likely an image-only/scanned PDF; OCR is out of scope for Phase C.`,\n );\n }\n\n return {\n source: basename(path),\n source_url: null,\n source_kind: 'pdf',\n content: text,\n };\n}\n","import { readFile } from 'node:fs/promises';\nimport { basename, extname } from 'node:path';\n\nimport type { LoadedSource, SourceKind } from './types.js';\nimport { SourceError } from './types.js';\n\nconst KIND_BY_EXT: Record<string, SourceKind> = {\n '.txt': 'text',\n '.md': 'markdown',\n};\n\nexport const TEXT_EXTENSIONS = Object.keys(KIND_BY_EXT);\n\nexport function isTextPath(path: string): boolean {\n return Object.prototype.hasOwnProperty.call(KIND_BY_EXT, extname(path).toLowerCase());\n}\n\nexport async function loadTextSource(path: string): Promise<LoadedSource> {\n const ext = extname(path).toLowerCase();\n const kind = KIND_BY_EXT[ext];\n if (kind === undefined) {\n throw new SourceError(\n `Not a text source: ${path} (extension ${ext || '(none)'} is not .txt or .md).`,\n );\n }\n let content: string;\n try {\n content = await readFile(path, 'utf8');\n } catch (err) {\n throw new SourceError(`Could not read ${path}: ${(err as Error).message}`);\n }\n return {\n source: basename(path),\n source_url: null,\n source_kind: kind,\n content,\n };\n}\n","import { lookup as dnsLookup } from 'node:dns/promises';\nimport { isIP } from 'node:net';\n\nimport type { LoadedSource } from './types.js';\nimport { SourceError } from './types.js';\n\nexport const DEFAULT_TIMEOUT_MS = 30_000;\nexport const DEFAULT_MAX_BYTES = 10 * 1024 * 1024;\n// __MODEX_VERSION__ is injected at build time (tsup) and test time (vitest)\n// from package.json, so this never drifts from the published version.\nexport const DEFAULT_USER_AGENT = `modex-cli/${__MODEX_VERSION__} (+https://modex.md)`;\nconst MAX_REDIRECTS = 10;\nconst ALLOWED_CONTENT_TYPES = [\n 'text/html',\n 'application/xhtml+xml',\n 'text/plain',\n];\n\nexport interface WebOptions {\n fetch?: typeof globalThis.fetch;\n dnsLookup?: (hostname: string) => Promise<{ address: string; family: 4 | 6 }>;\n timeoutMs?: number;\n maxBytes?: number;\n userAgent?: string;\n}\n\n// --- URL normalization ----------------------------------------------------\n\n// Strip the fragment (server returns the same bytes regardless), lowercase\n// the host, and strip default ports. Preserve query and path case — they can\n// be load-bearing on case-sensitive servers.\nexport function normalizeUrl(input: string): string {\n let u: URL;\n try {\n u = new URL(input);\n } catch {\n throw new SourceError(`Invalid URL: ${input}`);\n }\n if (u.protocol !== 'http:' && u.protocol !== 'https:') {\n throw new SourceError(`Unsupported URL scheme: ${u.protocol} (only http and https are allowed).`);\n }\n u.hash = '';\n u.hostname = u.hostname.toLowerCase();\n if ((u.protocol === 'http:' && u.port === '80') || (u.protocol === 'https:' && u.port === '443')) {\n u.port = '';\n }\n return u.toString();\n}\n\n// --- SSRF guard -----------------------------------------------------------\n\n// Returns true if an IPv4 address sits in a range we never want to fetch from.\n// Includes loopback, RFC1918 private, link-local (incl. EC2 metadata\n// 169.254.169.254), CGNAT, and the \"current network\" 0/8.\nfunction isPrivateIPv4(ip: string): boolean {\n const parts = ip.split('.').map(Number);\n if (parts.length !== 4 || parts.some((p) => Number.isNaN(p) || p < 0 || p > 255)) {\n return true; // malformed → treat as unsafe\n }\n const [a, b] = parts as [number, number, number, number];\n if (a === 0) return true;\n if (a === 10) return true;\n if (a === 127) return true;\n if (a === 169 && b === 254) return true;\n if (a === 172 && b >= 16 && b <= 31) return true;\n if (a === 192 && b === 168) return true;\n if (a === 100 && b >= 64 && b <= 127) return true;\n return false;\n}\n\n// Expand a (possibly compressed) IPv6 string into its 8 numeric hextets.\n// Returns null if the input isn't a parseable IPv6 address. Handles the `::`\n// run and a trailing embedded IPv4 (e.g. ::ffff:1.2.3.4).\nfunction parseHextets(ip: string): number[] | null {\n let work = ip.toLowerCase();\n\n // Split off an embedded IPv4 tail and convert it to two hextets.\n let ipv4Tail: number[] | null = null;\n const lastColon = work.lastIndexOf(':');\n const tail = lastColon >= 0 ? work.slice(lastColon + 1) : work;\n if (tail.includes('.')) {\n const octets = tail.split('.').map(Number);\n if (octets.length !== 4 || octets.some((o) => Number.isNaN(o) || o < 0 || o > 255)) {\n return null;\n }\n ipv4Tail = [\n (octets[0]! << 8) | octets[1]!,\n (octets[2]! << 8) | octets[3]!,\n ];\n work = work.slice(0, lastColon + 1) + '0:0';\n }\n\n const halves = work.split('::');\n if (halves.length > 2) return null;\n\n const toGroups = (s: string): number[] | null => {\n if (s === '') return [];\n const parts = s.split(':');\n const groups: number[] = [];\n for (const p of parts) {\n if (!/^[0-9a-f]{1,4}$/.test(p)) return null;\n groups.push(parseInt(p, 16));\n }\n return groups;\n };\n\n const head = toGroups(halves[0]!);\n const back = halves.length === 2 ? toGroups(halves[1]!) : [];\n if (head === null || back === null) return null;\n\n let groups: number[];\n if (halves.length === 2) {\n const fill = 8 - head.length - back.length;\n if (fill < 1) return null; // `::` must stand for at least one zero group\n groups = [...head, ...new Array<number>(fill).fill(0), ...back];\n } else {\n groups = head;\n }\n\n if (ipv4Tail) {\n // We replaced the IPv4 tail with `0:0` above; swap the real values back in.\n groups = [...groups.slice(0, 6), ...ipv4Tail];\n }\n\n return groups.length === 8 ? groups : null;\n}\n\n// IPv6: loopback ::1, unspecified ::, link-local fe80::/10, unique-local\n// fc00::/7, and IPv4-mapped ::ffff:a.b.c.d (delegated to the v4 check).\nfunction isPrivateIPv6(ip: string): boolean {\n const h = parseHextets(ip);\n if (h === null) return true; // unparseable → treat as unsafe\n\n // Unspecified :: and loopback ::1\n if (h.every((g) => g === 0)) return true;\n if (h.slice(0, 7).every((g) => g === 0) && h[7] === 1) return true;\n\n // IPv4-mapped ::ffff:0:0/96 → apply the v4 ruleset to the embedded address.\n if (h.slice(0, 5).every((g) => g === 0) && h[5] === 0xffff) {\n const a = (h[6]! >> 8) & 0xff;\n const b = h[6]! & 0xff;\n const c = (h[7]! >> 8) & 0xff;\n const d = h[7]! & 0xff;\n return isPrivateIPv4(`${a}.${b}.${c}.${d}`);\n }\n\n const first = h[0]!;\n // Link-local fe80::/10 → first hextet 0xfe80–0xfebf\n if (first >= 0xfe80 && first <= 0xfebf) return true;\n // Unique-local fc00::/7 → first hextet 0xfc00–0xfdff\n if (first >= 0xfc00 && first <= 0xfdff) return true;\n\n return false;\n}\n\nfunction isPrivateIP(ip: string, family: 4 | 6): boolean {\n return family === 4 ? isPrivateIPv4(ip) : isPrivateIPv6(ip);\n}\n\nasync function assertPublicHost(\n hostname: string,\n lookup: (host: string) => Promise<{ address: string; family: 4 | 6 }>,\n): Promise<void> {\n // Reject IP literals in the URL host outright. They bypass DNS and are the\n // obvious SSRF vector (e.g. http://169.254.169.254/metadata). URL parses\n // IPv6 hosts in bracketed form (`[::1]`); strip the brackets before\n // delegating to isIP.\n const unbracketed = hostname.startsWith('[') && hostname.endsWith(']')\n ? hostname.slice(1, -1)\n : hostname;\n if (isIP(unbracketed) !== 0) {\n throw new SourceError(\n `Refusing to fetch from an IP literal (${hostname}). Use a hostname.`,\n );\n }\n let result;\n try {\n result = await lookup(hostname);\n } catch (err) {\n throw new SourceError(`Could not resolve hostname ${hostname}: ${(err as Error).message}`);\n }\n if (isPrivateIP(result.address, result.family)) {\n throw new SourceError(\n `Refusing to fetch ${hostname}: resolves to a private/loopback address (${result.address}).`,\n );\n }\n // Note: this has a TOCTOU race against DNS rebinding (the address that fetch\n // ultimately connects to may differ from what we resolved). Acceptable for\n // Phase C; a fully ip-locked socket variant can land when web fetching\n // becomes an MCP-exposed tool.\n}\n\n// --- Body read with cap ---------------------------------------------------\n\nasync function readCappedBody(\n response: Response,\n maxBytes: number,\n): Promise<{ buffer: Buffer; charset: string }> {\n const ct = response.headers.get('content-type') ?? '';\n const charset = (/charset=([^;]+)/i.exec(ct)?.[1] ?? 'utf-8').trim().toLowerCase();\n const lengthHeader = response.headers.get('content-length');\n if (lengthHeader && Number(lengthHeader) > maxBytes) {\n throw new SourceError(\n `Response is ${lengthHeader} bytes (Content-Length); exceeds limit of ${maxBytes}.`,\n );\n }\n\n if (!response.body) {\n const text = await response.text();\n if (Buffer.byteLength(text) > maxBytes) {\n throw new SourceError(`Response body exceeded ${maxBytes} bytes.`);\n }\n return { buffer: Buffer.from(text, 'utf8'), charset };\n }\n\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let total = 0;\n // Manual stream read so we abort the moment we cross the cap.\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n total += value.byteLength;\n if (total > maxBytes) {\n await reader.cancel();\n throw new SourceError(`Response body exceeded ${maxBytes} bytes (streamed).`);\n }\n chunks.push(value);\n }\n return { buffer: Buffer.concat(chunks), charset };\n}\n\n// --- Fetch with manual redirect chain -------------------------------------\n\nasync function fetchWithGuards(\n url: string,\n opts: Required<Pick<WebOptions, 'timeoutMs' | 'maxBytes' | 'userAgent'>> & {\n fetch: typeof globalThis.fetch;\n lookup: (host: string) => Promise<{ address: string; family: 4 | 6 }>;\n },\n): Promise<{ finalUrl: string; html: string }> {\n let current = url;\n for (let hop = 0; hop <= MAX_REDIRECTS; hop++) {\n const u = new URL(current);\n await assertPublicHost(u.hostname, opts.lookup);\n\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs);\n let response: Response;\n try {\n response = await opts.fetch(current, {\n method: 'GET',\n redirect: 'manual',\n signal: ctrl.signal,\n headers: {\n 'user-agent': opts.userAgent,\n accept: 'text/html, application/xhtml+xml, text/plain;q=0.5',\n },\n });\n } catch (err) {\n const e = err as Error;\n if (e.name === 'AbortError') {\n throw new SourceError(`Fetch timed out after ${opts.timeoutMs}ms: ${current}`);\n }\n throw new SourceError(`Fetch failed for ${current}: ${e.message}`);\n } finally {\n clearTimeout(timer);\n }\n\n if (response.status >= 300 && response.status < 400) {\n const location = response.headers.get('location');\n if (!location) {\n throw new SourceError(`Redirect from ${current} without a Location header.`);\n }\n const next = new URL(location, current).toString();\n const nextProto = new URL(next).protocol;\n if (nextProto !== 'http:' && nextProto !== 'https:') {\n throw new SourceError(`Redirect from ${current} to non-http(s) target ${next}.`);\n }\n current = next;\n continue;\n }\n\n if (!response.ok) {\n throw new SourceError(`Fetch ${current} returned HTTP ${response.status}.`);\n }\n\n const ctype = (response.headers.get('content-type') ?? '').toLowerCase();\n const allowed = ALLOWED_CONTENT_TYPES.some((t) => ctype.startsWith(t));\n if (!allowed) {\n throw new SourceError(\n `Fetch ${current} returned unsupported content-type: ${ctype || '(none)'}. ` +\n `Phase C web fetching accepts ${ALLOWED_CONTENT_TYPES.join(', ')}.`,\n );\n }\n\n const { buffer, charset } = await readCappedBody(response, opts.maxBytes);\n let html: string;\n try {\n html = new TextDecoder(charset).decode(buffer);\n } catch {\n // Unknown charset → fall back to utf-8.\n html = new TextDecoder('utf-8').decode(buffer);\n }\n return { finalUrl: current, html };\n }\n\n throw new SourceError(`Exceeded ${MAX_REDIRECTS} redirects starting from ${url}.`);\n}\n\n// --- Readability extraction -----------------------------------------------\n\nasync function htmlToArticleText(html: string, url: string): Promise<string> {\n const { Readability } = await import('@mozilla/readability');\n const { parseHTML } = await import('linkedom');\n const dom = parseHTML(html);\n const doc = dom.document as unknown as {\n documentURI?: string;\n querySelector(s: string): { textContent?: string | null } | null;\n };\n // Readability needs a base URL to resolve relative links it strips later.\n // linkedom doesn't set this from the fragment, so we set it manually.\n try {\n (doc as { documentURI?: string }).documentURI = url;\n } catch {\n // Some DOM impls reject assignment; safe to skip.\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const article = new Readability(doc as any).parse();\n if (article && article.textContent && article.textContent.trim().length > 0) {\n return article.textContent.trim();\n }\n // Fall back: dump body text.\n const body = doc.querySelector('body');\n const fallback = (body?.textContent ?? '').trim();\n if (fallback.length === 0) {\n throw new SourceError(`Readability and body fallback both extracted empty text for ${url}.`);\n }\n return fallback;\n}\n\n// --- Public entrypoint ----------------------------------------------------\n\nexport async function loadWebSource(target: string, opts: WebOptions = {}): Promise<LoadedSource> {\n const url = normalizeUrl(target);\n const fetchImpl = opts.fetch ?? globalThis.fetch;\n const lookup =\n opts.dnsLookup ??\n (async (host: string) => {\n const r = await dnsLookup(host);\n return { address: r.address, family: (r.family === 6 ? 6 : 4) as 4 | 6 };\n });\n const { html } = await fetchWithGuards(url, {\n fetch: fetchImpl,\n lookup,\n timeoutMs: opts.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n maxBytes: opts.maxBytes ?? DEFAULT_MAX_BYTES,\n userAgent: opts.userAgent ?? DEFAULT_USER_AGENT,\n });\n const text = await htmlToArticleText(html, url);\n return {\n source: url,\n source_url: url,\n source_kind: 'web',\n content: text,\n };\n}\n","import { stat } from 'node:fs/promises';\nimport { isAbsolute, resolve } from 'node:path';\nimport { glob } from 'tinyglobby';\n\nimport { isWebUrl } from './sources/index.js';\nimport { SourceError } from './sources/types.js';\n\nconst GLOB_MAGIC = /[*?[\\]{}!]/;\n\nfunction isGlobLike(pattern: string): boolean {\n return GLOB_MAGIC.test(pattern);\n}\n\nexport interface ExpandOptions {\n cwd?: string;\n}\n\n// Expand a list of CLI patterns into concrete feed targets.\n// - URLs pass through unchanged.\n// - Globs (containing magic characters) expand via tinyglobby; zero matches\n// is an error (silent zero-matches mask typos).\n// - Plain paths must exist and resolve to a regular file.\n//\n// Order is preserved: results follow the order of the input patterns. Within\n// a single glob, results are sorted ascending by path so feed sequencing\n// across runs is deterministic.\nexport async function expandPatterns(\n patterns: readonly string[],\n opts: ExpandOptions = {},\n): Promise<string[]> {\n if (patterns.length === 0) {\n throw new SourceError('No patterns supplied.');\n }\n const cwd = opts.cwd ?? process.cwd();\n const out: string[] = [];\n\n for (const pattern of patterns) {\n if (isWebUrl(pattern)) {\n out.push(pattern);\n continue;\n }\n\n if (isGlobLike(pattern)) {\n const matches = await glob(pattern, { cwd, onlyFiles: true, absolute: true });\n if (matches.length === 0) {\n throw new SourceError(`Glob pattern matched zero files: ${pattern}`);\n }\n matches.sort();\n out.push(...matches);\n continue;\n }\n\n const abs = isAbsolute(pattern) ? pattern : resolve(cwd, pattern);\n let s;\n try {\n s = await stat(abs);\n } catch (err) {\n throw new SourceError(`Path does not exist: ${pattern} (${(err as Error).message})`);\n }\n if (!s.isFile()) {\n throw new SourceError(`Path is not a regular file: ${pattern}`);\n }\n out.push(abs);\n }\n\n return out;\n}\n","import { SCHEMA_VERSION, SkillsDocSchema, type Skill, type SkillsDoc } from './schema.js';\n\nexport class ParseSkillsError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ParseSkillsError';\n }\n}\n\nconst FIELD_PATTERN = /^\\*\\*([A-Z][A-Za-z]*):\\*\\* (.*)$/;\n\ninterface RawSkill {\n slug: string;\n name?: string;\n description?: string;\n tags?: string[];\n source?: string;\n}\n\n// Parse the canonical SKILLS.md format produced by serialize().\n// Format reminder:\n// ---\n// schema_version: 0\n// ---\n// <blank>\n// ## <slug>\n// <blank>\n// **Name:** ...\n// <blank>\n// **Description:** ...\n// <blank>\n// **Tags:** a, b, c\n// <blank>\n// **Source:** ...\n// <blank>\n// ---\n// <blank>\n// ## <next-slug>\n// ...\nexport function parseSkills(input: string): SkillsDoc {\n if (input.includes('\\r')) {\n throw new ParseSkillsError('CR characters are not allowed; expected LF line endings.');\n }\n\n const lines = input.split('\\n');\n if (\n lines[0] !== '---' ||\n lines[1] !== `schema_version: ${SCHEMA_VERSION}` ||\n lines[2] !== '---'\n ) {\n throw new ParseSkillsError(\n `Missing or unrecognized frontmatter (expected schema_version: ${SCHEMA_VERSION}).`,\n );\n }\n\n const skills: Skill[] = [];\n let i = 3;\n\n while (i < lines.length) {\n if (lines[i] === '' || lines[i] === undefined) {\n i++;\n continue;\n }\n const heading = lines[i]!;\n const slugMatch = heading.match(/^## (.+)$/);\n if (!slugMatch) {\n throw new ParseSkillsError(`Expected '## <slug>' heading, got: ${JSON.stringify(heading)}`);\n }\n const slug = slugMatch[1]!;\n i++;\n\n const raw: RawSkill = { slug };\n while (i < lines.length) {\n // skip leading blanks within a skill block\n if (lines[i] === '') {\n i++;\n continue;\n }\n const line = lines[i]!;\n if (line === '---') {\n i++;\n break;\n }\n const fieldMatch = line.match(FIELD_PATTERN);\n if (!fieldMatch) {\n throw new ParseSkillsError(\n `Expected '**Field:** value' or '---' inside skill '${slug}', got: ${JSON.stringify(line)}`,\n );\n }\n const [, field, value] = fieldMatch as unknown as [string, string, string];\n switch (field) {\n case 'Name':\n raw.name = value;\n break;\n case 'Description':\n raw.description = value;\n break;\n case 'Tags':\n raw.tags = value.split(',').map((t) => t.trim()).filter((t) => t.length > 0);\n break;\n case 'Source':\n raw.source = value;\n break;\n default:\n throw new ParseSkillsError(`Unknown field '${field}' inside skill '${slug}'.`);\n }\n i++;\n }\n\n if (\n raw.name === undefined ||\n raw.description === undefined ||\n raw.tags === undefined ||\n raw.source === undefined\n ) {\n throw new ParseSkillsError(\n `Skill '${slug}' is missing required fields (Name, Description, Tags, Source).`,\n );\n }\n\n skills.push({\n slug,\n name: raw.name,\n description: raw.description,\n tags: raw.tags,\n source: raw.source,\n });\n }\n\n // Final validation: schema must accept every parsed skill.\n return SkillsDocSchema.parse({ schema_version: SCHEMA_VERSION, skills });\n}\n","import type { Skill } from './schema.js';\n\nexport interface MergeResult {\n merged: Skill[];\n added: string[];\n updated: string[];\n}\n\n// Compare tag sets order- and duplicate-insensitive. The serializer sorts and\n// the schema rejects empty tag arrays, but a model can legitimately re-emit\n// the same set in a different order or with accidental duplicates — neither\n// should count as an \"update\".\nfunction normalizeTags(tags: readonly string[]): string[] {\n return [...new Set(tags)].sort();\n}\n\nfunction tagsEquivalent(a: readonly string[], b: readonly string[]): boolean {\n const na = normalizeTags(a);\n const nb = normalizeTags(b);\n if (na.length !== nb.length) return false;\n for (let i = 0; i < na.length; i++) if (na[i] !== nb[i]) return false;\n return true;\n}\n\nfunction skillsEqual(a: Skill, b: Skill): boolean {\n return (\n a.name === b.name &&\n a.description === b.description &&\n a.source === b.source &&\n tagsEquivalent(a.tags, b.tags)\n );\n}\n\n// Merge `incoming` into `existing` keyed by slug.\n// - new slug → `added`\n// - existing slug, content changed → `updated`\n// - existing slug, content identical → no-op (not in either list)\n// `merged` is the resulting union; the canonical serializer will sort it.\n// Both `added` and `updated` are returned sorted ascending for stable\n// provenance output.\nexport function mergeSkills(existing: readonly Skill[], incoming: readonly Skill[]): MergeResult {\n const bySlug = new Map<string, Skill>();\n for (const s of existing) bySlug.set(s.slug, s);\n\n const added: string[] = [];\n const updated: string[] = [];\n\n for (const s of incoming) {\n const prev = bySlug.get(s.slug);\n if (prev === undefined) {\n added.push(s.slug);\n } else if (!skillsEqual(prev, s)) {\n updated.push(s.slug);\n }\n bySlug.set(s.slug, s);\n }\n\n added.sort();\n updated.sort();\n\n return {\n merged: [...bySlug.values()],\n added,\n updated,\n };\n}\n","// Deterministic JSON serializer used to hash provenance entries.\n// Rules:\n// - Object keys sorted ascending by UTF-16 code unit (matches our slug ordering).\n// - No whitespace between tokens.\n// - Strings escaped via JSON.stringify (handles all valid Unicode).\n// - Numbers must be finite integers; floats and NaN/Infinity are rejected so we\n// never depend on float printer behavior. (Provenance entries only carry ints.)\n//\n// Not full RFC 8785: we don't need number normalization or full Unicode\n// canonical form because the value space is constrained to strings and\n// non-negative integers.\n\nexport type CanonicalJson =\n | string\n | number\n | boolean\n | null\n | CanonicalJson[]\n | { [key: string]: CanonicalJson };\n\nexport class CanonicalJsonError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'CanonicalJsonError';\n }\n}\n\nfunction compareCodepoints(a: string, b: string): number {\n if (a < b) return -1;\n if (a > b) return 1;\n return 0;\n}\n\nexport function canonicalize(value: CanonicalJson): string {\n if (value === null) return 'null';\n if (typeof value === 'boolean') return value ? 'true' : 'false';\n if (typeof value === 'string') return JSON.stringify(value);\n if (typeof value === 'number') {\n if (!Number.isInteger(value)) {\n throw new CanonicalJsonError(\n `non-integer number not allowed in canonical JSON: ${value}`,\n );\n }\n return String(value);\n }\n if (Array.isArray(value)) {\n return `[${value.map(canonicalize).join(',')}]`;\n }\n if (typeof value === 'object') {\n const keys = Object.keys(value).sort(compareCodepoints);\n const parts = keys.map((k) => `${JSON.stringify(k)}:${canonicalize(value[k]!)}`);\n return `{${parts.join(',')}}`;\n }\n throw new CanonicalJsonError(`unsupported value type: ${typeof value}`);\n}\n","import { open, readFile, unlink } from 'node:fs/promises';\n\n// Cross-process advisory lock built on O_EXCL file creation.\n//\n// `fs.open(path, 'wx')` atomically creates the lockfile or fails with EEXIST —\n// that atomicity is the whole mechanism. The holder writes its pid + acquire\n// timestamp into the file so a crashed holder's lock can be detected and\n// stolen rather than wedging every future writer.\n\nexport const DEFAULT_LOCK_TIMEOUT_MS = 10_000;\nexport const DEFAULT_STALE_MS = 30_000;\nconst RETRY_BACKOFF_MS = 50;\n\nexport class FileLockError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'FileLockError';\n }\n}\n\nexport interface LockOptions {\n // Give up acquiring after this long. Default 10s.\n timeoutMs?: number;\n // A lockfile older than this whose holder pid is gone is considered stale\n // and stolen. Default 30s.\n staleMs?: number;\n // Test seam: overrides Date.now for deterministic timeout/staleness tests.\n now?: () => number;\n}\n\ninterface LockHolder {\n pid: number;\n acquired_at: number;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n// Is the process holding the lock still alive? `kill(pid, 0)` sends no signal,\n// it just probes: ESRCH means the process is gone. EPERM means it exists but\n// is owned by someone else — still alive, so still a valid holder.\nfunction pidAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (err) {\n return (err as NodeJS.ErrnoException).code === 'EPERM';\n }\n}\n\nasync function readHolder(lockPath: string): Promise<LockHolder | null> {\n try {\n const raw = await readFile(lockPath, 'utf8');\n const parsed = JSON.parse(raw) as Partial<LockHolder>;\n if (typeof parsed.pid === 'number' && typeof parsed.acquired_at === 'number') {\n return { pid: parsed.pid, acquired_at: parsed.acquired_at };\n }\n return null;\n } catch {\n // Missing (released between EEXIST and read) or unparseable — caller retries.\n return null;\n }\n}\n\n// Acquire `<lockPath>`, run `fn`, release in a finally. The lockfile is\n// `<targetPath>.lock`. Concurrent callers serialize; a stale lock (dead\n// holder, or older than staleMs) is stolen.\nexport async function withFileLock<T>(\n targetPath: string,\n fn: () => Promise<T>,\n opts: LockOptions = {},\n): Promise<T> {\n const lockPath = `${targetPath}.lock`;\n const timeoutMs = opts.timeoutMs ?? DEFAULT_LOCK_TIMEOUT_MS;\n const staleMs = opts.staleMs ?? DEFAULT_STALE_MS;\n const now = opts.now ?? Date.now;\n\n const deadline = now() + timeoutMs;\n\n for (;;) {\n try {\n const handle = await open(lockPath, 'wx');\n try {\n await handle.writeFile(\n JSON.stringify({ pid: process.pid, acquired_at: now() } satisfies LockHolder),\n 'utf8',\n );\n } finally {\n await handle.close();\n }\n // Lock held — run the critical section, then always release.\n try {\n return await fn();\n } finally {\n await unlink(lockPath).catch(() => {\n // Already gone (e.g. stolen as stale). Nothing to do.\n });\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'EEXIST') throw err;\n\n // Someone holds it. Decide whether to wait or steal.\n const holder = await readHolder(lockPath);\n const stale =\n holder !== null &&\n (!pidAlive(holder.pid) || now() - holder.acquired_at > staleMs);\n if (stale) {\n await unlink(lockPath).catch(() => {\n // Lost the steal race — another waiter unlinked first. Just retry.\n });\n continue;\n }\n\n if (now() >= deadline) {\n throw new FileLockError(\n `Timed out after ${timeoutMs}ms acquiring ${lockPath}` +\n (holder ? ` (held by pid ${holder.pid})` : ''),\n );\n }\n await sleep(RETRY_BACKOFF_MS);\n }\n }\n}\n","import { createHash } from 'node:crypto';\n\nimport { AgentError, loadAgent, readAgentSkills, writeSkillsAtomic } from '../agent.js';\nimport { ExtractionError, extractSkills } from '../extract.js';\nimport { expandPatterns } from '../glob.js';\nimport { mergeSkills } from '../merge.js';\nimport { ParseSkillsError } from '../parseSkills.js';\nimport { MODEL_ID } from '../prompt.js';\nimport { ProvenanceError, recordEntry } from '../provenance.js';\nimport { buildDoc, serialize } from '../serialize.js';\nimport { readSource, SourceError, type LoadedSource } from '../sources/index.js';\nimport { estimateTokens } from '../tokenEstimate.js';\n\nexport interface FeedOptions {\n model?: string;\n baseDir?: string;\n // Test-only injection points. `client` is typed loosely so callers that\n // never touch the SDK don't have to import its types; extractSkills\n // validates the shape it actually needs.\n client?: unknown;\n apiKey?: string;\n ts?: string | (() => string);\n // Optional source loader override for tests (PDF/EPUB/web tests use the real\n // loaders; this lets feed-level tests skip those entirely).\n loadSource?: (target: string) => Promise<LoadedSource>;\n // Stream overrides (defaults: process.stdout / process.stderr):\n stdout?: NodeJS.WritableStream;\n stderr?: NodeJS.WritableStream;\n}\n\nexport interface PerSourceResult {\n target: string;\n source: string;\n added: string[];\n updated: string[];\n skillsMdSha256: string;\n skillsMdBytes: number;\n estimatedTokens: number;\n warnedOverCap: boolean;\n}\n\nexport interface FeedResult {\n agentId: string;\n perSource: PerSourceResult[];\n}\n\nfunction sha256Hex(text: string): string {\n return createHash('sha256').update(text, 'utf8').digest('hex');\n}\n\nfunction resolveTs(ts: FeedOptions['ts']): string {\n if (ts === undefined) return new Date().toISOString();\n if (typeof ts === 'function') return ts();\n return ts;\n}\n\n/**\n * Run a batch of feeds: expand patterns, then for each resolved source\n * sequentially read → extract → merge → write skills.md → append a feed\n * entry to provenance.jsonl.\n *\n * Sequential is load-bearing: the provenance chain depends on a single\n * writer per agent (see provenance.ts). Stop-on-first-error is fine\n * because each source's provenance entry lands before the next runs, so\n * partial progress is always durable.\n *\n * Crash-window note: writeSkillsAtomic happens before recordEntry. A crash\n * (or kill -9) between the two leaves skills.md ahead of the chain by one\n * feed. Recovery is benign — the next feed of the same source produces an\n * identical-content merge (no-op) and a new chain entry, or, if the source\n * differs, an \"updated\" entry. The chain stays valid; the on-disk skills.md\n * is just slightly more current than the chain's last feed entry claims.\n */\nexport async function runFeed(\n agentId: string,\n patterns: readonly string[],\n opts: FeedOptions = {},\n): Promise<FeedResult> {\n const stdout = opts.stdout ?? process.stdout;\n const stderr = opts.stderr ?? process.stderr;\n\n const agent = await loadAgent(agentId, opts.baseDir);\n const targets = await expandPatterns(patterns, { cwd: opts.baseDir });\n const loader = opts.loadSource ?? readSource;\n const perSource: PerSourceResult[] = [];\n\n for (let i = 0; i < targets.length; i++) {\n const target = targets[i]!;\n const loaded = await loader(target);\n\n const incoming = await extractSkills(loaded.content, {\n source: loaded.source,\n model: opts.model,\n apiKey: opts.apiKey,\n client: opts.client as Parameters<typeof extractSkills>[1]['client'],\n });\n\n const existing = await readAgentSkills(agent.paths.skillsFile);\n const { merged, added, updated } = mergeSkills(existing, incoming);\n\n const skillsMd = serialize(buildDoc(merged));\n await writeSkillsAtomic(agent.paths.skillsFile, skillsMd);\n\n const skillsMdSha256 = sha256Hex(skillsMd);\n const skillsMdBytes = Buffer.byteLength(skillsMd, 'utf8');\n const sourceSha256 = sha256Hex(loaded.content);\n const sourceBytes = Buffer.byteLength(loaded.content, 'utf8');\n\n await recordEntry({\n path: agent.paths.provenanceFile,\n draft: {\n kind: 'feed',\n input: {\n source: loaded.source,\n source_url: loaded.source_url,\n source_kind: loaded.source_kind,\n source_sha256: sourceSha256,\n source_bytes: sourceBytes,\n model: opts.model ?? MODEL_ID,\n },\n output: {\n skills_added: added,\n skills_updated: updated,\n skills_removed: [],\n skills_md_sha256: skillsMdSha256,\n skills_md_bytes: skillsMdBytes,\n },\n },\n ts: resolveTs(opts.ts),\n });\n\n const estimatedTokens = estimateTokens(skillsMd);\n const warnedOverCap = estimatedTokens >= agent.config.token_cap_warn_at;\n if (warnedOverCap) {\n stderr.write(\n `warning: skills.md is ~${estimatedTokens} tokens (cap: ${agent.config.token_cap_warn_at}). ` +\n `Consider splitting into multiple agents.\\n`,\n );\n }\n\n stdout.write(\n `[${i + 1}/${targets.length}] ${loaded.source}: ` +\n `+${added.length} added, ${updated.length} updated, sha256=${skillsMdSha256.slice(0, 12)}\\n`,\n );\n\n perSource.push({\n target,\n source: loaded.source,\n added,\n updated,\n skillsMdSha256,\n skillsMdBytes,\n estimatedTokens,\n warnedOverCap,\n });\n }\n\n const totalAdded = perSource.reduce((n, r) => n + r.added.length, 0);\n const totalUpdated = perSource.reduce((n, r) => n + r.updated.length, 0);\n stdout.write(\n `done: ${perSource.length} source${perSource.length === 1 ? '' : 's'}, ` +\n `${totalAdded} added, ${totalUpdated} updated total\\n`,\n );\n\n return { agentId: agent.config.id, perSource };\n}\n\n// True for the errors runFeed raises that are the user's to fix (bad path,\n// unparseable skills.md, API failure) rather than internal bugs.\nexport function isFeedError(err: unknown): err is Error {\n return (\n err instanceof ExtractionError ||\n err instanceof SourceError ||\n err instanceof AgentError ||\n err instanceof ParseSkillsError ||\n err instanceof ProvenanceError\n );\n}\n","import { mkdir, readFile, readdir, rename, stat, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { v7 as uuidv7 } from 'uuid';\nimport { z } from 'zod';\n\nimport { parseSkills } from './parseSkills.js';\nimport { recordEntry } from './provenance.js';\n\nexport const AGENT_CONFIG_SCHEMA_VERSION = 0;\nexport const DEFAULT_TOKEN_CAP_WARN_AT = 32_000;\nexport const MODEX_DIR_NAME = '.modex';\n\nconst UUID7_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\nexport const AgentConfigSchema = z.object({\n schema_version: z.literal(AGENT_CONFIG_SCHEMA_VERSION),\n id: z.string().regex(UUID7_PATTERN, 'agent id must be a UUIDv7'),\n name: z.string(),\n created_at: z.string().min(1),\n token_cap_warn_at: z.number().int().positive(),\n});\n\nexport type AgentConfig = z.infer<typeof AgentConfigSchema>;\n\nexport interface AgentPaths {\n dir: string;\n configFile: string;\n skillsFile: string;\n provenanceFile: string;\n // Bound-state cache, written by `modex bind`. Absent until the agent is\n // first bound to a registry.\n registryFile: string;\n}\n\nexport interface AgentRecord {\n config: AgentConfig;\n paths: AgentPaths;\n}\n\nexport class AgentError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'AgentError';\n }\n}\n\nfunction modexDir(baseDir: string): string {\n return join(baseDir, MODEX_DIR_NAME);\n}\n\nfunction agentPaths(baseDir: string, id: string): AgentPaths {\n const dir = join(modexDir(baseDir), id);\n return {\n dir,\n configFile: join(dir, 'config.json'),\n skillsFile: join(dir, 'skills.md'),\n provenanceFile: join(dir, 'provenance.jsonl'),\n registryFile: join(dir, 'registry.json'),\n };\n}\n\nasync function writeJsonAtomic(path: string, value: unknown): Promise<void> {\n const tmp = `${path}.tmp.${process.pid}.${Date.now()}`;\n // Pretty-print config.json — humans will read and occasionally edit it.\n // (Provenance entries are canonical; configs aren't hashed.)\n await writeFile(tmp, JSON.stringify(value, null, 2) + '\\n', 'utf8');\n await rename(tmp, path);\n}\n\nexport async function writeSkillsAtomic(path: string, content: string): Promise<void> {\n const tmp = `${path}.tmp.${process.pid}.${Date.now()}`;\n await writeFile(tmp, content, 'utf8');\n await rename(tmp, path);\n}\n\n// Ensure `.modex/.gitignore` exists, ignoring the transient `*.lock` files\n// the per-file provenance lock creates. Users may commit their `.modex/`\n// directory (the \"reading lists in git\" use case) and a lockfile must never\n// ride along. The `wx` flag means we create it once and never clobber a\n// user-customized version.\nasync function ensureModexGitignore(baseDir: string): Promise<void> {\n const gitignorePath = join(modexDir(baseDir), '.gitignore');\n try {\n await writeFile(gitignorePath, '*.lock\\n', { flag: 'wx' });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'EEXIST') throw err;\n }\n}\n\nexport interface CreateAgentOptions {\n name?: string;\n baseDir?: string;\n // Test-only overrides:\n id?: string;\n ts?: string;\n tokenCapWarnAt?: number;\n}\n\nexport async function createAgent(opts: CreateAgentOptions = {}): Promise<AgentRecord> {\n const baseDir = opts.baseDir ?? process.cwd();\n const id = opts.id ?? uuidv7();\n const created_at = opts.ts ?? new Date().toISOString();\n const name = opts.name ?? '';\n const token_cap_warn_at = opts.tokenCapWarnAt ?? DEFAULT_TOKEN_CAP_WARN_AT;\n\n const paths = agentPaths(baseDir, id);\n\n // mkdir -p .modex/<id>\n await mkdir(paths.dir, { recursive: true });\n await ensureModexGitignore(baseDir);\n\n const config: AgentConfig = {\n schema_version: AGENT_CONFIG_SCHEMA_VERSION,\n id,\n name,\n created_at,\n token_cap_warn_at,\n };\n await writeJsonAtomic(paths.configFile, config);\n\n // Genesis provenance entry.\n await recordEntry({\n path: paths.provenanceFile,\n draft: {\n kind: 'agent_created',\n input: { name },\n output: { agent_id: id },\n },\n ts: created_at,\n });\n\n return { config, paths };\n}\n\nexport async function loadAgent(id: string, baseDir?: string): Promise<AgentRecord> {\n const root = baseDir ?? process.cwd();\n const paths = agentPaths(root, id);\n let raw: string;\n try {\n raw = await readFile(paths.configFile, 'utf8');\n } catch (err) {\n const e = err as NodeJS.ErrnoException;\n if (e.code === 'ENOENT') {\n throw new AgentError(\n `Agent '${id}' not found at ${paths.configFile}. Run 'modex agents create' first, or 'modex agents list' to see existing agents.`,\n );\n }\n throw err;\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n throw new AgentError(`Agent '${id}' has invalid config.json: ${(err as Error).message}`);\n }\n const result = AgentConfigSchema.safeParse(parsed);\n if (!result.success) {\n throw new AgentError(\n `Agent '${id}' config.json failed validation: ${result.error.issues\n .map((i) => `${i.path.join('.')}: ${i.message}`)\n .join('; ')}`,\n );\n }\n return { config: result.data, paths };\n}\n\nexport async function listAgents(baseDir?: string): Promise<AgentRecord[]> {\n const root = baseDir ?? process.cwd();\n const dir = modexDir(root);\n let entries: string[];\n try {\n entries = await readdir(dir);\n } catch (err) {\n const e = err as NodeJS.ErrnoException;\n if (e.code === 'ENOENT') return [];\n throw err;\n }\n const records: AgentRecord[] = [];\n for (const name of entries) {\n if (!UUID7_PATTERN.test(name)) continue;\n const candidate = join(dir, name);\n let s;\n try {\n s = await stat(candidate);\n } catch {\n continue;\n }\n if (!s.isDirectory()) continue;\n try {\n records.push(await loadAgent(name, root));\n } catch {\n // Skip directories without a valid config.\n continue;\n }\n }\n records.sort((a, b) => (a.config.created_at < b.config.created_at ? -1 : 1));\n return records;\n}\n\n// Read an agent's skills.md and parse it into Skill[]. Returns [] if the file\n// doesn't exist yet (i.e. the agent has never been fed).\nexport async function readAgentSkills(skillsFile: string) {\n let raw: string;\n try {\n raw = await readFile(skillsFile, 'utf8');\n } catch (err) {\n const e = err as NodeJS.ErrnoException;\n if (e.code === 'ENOENT') return [];\n throw err;\n }\n return parseSkills(raw).skills;\n}\n","// Hash-chained, append-only provenance log.\n//\n// Concurrency: recordEntry's read-head → compute → append sequence is wrapped\n// in a per-file exclusive lock (withFileLock). Two parallel recordEntry calls\n// on the same path — e.g. concurrent MCP tool invocations — serialize on the\n// lockfile rather than racing the head read and producing two entries that\n// both claim the same `prev`. Readers (readChain) stay lock-free: a single\n// canonical line is < PIPE_BUF, so appendFile is atomic and a reader never\n// observes a torn line.\n\nimport { createHash } from 'node:crypto';\nimport { appendFile, readFile } from 'node:fs/promises';\nimport { z } from 'zod';\n\nimport { canonicalize, type CanonicalJson } from './canonicalJson.js';\nimport { withFileLock, type LockOptions } from './fileLock.js';\n\nexport const PROVENANCE_SCHEMA_VERSION = 1;\n\nconst SHA256_HEX = /^[0-9a-f]{64}$/;\n\nexport const SOURCE_KINDS = ['text', 'markdown', 'pdf', 'epub', 'web'] as const;\nexport type SourceKind = (typeof SOURCE_KINDS)[number];\n\nconst FeedInputSchema = z.object({\n source: z.string().min(1),\n source_url: z.union([z.string().url(), z.null()]),\n source_kind: z.enum(SOURCE_KINDS),\n source_sha256: z.string().regex(SHA256_HEX),\n source_bytes: z.number().int().nonnegative(),\n model: z.string().min(1),\n});\n\nconst FeedOutputSchema = z.object({\n skills_added: z.array(z.string()),\n skills_updated: z.array(z.string()),\n skills_removed: z.array(z.string()),\n skills_md_sha256: z.string().regex(SHA256_HEX),\n skills_md_bytes: z.number().int().nonnegative(),\n});\n\nconst AgentCreatedInputSchema = z.object({ name: z.string() });\nconst AgentCreatedOutputSchema = z.object({ agent_id: z.string().min(1) });\n\n// Phase D — registry binding. Both new kinds stay at schema_version 1: they\n// are *additive* (no existing entry shape changed), so the version, which\n// tracks per-kind entry shape, does not move. A v1 `feed` entry written by\n// Phase C and one written by Phase D are byte-identical.\nconst BoundInputSchema = z.object({\n skills_md_sha256: z.string().regex(SHA256_HEX),\n aspiration_sha256s: z.array(z.string().regex(SHA256_HEX)),\n});\nconst BoundOutputSchema = z.object({\n registry_url: z.string().url(),\n bound_at: z.string().min(1),\n});\n\nconst AspirationAddedInputSchema = z.object({\n aspiration_sha256: z.string().regex(SHA256_HEX),\n aspiration_bytes: z.number().int().nonnegative(),\n source: z.string().min(1),\n});\nconst AspirationAddedOutputSchema = z.object({\n registry_url: z.string().url(),\n});\n\nconst BaseEntryFieldsSchema = {\n schema_version: z.literal(PROVENANCE_SCHEMA_VERSION),\n seq: z.number().int().positive(),\n ts: z.string().min(1),\n prev: z.union([z.string().regex(SHA256_HEX), z.null()]),\n entry_sha256: z.string().regex(SHA256_HEX),\n};\n\nexport const FeedEntrySchema = z.object({\n ...BaseEntryFieldsSchema,\n kind: z.literal('feed'),\n input: FeedInputSchema,\n output: FeedOutputSchema,\n});\n\nexport const AgentCreatedEntrySchema = z.object({\n ...BaseEntryFieldsSchema,\n kind: z.literal('agent_created'),\n input: AgentCreatedInputSchema,\n output: AgentCreatedOutputSchema,\n});\n\nexport const BoundEntrySchema = z.object({\n ...BaseEntryFieldsSchema,\n kind: z.literal('bound'),\n input: BoundInputSchema,\n output: BoundOutputSchema,\n});\n\nexport const AspirationAddedEntrySchema = z.object({\n ...BaseEntryFieldsSchema,\n kind: z.literal('aspiration_added'),\n input: AspirationAddedInputSchema,\n output: AspirationAddedOutputSchema,\n});\n\nexport const ProvenanceEntrySchema = z.discriminatedUnion('kind', [\n FeedEntrySchema,\n AgentCreatedEntrySchema,\n BoundEntrySchema,\n AspirationAddedEntrySchema,\n]);\n\n// The set of `kind` values this build understands. Used by readChain to give\n// a friendly \"upgrade modex-cli\" error when a newer build wrote a kind we\n// don't recognize, instead of zod's cryptic discriminated-union failure.\nexport const KNOWN_ENTRY_KINDS = [\n 'feed',\n 'agent_created',\n 'bound',\n 'aspiration_added',\n] as const;\n\nexport type FeedEntry = z.infer<typeof FeedEntrySchema>;\nexport type AgentCreatedEntry = z.infer<typeof AgentCreatedEntrySchema>;\nexport type BoundEntry = z.infer<typeof BoundEntrySchema>;\nexport type AspirationAddedEntry = z.infer<typeof AspirationAddedEntrySchema>;\nexport type ProvenanceEntry = z.infer<typeof ProvenanceEntrySchema>;\n\nexport type EntryDraft =\n | {\n kind: 'feed';\n input: z.input<typeof FeedInputSchema>;\n output: z.input<typeof FeedOutputSchema>;\n ts?: string;\n }\n | {\n kind: 'agent_created';\n input: z.input<typeof AgentCreatedInputSchema>;\n output: z.input<typeof AgentCreatedOutputSchema>;\n ts?: string;\n }\n | {\n kind: 'bound';\n input: z.input<typeof BoundInputSchema>;\n output: z.input<typeof BoundOutputSchema>;\n ts?: string;\n }\n | {\n kind: 'aspiration_added';\n input: z.input<typeof AspirationAddedInputSchema>;\n output: z.input<typeof AspirationAddedOutputSchema>;\n ts?: string;\n };\n\nexport class ProvenanceError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ProvenanceError';\n }\n}\n\nfunction sha256Hex(input: string): string {\n return createHash('sha256').update(input, 'utf8').digest('hex');\n}\n\n// Hash an entry by canonicalizing every field except entry_sha256.\nexport function computeEntryHash(entry: Omit<ProvenanceEntry, 'entry_sha256'>): string {\n return sha256Hex(canonicalize(entry as unknown as CanonicalJson));\n}\n\n// Read all entries from a JSONL file. Missing file returns []. Each line must\n// parse as an entry; the chain is NOT verified here — call verifyChain.\nexport async function readChain(path: string): Promise<ProvenanceEntry[]> {\n let raw: string;\n try {\n raw = await readFile(path, 'utf8');\n } catch (err) {\n const e = err as NodeJS.ErrnoException;\n if (e.code === 'ENOENT') return [];\n throw err;\n }\n if (raw.length === 0) return [];\n\n const lines = raw.split('\\n').filter((l) => l.length > 0);\n const entries: ProvenanceEntry[] = [];\n for (let i = 0; i < lines.length; i++) {\n let parsedJson: unknown;\n try {\n parsedJson = JSON.parse(lines[i]!);\n } catch (err) {\n throw new ProvenanceError(`Line ${i + 1}: invalid JSON (${(err as Error).message})`);\n }\n // Detect v0 chains explicitly so the user gets actionable guidance instead\n // of a generic discriminated-union schema failure.\n if (\n parsedJson !== null &&\n typeof parsedJson === 'object' &&\n 'schema_version' in parsedJson &&\n (parsedJson as { schema_version: unknown }).schema_version === 0\n ) {\n throw new ProvenanceError(\n `Line ${i + 1}: provenance entry has schema_version=0 (modex-cli@0.1.x, Phase B). ` +\n `v1 (Phase C) is not backward-compatible: the feed entry shape gained source_kind and source_url. ` +\n `Create a fresh agent under .modex/, or pin to @modexagents/cli@0.1.x for legacy agents.`,\n );\n }\n // Forward-compat: a v1 entry with a `kind` this build doesn't know was\n // almost certainly written by a newer modex-cli. Say so plainly rather\n // than letting zod emit an opaque discriminator error.\n if (\n parsedJson !== null &&\n typeof parsedJson === 'object' &&\n 'kind' in parsedJson &&\n typeof (parsedJson as { kind: unknown }).kind === 'string' &&\n !(KNOWN_ENTRY_KINDS as readonly string[]).includes((parsedJson as { kind: string }).kind)\n ) {\n throw new ProvenanceError(\n `Line ${i + 1}: provenance entry kind '${(parsedJson as { kind: string }).kind}' ` +\n `is not recognized by this build of modex-cli. It was likely written by a newer ` +\n `version — upgrade modex-cli to read this chain.`,\n );\n }\n const result = ProvenanceEntrySchema.safeParse(parsedJson);\n if (!result.success) {\n throw new ProvenanceError(\n `Line ${i + 1}: schema mismatch (${result.error.issues\n .map((iss) => `${iss.path.join('.')}: ${iss.message}`)\n .join('; ')})`,\n );\n }\n entries.push(result.data);\n }\n return entries;\n}\n\n// Verify the chain: monotonic seq from 1, prev links match the previous\n// entry's entry_sha256, and each entry_sha256 recomputes correctly.\n// Throws ProvenanceError on the first violation.\nexport function verifyChain(entries: readonly ProvenanceEntry[]): void {\n let expectedPrev: string | null = null;\n for (let i = 0; i < entries.length; i++) {\n const e = entries[i]!;\n if (e.seq !== i + 1) {\n throw new ProvenanceError(\n `Entry ${i}: expected seq=${i + 1}, got seq=${e.seq}`,\n );\n }\n if (e.prev !== expectedPrev) {\n throw new ProvenanceError(\n `Entry ${i} (seq=${e.seq}): prev=${e.prev ?? 'null'} does not match previous entry_sha256=${expectedPrev ?? 'null'}`,\n );\n }\n const { entry_sha256, ...rest } = e;\n const recomputed = computeEntryHash(rest as Omit<ProvenanceEntry, 'entry_sha256'>);\n if (recomputed !== entry_sha256) {\n throw new ProvenanceError(\n `Entry ${i} (seq=${e.seq}): entry_sha256 mismatch (stored=${entry_sha256}, recomputed=${recomputed})`,\n );\n }\n expectedPrev = entry_sha256;\n }\n}\n\nexport interface RecordEntryOptions {\n path: string;\n draft: EntryDraft;\n // If supplied, used as the entry timestamp. Otherwise new Date().toISOString().\n ts?: string;\n // If supplied, used as the previous-entry hash and seq. Otherwise read from disk.\n prev?: string | null;\n seq?: number;\n // Tuning / test seam for the per-file lock that serializes appends.\n lock?: LockOptions;\n}\n\n// Append a new entry to the chain. Reads the head from disk to determine\n// seq + prev (unless provided), computes entry_sha256, then writes a single\n// canonical JSON line.\n//\n// The read-head → compute → append sequence runs under a per-file exclusive\n// lock so concurrent callers (e.g. parallel MCP tool invocations) serialize\n// instead of racing the head read. When seq AND prev are both supplied the\n// caller has taken responsibility for ordering, but we still lock to keep the\n// physical append atomic against other writers.\n//\n// On disk we write the canonical form (sorted keys, no whitespace) so that\n// the line bytes are byte-identical for any reader and re-canonicalization\n// after parse is a no-op.\nexport async function recordEntry(opts: RecordEntryOptions): Promise<ProvenanceEntry> {\n return withFileLock(\n opts.path,\n async () => {\n let seq = opts.seq;\n let prev = opts.prev;\n if (seq === undefined || prev === undefined) {\n const existing = await readChain(opts.path);\n seq = seq ?? existing.length + 1;\n prev =\n prev ?? (existing.length === 0 ? null : existing[existing.length - 1]!.entry_sha256);\n }\n\n const ts = opts.ts ?? opts.draft.ts ?? new Date().toISOString();\n\n const skeleton = {\n schema_version: PROVENANCE_SCHEMA_VERSION,\n seq,\n ts,\n kind: opts.draft.kind,\n input: opts.draft.input,\n output: opts.draft.output,\n prev,\n };\n\n // Validate skeleton against the schema (without entry_sha256) by attaching\n // a placeholder hash, so we surface bad inputs before hashing.\n const validation = ProvenanceEntrySchema.safeParse({\n ...skeleton,\n entry_sha256: '0'.repeat(64),\n });\n if (!validation.success) {\n throw new ProvenanceError(\n `Invalid entry: ${validation.error.issues\n .map((i) => `${i.path.join('.')}: ${i.message}`)\n .join('; ')}`,\n );\n }\n\n const entry_sha256 = computeEntryHash(skeleton as Omit<ProvenanceEntry, 'entry_sha256'>);\n const full = { ...skeleton, entry_sha256 } as ProvenanceEntry;\n const line = canonicalize(full as unknown as CanonicalJson) + '\\n';\n await appendFile(opts.path, line, 'utf8');\n return full;\n },\n opts.lock,\n );\n}\n","// Soft token estimate: ~4 characters per token. Counts Unicode code points\n// (not UTF-16 code units) so multi-codepoint emoji don't undercount badly.\n// Real tokenizer can land in Phase D if the registry needs precise counts.\nexport function estimateTokens(text: string): number {\n let count = 0;\n for (const _ of text) count++;\n return Math.ceil(count / 4);\n}\n","import { createAgent, listAgents, readAgentSkills } from '../agent.js';\n\nexport interface AgentsCreateOptions {\n name?: string;\n baseDir?: string;\n stdout?: NodeJS.WritableStream;\n}\n\nexport async function runAgentsCreate(opts: AgentsCreateOptions = {}): Promise<string> {\n const stdout = opts.stdout ?? process.stdout;\n const agent = await createAgent({ name: opts.name, baseDir: opts.baseDir });\n stdout.write(`${agent.config.id}\\n`);\n return agent.config.id;\n}\n\nexport interface AgentsListOptions {\n baseDir?: string;\n stdout?: NodeJS.WritableStream;\n}\n\nexport async function runAgentsList(opts: AgentsListOptions = {}): Promise<void> {\n const stdout = opts.stdout ?? process.stdout;\n const agents = await listAgents(opts.baseDir);\n if (agents.length === 0) {\n stdout.write('(no agents in this directory — run `modex agents create` to make one)\\n');\n return;\n }\n for (const a of agents) {\n const skills = await readAgentSkills(a.paths.skillsFile);\n const name = a.config.name.length > 0 ? a.config.name : '(unnamed)';\n stdout.write(`${a.config.id}\\t${name}\\t${a.config.created_at}\\t${skills.length} skills\\n`);\n }\n}\n","import { chmod, mkdir, readFile, rename, unlink, writeFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { z } from 'zod';\n\nexport const CREDENTIALS_SCHEMA_VERSION = 1;\nexport const DEFAULT_REGISTRY_URL = 'https://registry.modex.md';\n\nexport const CredentialsSchema = z.object({\n schema_version: z.literal(CREDENTIALS_SCHEMA_VERSION),\n access_token: z.string().min(1),\n registry_url: z.string().url(),\n});\n\nexport type Credentials = z.infer<typeof CredentialsSchema>;\n\nexport class CredentialsError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'CredentialsError';\n }\n}\n\n// ${XDG_CONFIG_HOME:-~/.config}/modex\nexport function configDir(): string {\n const xdg = process.env['XDG_CONFIG_HOME'];\n const base = xdg && xdg.length > 0 ? xdg : join(homedir(), '.config');\n return join(base, 'modex');\n}\n\nexport function credentialsPath(dir: string = configDir()): string {\n return join(dir, 'credentials.json');\n}\n\n// Returns null when the user has not logged in. Throws CredentialsError only\n// when the file exists but is unreadable or malformed.\nexport async function loadCredentials(dir: string = configDir()): Promise<Credentials | null> {\n const path = credentialsPath(dir);\n let raw: string;\n try {\n raw = await readFile(path, 'utf8');\n } catch (err) {\n const e = err as NodeJS.ErrnoException;\n if (e.code === 'ENOENT') return null;\n throw new CredentialsError(`Could not read ${path}: ${e.message}`);\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n throw new CredentialsError(`${path} is not valid JSON: ${(err as Error).message}`);\n }\n const result = CredentialsSchema.safeParse(parsed);\n if (!result.success) {\n throw new CredentialsError(\n `${path} failed validation: ${result.error.issues\n .map((i) => `${i.path.join('.')}: ${i.message}`)\n .join('; ')}`,\n );\n }\n return result.data;\n}\n\n// Atomic write at mode 0600. The directory is created 0700. We set the mode at\n// open time AND chmod afterwards: writeFile's `mode` only applies on create and\n// is still subject to umask, so the explicit chmod guarantees 0600 regardless.\nexport async function saveCredentials(\n credentials: Credentials,\n dir: string = configDir(),\n): Promise<void> {\n await mkdir(dir, { recursive: true, mode: 0o700 });\n const path = credentialsPath(dir);\n const tmp = `${path}.tmp.${process.pid}.${Date.now()}`;\n const body = JSON.stringify(credentials, null, 2) + '\\n';\n await writeFile(tmp, body, { mode: 0o600, encoding: 'utf8' });\n await chmod(tmp, 0o600);\n await rename(tmp, path);\n await chmod(path, 0o600);\n}\n\n// Remove the credentials file. Missing file is not an error — clearing an\n// already-absent credential is a no-op (used on the 401 path).\nexport async function clearCredentials(dir: string = configDir()): Promise<void> {\n try {\n await unlink(credentialsPath(dir));\n } catch (err) {\n const e = err as NodeJS.ErrnoException;\n if (e.code === 'ENOENT') return;\n throw new CredentialsError(`Could not clear credentials: ${e.message}`);\n }\n}\n","import { z } from 'zod';\n\n// --- Errors ---------------------------------------------------------------\n\nexport class RegistryError extends Error {\n // HTTP status, or null for transport-level failures (DNS, connection reset).\n readonly status: number | null;\n // The `error` field from a structured error body, if the registry sent one.\n readonly code: string | null;\n\n constructor(\n message: string,\n opts: { status?: number | null; code?: string | null } = {},\n ) {\n super(message);\n this.name = 'RegistryError';\n this.status = opts.status ?? null;\n this.code = opts.code ?? null;\n }\n}\n\n// --- Device-code auth -----------------------------------------------------\n\nexport const DeviceCodeStartSchema = z.object({\n device_code: z.string().min(1),\n user_code: z.string().min(1),\n verify_url: z.string().url(),\n expires_in: z.number().int().positive(),\n interval: z.number().int().positive(),\n});\nexport type DeviceCodeStart = z.infer<typeof DeviceCodeStartSchema>;\n\n// The token endpoint returns either a token or a polling-status error.\nexport const TokenResponseSchema = z.union([\n z.object({ access_token: z.string().min(1) }),\n z.object({ error: z.string().min(1) }),\n]);\nexport type TokenResponse = z.infer<typeof TokenResponseSchema>;\n\n// --- Bind -----------------------------------------------------------------\n\nexport interface BindRequest {\n skills_md: string;\n skills_md_sha256: string;\n provenance_head_sha256: string;\n aspiration_sha256s: string[];\n}\n\n// Parsed leniently: we only require what the CLI consumes; the registry may\n// send more (owner, lineage, etc.) and that's fine.\nexport const BindResponseSchema = z\n .object({\n skills_md_sha256: z.string().min(1),\n bound_at: z.string().min(1),\n })\n .passthrough();\nexport type BindResponse = z.infer<typeof BindResponseSchema>;\n\n// --- Aspirations ----------------------------------------------------------\n\nexport interface AspirationRequest {\n sha256: string;\n content: string;\n}\n\nexport const AspirationResponseSchema = z\n .object({\n created_at: z.string().min(1).optional(),\n })\n .passthrough();\nexport type AspirationResponse = z.infer<typeof AspirationResponseSchema>;\n","import {\n type AspirationRequest,\n type AspirationResponse,\n AspirationResponseSchema,\n type BindRequest,\n type BindResponse,\n BindResponseSchema,\n type DeviceCodeStart,\n DeviceCodeStartSchema,\n RegistryError,\n type TokenResponse,\n TokenResponseSchema,\n} from './types.js';\n\n// RFC 8628: on `slow_down` the client must lengthen the poll interval by 5s.\nconst SLOW_DOWN_INCREMENT_S = 5;\n\nexport interface RegistryDeps {\n fetch?: typeof globalThis.fetch;\n sleep?: (ms: number) => Promise<void>;\n now?: () => number;\n}\n\ninterface ResolvedDeps {\n fetch: typeof globalThis.fetch;\n sleep: (ms: number) => Promise<void>;\n now: () => number;\n}\n\nfunction resolveDeps(deps: RegistryDeps = {}): ResolvedDeps {\n return {\n fetch: deps.fetch ?? globalThis.fetch,\n sleep: deps.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms))),\n now: deps.now ?? Date.now,\n };\n}\n\nfunction endpoint(registryUrl: string, path: string): string {\n return registryUrl.replace(/\\/+$/, '') + path;\n}\n\ninterface PostResult {\n status: number;\n json: unknown;\n}\n\n// POST JSON, parse JSON back. Transport failures become RegistryError with a\n// null status; HTTP-level status is returned to the caller to interpret.\nasync function postJson(\n fetchImpl: typeof globalThis.fetch,\n url: string,\n body: unknown,\n token?: string,\n): Promise<PostResult> {\n const headers: Record<string, string> = { 'content-type': 'application/json' };\n if (token) headers['authorization'] = `Bearer ${token}`;\n\n let response: Response;\n try {\n response = await fetchImpl(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n });\n } catch (err) {\n throw new RegistryError(\n `Could not reach the registry at ${url}: ${(err as Error).message}`,\n { status: null },\n );\n }\n\n let json: unknown = null;\n const text = await response.text();\n if (text.length > 0) {\n try {\n json = JSON.parse(text);\n } catch {\n // Non-JSON body — leave json as null; caller decides based on status.\n }\n }\n return { status: response.status, json };\n}\n\nfunction bodyErrorCode(json: unknown): string | null {\n if (json !== null && typeof json === 'object' && 'error' in json) {\n const code = (json as { error: unknown }).error;\n return typeof code === 'string' ? code : null;\n }\n return null;\n}\n\n// --- Device-code flow -----------------------------------------------------\n\nexport async function startDeviceCode(\n registryUrl: string,\n deps?: RegistryDeps,\n): Promise<DeviceCodeStart> {\n const { fetch } = resolveDeps(deps);\n const { status, json } = await postJson(\n fetch,\n endpoint(registryUrl, '/v1/auth/cli/device-code'),\n {},\n );\n if (status !== 200) {\n throw new RegistryError(\n `Registry rejected the device-code request (HTTP ${status}).`,\n { status, code: bodyErrorCode(json) },\n );\n }\n const parsed = DeviceCodeStartSchema.safeParse(json);\n if (!parsed.success) {\n throw new RegistryError(\n `Registry device-code response was malformed: ${parsed.error.issues\n .map((i) => `${i.path.join('.')}: ${i.message}`)\n .join('; ')}`,\n { status },\n );\n }\n return parsed.data;\n}\n\nexport interface PollDeps extends RegistryDeps {\n // Called each time the registry says \"still pending\" — lets the CLI show\n // progress without this module touching stdout.\n onPending?: () => void;\n}\n\n// Poll the token endpoint until the user approves, the device code expires,\n// or the registry returns a hard error. Honors `slow_down` (interval += 5s)\n// and `expires_in` (overall deadline) from the start payload.\nexport async function pollForToken(\n registryUrl: string,\n start: DeviceCodeStart,\n deps?: PollDeps,\n): Promise<string> {\n const { fetch, sleep, now } = resolveDeps(deps);\n const onPending = deps?.onPending;\n\n const deadline = now() + start.expires_in * 1000;\n let intervalS = start.interval;\n const url = endpoint(registryUrl, '/v1/auth/cli/token');\n\n for (;;) {\n if (now() >= deadline) {\n throw new RegistryError(\n 'The login code expired before it was approved. Run `modex login` again.',\n { code: 'expired_token' },\n );\n }\n\n await sleep(intervalS * 1000);\n\n const { status, json } = await postJson(fetch, url, { device_code: start.device_code });\n const parsed = TokenResponseSchema.safeParse(json);\n\n if (parsed.success && 'access_token' in parsed.data) {\n return parsed.data.access_token;\n }\n\n const code = parsed.success && 'error' in parsed.data ? parsed.data.error : bodyErrorCode(json);\n\n if (code === 'authorization_pending') {\n onPending?.();\n continue;\n }\n if (code === 'slow_down') {\n intervalS += SLOW_DOWN_INCREMENT_S;\n onPending?.();\n continue;\n }\n\n // Any other outcome is terminal.\n throw new RegistryError(\n code\n ? `Registry refused the login: ${code}.`\n : `Registry token endpoint returned an unexpected response (HTTP ${status}).`,\n { status, code: code ?? null },\n );\n }\n}\n\n// --- Bind -----------------------------------------------------------------\n\nexport async function bindAgent(\n registryUrl: string,\n agentId: string,\n token: string,\n body: BindRequest,\n deps?: RegistryDeps,\n): Promise<BindResponse> {\n const { fetch } = resolveDeps(deps);\n const { status, json } = await postJson(\n fetch,\n endpoint(registryUrl, `/v1/agents/${encodeURIComponent(agentId)}/bind`),\n body,\n token,\n );\n\n if (status === 401) {\n throw new RegistryError('Your registry token is no longer valid.', { status, code: bodyErrorCode(json) });\n }\n if (status === 409) {\n throw new RegistryError(\n `Agent ${agentId} is already bound to a different user. ` +\n `Re-bind is only allowed by the user who first claimed it.`,\n { status, code: bodyErrorCode(json) },\n );\n }\n if (status < 200 || status >= 300) {\n throw new RegistryError(\n `Registry rejected the bind (HTTP ${status}).`,\n { status, code: bodyErrorCode(json) },\n );\n }\n\n const parsed = BindResponseSchema.safeParse(json);\n if (!parsed.success) {\n throw new RegistryError(\n `Registry bind response was malformed: ${parsed.error.issues\n .map((i) => `${i.path.join('.')}: ${i.message}`)\n .join('; ')}`,\n { status },\n );\n }\n return parsed.data;\n}\n\n// --- Aspirations ----------------------------------------------------------\n\nexport async function addAspiration(\n registryUrl: string,\n agentId: string,\n token: string,\n body: AspirationRequest,\n deps?: RegistryDeps,\n): Promise<AspirationResponse> {\n const { fetch } = resolveDeps(deps);\n const { status, json } = await postJson(\n fetch,\n endpoint(registryUrl, `/v1/agents/${encodeURIComponent(agentId)}/aspirations`),\n body,\n token,\n );\n\n if (status === 401) {\n throw new RegistryError('Your registry token is no longer valid.', { status, code: bodyErrorCode(json) });\n }\n if (status === 404) {\n throw new RegistryError(\n `Agent ${agentId} is not bound on the registry. Run \\`modex bind ${agentId}\\` first.`,\n { status, code: bodyErrorCode(json) },\n );\n }\n if (status < 200 || status >= 300) {\n throw new RegistryError(\n `Registry rejected the aspiration (HTTP ${status}).`,\n { status, code: bodyErrorCode(json) },\n );\n }\n\n const parsed = AspirationResponseSchema.safeParse(json ?? {});\n if (!parsed.success) {\n throw new RegistryError(\n `Registry aspiration response was malformed: ${parsed.error.issues\n .map((i) => `${i.path.join('.')}: ${i.message}`)\n .join('; ')}`,\n { status },\n );\n }\n return parsed.data;\n}\n\nexport type { TokenResponse };\n","import {\n clearCredentials,\n CredentialsError,\n DEFAULT_REGISTRY_URL,\n saveCredentials,\n} from '../credentials.js';\nimport { pollForToken, RegistryError, startDeviceCode } from '../registry/index.js';\n\nexport interface LoginOptions {\n registry?: string;\n // Test injection points:\n configDir?: string;\n fetch?: typeof globalThis.fetch;\n sleep?: (ms: number) => Promise<void>;\n now?: () => number;\n stdout?: NodeJS.WritableStream;\n stderr?: NodeJS.WritableStream;\n}\n\nexport interface LoginResult {\n registryUrl: string;\n}\n\nexport async function runLogin(opts: LoginOptions = {}): Promise<LoginResult> {\n const stdout = opts.stdout ?? process.stdout;\n const registryUrl = opts.registry ?? DEFAULT_REGISTRY_URL;\n const deps = { fetch: opts.fetch, sleep: opts.sleep, now: opts.now };\n\n const start = await startDeviceCode(registryUrl, deps);\n stdout.write(\n `To authorize this CLI, open:\\n ${start.verify_url}\\n` +\n `and enter the code:\\n ${start.user_code}\\n\\n` +\n `Waiting for approval…\\n`,\n );\n\n const accessToken = await pollForToken(registryUrl, start, {\n ...deps,\n onPending: () => stdout.write('.'),\n });\n stdout.write('\\n');\n\n await saveCredentials(\n { schema_version: 1, access_token: accessToken, registry_url: registryUrl },\n opts.configDir,\n );\n stdout.write(`Logged in to ${registryUrl}.\\n`);\n return { registryUrl };\n}\n\nexport interface LogoutOptions {\n configDir?: string;\n stdout?: NodeJS.WritableStream;\n}\n\nexport async function runLogout(opts: LogoutOptions = {}): Promise<void> {\n const stdout = opts.stdout ?? process.stdout;\n await clearCredentials(opts.configDir);\n stdout.write('Logged out. Local credentials cleared.\\n');\n}\n\nexport function isLoginError(err: unknown): err is Error {\n return err instanceof RegistryError || err instanceof CredentialsError;\n}\n","import { createHash } from 'node:crypto';\nimport { readFile } from 'node:fs/promises';\n\nimport { AgentError, loadAgent, readAgentSkills } from '../agent.js';\nimport { clearCredentials, CredentialsError, loadCredentials } from '../credentials.js';\nimport {\n type AspirationAddedEntry,\n type ProvenanceEntry,\n ProvenanceError,\n readChain,\n recordEntry,\n} from '../provenance.js';\nimport { bindAgent, RegistryError } from '../registry/index.js';\nimport { RegistryStateError, writeRegistryState } from '../registryState.js';\nimport { buildDoc, serialize } from '../serialize.js';\n\nconst isAspirationAdded = (e: ProvenanceEntry): e is AspirationAddedEntry =>\n e.kind === 'aspiration_added';\n\nexport interface BindOptions {\n baseDir?: string;\n configDir?: string;\n fetch?: typeof globalThis.fetch;\n ts?: string;\n stdout?: NodeJS.WritableStream;\n stderr?: NodeJS.WritableStream;\n}\n\nexport interface BindResult {\n agentId: string;\n registryUrl: string;\n skillsMdSha256: string;\n boundAt: string;\n}\n\nfunction sha256Hex(text: string): string {\n return createHash('sha256').update(text, 'utf8').digest('hex');\n}\n\n/**\n * Bind a local agent to the registry it was logged into.\n *\n * Ordering: the registry POST happens first; the local `bound` provenance\n * entry and registry.json are written only on a 2xx. This keeps the local\n * chain a subset of registry truth — a crash after a successful POST but\n * before the local write is benign, because a re-run is a same-user re-bind\n * (allowed by the registry) and simply records the entry then.\n */\nexport async function runBind(agentId: string, opts: BindOptions = {}): Promise<BindResult> {\n const stdout = opts.stdout ?? process.stdout;\n\n const credentials = await loadCredentials(opts.configDir);\n if (credentials === null) {\n throw new CredentialsError('Not logged in. Run `modex login` first.');\n }\n\n const agent = await loadAgent(agentId, opts.baseDir);\n\n // The on-disk skills.md is canonical (feed writes it via writeSkillsAtomic).\n // A never-fed agent has no file — bind the canonical empty doc.\n let skillsMd: string;\n try {\n skillsMd = await readFile(agent.paths.skillsFile, 'utf8');\n } catch (err) {\n const e = err as NodeJS.ErrnoException;\n if (e.code !== 'ENOENT') throw err;\n skillsMd = serialize(buildDoc(await readAgentSkills(agent.paths.skillsFile)));\n }\n const skillsMdSha256 = sha256Hex(skillsMd);\n\n const chain = await readChain(agent.paths.provenanceFile);\n if (chain.length === 0) {\n throw new AgentError(\n `Agent ${agentId} has an empty provenance chain — cannot bind. The chain should ` +\n `always contain at least the agent_created entry.`,\n );\n }\n const provenanceHead = chain[chain.length - 1]!.entry_sha256;\n const aspirationSha256s = chain\n .filter(isAspirationAdded)\n .map((e) => e.input.aspiration_sha256);\n\n let response;\n try {\n response = await bindAgent(\n credentials.registry_url,\n agent.config.id,\n credentials.access_token,\n {\n skills_md: skillsMd,\n skills_md_sha256: skillsMdSha256,\n provenance_head_sha256: provenanceHead,\n aspiration_sha256s: aspirationSha256s,\n },\n { fetch: opts.fetch },\n );\n } catch (err) {\n if (err instanceof RegistryError && err.status === 401) {\n await clearCredentials(opts.configDir);\n throw new RegistryError(\n 'Your registry token is no longer valid and has been cleared. Run `modex login` again.',\n { status: 401 },\n );\n }\n throw err;\n }\n\n // Registry accepted the bind — now record it locally.\n await recordEntry({\n path: agent.paths.provenanceFile,\n draft: {\n kind: 'bound',\n input: {\n skills_md_sha256: skillsMdSha256,\n aspiration_sha256s: aspirationSha256s,\n },\n output: {\n registry_url: credentials.registry_url,\n bound_at: response.bound_at,\n },\n },\n ts: opts.ts,\n });\n\n await writeRegistryState(agent.paths.registryFile, {\n schema_version: 1,\n registry_url: credentials.registry_url,\n agent_id: agent.config.id,\n bound_at: response.bound_at,\n last_server_skills_md_sha256: response.skills_md_sha256,\n });\n\n stdout.write(\n `Bound ${agent.config.id} to ${credentials.registry_url}\\n` +\n ` skills.md sha256: ${skillsMdSha256.slice(0, 12)}…\\n` +\n ` bound_at: ${response.bound_at}\\n`,\n );\n\n return {\n agentId: agent.config.id,\n registryUrl: credentials.registry_url,\n skillsMdSha256,\n boundAt: response.bound_at,\n };\n}\n\nexport function isBindError(err: unknown): err is Error {\n return (\n err instanceof RegistryError ||\n err instanceof CredentialsError ||\n err instanceof AgentError ||\n err instanceof ProvenanceError ||\n err instanceof RegistryStateError\n );\n}\n","import { readFile, rename, writeFile } from 'node:fs/promises';\nimport { z } from 'zod';\n\n// Denormalized \"latest bound state\" cache, written to .modex/<id>/registry.json\n// by `modex bind`. The provenance chain's `bound` entries are authoritative;\n// this file just lets the CLI quickly answer \"is this agent bound, and is the\n// local skills.md ahead of what the registry last saw?\" without replaying the\n// chain. An agent that has never been bound simply has no registry.json.\n\nexport const REGISTRY_STATE_SCHEMA_VERSION = 1;\n\nconst SHA256_HEX = /^[0-9a-f]{64}$/;\n\nexport const RegistryStateSchema = z.object({\n schema_version: z.literal(REGISTRY_STATE_SCHEMA_VERSION),\n registry_url: z.string().url(),\n agent_id: z.string().min(1),\n bound_at: z.string().min(1),\n last_server_skills_md_sha256: z.string().regex(SHA256_HEX),\n});\n\nexport type RegistryState = z.infer<typeof RegistryStateSchema>;\n\nexport class RegistryStateError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'RegistryStateError';\n }\n}\n\n// Returns null when the agent has never been bound.\nexport async function readRegistryState(path: string): Promise<RegistryState | null> {\n let raw: string;\n try {\n raw = await readFile(path, 'utf8');\n } catch (err) {\n const e = err as NodeJS.ErrnoException;\n if (e.code === 'ENOENT') return null;\n throw new RegistryStateError(`Could not read ${path}: ${e.message}`);\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n throw new RegistryStateError(`${path} is not valid JSON: ${(err as Error).message}`);\n }\n const result = RegistryStateSchema.safeParse(parsed);\n if (!result.success) {\n throw new RegistryStateError(\n `${path} failed validation: ${result.error.issues\n .map((i) => `${i.path.join('.')}: ${i.message}`)\n .join('; ')}`,\n );\n }\n return result.data;\n}\n\nexport async function writeRegistryState(path: string, state: RegistryState): Promise<void> {\n const tmp = `${path}.tmp.${process.pid}.${Date.now()}`;\n // Pretty-printed — humans read this file; it isn't hashed.\n await writeFile(tmp, JSON.stringify(state, null, 2) + '\\n', 'utf8');\n await rename(tmp, path);\n}\n","import { createHash } from 'node:crypto';\nimport { readFile } from 'node:fs/promises';\nimport { basename } from 'node:path';\n\nimport { AgentError, loadAgent } from '../agent.js';\nimport { clearCredentials, CredentialsError, loadCredentials } from '../credentials.js';\nimport { ProvenanceError, recordEntry } from '../provenance.js';\nimport { addAspiration, RegistryError } from '../registry/index.js';\nimport { readRegistryState, RegistryStateError } from '../registryState.js';\n\nexport interface AspirationsAddOptions {\n baseDir?: string;\n configDir?: string;\n fetch?: typeof globalThis.fetch;\n ts?: string;\n stdout?: NodeJS.WritableStream;\n stderr?: NodeJS.WritableStream;\n}\n\nexport interface AspirationsAddResult {\n agentId: string;\n registryUrl: string;\n aspirationSha256: string;\n source: string;\n}\n\nfunction sha256Hex(text: string): string {\n return createHash('sha256').update(text, 'utf8').digest('hex');\n}\n\n/**\n * Append an aspiration to a bound agent.\n *\n * Append-only: there is deliberately no edit or delete operation — the\n * registry rejects mutation and so does this surface by omission.\n *\n * Requires a prior bind: we check the local registry.json and fail fast with\n * guidance rather than letting the registry return a 404.\n *\n * Ordering matches bind — POST first, record the `aspiration_added`\n * provenance entry only on a 2xx.\n */\nexport async function runAspirationsAdd(\n agentId: string,\n mdFile: string,\n opts: AspirationsAddOptions = {},\n): Promise<AspirationsAddResult> {\n const stdout = opts.stdout ?? process.stdout;\n\n const credentials = await loadCredentials(opts.configDir);\n if (credentials === null) {\n throw new CredentialsError('Not logged in. Run `modex login` first.');\n }\n\n const agent = await loadAgent(agentId, opts.baseDir);\n\n const registryState = await readRegistryState(agent.paths.registryFile);\n if (registryState === null) {\n throw new AgentError(\n `Agent ${agentId} is not bound to a registry. Run \\`modex bind ${agentId}\\` first.`,\n );\n }\n\n let content: string;\n try {\n content = await readFile(mdFile, 'utf8');\n } catch (err) {\n throw new AgentError(`Could not read aspiration file ${mdFile}: ${(err as Error).message}`);\n }\n if (content.trim().length === 0) {\n throw new AgentError(`Aspiration file ${mdFile} is empty.`);\n }\n\n const aspirationSha256 = sha256Hex(content);\n const source = basename(mdFile);\n\n try {\n await addAspiration(\n registryState.registry_url,\n agent.config.id,\n credentials.access_token,\n { sha256: aspirationSha256, content },\n { fetch: opts.fetch },\n );\n } catch (err) {\n if (err instanceof RegistryError && err.status === 401) {\n await clearCredentials(opts.configDir);\n throw new RegistryError(\n 'Your registry token is no longer valid and has been cleared. Run `modex login` again.',\n { status: 401 },\n );\n }\n throw err;\n }\n\n await recordEntry({\n path: agent.paths.provenanceFile,\n draft: {\n kind: 'aspiration_added',\n input: {\n aspiration_sha256: aspirationSha256,\n aspiration_bytes: Buffer.byteLength(content, 'utf8'),\n source,\n },\n output: {\n registry_url: registryState.registry_url,\n },\n },\n ts: opts.ts,\n });\n\n stdout.write(\n `Added aspiration to ${agent.config.id}\\n` +\n ` source: ${source}\\n` +\n ` sha256: ${aspirationSha256.slice(0, 12)}…\\n`,\n );\n\n return {\n agentId: agent.config.id,\n registryUrl: registryState.registry_url,\n aspirationSha256,\n source,\n };\n}\n\nexport function isAspirationsError(err: unknown): err is Error {\n return (\n err instanceof RegistryError ||\n err instanceof CredentialsError ||\n err instanceof AgentError ||\n err instanceof ProvenanceError ||\n err instanceof RegistryStateError\n );\n}\n","// High-level orchestrators shared by every surface (CLI, MCP server, GitHub\n// Action). Each `run*` function is self-contained and accepts injectable\n// baseDir / configDir / fetch / streams, so a wrapper only has to translate\n// its native input into a call here.\n\nexport {\n runFeed,\n isFeedError,\n type FeedOptions,\n type FeedResult,\n type PerSourceResult,\n} from './feed.js';\n\nexport {\n runAgentsCreate,\n runAgentsList,\n type AgentsCreateOptions,\n type AgentsListOptions,\n} from './agents.js';\n\nexport {\n runLogin,\n runLogout,\n isLoginError,\n type LoginOptions,\n type LoginResult,\n type LogoutOptions,\n} from './login.js';\n\nexport {\n runBind,\n isBindError,\n type BindOptions,\n type BindResult,\n} from './bind.js';\n\nexport {\n runAspirationsAdd,\n isAspirationsError,\n type AspirationsAddOptions,\n type AspirationsAddResult,\n} from './aspirations.js';\n\nimport { isAspirationsError } from './aspirations.js';\nimport { isBindError } from './bind.js';\nimport { isFeedError } from './feed.js';\nimport { isLoginError } from './login.js';\n\n// True for any error a surface should present to the user as a plain message\n// (bad input, auth needed, registry rejection) rather than an internal crash.\nexport function isUserFacingError(err: unknown): err is Error {\n return (\n isFeedError(err) || isLoginError(err) || isBindError(err) || isAspirationsError(err)\n );\n}\n"],"mappings":"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","names":["extname","basename","basename","readFile","basename","readFile","basename","groups","extname","compareCodepoints","readFile","resolve","createHash","readFile","stat","z","readFile","z","z","readFile","z","readFile","stat","sha256Hex","createHash","mkdir","readFile","rename","unlink","writeFile","join","z","z","sleep","createHash","readFile","readFile","rename","writeFile","z","SHA256_HEX","sha256Hex","createHash","readFile","createHash","readFile","basename","sha256Hex","createHash","readFile","basename"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@modexagents/core",
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"description": "Core extraction, canonical SKILLS.md serialization, hash-chained provenance, and registry client for modex-cli",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE"
|
|
19
|
+
],
|
|
20
|
+
"keywords": [
|
|
21
|
+
"modex",
|
|
22
|
+
"skills",
|
|
23
|
+
"skills.md",
|
|
24
|
+
"provenance",
|
|
25
|
+
"ai-agents",
|
|
26
|
+
"anthropic"
|
|
27
|
+
],
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "git+https://github.com/rickyjs1955/modex-cli.git",
|
|
31
|
+
"directory": "packages/core"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://github.com/rickyjs1955/modex-cli/tree/main/packages/core#readme",
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://github.com/rickyjs1955/modex-cli/issues"
|
|
36
|
+
},
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@anthropic-ai/sdk": "^0.95.0",
|
|
42
|
+
"@mozilla/readability": "^0.6.0",
|
|
43
|
+
"epub2": "^3.0.2",
|
|
44
|
+
"linkedom": "^0.18.12",
|
|
45
|
+
"tinyglobby": "^0.2.16",
|
|
46
|
+
"unpdf": "^1.6.2",
|
|
47
|
+
"uuid": "^14.0.0",
|
|
48
|
+
"zod": "^3.23.8"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/node": "^20.14.10",
|
|
52
|
+
"@types/uuid": "^10.0.0",
|
|
53
|
+
"tsup": "^8.3.0",
|
|
54
|
+
"typescript": "^5.6.3",
|
|
55
|
+
"vitest": "^2.1.4"
|
|
56
|
+
},
|
|
57
|
+
"engines": {
|
|
58
|
+
"node": ">=20"
|
|
59
|
+
},
|
|
60
|
+
"scripts": {
|
|
61
|
+
"build": "tsup",
|
|
62
|
+
"test": "vitest run",
|
|
63
|
+
"test:watch": "vitest",
|
|
64
|
+
"typecheck": "tsc --noEmit"
|
|
65
|
+
}
|
|
66
|
+
}
|