rafters 0.0.83 → 0.0.85
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +322 -42
- package/dist/registry/types.d.ts +1 -0
- package/dist/registry/types.js +2 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -526,6 +526,10 @@ function generateThemeBlock(groups) {
|
|
|
526
526
|
if (token.lineHeight) {
|
|
527
527
|
lines.push(` --${token.name}--line-height: ${token.lineHeight};`);
|
|
528
528
|
}
|
|
529
|
+
if (token.name.startsWith("line-height-")) {
|
|
530
|
+
const key = token.name.replace(/^line-height-/, "");
|
|
531
|
+
lines.push(` --leading-${key}: ${value};`);
|
|
532
|
+
}
|
|
529
533
|
}
|
|
530
534
|
lines.push("");
|
|
531
535
|
}
|
|
@@ -1182,6 +1186,8 @@ function deriveCandidates(themeCSS) {
|
|
|
1182
1186
|
candidates.add(`font-${name.slice(12)}`);
|
|
1183
1187
|
} else if (name.startsWith("ease-")) {
|
|
1184
1188
|
candidates.add(name);
|
|
1189
|
+
} else if (name.startsWith("leading-")) {
|
|
1190
|
+
candidates.add(name);
|
|
1185
1191
|
} else if (name.startsWith("animate-")) {
|
|
1186
1192
|
candidates.add(name);
|
|
1187
1193
|
} else if (name.startsWith("text-") && !name.includes("--")) {
|
|
@@ -27811,17 +27817,26 @@ var TokenGraph = class {
|
|
|
27811
27817
|
this.snapshot = /* @__PURE__ */ new Map();
|
|
27812
27818
|
for (const [k, v] of this.nodes) this.snapshot.set(k, structuredClone(v));
|
|
27813
27819
|
}
|
|
27820
|
+
// The caller (set/bind) takes a snapshot before invoking this. If any
|
|
27821
|
+
// dependent's transform throws partway through, we roll the whole graph
|
|
27822
|
+
// back to that snapshot and re-throw -- cascade is all-or-nothing, never
|
|
27823
|
+
// half-applied.
|
|
27814
27824
|
cascadeFrom(changed) {
|
|
27815
|
-
|
|
27816
|
-
|
|
27817
|
-
|
|
27818
|
-
|
|
27819
|
-
const
|
|
27820
|
-
|
|
27821
|
-
|
|
27822
|
-
|
|
27823
|
-
|
|
27824
|
-
|
|
27825
|
+
try {
|
|
27826
|
+
const dependents = this.collectDependents(changed);
|
|
27827
|
+
if (dependents.size === 0) return;
|
|
27828
|
+
const ordered = this.topoSort(dependents);
|
|
27829
|
+
for (const name of ordered) {
|
|
27830
|
+
const node = this.nodes.get(name);
|
|
27831
|
+
if (!node || node.userOverride || !node.binding) continue;
|
|
27832
|
+
const plugin = this.requirePlugin(node.binding.plugin);
|
|
27833
|
+
const value = plugin.transform(node.binding.input, (n2) => this.get(n2));
|
|
27834
|
+
plugin.outputSchema.parse(value);
|
|
27835
|
+
this.nodes.set(name, { ...node, value });
|
|
27836
|
+
}
|
|
27837
|
+
} catch (error47) {
|
|
27838
|
+
this.undo();
|
|
27839
|
+
throw error47;
|
|
27825
27840
|
}
|
|
27826
27841
|
}
|
|
27827
27842
|
collectDependents(changed) {
|
|
@@ -27941,8 +27956,15 @@ function senseShadcnCss(css) {
|
|
|
27941
27956
|
|
|
27942
27957
|
// ../design-tokens/src/outputs.ts
|
|
27943
27958
|
import { existsSync, realpathSync } from "fs";
|
|
27944
|
-
import { mkdir, writeFile } from "fs/promises";
|
|
27959
|
+
import { mkdir, unlink, writeFile } from "fs/promises";
|
|
27945
27960
|
import { isAbsolute, join as join2, resolve } from "path";
|
|
27961
|
+
var KNOWN_OUTPUT_FILENAMES = [
|
|
27962
|
+
"rafters.css",
|
|
27963
|
+
"rafters.ts",
|
|
27964
|
+
"rafters.json",
|
|
27965
|
+
"rafters.standalone.css",
|
|
27966
|
+
"rafters.documentation.css"
|
|
27967
|
+
];
|
|
27946
27968
|
function fieldToPaths(field) {
|
|
27947
27969
|
if (!field) return [];
|
|
27948
27970
|
if (typeof field === "string") return [field];
|
|
@@ -28007,6 +28029,16 @@ async function regenerateOutputs(registry2, input, hooks2 = {}) {
|
|
|
28007
28029
|
await writeFile(join2(outputDir2, "rafters.documentation.css"), doc);
|
|
28008
28030
|
written.push("rafters.documentation.css");
|
|
28009
28031
|
}
|
|
28032
|
+
const writtenSet = new Set(written);
|
|
28033
|
+
for (const filename of KNOWN_OUTPUT_FILENAMES) {
|
|
28034
|
+
if (writtenSet.has(filename)) continue;
|
|
28035
|
+
const filePath = join2(outputDir2, filename);
|
|
28036
|
+
if (!existsSync(filePath)) continue;
|
|
28037
|
+
try {
|
|
28038
|
+
await unlink(filePath);
|
|
28039
|
+
} catch {
|
|
28040
|
+
}
|
|
28041
|
+
}
|
|
28010
28042
|
hooks2.notify?.();
|
|
28011
28043
|
return written;
|
|
28012
28044
|
}
|
|
@@ -28040,10 +28072,9 @@ var TokenRegistry = class {
|
|
|
28040
28072
|
...t.binding ? { binding: t.binding } : {}
|
|
28041
28073
|
});
|
|
28042
28074
|
}
|
|
28043
|
-
|
|
28044
|
-
|
|
28045
|
-
|
|
28046
|
-
this.graph.bind(t.name, t.binding.plugin, t.binding.input);
|
|
28075
|
+
const ordered = topoSortPass2(parsed, this.plugins);
|
|
28076
|
+
for (const entry of ordered) {
|
|
28077
|
+
this.graph.bind(entry.name, entry.binding.plugin, entry.binding.input);
|
|
28047
28078
|
}
|
|
28048
28079
|
}
|
|
28049
28080
|
registerPlugin(plugin) {
|
|
@@ -28152,6 +28183,39 @@ function toUserOverrideField(override, baseValue) {
|
|
|
28152
28183
|
if (override.kind) result.kind = override.kind;
|
|
28153
28184
|
return result;
|
|
28154
28185
|
}
|
|
28186
|
+
function topoSortPass2(parsed, plugins) {
|
|
28187
|
+
const entries = [];
|
|
28188
|
+
for (const t of parsed) {
|
|
28189
|
+
if (!t.binding || t.userOverride) continue;
|
|
28190
|
+
entries.push({ name: t.name, binding: t.binding });
|
|
28191
|
+
}
|
|
28192
|
+
const entryByName = /* @__PURE__ */ new Map();
|
|
28193
|
+
for (const e of entries) entryByName.set(e.name, e);
|
|
28194
|
+
const sorted = [];
|
|
28195
|
+
const visited = /* @__PURE__ */ new Set();
|
|
28196
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
28197
|
+
const visit = (name, path) => {
|
|
28198
|
+
if (visited.has(name)) return;
|
|
28199
|
+
if (visiting.has(name)) {
|
|
28200
|
+
throw new CircularDependencyError([...path, name]);
|
|
28201
|
+
}
|
|
28202
|
+
visiting.add(name);
|
|
28203
|
+
const entry = entryByName.get(name);
|
|
28204
|
+
if (entry) {
|
|
28205
|
+
const plugin = plugins.get(entry.binding.plugin);
|
|
28206
|
+
if (plugin) {
|
|
28207
|
+
for (const dep of plugin.dependsOn(entry.binding.input)) {
|
|
28208
|
+
if (entryByName.has(dep)) visit(dep, [...path, name]);
|
|
28209
|
+
}
|
|
28210
|
+
}
|
|
28211
|
+
}
|
|
28212
|
+
visiting.delete(name);
|
|
28213
|
+
visited.add(name);
|
|
28214
|
+
if (entry) sorted.push(entry);
|
|
28215
|
+
};
|
|
28216
|
+
for (const e of entries) visit(e.name, []);
|
|
28217
|
+
return sorted;
|
|
28218
|
+
}
|
|
28155
28219
|
|
|
28156
28220
|
// ../design-tokens/src/persistence.ts
|
|
28157
28221
|
function loadRegistryFromDir(dir, plugins = []) {
|
|
@@ -28427,7 +28491,8 @@ var RegistryItemSchema = external_exports.object({
|
|
|
28427
28491
|
// Per-target facets. zod v4's `z.record(enum, ...)` demands EVERY enum key be
|
|
28428
28492
|
// present; a component built for only some targets must parse, so this is a
|
|
28429
28493
|
// partial record (only the built targets appear).
|
|
28430
|
-
facets: external_exports.partialRecord(ComponentTargetSchema, FacetSchema).default({})
|
|
28494
|
+
facets: external_exports.partialRecord(ComponentTargetSchema, FacetSchema).default({}),
|
|
28495
|
+
parent: external_exports.string().optional()
|
|
28431
28496
|
});
|
|
28432
28497
|
var RegistryIndexSchema = external_exports.object({
|
|
28433
28498
|
name: external_exports.string(),
|
|
@@ -31315,6 +31380,8 @@ function resolveWorkspace(workspaces, defaultWorkspace, name) {
|
|
|
31315
31380
|
}
|
|
31316
31381
|
|
|
31317
31382
|
// src/mcp/graph.ts
|
|
31383
|
+
var EXPAND_OP = "*";
|
|
31384
|
+
var PROBE_OP = "?";
|
|
31318
31385
|
function assembleGraph(items) {
|
|
31319
31386
|
const nodes = /* @__PURE__ */ new Map();
|
|
31320
31387
|
for (const item of items) {
|
|
@@ -31330,13 +31397,45 @@ function assembleGraph(items) {
|
|
|
31330
31397
|
if (src?.accessibility !== void 0) intel.accessibility = src.accessibility;
|
|
31331
31398
|
if (src?.attentionEconomics !== void 0) intel.attentionEconomics = src.attentionEconomics;
|
|
31332
31399
|
if (src?.trustBuilding !== void 0) intel.trustBuilding = src.trustBuilding;
|
|
31333
|
-
|
|
31400
|
+
const gn = {
|
|
31334
31401
|
id: item.name,
|
|
31335
31402
|
kind,
|
|
31336
31403
|
intel,
|
|
31337
31404
|
facets: item.facets ?? {},
|
|
31338
|
-
composesWith: item.composites
|
|
31339
|
-
|
|
31405
|
+
composesWith: item.composites,
|
|
31406
|
+
parts: []
|
|
31407
|
+
};
|
|
31408
|
+
if (item.parent !== void 0) gn.parent = item.parent;
|
|
31409
|
+
nodes.set(item.name, gn);
|
|
31410
|
+
}
|
|
31411
|
+
for (const node of nodes.values()) {
|
|
31412
|
+
if (node.parent === void 0) continue;
|
|
31413
|
+
if (node.parent === node.id) {
|
|
31414
|
+
throw new Error(`graph: node "${node.id}" parent references itself`);
|
|
31415
|
+
}
|
|
31416
|
+
if (!nodes.has(node.parent)) {
|
|
31417
|
+
throw new Error(`graph: node "${node.id}" parent names unknown id "${node.parent}"`);
|
|
31418
|
+
}
|
|
31419
|
+
}
|
|
31420
|
+
for (const node of nodes.values()) {
|
|
31421
|
+
if (node.parent === void 0) continue;
|
|
31422
|
+
const visited = /* @__PURE__ */ new Set();
|
|
31423
|
+
visited.add(node.id);
|
|
31424
|
+
let current = node.parent;
|
|
31425
|
+
while (current !== void 0) {
|
|
31426
|
+
if (visited.has(current)) {
|
|
31427
|
+
throw new Error(
|
|
31428
|
+
`graph: node "${node.id}" has a circular parent chain through "${current}"`
|
|
31429
|
+
);
|
|
31430
|
+
}
|
|
31431
|
+
visited.add(current);
|
|
31432
|
+
current = nodes.get(current)?.parent;
|
|
31433
|
+
}
|
|
31434
|
+
}
|
|
31435
|
+
for (const node of nodes.values()) {
|
|
31436
|
+
if (node.parent === void 0) continue;
|
|
31437
|
+
const parentNode = nodes.get(node.parent);
|
|
31438
|
+
if (parentNode) parentNode.parts.push(node.id);
|
|
31340
31439
|
}
|
|
31341
31440
|
for (const node of nodes.values()) {
|
|
31342
31441
|
for (const target of node.composesWith) {
|
|
@@ -31366,6 +31465,7 @@ function describe(addr, graph, target) {
|
|
|
31366
31465
|
const [head, ...rest] = parts;
|
|
31367
31466
|
if (head === void 0) return { error: `cannot resolve: ${addr}` };
|
|
31368
31467
|
if (head === "components" || head === "composites") {
|
|
31468
|
+
if (rest.length > 0) return { error: `cannot expand: ${addr}` };
|
|
31369
31469
|
const kind = head === "components" ? "component" : "composite";
|
|
31370
31470
|
const roster = [];
|
|
31371
31471
|
for (const node2 of graph.nodes.values()) {
|
|
@@ -31373,9 +31473,24 @@ function describe(addr, graph, target) {
|
|
|
31373
31473
|
}
|
|
31374
31474
|
return roster;
|
|
31375
31475
|
}
|
|
31476
|
+
if (parts[parts.length - 1] === PROBE_OP) {
|
|
31477
|
+
const baseAddr = parts.slice(0, -1).join(".");
|
|
31478
|
+
const result = describe(baseAddr, graph, target);
|
|
31479
|
+
if (typeof result === "object" && result !== null && "error" in result) return null;
|
|
31480
|
+
return result;
|
|
31481
|
+
}
|
|
31482
|
+
if (head === EXPAND_OP || head === PROBE_OP) {
|
|
31483
|
+
return { error: `cannot expand at root: use 'components' or 'composites'` };
|
|
31484
|
+
}
|
|
31376
31485
|
const node = graph.nodes.get(head);
|
|
31377
31486
|
if (!node) return { error: `unknown node: ${head}` };
|
|
31378
|
-
if (rest.length === 0) return layer0(node, target);
|
|
31487
|
+
if (rest.length === 0) return layer0(node, graph, target);
|
|
31488
|
+
if (rest[rest.length - 1] === EXPAND_OP) {
|
|
31489
|
+
const prefix = rest.slice(0, -1);
|
|
31490
|
+
if (prefix.length === 0) return expandNode(node, target);
|
|
31491
|
+
if (prefix.length === 1 && prefix[0] === "props") return expandProps(node, target);
|
|
31492
|
+
return { error: `cannot expand: ${addr}` };
|
|
31493
|
+
}
|
|
31379
31494
|
if (rest.length === 1 && rest[0] === "composesWith") {
|
|
31380
31495
|
return resolveEdges(node, graph, target);
|
|
31381
31496
|
}
|
|
@@ -31396,7 +31511,7 @@ function toAgentProp(prop) {
|
|
|
31396
31511
|
}
|
|
31397
31512
|
return prop;
|
|
31398
31513
|
}
|
|
31399
|
-
function layer0(node, target) {
|
|
31514
|
+
function layer0(node, graph, target) {
|
|
31400
31515
|
const facet = target === void 0 ? void 0 : node.facets[target];
|
|
31401
31516
|
const children = [];
|
|
31402
31517
|
if (facet) {
|
|
@@ -31409,12 +31524,23 @@ function layer0(node, target) {
|
|
|
31409
31524
|
if (node.composesWith.length > 0) {
|
|
31410
31525
|
children.push({ addr: `${node.id}.composesWith`, type: "edge" });
|
|
31411
31526
|
}
|
|
31527
|
+
for (const partId of node.parts) {
|
|
31528
|
+
children.push({ addr: partId, type: "part" });
|
|
31529
|
+
}
|
|
31412
31530
|
const result = { id: node.id, kind: node.kind, intel: node.intel, children };
|
|
31413
31531
|
if (facet) {
|
|
31414
31532
|
result.snippet = facet.snippet;
|
|
31415
31533
|
if (facet.slots !== void 0) result.slots = facet.slots;
|
|
31416
31534
|
if (facet.events !== void 0) result.events = facet.events;
|
|
31417
31535
|
}
|
|
31536
|
+
if (node.parent !== void 0) {
|
|
31537
|
+
result.parent = node.parent;
|
|
31538
|
+
const parentNode = graph.nodes.get(node.parent);
|
|
31539
|
+
if (parentNode) {
|
|
31540
|
+
const siblings = parentNode.parts.filter((id) => id !== node.id);
|
|
31541
|
+
if (siblings.length > 0) result.siblings = siblings;
|
|
31542
|
+
}
|
|
31543
|
+
}
|
|
31418
31544
|
return result;
|
|
31419
31545
|
}
|
|
31420
31546
|
function resolveEdges(node, graph, target) {
|
|
@@ -31424,10 +31550,43 @@ function resolveEdges(node, graph, target) {
|
|
|
31424
31550
|
if (seen.has(edgeId)) continue;
|
|
31425
31551
|
seen.add(edgeId);
|
|
31426
31552
|
const edgeNode = graph.nodes.get(edgeId);
|
|
31427
|
-
if (edgeNode) results.push(layer0(edgeNode, target));
|
|
31553
|
+
if (edgeNode) results.push(layer0(edgeNode, graph, target));
|
|
31428
31554
|
}
|
|
31429
31555
|
return results;
|
|
31430
31556
|
}
|
|
31557
|
+
function expandProps(node, target) {
|
|
31558
|
+
const facet = target === void 0 ? void 0 : node.facets[target];
|
|
31559
|
+
const props = {};
|
|
31560
|
+
if (facet) {
|
|
31561
|
+
for (const [name, prop] of Object.entries(facet.props)) {
|
|
31562
|
+
props[name] = toAgentProp(prop);
|
|
31563
|
+
}
|
|
31564
|
+
}
|
|
31565
|
+
return { expanded: true, props };
|
|
31566
|
+
}
|
|
31567
|
+
function expandNode(node, target) {
|
|
31568
|
+
const facet = target === void 0 ? void 0 : node.facets[target];
|
|
31569
|
+
const props = {};
|
|
31570
|
+
if (facet) {
|
|
31571
|
+
for (const [name, prop] of Object.entries(facet.props)) {
|
|
31572
|
+
props[name] = toAgentProp(prop);
|
|
31573
|
+
}
|
|
31574
|
+
}
|
|
31575
|
+
const result = {
|
|
31576
|
+
id: node.id,
|
|
31577
|
+
kind: node.kind,
|
|
31578
|
+
intel: node.intel,
|
|
31579
|
+
props
|
|
31580
|
+
};
|
|
31581
|
+
if (node.composesWith.length > 0) result.composesWith = node.composesWith;
|
|
31582
|
+
if (node.parts.length > 0) result.parts = node.parts;
|
|
31583
|
+
if (facet) {
|
|
31584
|
+
result.snippet = facet.snippet;
|
|
31585
|
+
if (facet.slots !== void 0) result.slots = facet.slots;
|
|
31586
|
+
if (facet.events !== void 0) result.events = facet.events;
|
|
31587
|
+
}
|
|
31588
|
+
return result;
|
|
31589
|
+
}
|
|
31431
31590
|
|
|
31432
31591
|
// src/mcp/intent.ts
|
|
31433
31592
|
var INTENT_TAGS = {
|
|
@@ -31551,7 +31710,7 @@ function selectNearMiss(use, decisive, matchedTags, graph) {
|
|
|
31551
31710
|
}
|
|
31552
31711
|
function describeNode(id, graph) {
|
|
31553
31712
|
const result = describe(id, graph);
|
|
31554
|
-
if (!Array.isArray(result) && "children" in result) return result;
|
|
31713
|
+
if (result !== null && !Array.isArray(result) && "children" in result) return result;
|
|
31555
31714
|
return void 0;
|
|
31556
31715
|
}
|
|
31557
31716
|
function noMatch() {
|
|
@@ -31573,22 +31732,32 @@ function describeWithOverlay(addr, graph, ctx) {
|
|
|
31573
31732
|
return roster.map((entry) => ({ id: entry.id, presence: presenceOf(set3, entry.id) }));
|
|
31574
31733
|
}
|
|
31575
31734
|
if (addr !== "" && !addr.includes(".") && isNodeResult(result)) {
|
|
31576
|
-
|
|
31577
|
-
|
|
31578
|
-
|
|
31579
|
-
|
|
31580
|
-
target: ctx.target,
|
|
31581
|
-
rendersForTarget: ctx.target !== void 0 && graph.nodes.get(result.id)?.facets[ctx.target] !== void 0
|
|
31582
|
-
};
|
|
31735
|
+
return { ...result, ...stampOf(result.id, result.kind, graph, ctx) };
|
|
31736
|
+
}
|
|
31737
|
+
if (isExpandedNodeResult(result)) {
|
|
31738
|
+
return { ...result, ...stampOf(result.id, result.kind, graph, ctx) };
|
|
31583
31739
|
}
|
|
31584
31740
|
return result;
|
|
31585
31741
|
}
|
|
31586
31742
|
function presenceOf(set3, id) {
|
|
31587
31743
|
return set3.has(id) ? "installed" : "available";
|
|
31588
31744
|
}
|
|
31745
|
+
function stampOf(id, kind, graph, ctx) {
|
|
31746
|
+
const set3 = kind === "component" ? ctx.installed.components : ctx.installed.composites;
|
|
31747
|
+
return {
|
|
31748
|
+
presence: presenceOf(set3, id),
|
|
31749
|
+
target: ctx.target,
|
|
31750
|
+
// rendersForTarget reads the node's own facets (on the universal graph):
|
|
31751
|
+
// does a facet for the resolved target exist?
|
|
31752
|
+
rendersForTarget: ctx.target !== void 0 && graph.nodes.get(id)?.facets[ctx.target] !== void 0
|
|
31753
|
+
};
|
|
31754
|
+
}
|
|
31589
31755
|
function isNodeResult(result) {
|
|
31590
31756
|
return typeof result === "object" && result !== null && !Array.isArray(result) && "id" in result && "kind" in result && "children" in result;
|
|
31591
31757
|
}
|
|
31758
|
+
function isExpandedNodeResult(result) {
|
|
31759
|
+
return typeof result === "object" && result !== null && !Array.isArray(result) && "id" in result && "kind" in result && "props" in result && !("children" in result);
|
|
31760
|
+
}
|
|
31592
31761
|
|
|
31593
31762
|
// src/mcp/tools.ts
|
|
31594
31763
|
function isSafeRelPath(p2) {
|
|
@@ -31637,6 +31806,39 @@ var WORKSPACE_PARAM = {
|
|
|
31637
31806
|
description: "Workspace name (directory basename). Required when the MCP session has multiple workspaces and none matches cwd. Call rafters_workspaces to list options."
|
|
31638
31807
|
}
|
|
31639
31808
|
};
|
|
31809
|
+
var GENERATE_LEADING_FILLER = [
|
|
31810
|
+
"give me a ",
|
|
31811
|
+
"give me an ",
|
|
31812
|
+
"give me ",
|
|
31813
|
+
"i need a ",
|
|
31814
|
+
"i need an ",
|
|
31815
|
+
"i need ",
|
|
31816
|
+
"i want a ",
|
|
31817
|
+
"i want an ",
|
|
31818
|
+
"i want ",
|
|
31819
|
+
"create a ",
|
|
31820
|
+
"create an ",
|
|
31821
|
+
"create ",
|
|
31822
|
+
"make me a ",
|
|
31823
|
+
"make me an ",
|
|
31824
|
+
"make a ",
|
|
31825
|
+
"make an ",
|
|
31826
|
+
"make ",
|
|
31827
|
+
"a ",
|
|
31828
|
+
"an ",
|
|
31829
|
+
"the "
|
|
31830
|
+
];
|
|
31831
|
+
function normalizeGenerateQuery(intent) {
|
|
31832
|
+
const lowered = intent.trim().toLowerCase();
|
|
31833
|
+
let candidate = lowered;
|
|
31834
|
+
for (const filler of GENERATE_LEADING_FILLER) {
|
|
31835
|
+
if (candidate.startsWith(filler)) {
|
|
31836
|
+
candidate = candidate.slice(filler.length);
|
|
31837
|
+
break;
|
|
31838
|
+
}
|
|
31839
|
+
}
|
|
31840
|
+
return candidate.trim().replace(/[.,!?]+$/, "");
|
|
31841
|
+
}
|
|
31640
31842
|
var TOOL_DEFINITIONS = [
|
|
31641
31843
|
{
|
|
31642
31844
|
name: "rafters_workspaces",
|
|
@@ -31679,7 +31881,7 @@ var TOOL_DEFINITIONS = [
|
|
|
31679
31881
|
},
|
|
31680
31882
|
{
|
|
31681
31883
|
name: "rafters_describe",
|
|
31682
|
-
description: 'Recursively introspect the component/composite intel graph. describe() returns the installed surface; describe(components)/describe(composites) list the kind roster; describe(button) returns a node -- intel plus type-marked, drillable children; describe(button.props.fill) drills into a prop; describe(button.props.fill.vocab) returns the real token values. A natural-language question (e.g. "what do I use when it needs to be above everything") routes to the best-matching node plus a near-miss counter-example instead of an address.',
|
|
31884
|
+
description: 'Recursively introspect the component/composite intel graph. describe() returns the installed surface; describe(components)/describe(composites) list the kind roster; describe(button) returns a node -- intel plus type-marked, drillable children; describe(button.props.fill) drills into a prop; describe(button.props.fill.vocab) returns the real token values. describe(button.*) expands all props inline in one call (no more drill-per-prop round trips); describe(button.props.fill.?) probes safely (null on miss, not an error). A natural-language question (e.g. "what do I use when it needs to be above everything") routes to the best-matching node plus a near-miss counter-example instead of an address.',
|
|
31683
31885
|
inputSchema: {
|
|
31684
31886
|
type: "object",
|
|
31685
31887
|
properties: {
|
|
@@ -31694,12 +31896,12 @@ var TOOL_DEFINITIONS = [
|
|
|
31694
31896
|
},
|
|
31695
31897
|
{
|
|
31696
31898
|
name: "rafters_generate",
|
|
31697
|
-
description:
|
|
31899
|
+
description: 'Resolve a prose query to ONE registry component and return its verbatim, target-correct snippet with open content slots. A bare component name (e.g. "button", "give me a modal") resolves directly; a semantic question (e.g. "what do I use when it needs to be above everything") falls back to the intent door. Returns { component, target, snippet, slots } where snippet is the registry facet verbatim and each slot is left for the caller to fill. v1 serves single components only -- no parameterization, no composites, no writes.',
|
|
31698
31900
|
inputSchema: {
|
|
31699
31901
|
type: "object",
|
|
31700
31902
|
properties: {
|
|
31701
31903
|
...WORKSPACE_PARAM,
|
|
31702
|
-
intent: { type: "string", description: "
|
|
31904
|
+
intent: { type: "string", description: "A component name or a natural-language request" }
|
|
31703
31905
|
},
|
|
31704
31906
|
required: ["intent"]
|
|
31705
31907
|
}
|
|
@@ -31757,6 +31959,11 @@ var TOOL_DEFINITIONS = [
|
|
|
31757
31959
|
}
|
|
31758
31960
|
];
|
|
31759
31961
|
var DEPRECATED_MSG = "use rafters_describe instead";
|
|
31962
|
+
var OverlayInstalledSchema = external_exports.object({
|
|
31963
|
+
components: external_exports.array(external_exports.string()).optional(),
|
|
31964
|
+
primitives: external_exports.array(external_exports.string()).optional(),
|
|
31965
|
+
composites: external_exports.array(external_exports.string()).optional()
|
|
31966
|
+
});
|
|
31760
31967
|
var RaftersToolHandler = class {
|
|
31761
31968
|
workspaces;
|
|
31762
31969
|
defaultWorkspace;
|
|
@@ -32004,8 +32211,22 @@ var RaftersToolHandler = class {
|
|
|
32004
32211
|
*/
|
|
32005
32212
|
async overlayContext(workspace) {
|
|
32006
32213
|
const config2 = workspace ? await this.readConfig(workspace.root) : null;
|
|
32007
|
-
const
|
|
32008
|
-
|
|
32214
|
+
const parsedInstalled = OverlayInstalledSchema.safeParse(config2?.installed ?? {});
|
|
32215
|
+
if (!parsedInstalled.success) {
|
|
32216
|
+
const issue2 = parsedInstalled.error.issues[0];
|
|
32217
|
+
const field = issue2 && issue2.path.length > 0 ? `installed.${issue2.path.join(".")}` : "installed";
|
|
32218
|
+
const configPath2 = workspace ? getRaftersPaths(workspace.root).config : "config.rafters.json";
|
|
32219
|
+
return {
|
|
32220
|
+
configError: `malformed config at ${configPath2}: ${field} ${issue2?.message ?? "is invalid"}`
|
|
32221
|
+
};
|
|
32222
|
+
}
|
|
32223
|
+
const base = buildInstalledSet({
|
|
32224
|
+
installed: {
|
|
32225
|
+
components: parsedInstalled.data.components ?? [],
|
|
32226
|
+
composites: parsedInstalled.data.composites ?? []
|
|
32227
|
+
}
|
|
32228
|
+
});
|
|
32229
|
+
const components = /* @__PURE__ */ new Set([...base.components, ...parsedInstalled.data.primitives ?? []]);
|
|
32009
32230
|
const parsedTarget = ComponentTargetSchema.safeParse(config2?.componentTarget);
|
|
32010
32231
|
return {
|
|
32011
32232
|
target: parsedTarget.success ? parsedTarget.data : void 0,
|
|
@@ -32034,23 +32255,79 @@ var RaftersToolHandler = class {
|
|
|
32034
32255
|
return this.jsonResult(matchIntent(address, graph));
|
|
32035
32256
|
}
|
|
32036
32257
|
const ctx = await this.overlayContext(resolved);
|
|
32258
|
+
if ("configError" in ctx) {
|
|
32259
|
+
return this.errorResult(ctx.configError);
|
|
32260
|
+
}
|
|
32037
32261
|
return this.jsonResult(describeWithOverlay(address, graph, ctx));
|
|
32038
32262
|
}
|
|
32039
32263
|
/**
|
|
32040
|
-
* The `rafters_generate`
|
|
32041
|
-
*
|
|
32042
|
-
*
|
|
32043
|
-
*
|
|
32044
|
-
*
|
|
32264
|
+
* The `rafters_generate` handler. A prose query resolves -- first through a
|
|
32265
|
+
* light, deterministic direct-name lookup (tier b), then through the existing
|
|
32266
|
+
* intent door (tier c) -- to a single registry component, and the tool returns
|
|
32267
|
+
* that component's authoritative, target-correct snippet verbatim with its
|
|
32268
|
+
* content slots marked open for the caller. Both tiers re-resolve the winning
|
|
32269
|
+
* id through `describe(id, graph, ctx.target)`, so the response always carries
|
|
32270
|
+
* the workspace target's facet, never the intent door's untargeted fields.
|
|
32271
|
+
* v1 serves components only: composites, parameterization, composition,
|
|
32272
|
+
* writes, and MCP-side validation are all out of scope.
|
|
32045
32273
|
*/
|
|
32046
32274
|
async handleGenerate(intent, workspaceName) {
|
|
32047
32275
|
const resolved = this.resolve(workspaceName);
|
|
32048
32276
|
if (workspaceName && !resolved) {
|
|
32049
32277
|
return this.workspaceRequiredError();
|
|
32050
32278
|
}
|
|
32279
|
+
let graph;
|
|
32280
|
+
try {
|
|
32281
|
+
graph = await this.ensureGraph(resolved);
|
|
32282
|
+
} catch (err) {
|
|
32283
|
+
const message = err instanceof Error ? err.message : "Unknown error";
|
|
32284
|
+
return this.errorResult(`failed to build intel graph: ${message}`);
|
|
32285
|
+
}
|
|
32286
|
+
const ctx = await this.overlayContext(resolved);
|
|
32287
|
+
if ("configError" in ctx) {
|
|
32288
|
+
return this.errorResult(ctx.configError);
|
|
32289
|
+
}
|
|
32290
|
+
const candidate = normalizeGenerateQuery(intent);
|
|
32291
|
+
const directHit = graph.nodes.get(candidate);
|
|
32292
|
+
let nodeId;
|
|
32293
|
+
if (directHit && directHit.kind === "component") {
|
|
32294
|
+
nodeId = candidate;
|
|
32295
|
+
} else {
|
|
32296
|
+
const match = matchIntent(intent, graph);
|
|
32297
|
+
if ("use" in match) nodeId = match.use.id;
|
|
32298
|
+
}
|
|
32299
|
+
if (nodeId === void 0) {
|
|
32300
|
+
return this.errorResult("no registry component matches this query");
|
|
32301
|
+
}
|
|
32302
|
+
const result = describe(nodeId, graph, ctx.target);
|
|
32303
|
+
if (result === null || Array.isArray(result) || !("children" in result)) {
|
|
32304
|
+
return this.errorResult("no registry component matches this query");
|
|
32305
|
+
}
|
|
32306
|
+
const node = result;
|
|
32307
|
+
if (node.kind !== "component") {
|
|
32308
|
+
return this.errorResult(
|
|
32309
|
+
`${node.id} resolved, but is a composite -- rafters_generate v1 returns single components only`
|
|
32310
|
+
);
|
|
32311
|
+
}
|
|
32312
|
+
if (ctx.target === void 0) {
|
|
32313
|
+
return this.errorResult(
|
|
32314
|
+
`${node.id} resolved, but no componentTarget is configured for this workspace -- generate cannot choose a snippet without one`
|
|
32315
|
+
);
|
|
32316
|
+
}
|
|
32317
|
+
if (node.snippet === void 0) {
|
|
32318
|
+
return this.errorResult(
|
|
32319
|
+
`${node.id} resolved, but has no ${ctx.target} facet -- nothing to generate for this target`
|
|
32320
|
+
);
|
|
32321
|
+
}
|
|
32051
32322
|
return this.jsonResult({
|
|
32052
|
-
|
|
32053
|
-
|
|
32323
|
+
component: node.id,
|
|
32324
|
+
target: ctx.target,
|
|
32325
|
+
snippet: node.snippet,
|
|
32326
|
+
slots: (node.slots ?? []).map((slot) => ({
|
|
32327
|
+
slot,
|
|
32328
|
+
ownedBy: "caller",
|
|
32329
|
+
status: "open"
|
|
32330
|
+
}))
|
|
32054
32331
|
});
|
|
32055
32332
|
}
|
|
32056
32333
|
/**
|
|
@@ -32185,6 +32462,9 @@ var RaftersToolHandler = class {
|
|
|
32185
32462
|
});
|
|
32186
32463
|
}
|
|
32187
32464
|
const ctx = await this.overlayContext(resolved);
|
|
32465
|
+
if ("configError" in ctx) {
|
|
32466
|
+
return this.errorResult(ctx.configError, { deprecated: DEPRECATED_MSG });
|
|
32467
|
+
}
|
|
32188
32468
|
const out = describeWithOverlay(id, graph, ctx);
|
|
32189
32469
|
return this.jsonResult(this.withDeprecated(out));
|
|
32190
32470
|
}
|
package/dist/registry/types.d.ts
CHANGED
|
@@ -209,6 +209,7 @@ declare const RegistryItemSchema: z.ZodObject<{
|
|
|
209
209
|
events: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
210
210
|
snippet: z.ZodString;
|
|
211
211
|
}, z.core.$strip>>>;
|
|
212
|
+
parent: z.ZodOptional<z.ZodString>;
|
|
212
213
|
}, z.core.$strip>;
|
|
213
214
|
type RegistryItem = z.infer<typeof RegistryItemSchema>;
|
|
214
215
|
/**
|
package/dist/registry/types.js
CHANGED
|
@@ -67,7 +67,8 @@ var RegistryItemSchema = z.object({
|
|
|
67
67
|
// Per-target facets. zod v4's `z.record(enum, ...)` demands EVERY enum key be
|
|
68
68
|
// present; a component built for only some targets must parse, so this is a
|
|
69
69
|
// partial record (only the built targets appear).
|
|
70
|
-
facets: z.partialRecord(ComponentTargetSchema, FacetSchema).default({})
|
|
70
|
+
facets: z.partialRecord(ComponentTargetSchema, FacetSchema).default({}),
|
|
71
|
+
parent: z.string().optional()
|
|
71
72
|
});
|
|
72
73
|
var RegistryIndexSchema = z.object({
|
|
73
74
|
name: z.string(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rafters",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.85",
|
|
4
4
|
"description": "Design Intelligence CLI. Scaffold tokens, import existing shadcn/Tailwind v4 sources, add components, and serve an MCP server so AI agents read decisions instead of guessing.",
|
|
5
5
|
"homepage": "https://rafters.studio",
|
|
6
6
|
"license": "MIT",
|