@dowel-ui/mcp 0.7.0
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/dist/index.d.ts +1 -0
- package/dist/index.js +1076 -0
- package/dist/index.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/branding.ts","../../registry/dist/generate.js","../../registry/dist/schema-BbyNjH6Q.js","../../registry/dist/index.js","../src/registry.ts","../src/server.ts","../src/index.ts"],"sourcesContent":["/**\n * Branding, mirrored from the repository root config.\n *\n * Duplicated deliberately: the published server cannot import from the monorepo\n * root, and `pnpm rebrand` rewrites every copy in the same pass.\n */\nexport const branding = {\n libraryName: \"Dowel\",\n cliPackage: \"@dowel-ui/cli\",\n packageScope: \"@dowel-ui\",\n registryUrl: \"https://dowel-eight.vercel.app/r\",\n} as const;\n","//#region src/generate.ts\n/**\n* Turning a description of a screen into a plan made of components that exist.\n*\n* The hard part of generating UI is not writing JSX. It is not inventing: a\n* model asked for a billing page will cheerfully produce `<PricingTable>` and\n* `<InvoiceList>` and a `variant=\"subtle\"` that was never implemented, and the\n* result reads perfectly and compiles nowhere.\n*\n* So this resolves a prompt against the registry first, and everything it\n* emits afterwards is drawn from what came back. It cannot name a component\n* that is not installable, because it only ever repeats names the registry\n* gave it.\n*\n* It does not guess at props. The registry publishes what a component *is* and\n* what it depends on, not the shape of its arguments, so the output stops at\n* the composition and points at the page where the props are documented.\n* Emitting a plausible prop is worse than emitting none — one is a gap, the\n* other is a bug that looks like working code.\n*/\n/** Words that carry no signal about which component is wanted. */\nconst STOPWORDS = /* @__PURE__ */ new Set([\n\t\"a\",\n\t\"an\",\n\t\"the\",\n\t\"and\",\n\t\"or\",\n\t\"of\",\n\t\"for\",\n\t\"with\",\n\t\"to\",\n\t\"in\",\n\t\"on\",\n\t\"at\",\n\t\"by\",\n\t\"is\",\n\t\"are\",\n\t\"be\",\n\t\"make\",\n\t\"build\",\n\t\"create\",\n\t\"want\",\n\t\"need\",\n\t\"add\",\n\t\"show\",\n\t\"page\",\n\t\"screen\",\n\t\"app\",\n\t\"application\",\n\t\"ui\",\n\t\"interface\",\n\t\"component\",\n\t\"components\",\n\t\"me\",\n\t\"my\",\n\t\"our\",\n\t\"i\",\n\t\"it\",\n\t\"that\",\n\t\"this\",\n\t\"some\",\n\t\"using\",\n\t\"use\",\n\t\"like\"\n]);\n/**\n* Words a reader would use that are not the words the registry uses.\n*\n* Hand-written, and deliberately so. \"Sign in\" is what someone types and\n* `login` is what the item is called; no amount of string similarity bridges\n* that, and pretending otherwise produces a matcher that works on the examples\n* it was tuned against and nothing else.\n*/\nconst SYNONYMS = {\n\t\"sign in\": [\"login\"],\n\tsignin: [\"login\"],\n\t\"log in\": [\"login\"],\n\t\"sign up\": [\"signup\"],\n\tregister: [\"signup\"],\n\tregistration: [\"signup\"],\n\t\"forgot password\": [\"forgot-password\"],\n\t\"reset password\": [\"forgot-password\"],\n\tchat: [\n\t\t\"ai-chat\",\n\t\t\"ai-conversation\",\n\t\t\"ai-prompt-input\"\n\t],\n\tconversation: [\"ai-chat\"],\n\tassistant: [\"ai-chat\"],\n\tcopilot: [\"ai-chat\"],\n\tagent: [\n\t\t\"agent-console\",\n\t\t\"ai-agent-status\",\n\t\t\"ai-agent-plan\"\n\t],\n\tagents: [\"agent-console\"],\n\ttool: [\"ai-tool\"],\n\tapproval: [\"ai-approval-request\"],\n\tapprove: [\"ai-approval-request\"],\n\tundo: [\"ai-action-ledger\"],\n\taudit: [\"ai-action-ledger\", \"activity-feed\"],\n\ttokens: [\"ai-token-usage\"],\n\tspend: [\"ai-dashboard\", \"billing\"],\n\tcost: [\"ai-dashboard\", \"billing\"],\n\tusage: [\"ai-dashboard\", \"billing\"],\n\tsubscription: [\"billing\", \"pricing\"],\n\tinvoice: [\"billing\"],\n\tinvoices: [\"billing\"],\n\tpayment: [\"billing\"],\n\tplan: [\"pricing\", \"billing\"],\n\tplans: [\"pricing\"],\n\tmetrics: [\n\t\t\"analytics\",\n\t\t\"dashboard\",\n\t\t\"metric-delta\"\n\t],\n\tchart: [\"analytics\"],\n\tcharts: [\"analytics\"],\n\tgraph: [\"analytics\"],\n\tstats: [\"dashboard\", \"analytics\"],\n\toverview: [\"dashboard\"],\n\tgrid: [\"data-table\", \"table\"],\n\tspreadsheet: [\"data-table\"],\n\tlist: [\"table\", \"data-table\"],\n\tsearch: [\"command\", \"combobox\"],\n\tpalette: [\"command\"],\n\tshortcut: [\"command\", \"shortcut-recorder\"],\n\tmodal: [\"dialog\"],\n\tpopup: [\"dialog\", \"popover\"],\n\tdropdown: [\"dropdown-menu\", \"select\"],\n\ttoast: [\"toast\"],\n\tnotification: [\"toast\", \"activity-feed\"],\n\tnotifications: [\"toast\", \"settings\"],\n\tupload: [\"file-upload\"],\n\tfile: [\"file-upload\"],\n\tdate: [\"date-picker\", \"calendar\"],\n\ttime: [\"time-range-picker\"],\n\tschedule: [\"cron-editor\"],\n\tcron: [\"cron-editor\"],\n\tteam: [\"admin-users\", \"settings\"],\n\tmembers: [\"admin-users\"],\n\tusers: [\"admin-users\"],\n\tadmin: [\"admin-users\"],\n\tpermissions: [\"permission-matrix\"],\n\troles: [\"permission-matrix\"],\n\tprofile: [\"settings\"],\n\tpreferences: [\"settings\"],\n\taccount: [\"settings\", \"billing\"],\n\tsetup: [\"onboarding\"],\n\tchecklist: [\"onboarding\"],\n\twizard: [\"onboarding\"],\n\tlogs: [\"log-viewer\"],\n\tlog: [\"log-viewer\"],\n\tdiff: [\"diff-viewer\", \"record-diff\"],\n\tsecret: [\"secret-field\"],\n\t\"api key\": [\"secret-field\"],\n\tkey: [\"secret-field\"],\n\tdns: [\"dns-record\"]\n};\nfunction normalise(prompt) {\n\treturn prompt.toLowerCase().replace(/[^a-z0-9\\s-]/g, \" \");\n}\nfunction words(prompt) {\n\treturn normalise(prompt).split(/\\s+/).filter((word) => word.length > 2 && !STOPWORDS.has(word));\n}\nfunction synonymHits(prompt) {\n\tconst text = normalise(prompt);\n\tconst hits = /* @__PURE__ */ new Map();\n\tconst consumed = /* @__PURE__ */ new Set();\n\tfor (const [phrase, names] of Object.entries(SYNONYMS)) {\n\t\tif (!new RegExp(`(^|\\\\s)${phrase.replace(/\\s+/g, \"\\\\s+\")}(\\\\s|$)`).test(text)) continue;\n\t\tfor (const word of phrase.split(/\\s+/)) consumed.add(word);\n\t\tfor (const name of names) if (!hits.has(name)) hits.set(name, phrase);\n\t}\n\treturn {\n\t\thits,\n\t\tconsumed\n\t};\n}\n/** Below this a match is coincidence rather than intent. */\nconst MINIMUM_SCORE = 20;\nfunction scoreEntry(entry, terms, synonyms) {\n\tconst name = entry.name.toLowerCase();\n\tconst title = entry.title.toLowerCase();\n\tconst description = entry.description.toLowerCase();\n\tlet score = 0;\n\tconst reasons = [];\n\tconst synonym = synonyms.get(entry.name);\n\tif (synonym) {\n\t\tscore += 60;\n\t\treasons.push(`\"${synonym}\"`);\n\t}\n\tfor (const term of terms) if (name === term) {\n\t\tscore += 50;\n\t\treasons.push(`named \"${term}\"`);\n\t} else if (name.split(\"-\").includes(term)) {\n\t\tscore += 30;\n\t\treasons.push(`\"${term}\" in its name`);\n\t} else if (title.includes(term)) {\n\t\tscore += 20;\n\t\treasons.push(`\"${term}\" in its title`);\n\t} else if (entry.category === term) {\n\t\tscore += 12;\n\t\treasons.push(`the ${term} category`);\n\t} else if (description.includes(term)) {\n\t\tscore += 8;\n\t\treasons.push(`\"${term}\" in its description`);\n\t}\n\tif (score === 0) return void 0;\n\tconst rank = score + (entry.type === \"registry:block\" ? 25 : 0);\n\treturn {\n\t\tentry,\n\t\tscore,\n\t\trank,\n\t\tbecause: [...new Set(reasons)].slice(0, 3).join(\", \")\n\t};\n}\nfunction planUi(prompt, index, options = {}) {\n\tconst { maxBlocks = 3, maxComponents = 6 } = options;\n\tconst { hits: synonyms, consumed } = synonymHits(prompt);\n\tconst terms = words(prompt).filter((term) => !consumed.has(term));\n\tconst scored = index.items.filter((entry) => entry.type === \"registry:ui\" || entry.type === \"registry:block\").map((entry) => scoreEntry(entry, terms, synonyms)).filter((candidate) => candidate !== void 0).filter((candidate) => candidate.score >= MINIMUM_SCORE).sort((a, b) => b.rank - a.rank || a.entry.name.localeCompare(b.entry.name));\n\tconst blocks = scored.filter((candidate) => candidate.entry.type === \"registry:block\").slice(0, maxBlocks);\n\tconst covered = new Set(blocks.flatMap((candidate) => [candidate.entry.name, ...candidate.entry.registryDependencies]));\n\tconst components = scored.filter((candidate) => candidate.entry.type === \"registry:ui\" && !covered.has(candidate.entry.name)).slice(0, maxComponents);\n\tconst toEntry = (candidate) => ({\n\t\tentry: candidate.entry,\n\t\tbecause: candidate.because\n\t});\n\treturn {\n\t\tprompt,\n\t\tblocks: blocks.map(toEntry),\n\t\tcomponents: components.map(toEntry),\n\t\tinstall: [...blocks, ...components].map((candidate) => candidate.entry.name),\n\t\tempty: blocks.length === 0 && components.length === 0\n\t};\n}\n/** PascalCase export name for a registry name, e.g. \"ai-tool\" -> \"AiTool\". */\nfunction tag(name) {\n\treturn name.split(\"-\").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(\"\");\n}\n/** Blocks export a `…Block` component; components export their own name. */\nfunction componentName(entry) {\n\tconst base = tag(entry.name);\n\treturn entry.type === \"registry:block\" ? `${base}Block` : base;\n}\n/**\n* Where an installed block lives.\n*\n* A project alias like `@/components/ui` has a sibling `@/components/blocks`. A\n* bare package specifier has no block path at all, so the conventional install\n* location is used instead of inventing one under the package.\n*/\nfunction blocksPathFor(importFrom) {\n\tif (importFrom.endsWith(\"/ui\")) return `${importFrom.slice(0, -3)}/blocks`;\n\tif (importFrom.startsWith(\"@/\") || importFrom.startsWith(\"~/\")) return `${importFrom}/blocks`;\n\treturn \"@/components/blocks\";\n}\n/**\n* The plan as a starting file.\n*\n* Imports and composition only. Every element carries the page its props are\n* documented on, because the registry does not publish prop shapes and a\n* plausible invented prop is worse than an obvious gap — one is a TODO, the\n* other is a bug wearing the costume of working code.\n*/\nfunction renderPlan(plan, options = {}) {\n\tconst { importFrom = \"@/components/ui\", docsUrl = \"https://dowel-eight.vercel.app\", blocksImportFrom = blocksPathFor(importFrom) } = options;\n\tif (plan.empty) return `// Nothing in the registry matched \"${plan.prompt}\".\\n`;\n\tconst chosen = [...plan.blocks, ...plan.components];\n\tconst imports = chosen.map((item) => {\n\t\tconst from = item.entry.type === \"registry:block\" ? `${blocksImportFrom}/${item.entry.name}` : `${importFrom}/${item.entry.name}`;\n\t\treturn `import { ${componentName(item.entry)} } from \"${from}\";`;\n\t}).sort();\n\tconst body = chosen.map((item) => {\n\t\tconst name = componentName(item.entry);\n\t\treturn [` {/* ${item.entry.title} — props: ${docsUrl}/docs/${item.entry.type === \"registry:block\" ? \"blocks\" : \"components\"}/${item.entry.name} */}`, ` <${name} />`].join(\"\\n\");\n\t}).join(\"\\n\\n\");\n\treturn `${imports.join(\"\\n\")}\n\nexport default function Page() {\n return (\n <div className=\"flex flex-col gap-6\">\n${body}\n </div>\n );\n}\n`;\n}\n/**\n* The plan as a brief for a coding agent.\n*\n* The most useful thing this can produce. The agent has the project, the\n* editor and the ability to write the props; what it lacks is the knowledge\n* that these components exist and that it must not invent others. That is\n* exactly what a grounded plan supplies.\n*/\nfunction renderBrief(plan, options = {}) {\n\tconst { cliPackage = \"@dowel-ui/cli\", docsUrl = \"https://dowel-eight.vercel.app\", importFrom = \"@/components/ui\" } = options;\n\tif (plan.empty) return `Nothing in the registry matched \"${plan.prompt}\". Search the catalogue at ${docsUrl}/docs/components before building anything by hand.`;\n\tconst lines = [\n\t\t`Build: ${plan.prompt}`,\n\t\t\"\",\n\t\t\"Use these, which are already in the registry. Do not write your own versions,\",\n\t\t\"and do not use any component not listed here without checking the catalogue first.\",\n\t\t\"\"\n\t];\n\tif (plan.blocks.length > 0) {\n\t\tlines.push(\"Blocks (whole sections — each installs its own components):\");\n\t\tfor (const item of plan.blocks) lines.push(`- ${item.entry.name} — ${item.entry.description}`);\n\t\tlines.push(\"\");\n\t}\n\tif (plan.components.length > 0) {\n\t\tlines.push(\"Components:\");\n\t\tfor (const item of plan.components) lines.push(`- ${item.entry.name} — ${item.entry.description}`);\n\t\tlines.push(\"\");\n\t}\n\tlines.push(\"Install first:\", \"\", ` npx ${cliPackage} add ${plan.install.join(\" \")}`, \"\", `Import from \\`${importFrom}\\`. Each component's props are on its page under`, `${docsUrl}/docs/components — read the page rather than guessing a prop name.`, \"\", \"Style with semantic tokens only (bg-background, text-muted-foreground). Never raw\", \"hex, never Tailwind's own palette — those do not follow the theme.\");\n\treturn lines.join(\"\\n\");\n}\n//#endregion\nexport { blocksPathFor, planUi, renderBrief, renderPlan };\n\n//# sourceMappingURL=generate.js.map","import { z } from \"zod\";\nimport { createHash } from \"node:crypto\";\n//#region src/hash.ts\n/**\n* Content hash used to detect local edits to an installed file.\n*\n* Line endings are normalised before hashing so a Windows checkout does not\n* read as \"every file modified\", which would make `update` useless there.\n*/\nfunction hashContent(content) {\n\tconst normalised = content.replace(/\\r\\n/g, \"\\n\");\n\treturn `sha256:${createHash(\"sha256\").update(normalised, \"utf8\").digest(\"hex\")}`;\n}\n//#endregion\n//#region src/schema.ts\n/**\n* The public registry contract.\n*\n* This is the boundary between the library and every consumer's project, so it\n* is validated on both sides: the build refuses to emit anything that does not\n* satisfy it, and the CLI refuses to install anything that does not parse. A\n* registry that serves malformed data breaks builds in someone else's\n* repository, where it is hardest to diagnose.\n*/\n/** Bumped only for a breaking change to the shape below. */\nconst REGISTRY_VERSION = 1;\nconst registryFileTypeSchema = z.enum([\n\t\"registry:ui\",\n\t\"registry:lib\",\n\t\"registry:hook\",\n\t\"registry:block\",\n\t\"registry:style\"\n]);\nconst registryItemTypeSchema = z.enum([\n\t\"registry:ui\",\n\t\"registry:lib\",\n\t\"registry:hook\",\n\t\"registry:theme\",\n\t\"registry:block\"\n]);\n/**\n* Whether an item's source is public.\n*\n* `free` is the default and stays the default: an item that has ever been\n* installable without a licence must never quietly become one that is not.\n* Existing registries carry no `access` field at all, which parses as `free` —\n* so an older registry read by a newer CLI behaves exactly as it did.\n*/\nconst registryAccessSchema = z.enum([\"free\", \"pro\"]).default(\"free\");\nconst registryFileSchema = z.object({\n\t/**\n\t* Logical path within the registry, e.g. `ui/button.tsx`, `lib/utils.ts`.\n\t*\n\t* The leading segment selects which of the consumer's aliases the file is\n\t* written under. The registry deliberately does not know the destination —\n\t* that depends on a project layout it has never seen.\n\t*/\n\tpath: z.string().min(1),\n\ttype: registryFileTypeSchema,\n\tcontent: z.string(),\n\t/**\n\t* `sha256:<hex>` of `content` as published.\n\t*\n\t* Recorded at install time so `update` can tell an untouched file from one\n\t* the user has edited. This cannot be added later: an install that did not\n\t* record a hash leaves no way to know what it originally wrote.\n\t*/\n\thash: z.string().regex(/^sha256:[0-9a-f]{64}$/)\n});\nconst registryItemSchema = z.object({\n\t$schema: z.string().optional(),\n\tregistryVersion: z.literal(1),\n\tname: z.string().regex(/^[a-z][a-z0-9-]*$/),\n\ttype: registryItemTypeSchema,\n\ttitle: z.string().min(1),\n\tdescription: z.string().min(10),\n\tcategory: z.string().min(1),\n\tstatus: z.enum([\n\t\t\"stable\",\n\t\t\"beta\",\n\t\t\"experimental\"\n\t]),\n\t/** npm packages to install alongside the files. */\n\tdependencies: z.array(z.string()),\n\t/** Other registry items to install first. */\n\tregistryDependencies: z.array(z.string()),\n\tfiles: z.array(registryFileSchema).min(1),\n\ta11y: z.string().optional(),\n\taccess: registryAccessSchema\n});\n/**\n* The index entry.\n*\n* Carries `access` so a licensed item is *listed* — with its title, what it\n* depends on and how many files it has — while its source is not. Hiding paid\n* items entirely would mean nobody could discover them; including their source\n* would mean nobody needed to buy them. The index is the catalogue; the item\n* body is the goods.\n*/\nconst registryIndexEntrySchema = registryItemSchema.pick({\n\tname: true,\n\ttype: true,\n\ttitle: true,\n\tdescription: true,\n\tcategory: true,\n\tstatus: true,\n\tdependencies: true,\n\tregistryDependencies: true,\n\taccess: true\n}).extend({ fileCount: z.number().int().positive() });\nconst registryIndexSchema = z.object({\n\t$schema: z.string().optional(),\n\tregistryVersion: z.literal(1),\n\t/** Version of the package the registry was generated from. */\n\tgeneratedFrom: z.string().min(1),\n\titems: z.array(registryIndexEntrySchema)\n});\n//#endregion\nexport { registryIndexEntrySchema as a, registryItemTypeSchema as c, registryFileTypeSchema as i, hashContent as l, registryAccessSchema as n, registryIndexSchema as o, registryFileSchema as r, registryItemSchema as s, REGISTRY_VERSION as t };\n\n//# sourceMappingURL=schema-BbyNjH6Q.js.map","import { blocksPathFor, planUi, renderBrief, renderPlan } from \"./generate.js\";\nimport { a as registryIndexEntrySchema, c as registryItemTypeSchema, i as registryFileTypeSchema, l as hashContent, n as registryAccessSchema, o as registryIndexSchema, r as registryFileSchema, s as registryItemSchema, t as REGISTRY_VERSION } from \"./schema-BbyNjH6Q.js\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { z } from \"zod\";\n//#region src/custom.ts\n/**\n* Building a registry of your own components.\n*\n* The CLI has always been able to install from any registry — `--registry`\n* takes a URL or a directory — but producing one meant reimplementing this\n* package. So an organisation that wanted its own components installed the same\n* way had the consumer half and none of the producer half.\n*\n* The authoring shape is declared here rather than imported from the component\n* package, because the registry *is* the contract. A team publishing their own\n* components should not have to depend on somebody else's component library to\n* describe their own.\n*/\n/** Where an item's files are written in the consuming project. */\nconst itemGroupSchema = z.enum([\n\t\"ui\",\n\t\"blocks\",\n\t\"lib\",\n\t\"hooks\"\n]);\nconst GROUP_FILE_TYPE = {\n\tui: \"registry:ui\",\n\tblocks: \"registry:block\",\n\tlib: \"registry:lib\",\n\thooks: \"registry:hook\"\n};\nconst itemSourceSchema = z.object({\n\tname: z.string().regex(/^[a-z][a-z0-9-]*$/),\n\ttitle: z.string().min(1),\n\tdescription: z.string().min(10),\n\tcategory: z.string().min(1),\n\tstatus: z.enum([\n\t\t\"stable\",\n\t\t\"beta\",\n\t\t\"experimental\"\n\t]).default(\"stable\"),\n\t/** Where the files land. Defaults to `ui`. */\n\tgroup: itemGroupSchema.default(\"ui\"),\n\t/** npm packages the source imports. */\n\tdependencies: z.array(z.string()).default([]),\n\t/** Other registry items this one imports, upstream ones included. */\n\tregistryDependencies: z.array(z.string()).default([]),\n\t/** Files to publish, relative to the item's own directory. */\n\tfiles: z.array(z.string().min(1)).min(1),\n\ta11y: z.string().optional(),\n\taccess: registryAccessSchema,\n\t/**\n\t* Overrides where the item's directory is, relative to the registry root.\n\t* Defaults to `<group>/<name>`, which is the layout this repository uses.\n\t*/\n\tdirectory: z.string().optional()\n});\nconst registryConfigSchema = z.object({\n\t/** Absolute path the item directories are resolved against. */\n\troot: z.string().min(1),\n\titems: z.array(itemSourceSchema).min(1),\n\t/**\n\t* A registry to layer on top of — a URL, or a directory on disk.\n\t*\n\t* The reason a private registry is worth having at all: one URL that serves\n\t* both the upstream components and yours, so a consumer configures one place\n\t* and `add` resolves across both.\n\t*/\n\textends: z.string().min(1).optional(),\n\t/** Written into the index, so a consumer can see what produced it. */\n\tgeneratedFrom: z.string().min(1).default(\"custom-registry\")\n});\n/** Identity helper, for editor autocomplete inside a config file. */\nfunction defineRegistryConfig(config) {\n\treturn config;\n}\n/**\n* Every `@/...` import a source file makes, as `[group, rest]`.\n*\n* Published source is authored against the library's own aliases and rewritten\n* at install time to wherever the consuming project keeps things. Both checks\n* below depend on reading those imports.\n*/\nfunction authoredImports(content) {\n\tconst found = [];\n\tfor (const match of content.matchAll(/[\"']@\\/(components|lib|hooks|blocks)\\/([^\"']+)[\"']/g)) if (match[1] && match[2]) found.push({\n\t\tgroup: match[1],\n\t\trest: match[2]\n\t});\n\treturn found;\n}\n/**\n* Catches source written against the *installed* paths instead of the authored\n* ones.\n*\n* `@/components/ui/badge` looks right — it is where the file ends up — and\n* rewrites to `@/components/ui/ui/badge`, because the rewriter maps\n* `@/components/` to wherever the project keeps its components. The result\n* compiles nowhere and the doubled segment is easy to stare past. The authored\n* form is `@/components/badge`.\n*/\nfunction assertAuthoredPaths(name, content) {\n\tconst groups = /* @__PURE__ */ new Set([\n\t\t\"ui\",\n\t\t\"blocks\",\n\t\t\"lib\",\n\t\t\"hooks\"\n\t]);\n\tconst mistaken = authoredImports(content).filter((entry) => groups.has(entry.rest.split(\"/\")[0] ?? \"\")).map((entry) => `@/${entry.group}/${entry.rest}`);\n\tif (mistaken.length > 0) throw new Error(`Item \"${name}\" imports from an installed path rather than an authored one:\\n ${[...new Set(mistaken)].join(\"\\n \")}\\nWrite \\`@/components/badge\\`, not \\`@/components/ui/badge\\` — the leading group is rewritten to wherever the consuming project keeps its components, so naming it twice produces a path that resolves nowhere.`);\n}\n/**\n* Catches a component importing something it never declared.\n*\n* The undeclared dependency is not installed alongside it, so the install\n* succeeds and the project fails to build — in someone else's repository, where\n* it is hardest to trace back to here.\n*/\nfunction assertDeclaredDependencies(source, content) {\n\tconst declared = /* @__PURE__ */ new Set([...source.registryDependencies, source.name]);\n\tconst undeclared = authoredImports(content).filter((entry) => entry.group === \"components\" || entry.group === \"blocks\").map((entry) => entry.rest.split(\"/\")[0] ?? \"\").filter((imported) => imported.length > 0 && !declared.has(imported));\n\tif (undeclared.length > 0) throw new Error(`Item \"${source.name}\" imports ${[...new Set(undeclared)].join(\", \")} but does not list them in registryDependencies. They would not be installed alongside it, and the failure would surface as a build error in the consuming project.`);\n}\nfunction toItem(root, source) {\n\tconst directory = source.directory ?? join(source.group, source.name);\n\tconst itemDir = join(root, directory);\n\tconst files = source.files.map((file) => {\n\t\tconst path = join(itemDir, file);\n\t\tif (!existsSync(path)) throw new Error(`Item \"${source.name}\" lists ${file}, but ${path} does not exist. A registry that names a file it cannot read produces a broken install in someone else's project, where it is hardest to diagnose.`);\n\t\tconst content = readFileSync(path, \"utf8\");\n\t\tassertAuthoredPaths(source.name, content);\n\t\tassertDeclaredDependencies(source, content);\n\t\treturn {\n\t\t\tpath: `${source.group}/${file}`,\n\t\t\ttype: GROUP_FILE_TYPE[source.group],\n\t\t\tcontent,\n\t\t\thash: hashContent(content)\n\t\t};\n\t});\n\treturn registryItemSchema.parse({\n\t\tregistryVersion: 1,\n\t\tname: source.name,\n\t\ttype: registryItemTypeSchema.parse(GROUP_FILE_TYPE[source.group]),\n\t\ttitle: source.title,\n\t\tdescription: source.description,\n\t\tcategory: source.category,\n\t\tstatus: source.status,\n\t\tdependencies: source.dependencies,\n\t\tregistryDependencies: source.registryDependencies,\n\t\tfiles,\n\t\ta11y: source.a11y,\n\t\taccess: source.access\n\t});\n}\nasync function readUpstream(base) {\n\tconst isHttp = base.startsWith(\"http://\") || base.startsWith(\"https://\");\n\tconst load = async (file) => {\n\t\tif (!isHttp) {\n\t\t\tconst root = base.startsWith(\"file:\") ? fileURLToPath(base) : base;\n\t\t\tconst path = join(root, file);\n\t\t\tif (!existsSync(path)) throw new Error(`Upstream registry has no ${file} at ${path}.`);\n\t\t\treturn JSON.parse(readFileSync(path, \"utf8\"));\n\t\t}\n\t\tconst url = `${base.replace(/\\/$/, \"\")}/${file}`;\n\t\tconst response = await fetch(url);\n\t\tif (!response.ok) throw new Error(`Upstream registry returned ${String(response.status)} for ${url}.`);\n\t\treturn await response.json();\n\t};\n\tconst index = registryIndexSchema.parse(await load(\"index.json\"));\n\tconst items = [];\n\tfor (const entry of index.items) {\n\t\tif (entry.access === \"pro\") continue;\n\t\titems.push(registryItemSchema.parse(await load(`${entry.name}.json`)));\n\t}\n\treturn items;\n}\n/**\n* Every `registryDependencies` name must exist in the finished registry.\n*\n* Checked here, once, rather than discovered by a consumer whose `add` walks\n* into a name nothing serves. This is the single most common way a\n* hand-assembled registry is broken, and it is invisible until someone installs.\n*/\nfunction assertResolvable(items) {\n\tconst known = new Set(items.map((item) => item.name));\n\tconst missing = [];\n\tfor (const item of items) for (const dependency of item.registryDependencies) if (!known.has(dependency)) missing.push(`${item.name} → ${dependency}`);\n\tif (missing.length > 0) throw new Error(`These registry dependencies are not in the registry:\\n ${missing.join(\"\\n \")}\\nAdd them, or extend a registry that has them.`);\n}\nasync function buildCustomRegistry(config) {\n\tconst parsed = registryConfigSchema.parse(config);\n\tconst local = parsed.items.map((item) => toItem(parsed.root, item));\n\tconst duplicates = local.map((item) => item.name).filter((name, index, all) => all.indexOf(name) !== index);\n\tif (duplicates.length > 0) throw new Error(`Declared more than once: ${[...new Set(duplicates)].join(\", \")}.`);\n\tif (!parsed.extends) {\n\t\tassertResolvable(local);\n\t\treturn {\n\t\t\titems: local,\n\t\t\toverridden: [],\n\t\t\tinherited: 0\n\t\t};\n\t}\n\tconst upstream = await readUpstream(parsed.extends);\n\tconst localNames = new Set(local.map((item) => item.name));\n\tconst overridden = upstream.filter((item) => localNames.has(item.name)).map((item) => item.name);\n\tconst inherited = upstream.filter((item) => !localNames.has(item.name));\n\tconst items = [...inherited, ...local].sort((a, b) => a.name.localeCompare(b.name));\n\tassertResolvable(items);\n\treturn {\n\t\titems,\n\t\toverridden,\n\t\tinherited: inherited.length\n\t};\n}\n//#endregion\n//#region src/agent-docs.ts\nconst CATEGORY_LABELS = {\n\tfoundation: \"Foundation\",\n\tform: \"Forms\",\n\toverlay: \"Overlays\",\n\tnavigation: \"Navigation\",\n\tdisplay: \"Display\",\n\tdata: \"Data\",\n\tfeedback: \"Feedback\",\n\tlayout: \"Layout\",\n\tai: \"AI\"\n};\nconst CATEGORY_ORDER = [\n\t\"foundation\",\n\t\"form\",\n\t\"overlay\",\n\t\"navigation\",\n\t\"display\",\n\t\"data\",\n\t\"feedback\",\n\t\"layout\",\n\t\"ai\"\n];\nfunction label(category) {\n\treturn CATEGORY_LABELS[category] ?? category;\n}\n/** Ordered by curation where curated, alphabetical for anything new. */\nfunction categoriesOf(entries) {\n\tconst present = new Set(entries.map((entry) => entry.category));\n\tconst known = CATEGORY_ORDER.filter((category) => present.has(category));\n\tconst rest = [...present].filter((category) => !CATEGORY_ORDER.includes(category)).sort();\n\treturn [...known, ...rest];\n}\nfunction byType(index, type) {\n\treturn index.items.filter((entry) => entry.type === type).sort((a, b) => a.name.localeCompare(b.name));\n}\nfunction components(index) {\n\treturn byType(index, \"registry:ui\");\n}\nfunction blocks(index) {\n\treturn byType(index, \"registry:block\");\n}\n/**\n* Accessibility rules that differ from what a model has seen elsewhere.\n*\n* An agent trained on every other React library will reach for `disabled` on a\n* loading button and a live region on every alert. Stating only the deltas is\n* deliberate: a general accessibility lecture is ignored, a short list of\n* \"here this is different\" is followed.\n*/\nconst ACCESSIBILITY_DELTAS = [\n\t\"A loading `Button` uses `aria-disabled` + `aria-busy` and guards its own click handler. Never add `disabled` to it — disabling a control mid-action strands keyboard focus.\",\n\t\"`Alert` is not a live region by default. One that exists on first paint announces for no reason. Opt in with `live=\\\"polite\\\"` or `live=\\\"assertive\\\"` only when the alert appears in response to something.\",\n\t\"`Separator`, `Skeleton` and `Spinner` are decorative and stay out of the accessibility tree unless given a label. Do not add `role` or `aria-label` to them by reflex.\",\n\t\"`PopoverContent` carries `role=\\\"dialog\\\"` and warns in development without an accessible name. Always give it `aria-label` or `aria-labelledby`.\",\n\t\"Never use colour as the only signal. The `monochrome` preset exists as a standing check on exactly this — if a state is unreadable under it, the component is wrong.\"\n];\nconst TOKEN_RULES = [\n\t\"Use semantic tokens (`bg-background`, `text-foreground`, `border-border`, `ring-ring`, `bg-primary`, `text-muted-foreground`). Never raw hex, and never Tailwind's own palette (`bg-slate-900`, `text-gray-500`) — those do not follow the theme and break every preset and dark mode.\",\n\t\"Spacing, radius and type come from the scale. `rounded-md` and `rounded-lg` re-proportion with `--radius-scale`; an arbitrary `rounded-[7px]` does not.\",\n\t\"Durations derive from `--motion-scale`. Do not hardcode transition timings.\",\n\t\"Compose class names with `cn()` from the project's utils, so consumer overrides win over defaults.\"\n];\nfunction conventionsDoc(context) {\n\tconst { libraryName, cliPackage, importFrom, docsUrl } = context;\n\treturn `# ${libraryName} — conventions\n\nRules for writing code in this project. ${libraryName} is **source-first**: its\ncomponents are files in this repository, not a dependency you can reason about\nfrom its README. They are yours to edit, and edits are preserved across updates.\n\n## The rule that matters most\n\n**Do not hand-write a component that ${libraryName} already has.** Check the\ncatalogue in \\`components.md\\` first. Writing a second Button — with different\nfocus rings, different disabled semantics, different tokens — is the single\nmost common and most damaging thing to do here.\n\n## Adding a component\n\n\\`\\`\\`bash\nnpx ${cliPackage} add <name>\n\\`\\`\\`\n\nThis writes the source into the project and installs whatever it depends on.\n\\`add\\` is safe to re-run: an untouched file is left alone, an edited one is\nnever overwritten without \\`--overwrite\\`.\n\nDo not \\`npm install\\` a component. Do not copy source out of the documentation\nby hand — the CLI resolves the dependency graph and rewrites imports to this\nproject's path alias, and doing it manually gets both wrong.\n\n## Importing\n\n\\`\\`\\`tsx\nimport { Button, Card, CardContent } from \"${importFrom}\";\n\\`\\`\\`\n\n## Styling\n\n${TOKEN_RULES.map((rule) => `- ${rule}`).join(\"\\n\")}\n\n## Accessibility\n\nTargeted at WCAG 2.2 AA, verified with axe per component. Where ${libraryName}\ndiffers from what you have seen in other libraries:\n\n${ACCESSIBILITY_DELTAS.map((rule) => `- ${rule}`).join(\"\\n\")}\n\n## Before you build a page\n\nCheck \\`components.md\\` for a **block** that already covers it. A block is a\nwhole section — a login form, a settings page, a chat surface — and installing\none brings every component it is assembled from. Building a dashboard out of\nindividual primitives when \\`add dashboard\\` exists is wasted work.\n\n## Reference\n\n- Documentation: ${docsUrl}\n- Full text for models: ${docsUrl}/llms-full.txt\n`;\n}\nfunction componentsDoc(context) {\n\tconst { index, libraryName, cliPackage, installed } = context;\n\tconst have = new Set(installed ?? []);\n\tconst known = installed !== void 0;\n\tconst ui = components(index);\n\tconst blk = blocks(index);\n\tconst lines = [\n\t\t`# ${libraryName} — catalogue`,\n\t\t\"\",\n\t\t`${String(ui.length)} components and ${String(blk.length)} blocks, generated from \\`${index.generatedFrom}\\`. This is the complete list — anything not here does not exist.`,\n\t\t\"\"\n\t];\n\tif (known) lines.push(\"`✓` marks what is already installed in this project. Everything else needs\", `\\`npx ${cliPackage} add <name>\\` before it can be imported.`, \"\");\n\tconst mark = (entry) => known ? have.has(entry.name) ? \"✓ \" : \" \" : \"\";\n\tfor (const category of categoriesOf(ui)) {\n\t\tlines.push(`## ${label(category)}`, \"\");\n\t\tfor (const entry of ui.filter((item) => item.category === category)) {\n\t\t\tconst status = entry.status === \"stable\" ? \"\" : ` _(${entry.status})_`;\n\t\t\tlines.push(`- ${mark(entry)}**${entry.name}** — ${entry.description}${status}`);\n\t\t}\n\t\tlines.push(\"\");\n\t}\n\tlines.push(\"## Blocks\", \"\", \"Whole sections. Installing one installs every component it is built from.\", \"\");\n\tfor (const entry of blk) {\n\t\tconst deps = entry.registryDependencies.length;\n\t\tconst resolves = deps > 0 ? ` _(resolves ${String(deps)} components)_` : \"\";\n\t\tlines.push(`- ${mark(entry)}**${entry.name}** — ${entry.description}${resolves}`);\n\t}\n\tlines.push(\"\");\n\treturn lines.join(\"\\n\");\n}\nfunction aiDoc(context) {\n\tconst { index, libraryName, cliPackage } = context;\n\tconst ai = components(index).filter((entry) => entry.category === \"ai\");\n\treturn `# ${libraryName} — AI components\n\n${String(ai.length)} surfaces for AI features. Reach for these before building\nanything custom for a model-facing interface.\n\nMost component sets ship a chat transcript and stop. Real AI features are\nextraction, enrichment, autofill and agents that *change things* — so the parts\nthat matter are the ones around the transcript, not the transcript itself.\n\n${ai.map((entry) => `- **${entry.name}** — ${entry.description}`).join(\"\\n\")}\n\n## Choosing between them\n\n- Rendering a conversation → \\`ai-conversation\\` with \\`ai-message\\` and \\`ai-response\\`.\n- The composer → \\`ai-prompt-input\\`, with \\`ai-model-selector\\` if the model is switchable.\n- A tool the model called → \\`ai-tool\\`. Its arguments and result belong there, not in prose.\n- Asking permission *before* a tool runs → \\`ai-approval-request\\`.\n- Reporting what it did *after* → \\`ai-action-ledger\\`, which is also where reversibility belongs. A deletion can be undone, a refund can only be offset, a sent email cannot be taken back — the ledger is where that distinction is shown.\n- An object streaming in field by field → \\`ai-structured-output\\`, which reserves layout up front so nothing jumps.\n- Ghost text in a real textarea → \\`ai-inline-completion\\`. Escape always returns Tab to focus management, so a keyboard user is never trapped.\n- A value the model proposes for a form field → \\`ai-suggested-value\\`.\n- Reviewing what was pulled out of a document → \\`ai-extraction-review\\`.\n- Long-running work → \\`ai-agent-status\\` and \\`ai-agent-plan\\`.\n- Where an answer came from → \\`ai-sources\\`. Cost → \\`ai-token-usage\\`. Chain of thought → \\`ai-reasoning\\`.\n\n## Whole surface at once\n\n\\`\\`\\`bash\nnpx ${cliPackage} add ai-chat\n\\`\\`\\`\n`;\n}\nfunction themesDoc(context) {\n\tconst { libraryName } = context;\n\treturn `# ${libraryName} — theming\n\nTokens are two-tier. **Tier 1** is raw scales: an OKLCH neutral ramp, a radius\nladder, a 15px-base type scale, elevation, motion. **Tier 2** is semantic\naliases — \\`--primary\\`, \\`--background\\`, \\`--border\\`, \\`--ring\\` — and components\nconsume Tier 2 *exclusively*.\n\nRe-skinning the system means reassigning Tier 2. It never means editing a\ncomponent file. If you find yourself changing a colour inside a component, the\nchange belongs in the token layer instead.\n\n## Presets\n\n\\`default\\`, \\`ocean\\`, \\`emerald\\`, \\`violet\\`, \\`rose\\`, \\`amber\\`, \\`monochrome\\`.\n\n\\`\\`\\`html\n<html data-theme=\"ocean\" class=\"dark\">\n\\`\\`\\`\n\n\\`data-theme\\` selects the preset; the \\`dark\\` class selects the mode. They are\nindependent — every preset works in both.\n\n\\`monochrome\\` is not only a style. It is a standing check that no component uses\ncolour as its only signal, so verify new work under it.\n\n## Two properties that re-proportion everything\n\n- \\`--radius-scale\\` — one multiplier behind every corner in the system. \\`1\\` is the designed default, \\`0\\` is fully square.\n- \\`--motion-scale\\` — one multiplier every duration derives from. Under \\`prefers-reduced-motion\\` it collapses, but indicators that report ongoing state are *slowed* rather than stopped via \\`--motion-scale-indicator\\`, because a frozen spinner reads as a hung application.\n\n## Contrast\n\nAll semantic pairs are verified against WCAG 2.2 AA across both modes and every\npreset, in CI. A new token pair has to pass the same check — do not introduce\none without running \\`audit:contrast\\`.\n`;\n}\n/** Frontmatter-carrying skill file for Claude Code. */\nfunction skillDoc(context) {\n\tconst { index, libraryName, cliPackage, importFrom } = context;\n\tconst ui = components(index);\n\tconst blk = blocks(index);\n\tconst names = ui.map((entry) => entry.name).join(\", \");\n\treturn `---\nname: ${libraryName.toLowerCase()}-ui\ndescription: >-\n Build React interfaces with ${libraryName}, the source-first component system\n installed in this project. Use whenever writing or editing React UI here —\n any button, form, dialog, table, dashboard or AI surface. Covers the\n ${String(ui.length)}-component catalogue, the ${String(blk.length)} blocks, design tokens, theming\n and the accessibility rules that differ from other libraries.\n---\n\n# ${libraryName}\n\nSource-first React components. They are **files in this repository**, not a\ndependency — installed with a CLI, then owned and edited like any other code.\n\n## Do this first\n\nNever hand-write a component ${libraryName} already has. The catalogue:\n\n${names}\n\nBlocks (whole sections, each resolving its own components):\n${blk.map((entry) => entry.name).join(\", \")}\n\n## Adding one\n\n\\`\\`\\`bash\nnpx ${cliPackage} add button card dialog\n\\`\\`\\`\n\nResolves dependencies, installs npm packages, rewrites imports to this\nproject's alias. Safe to re-run — it will not overwrite a file you have edited\nwithout \\`--overwrite\\`.\n\n## Importing\n\n\\`\\`\\`tsx\nimport { Button, Card, CardContent } from \"${importFrom}\";\n\\`\\`\\`\n\n## Styling rules\n\n${TOKEN_RULES.map((rule) => `- ${rule}`).join(\"\\n\")}\n\n## Accessibility rules that differ here\n\n${ACCESSIBILITY_DELTAS.map((rule) => `- ${rule}`).join(\"\\n\")}\n\n## Reference files\n\n- \\`.dowel/components.md\\` — the full catalogue with descriptions\n- \\`.dowel/ai.md\\` — the AI components and when to use each\n- \\`.dowel/themes.md\\` — tokens, presets, radius and motion scales\n- \\`.dowel/conventions.md\\` — the rules above, in full\n`;\n}\n/** Cursor project rule (`.cursor/rules/*.mdc`). */\nfunction cursorRule(context) {\n\tconst { index, libraryName, cliPackage, importFrom } = context;\n\tconst ui = components(index);\n\treturn `---\ndescription: ${libraryName} component system — use for all React UI in this project\nglobs: [\"**/*.tsx\", \"**/*.jsx\"]\nalwaysApply: false\n---\n\n${libraryName} is source-first: its ${String(ui.length)} components are files in this\nrepository. Never hand-write one that already exists.\n\nAdd: \\`npx ${cliPackage} add <name>\\`\nImport: \\`import { Button } from \"${importFrom}\"\\`\n\nAvailable: ${ui.map((entry) => entry.name).join(\", \")}\n\n${TOKEN_RULES.map((rule) => `- ${rule}`).join(\"\\n\")}\n${ACCESSIBILITY_DELTAS.map((rule) => `- ${rule}`).join(\"\\n\")}\n\nFull catalogue and reasoning: \\`.dowel/\\`\n`;\n}\nconst AGENTS_MARKER_START = \"<!-- dowel:start -->\";\nconst AGENTS_MARKER_END = \"<!-- dowel:end -->\";\n/**\n* The block written into a project's AGENTS.md.\n*\n* Marker-wrapped rather than written as a whole file: AGENTS.md belongs to the\n* project and usually already says things about the project. Replacing it would\n* destroy that; appending without markers would duplicate the section on every\n* regeneration.\n*/\nfunction agentsSection(context) {\n\tconst { index, libraryName, cliPackage, importFrom } = context;\n\tconst ui = components(index);\n\treturn `${AGENTS_MARKER_START}\n\n## UI components — ${libraryName}\n\nThis project uses ${libraryName}, a **source-first** component system: its\n${String(ui.length)} components live in this repository as editable files.\n\n- **Never hand-write a component that already exists.** The full catalogue is in \\`.dowel/components.md\\`.\n- Add one with \\`npx ${cliPackage} add <name>\\` — never \\`npm install\\`, never copy source by hand.\n- Import from \\`${importFrom}\\`.\n- Style with semantic tokens only (\\`bg-background\\`, \\`text-muted-foreground\\`), never raw hex and never Tailwind's own palette.\n- Building a page? Check \\`.dowel/components.md\\` for a **block** first.\n- Building an AI feature? \\`.dowel/ai.md\\` lists surfaces you will not find elsewhere.\n- Accessibility deltas from other libraries are in \\`.dowel/conventions.md\\`. Read them before adding ARIA by reflex.\n\n${AGENTS_MARKER_END}`;\n}\n/** Replaces the marked block, or appends it if there is none. */\nfunction upsertAgentsSection(existing, section) {\n\tconst start = existing.indexOf(AGENTS_MARKER_START);\n\tconst end = existing.indexOf(AGENTS_MARKER_END);\n\tif (start !== -1 && end !== -1 && end > start) return existing.slice(0, start) + section + existing.slice(end + 18);\n\tconst base = existing.trimEnd();\n\treturn base.length > 0 ? `${base}\\n\\n${section}\\n` : `${section}\\n`;\n}\n/**\n* The llms.txt index.\n*\n* Deliberately a map rather than a dump: it names every component and points at\n* the one URL that carries everything, so a model with a small budget can find\n* the right page and one with a large budget can take the lot.\n*/\nfunction llmsTxt(context) {\n\tconst { index, libraryName, docsUrl, cliPackage } = context;\n\tconst ui = components(index);\n\tconst blk = blocks(index);\n\tconst lines = [\n\t\t`# ${libraryName}`,\n\t\t\"\",\n\t\t`> Source-first React components for SaaS and AI products. ${String(ui.length)} components and ${String(blk.length)} blocks, installed as code you own rather than imported from a dependency. Built on Tailwind v4 and OKLCH design tokens, targeted at WCAG 2.2 AA.`,\n\t\t\"\",\n\t\t`Install: \\`npx ${cliPackage} add <name>\\` writes the component's source into your project.`,\n\t\t\"Re-running is safe — files you have edited are never overwritten without `--overwrite`.\",\n\t\t\"\",\n\t\t`Generated from ${index.generatedFrom}.`,\n\t\t\"\",\n\t\t\"## Start here\",\n\t\t\"\",\n\t\t`- [Everything, in one file](${docsUrl}/llms-full.txt): the complete catalogue with descriptions, accessibility notes and conventions`,\n\t\t`- [Installation](${docsUrl}/docs/installation)`,\n\t\t`- [CLI](${docsUrl}/docs/cli)`,\n\t\t`- [Theming](${docsUrl}/docs/themes)`,\n\t\t`- [Accessibility](${docsUrl}/docs/accessibility)`,\n\t\t\"\"\n\t];\n\tfor (const category of categoriesOf(ui)) {\n\t\tlines.push(`## ${label(category)}`, \"\");\n\t\tfor (const entry of ui.filter((item) => item.category === category)) lines.push(`- [${entry.name}](${docsUrl}/docs/components/${entry.name}): ${entry.description}`);\n\t\tlines.push(\"\");\n\t}\n\tlines.push(\"## Blocks\", \"\");\n\tfor (const entry of blk) lines.push(`- [${entry.name}](${docsUrl}/docs/blocks/${entry.name}): ${entry.description}`);\n\tlines.push(\"\");\n\treturn lines.join(\"\\n\");\n}\n/** Everything an agent needs, in one request. */\nfunction llmsFullTxt(context) {\n\tconst { index, items, libraryName, docsUrl } = context;\n\tconst detail = new Map((items ?? []).map((item) => [item.name, item]));\n\tconst parts = [\n\t\tconventionsDoc(context),\n\t\tcomponentsDoc({\n\t\t\t...context,\n\t\t\tinstalled: void 0\n\t\t}),\n\t\taiDoc(context),\n\t\tthemesDoc(context)\n\t];\n\tconst lines = [\n\t\t`# ${libraryName} — full reference`,\n\t\t\"\",\n\t\t`Generated from ${index.generatedFrom}. Canonical source: ${docsUrl}`,\n\t\t\"\",\n\t\t\"---\",\n\t\t\"\",\n\t\tparts.join(\"\\n---\\n\\n\")\n\t];\n\tif (detail.size > 0) {\n\t\tlines.push(\"---\", \"\", \"# Per-component detail\", \"\");\n\t\tfor (const entry of components(index)) {\n\t\t\tconst item = detail.get(entry.name);\n\t\t\tlines.push(`## ${entry.title} \\`${entry.name}\\``, \"\", entry.description, \"\");\n\t\t\tlines.push(`- Category: ${label(entry.category)} · Status: ${entry.status}`, `- Install: \\`add ${entry.name}\\``);\n\t\t\tif (entry.registryDependencies.length > 0) lines.push(`- Also installs: ${entry.registryDependencies.join(\", \")}`);\n\t\t\tif (entry.dependencies.length > 0) lines.push(`- npm: ${entry.dependencies.join(\", \")}`);\n\t\t\tif (item?.a11y) lines.push(`- Accessibility: ${item.a11y}`);\n\t\t\tlines.push(\"\");\n\t\t}\n\t}\n\treturn lines.join(\"\\n\");\n}\n//#endregion\nexport { AGENTS_MARKER_END, AGENTS_MARKER_START, REGISTRY_VERSION, agentsSection, aiDoc, assertResolvable, blocksPathFor, buildCustomRegistry, componentsDoc, conventionsDoc, cursorRule, defineRegistryConfig, hashContent, itemGroupSchema, itemSourceSchema, llmsFullTxt, llmsTxt, planUi, registryAccessSchema, registryConfigSchema, registryFileSchema, registryFileTypeSchema, registryIndexEntrySchema, registryIndexSchema, registryItemSchema, registryItemTypeSchema, renderBrief, renderPlan, skillDoc, themesDoc, upsertAgentsSection };\n\n//# sourceMappingURL=index.js.map","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport {\n registryIndexSchema,\n registryItemSchema,\n type RegistryIndex,\n type RegistryItem,\n} from \"@dowel-ui/registry\";\n\n/**\n * Reads the registry over HTTP, or from a directory on disk.\n *\n * A deliberate copy of the CLI's client rather than a shared module: this\n * process is long-lived and answers many questions about the same registry, so\n * it caches, while the CLI runs once and does not. Sharing the code would mean\n * one of the two carrying machinery it does not want.\n */\nexport class RegistryClient {\n readonly baseUrl: string;\n #index: Promise<RegistryIndex> | undefined;\n readonly #items = new Map<string, Promise<RegistryItem>>();\n\n constructor(baseUrl: string) {\n this.baseUrl = baseUrl;\n }\n\n get #isHttp(): boolean {\n return this.baseUrl.startsWith(\"http://\") || this.baseUrl.startsWith(\"https://\");\n }\n\n async #readJson(file: string): Promise<unknown> {\n if (!this.#isHttp) {\n const root = this.baseUrl.startsWith(\"file:\")\n ? fileURLToPath(this.baseUrl)\n : this.baseUrl;\n const path = join(root, file);\n if (!existsSync(path)) throw new Error(`Not found in the registry: ${file}`);\n return JSON.parse(readFileSync(path, \"utf8\"));\n }\n\n const url = `${this.baseUrl.replace(/\\/$/, \"\")}/${file}`;\n const response = await fetch(url);\n if (response.status === 404) throw new Error(`Not found in the registry: ${file}`);\n if (!response.ok) {\n throw new Error(`Registry returned ${String(response.status)} for ${url}`);\n }\n return await response.json();\n }\n\n /**\n * Cached for the life of the process.\n *\n * The registry is immutable for a given release, and an agent asks about it\n * dozens of times in a session; refetching would add latency to every tool\n * call for data that cannot have changed.\n */\n index(): Promise<RegistryIndex> {\n this.#index ??= this.#readJson(\"index.json\").then((raw) => {\n const parsed = registryIndexSchema.safeParse(raw);\n if (!parsed.success) {\n throw new Error(\n \"The registry index does not match the format this server understands. \" +\n \"Update @dowel-ui/mcp, or point it at a compatible registry.\",\n );\n }\n return parsed.data;\n });\n return this.#index;\n }\n\n item(name: string): Promise<RegistryItem> {\n let cached = this.#items.get(name);\n if (!cached) {\n cached = this.#readJson(`${name}.json`).then((raw) => {\n const parsed = registryItemSchema.safeParse(raw);\n if (!parsed.success) {\n throw new Error(`Registry entry \"${name}\" is malformed.`);\n }\n return parsed.data;\n });\n // A rejected promise must not be cached, or one network blip poisons the\n // name for the rest of the session.\n cached.catch(() => this.#items.delete(name));\n this.#items.set(name, cached);\n }\n return cached;\n }\n\n /** Items and everything they depend on, dependencies first. */\n async resolve(names: string[]): Promise<RegistryItem[]> {\n const ordered: RegistryItem[] = [];\n const placed = new Set<string>();\n const visiting = new Set<string>();\n\n const visit = async (name: string): Promise<void> => {\n if (placed.has(name) || visiting.has(name)) return;\n visiting.add(name);\n\n const item = await this.item(name);\n for (const dependency of item.registryDependencies) {\n await visit(dependency);\n }\n\n visiting.delete(name);\n placed.add(name);\n ordered.push(item);\n };\n\n for (const name of names) await visit(name);\n return ordered;\n }\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport {\n aiDoc,\n componentsDoc,\n conventionsDoc,\n planUi,\n renderBrief,\n renderPlan,\n themesDoc,\n type AgentDocsContext,\n type RegistryIndex,\n type RegistryIndexEntry,\n} from \"@dowel-ui/registry\";\nimport { z } from \"zod\";\n\nimport { RegistryClient } from \"./registry\";\n\nexport interface ServerOptions {\n registryUrl: string;\n docsUrl: string;\n cliPackage: string;\n libraryName: string;\n version: string;\n /**\n * What the consuming project imports components from.\n *\n * A source-first install resolves to the project's own path alias; there is\n * no way for this process to know it, so it is configuration rather than a\n * guess. The published package is the honest default.\n */\n importFrom: string;\n}\n\nfunction text(value: string) {\n return { content: [{ type: \"text\" as const, text: value }] };\n}\n\nfunction docsContext(options: ServerOptions, index: RegistryIndex): AgentDocsContext {\n return {\n index,\n registryUrl: options.registryUrl,\n docsUrl: options.docsUrl,\n cliPackage: options.cliPackage,\n libraryName: options.libraryName,\n importFrom: options.importFrom,\n };\n}\n\nfunction summarise(entry: RegistryIndexEntry): string {\n const kind = entry.type === \"registry:block\" ? \"block\" : \"component\";\n const status = entry.status === \"stable\" ? \"\" : ` (${entry.status})`;\n return `${entry.name} — ${kind}, ${entry.category}${status}\\n ${entry.description}`;\n}\n\n/**\n * Levenshtein distance, iterative with a single row.\n *\n * Only ever run against a name the caller got wrong, over a list of fewer than\n * a hundred short strings, so the row-per-character allocation a clearer\n * implementation would make is not worth avoiding — and the full matrix is not\n * worth keeping, since only the distance is wanted.\n */\nfunction distance(a: string, b: string): number {\n if (a === b) return 0;\n if (a.length === 0) return b.length;\n if (b.length === 0) return a.length;\n\n let previous = Array.from({ length: b.length + 1 }, (_, index) => index);\n\n for (let i = 1; i <= a.length; i += 1) {\n const current = [i];\n for (let j = 1; j <= b.length; j += 1) {\n const substitution = (previous[j - 1] ?? 0) + (a[i - 1] === b[j - 1] ? 0 : 1);\n const deletion = (previous[j] ?? 0) + 1;\n const insertion = (current[j - 1] ?? 0) + 1;\n current[j] = Math.min(substitution, deletion, insertion);\n }\n previous = current;\n }\n\n return previous[b.length] ?? 0;\n}\n\n/**\n * Names closest to one that does not exist.\n *\n * Substring matching alone answers nothing for a typo — \"datatabel\" shares no\n * run with \"data-table\" — and a typo is exactly the case where a suggestion is\n * worth most, because the agent already knows what it wants. Hyphens are\n * dropped before comparing so \"datatable\" reads as one edit from \"data-table\"\n * rather than two.\n */\nexport function nearest(names: string[], query: string, limit = 3): string[] {\n const needle = query.toLowerCase().replace(/-/g, \"\");\n\n return (\n names\n .map((name) => ({ name, gap: distance(name.toLowerCase().replace(/-/g, \"\"), needle) }))\n // A third of the length: enough for a transposition or a dropped letter,\n // not enough to suggest \"button\" for \"avatar\".\n .filter(({ gap }) => gap <= Math.max(2, Math.floor(needle.length / 3)))\n .sort((a, b) => a.gap - b.gap || a.name.localeCompare(b.name))\n .slice(0, limit)\n .map(({ name }) => name)\n );\n}\n\n/**\n * Scores a query against one entry.\n *\n * Name matches outrank description matches because an agent that already knows\n * roughly what a thing is called should get it first, and a word common to\n * thirty descriptions should not bury the component actually named after it.\n * Zero means no match, and no-match is excluded rather than ranked last.\n */\nfunction score(entry: RegistryIndexEntry, query: string): number {\n const needle = query.toLowerCase().trim();\n if (needle.length === 0) return 1;\n\n const name = entry.name.toLowerCase();\n if (name === needle) return 100;\n if (name.startsWith(needle)) return 50;\n if (name.includes(needle)) return 25;\n if (entry.title.toLowerCase().includes(needle)) return 20;\n if (entry.category.toLowerCase() === needle) return 15;\n if (entry.description.toLowerCase().includes(needle)) return 10;\n return 0;\n}\n\nexport function createServer(options: ServerOptions): McpServer {\n const registry = new RegistryClient(options.registryUrl);\n\n const server = new McpServer(\n { name: \"dowel-ui\", version: options.version },\n {\n instructions:\n `${options.libraryName} is a source-first React component system: components are ` +\n `installed into the project as editable files, not imported from a dependency.\\n\\n` +\n `Before writing any React UI, call search_components to check whether a component ` +\n `already exists — hand-writing a second Button is the most common mistake here. ` +\n `Call get_guide(\"conventions\") once per session for the styling and accessibility ` +\n `rules, which differ from other libraries in ways worth knowing.`,\n },\n );\n\n server.registerTool(\n \"search_components\",\n {\n title: \"Search components\",\n description:\n \"Search the component and block catalogue by name, description or category. \" +\n \"Call this before building any UI, to find what already exists. \" +\n \"Omit the query to list everything.\",\n inputSchema: {\n query: z\n .string()\n .optional()\n .describe('What you need, e.g. \"date\", \"chat\", \"table\", \"agent approval\"'),\n category: z\n .string()\n .optional()\n .describe(\n \"Restrict to one category: ai, form, overlay, data, feedback, navigation, display, layout, foundation\",\n ),\n kind: z\n .enum([\"component\", \"block\", \"any\"])\n .optional()\n .describe(\"Blocks are whole sections assembled from components. Default: any\"),\n },\n },\n async ({ query, category, kind }) => {\n const index = await registry.index();\n const wanted =\n kind === \"component\"\n ? [\"registry:ui\"]\n : kind === \"block\"\n ? [\"registry:block\"]\n : [\"registry:ui\", \"registry:block\"];\n\n const matches = index.items\n .filter((entry) => wanted.includes(entry.type))\n .filter((entry) => !category || entry.category === category)\n .map((entry) => ({ entry, rank: score(entry, query ?? \"\") }))\n .filter(({ rank }) => rank > 0)\n .sort((a, b) => b.rank - a.rank || a.entry.name.localeCompare(b.entry.name));\n\n if (matches.length === 0) {\n return text(\n `Nothing matches \"${query ?? \"\"}\". This registry has ` +\n `${String(index.items.length)} items — call search_components with no query to ` +\n `see them all. If nothing fits, build it from primitives rather than assuming ` +\n `a component exists.`,\n );\n }\n\n return text(\n `${String(matches.length)} match(es) in ${index.generatedFrom}:\\n\\n` +\n matches.map(({ entry }) => summarise(entry)).join(\"\\n\\n\") +\n `\\n\\nCall get_component for usage and source. Install with ` +\n `\\`npx ${options.cliPackage} add <name>\\`.`,\n );\n },\n );\n\n server.registerTool(\n \"get_component\",\n {\n title: \"Get a component\",\n description:\n \"Everything about one component or block: description, accessibility notes, what it \" +\n \"installs alongside, and optionally its full source. Use before writing code that \" +\n \"consumes it, so the props and markup come from the registry rather than memory.\",\n inputSchema: {\n name: z\n .string()\n .describe('Registry name, e.g. \"button\", \"ai-prompt-input\", \"dashboard\"'),\n include_source: z\n .boolean()\n .optional()\n .describe(\n \"Include the component's full source. Large — ask for it only when editing or extending the component. Default: false\",\n ),\n },\n },\n async ({ name, include_source }) => {\n const index = await registry.index();\n const entry = index.items.find((item) => item.name === name);\n\n if (!entry) {\n const substring = index.items\n .map((item) => ({ item, rank: score(item, name) }))\n .filter(({ rank }) => rank > 0)\n .sort((a, b) => b.rank - a.rank)\n .slice(0, 5)\n .map(({ item }) => item.name);\n\n const near =\n substring.length > 0\n ? substring\n : nearest(\n index.items.map((item) => item.name),\n name,\n );\n\n return text(\n `No component named \"${name}\".` +\n (near.length > 0 ? ` Did you mean: ${near.join(\", \")}?` : \"\") +\n ` Call search_components to see what exists — do not assume it does.`,\n );\n }\n\n // A licensed item has no public body to fetch. Everything the index knows\n // is still worth saying — what it is, what it is built from — followed by\n // how to get the rest, rather than a 404 that reads as the item not\n // existing when the point is that it does.\n if (entry.access === \"pro\") {\n return text(\n [\n `# ${entry.title} \\`${entry.name}\\``,\n \"\",\n entry.description,\n \"\",\n `Type: ${entry.type === \"registry:block\" ? \"block\" : \"component\"} · Category: ${entry.category} · Status: ${entry.status} · **Pro**`,\n \"\",\n `Install: \\`npx ${options.cliPackage} add ${entry.name}\\` — requires a licence. Sign in once with \\`npx ${options.cliPackage} login\\`, or set DOWEL_TOKEN in CI.`,\n \"\",\n entry.registryDependencies.length > 0\n ? `Also installs: ${entry.registryDependencies.join(\", \")}\\n`\n : \"\",\n `${String(entry.fileCount)} file(s). The source is served only to a licence holder, so this server cannot read it; once installed, read it from the project like any other file.`,\n ].join(\"\\n\"),\n );\n }\n\n const item = await registry.item(name);\n const lines = [\n `# ${item.title} \\`${item.name}\\``,\n \"\",\n item.description,\n \"\",\n `Type: ${item.type === \"registry:block\" ? \"block\" : \"component\"} · Category: ${item.category} · Status: ${item.status}`,\n \"\",\n `Install: \\`npx ${options.cliPackage} add ${item.name}\\``,\n `Import: \\`import { ... } from \"${options.importFrom}\"\\``,\n \"\",\n ];\n\n if (item.registryDependencies.length > 0) {\n lines.push(`Also installs: ${item.registryDependencies.join(\", \")}`, \"\");\n }\n if (item.dependencies.length > 0) {\n lines.push(`npm packages: ${item.dependencies.join(\", \")}`, \"\");\n }\n if (item.a11y) {\n lines.push(\"## Accessibility\", \"\", item.a11y, \"\");\n }\n\n if (include_source === true) {\n lines.push(\"## Source\", \"\");\n for (const file of item.files) {\n lines.push(`### \\`${file.path}\\``, \"\", \"```tsx\", file.content, \"```\", \"\");\n }\n } else {\n lines.push(\n `${String(item.files.length)} file(s): ${item.files.map((file) => file.path).join(\", \")}.`,\n \"Call again with include_source: true to read them.\",\n \"\",\n );\n }\n\n return text(lines.join(\"\\n\"));\n },\n );\n\n server.registerTool(\n \"get_guide\",\n {\n title: \"Get a guide\",\n description:\n \"The rules for writing code with this system: conventions and accessibility, theming \" +\n \"and tokens, the AI components, or the full catalogue. Read conventions once per \" +\n \"session before writing UI.\",\n inputSchema: {\n topic: z\n .enum([\"conventions\", \"theming\", \"ai\", \"catalogue\"])\n .describe(\n \"conventions: styling and accessibility rules that differ from other libraries. \" +\n \"theming: tokens, presets, radius and motion scales. \" +\n \"ai: the AI surfaces and when to use each. \" +\n \"catalogue: every component and block.\",\n ),\n },\n },\n async ({ topic }) => {\n const context = docsContext(options, await registry.index());\n const render = {\n conventions: conventionsDoc,\n theming: themesDoc,\n ai: aiDoc,\n catalogue: componentsDoc,\n }[topic];\n return text(render(context));\n },\n );\n\n server.registerTool(\n \"install_command\",\n {\n title: \"Get the install command\",\n description:\n \"The exact command to install components, and the full list of what it will write. \" +\n \"Use this instead of composing an npm/pnpm install — these components are source, not \" +\n \"a package, and the CLI resolves their dependency graph.\",\n inputSchema: {\n names: z.array(z.string()).min(1).describe(\"Registry names to install\"),\n },\n },\n async ({ names }) => {\n let resolved;\n try {\n resolved = await registry.resolve(names);\n } catch (error) {\n return text(\n `${error instanceof Error ? error.message : String(error)}\\n\\n` +\n \"Call search_components to check the name.\",\n );\n }\n\n const extra = resolved.filter((item) => !names.includes(item.name));\n const npm = [...new Set(resolved.flatMap((item) => item.dependencies))];\n\n return text(\n [\n `\\`\\`\\`bash`,\n `npx ${options.cliPackage} add ${names.join(\" \")}`,\n `\\`\\`\\``,\n \"\",\n `Writes ${String(resolved.length)} registry item(s): ${resolved.map((item) => item.name).join(\", \")}.`,\n extra.length > 0\n ? `${String(extra.length)} of those are dependencies pulled in automatically: ${extra.map((item) => item.name).join(\", \")}.`\n : \"Nothing extra is pulled in.\",\n npm.length > 0 ? `npm packages installed alongside: ${npm.join(\", \")}.` : \"\",\n \"\",\n \"Safe to re-run. A file the user has edited is never overwritten without `--overwrite`.\",\n ]\n .filter(Boolean)\n .join(\"\\n\"),\n );\n },\n );\n\n server.registerTool(\n \"plan_ui\",\n {\n title: \"Plan a screen\",\n description:\n \"Describe a screen and get the registry items that build it, the exact install \" +\n \"command, and a starting file. Use this before writing UI from a description — it \" +\n \"resolves against the catalogue, so it cannot suggest a component that does not exist.\",\n inputSchema: {\n prompt: z\n .string()\n .min(3)\n .describe('What to build, e.g. \"a billing page with usage and invoices\"'),\n format: z\n .enum([\"plan\", \"code\", \"both\"])\n .optional()\n .describe(\"plan: what to install and why. code: a starting file. Default: both\"),\n },\n },\n async ({ prompt, format }) => {\n const index = await registry.index();\n const plan = planUi(prompt, index);\n\n if (plan.empty) {\n return text(\n `Nothing in the registry matches \"${prompt}\".\\n\\n` +\n \"Call search_components with a simpler term before building anything by hand — \" +\n \"and if there genuinely is no component for it, build it from primitives rather \" +\n \"than assuming one exists under another name.\",\n );\n }\n\n const parts: string[] = [];\n\n if (format !== \"code\") {\n parts.push(\n renderBrief(plan, {\n cliPackage: options.cliPackage,\n docsUrl: options.docsUrl,\n importFrom: options.importFrom,\n }),\n );\n\n parts.push(\n \"\",\n \"Why each was chosen:\",\n ...[...plan.blocks, ...plan.components].map(\n (item) => `- ${item.entry.name}: ${item.because}`,\n ),\n );\n }\n\n if (format !== \"plan\") {\n parts.push(\n \"\",\n \"A starting file:\",\n \"\",\n \"```tsx\",\n renderPlan(plan, { importFrom: options.importFrom, docsUrl: options.docsUrl }).trim(),\n \"```\",\n );\n }\n\n // Deliberately not silent about the limit: the registry publishes what a\n // component is, not the shape of its props, so the plan stops at the\n // composition and the props come from get_component.\n parts.push(\n \"\",\n \"Call get_component for each of these before writing props. This plan does not \" +\n \"include prop shapes, and a plausible invented prop is worse than none.\",\n );\n\n return text(parts.join(\"\\n\"));\n },\n );\n\n return server;\n}\n","#!/usr/bin/env node\nimport { readFileSync } from \"node:fs\";\n\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\n\nimport { branding } from \"./branding\";\nimport { createServer } from \"./server\";\n\nconst { version } = JSON.parse(\n readFileSync(new URL(\"../package.json\", import.meta.url), \"utf8\"),\n) as { version: string };\n\n/**\n * Reads a `--flag value` pair from argv.\n *\n * Hand-rolled rather than pulled from a parser: this binary is launched by an\n * MCP client from a JSON config, takes two options, and every dependency here\n * is a dependency of every agent session that starts the server.\n */\nfunction flag(name: string): string | undefined {\n const index = process.argv.indexOf(`--${name}`);\n if (index === -1) return undefined;\n return process.argv[index + 1];\n}\n\nasync function main(): Promise<void> {\n const registryUrl = flag(\"registry\") ?? process.env.DOWEL_REGISTRY ?? branding.registryUrl;\n const importFrom =\n flag(\"import-from\") ?? process.env.DOWEL_IMPORT_FROM ?? `${branding.packageScope}/react`;\n\n const server = createServer({\n registryUrl,\n docsUrl: branding.registryUrl.replace(/\\/r$/, \"\"),\n cliPackage: branding.cliPackage,\n libraryName: branding.libraryName,\n importFrom,\n version,\n });\n\n // stdout is the protocol channel. Anything written to it that is not a JSON-RPC\n // message corrupts the stream, which is why there is no logging here at all —\n // diagnostics belong on stderr or nowhere.\n await server.connect(new StdioServerTransport());\n}\n\nvoid main().catch((error: unknown) => {\n console.error(error instanceof Error ? error.stack : String(error));\n process.exit(1);\n});\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dowel-ui/mcp",
|
|
3
|
+
"version": "0.7.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Model Context Protocol server for Dowel. Lets a coding agent search the component registry, read a component's source and conventions, and get the exact install command — instead of guessing what exists.",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"mcp",
|
|
8
|
+
"model-context-protocol",
|
|
9
|
+
"ai",
|
|
10
|
+
"agent",
|
|
11
|
+
"claude",
|
|
12
|
+
"cursor",
|
|
13
|
+
"react",
|
|
14
|
+
"ui",
|
|
15
|
+
"components",
|
|
16
|
+
"design-system",
|
|
17
|
+
"registry",
|
|
18
|
+
"dowel"
|
|
19
|
+
],
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"homepage": "https://dowel-eight.vercel.app",
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/aqkprogrammer/dowel-ui.git",
|
|
25
|
+
"directory": "packages/mcp"
|
|
26
|
+
},
|
|
27
|
+
"bugs": {
|
|
28
|
+
"url": "https://github.com/aqkprogrammer/dowel-ui/issues"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist"
|
|
32
|
+
],
|
|
33
|
+
"bin": {
|
|
34
|
+
"dowel-mcp": "./dist/index.js"
|
|
35
|
+
},
|
|
36
|
+
"exports": {
|
|
37
|
+
".": {
|
|
38
|
+
"types": "./dist/index.d.ts",
|
|
39
|
+
"default": "./dist/index.js"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=20"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@modelcontextprotocol/sdk": "1.30.0",
|
|
47
|
+
"zod": "4.5.4"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/node": "26.4.0",
|
|
51
|
+
"tsdown": "0.22.14",
|
|
52
|
+
"typescript": "6.0.3",
|
|
53
|
+
"vitest": "4.1.10",
|
|
54
|
+
"@dowel-ui/registry": "0.7.0",
|
|
55
|
+
"@dowel-ui/config": "0.7.0"
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"build": "tsdown",
|
|
59
|
+
"typecheck": "tsc --noEmit",
|
|
60
|
+
"test": "vitest run",
|
|
61
|
+
"clean": "rm -rf dist .turbo"
|
|
62
|
+
}
|
|
63
|
+
}
|