@fragments-sdk/context 0.1.3 → 0.2.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/dist/chunk-3FEHRHFQ.js +103 -0
- package/dist/chunk-3VPR67FN.js +76 -0
- package/dist/chunk-HINI3FCI.js +42 -0
- package/dist/chunk-JFV27WLV.js +168 -0
- package/dist/chunk-KKABP4K4.js +228 -0
- package/dist/chunk-KQIRG24U.js +260 -0
- package/dist/chunk-ZMBYQK43.js +91 -0
- package/dist/chunking/index.d.ts +53 -0
- package/dist/chunking/index.js +11 -0
- package/dist/citations/index.d.ts +94 -0
- package/dist/citations/index.js +10 -0
- package/dist/embeddings/voyage.d.ts +44 -0
- package/dist/embeddings/voyage.js +8 -0
- package/dist/generate/index.d.ts +43 -0
- package/dist/generate/index.js +10 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +56 -0
- package/dist/indexing/index.d.ts +52 -0
- package/dist/indexing/index.js +20 -0
- package/dist/search/index.d.ts +29 -0
- package/dist/search/index.js +8 -0
- package/dist/types/index.d.ts +170 -0
- package/dist/types/index.js +0 -0
- package/dist/types-B7duBj6U.d.ts +39 -0
- package/package.json +13 -1
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// src/citations/document-builder.ts
|
|
2
|
+
function buildCitationDocuments(chunks, options) {
|
|
3
|
+
const documents = [];
|
|
4
|
+
const documentMap = [];
|
|
5
|
+
const byFile = /* @__PURE__ */ new Map();
|
|
6
|
+
for (const chunk of chunks) {
|
|
7
|
+
const existing = byFile.get(chunk.filePath);
|
|
8
|
+
if (existing) {
|
|
9
|
+
existing.push(chunk);
|
|
10
|
+
} else {
|
|
11
|
+
byFile.set(chunk.filePath, [chunk]);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
for (const [filePath, fileChunks] of byFile) {
|
|
15
|
+
const docIndex = documents.length;
|
|
16
|
+
const contentBlocks = fileChunks.map((chunk) => ({
|
|
17
|
+
type: "text",
|
|
18
|
+
text: chunk.content
|
|
19
|
+
}));
|
|
20
|
+
const contextLines = fileChunks.map((chunk, i) => {
|
|
21
|
+
const parts = [`Block ${i}: lines ${chunk.startLine}-${chunk.endLine} (${chunk.language})`];
|
|
22
|
+
if (chunk.symbolName) parts.push(`symbol: ${chunk.symbolName}`);
|
|
23
|
+
return parts.join(", ");
|
|
24
|
+
});
|
|
25
|
+
documents.push({
|
|
26
|
+
type: "document",
|
|
27
|
+
source: { type: "content", content: contentBlocks },
|
|
28
|
+
title: filePath,
|
|
29
|
+
context: contextLines.join("\n"),
|
|
30
|
+
citations: { enabled: true }
|
|
31
|
+
});
|
|
32
|
+
documentMap.push({
|
|
33
|
+
documentIndex: docIndex,
|
|
34
|
+
filePath,
|
|
35
|
+
sourceType: "code",
|
|
36
|
+
chunks: fileChunks.map((chunk, i) => ({
|
|
37
|
+
blockIndex: i,
|
|
38
|
+
startLine: chunk.startLine,
|
|
39
|
+
endLine: chunk.endLine,
|
|
40
|
+
language: chunk.language,
|
|
41
|
+
symbolName: chunk.symbolName,
|
|
42
|
+
score: chunk.score
|
|
43
|
+
}))
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
if (options?.additionalDocuments) {
|
|
47
|
+
for (const doc of options.additionalDocuments) {
|
|
48
|
+
if (!doc.content.trim()) continue;
|
|
49
|
+
const docIndex = documents.length;
|
|
50
|
+
documents.push({
|
|
51
|
+
type: "document",
|
|
52
|
+
source: {
|
|
53
|
+
type: "text",
|
|
54
|
+
media_type: "text/plain",
|
|
55
|
+
data: doc.content
|
|
56
|
+
},
|
|
57
|
+
title: doc.title,
|
|
58
|
+
citations: { enabled: true }
|
|
59
|
+
});
|
|
60
|
+
documentMap.push({
|
|
61
|
+
documentIndex: docIndex,
|
|
62
|
+
filePath: doc.title,
|
|
63
|
+
sourceType: "plaintext",
|
|
64
|
+
chunks: []
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return { documents, documentMap };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// src/citations/resolver.ts
|
|
72
|
+
function resolveCitation(raw, documentMap, citationIndex, textOffset) {
|
|
73
|
+
const mapping = documentMap[raw.document_index];
|
|
74
|
+
const base = {
|
|
75
|
+
index: citationIndex,
|
|
76
|
+
citedText: raw.cited_text,
|
|
77
|
+
documentTitle: raw.document_title,
|
|
78
|
+
filePath: mapping?.filePath ?? raw.document_title ?? "unknown",
|
|
79
|
+
sourceType: mapping?.sourceType ?? "plaintext",
|
|
80
|
+
textOffset
|
|
81
|
+
};
|
|
82
|
+
if (raw.type === "content_block_location" && mapping?.sourceType === "code" && raw.start_block_index != null) {
|
|
83
|
+
const chunk = mapping.chunks[raw.start_block_index];
|
|
84
|
+
if (chunk) {
|
|
85
|
+
base.startLine = chunk.startLine;
|
|
86
|
+
base.endLine = chunk.endLine;
|
|
87
|
+
base.language = chunk.language;
|
|
88
|
+
base.symbolName = chunk.symbolName;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return base;
|
|
92
|
+
}
|
|
93
|
+
function resolveCitations(raws, documentMap, textOffsets) {
|
|
94
|
+
return raws.map(
|
|
95
|
+
(raw, i) => resolveCitation(raw, documentMap, i + 1, textOffsets[i] ?? 0)
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export {
|
|
100
|
+
buildCitationDocuments,
|
|
101
|
+
resolveCitation,
|
|
102
|
+
resolveCitations
|
|
103
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// src/embeddings/voyage.ts
|
|
2
|
+
var VOYAGE_EMBEDDINGS_URL = "https://api.voyageai.com/v1/embeddings";
|
|
3
|
+
var VOYAGE_RERANK_URL = "https://api.voyageai.com/v1/rerank";
|
|
4
|
+
var DEFAULT_MODEL = "voyage-code-3";
|
|
5
|
+
var DEFAULT_RERANK_MODEL = "rerank-2.5";
|
|
6
|
+
var DEFAULT_DIMENSIONS = 1024;
|
|
7
|
+
var DEFAULT_MAX_CHARS = 32e3;
|
|
8
|
+
var DEFAULT_BATCH_SIZE = 128;
|
|
9
|
+
async function generateEmbeddings(texts, options) {
|
|
10
|
+
if (texts.length === 0) return [];
|
|
11
|
+
const maxChars = options.maxChars ?? DEFAULT_MAX_CHARS;
|
|
12
|
+
const batchSize = options.batchSize ?? DEFAULT_BATCH_SIZE;
|
|
13
|
+
const dimensions = options.dimensions ?? DEFAULT_DIMENSIONS;
|
|
14
|
+
const truncated = texts.map(
|
|
15
|
+
(t) => t.length > maxChars ? t.slice(0, maxChars) : t
|
|
16
|
+
);
|
|
17
|
+
const results = [];
|
|
18
|
+
for (let i = 0; i < truncated.length; i += batchSize) {
|
|
19
|
+
const batch = truncated.slice(i, i + batchSize);
|
|
20
|
+
const response = await fetch(VOYAGE_EMBEDDINGS_URL, {
|
|
21
|
+
method: "POST",
|
|
22
|
+
headers: {
|
|
23
|
+
"Content-Type": "application/json",
|
|
24
|
+
Authorization: `Bearer ${options.apiKey}`
|
|
25
|
+
},
|
|
26
|
+
body: JSON.stringify({
|
|
27
|
+
model: DEFAULT_MODEL,
|
|
28
|
+
input: batch,
|
|
29
|
+
input_type: options.inputType,
|
|
30
|
+
output_dimension: dimensions
|
|
31
|
+
})
|
|
32
|
+
});
|
|
33
|
+
if (!response.ok) {
|
|
34
|
+
const body = await response.text();
|
|
35
|
+
throw new Error(`Voyage API error ${response.status}: ${body}`);
|
|
36
|
+
}
|
|
37
|
+
const data = await response.json();
|
|
38
|
+
const sorted = data.data.sort((a, b) => a.index - b.index);
|
|
39
|
+
for (const item of sorted) {
|
|
40
|
+
results.push(item.embedding);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return results;
|
|
44
|
+
}
|
|
45
|
+
async function rerankResults(query, documents, options) {
|
|
46
|
+
if (documents.length === 0) return [];
|
|
47
|
+
const topK = options.topK ?? 15;
|
|
48
|
+
const model = options.model ?? DEFAULT_RERANK_MODEL;
|
|
49
|
+
const response = await fetch(VOYAGE_RERANK_URL, {
|
|
50
|
+
method: "POST",
|
|
51
|
+
headers: {
|
|
52
|
+
"Content-Type": "application/json",
|
|
53
|
+
Authorization: `Bearer ${options.apiKey}`
|
|
54
|
+
},
|
|
55
|
+
body: JSON.stringify({
|
|
56
|
+
model,
|
|
57
|
+
query,
|
|
58
|
+
documents,
|
|
59
|
+
top_k: topK
|
|
60
|
+
})
|
|
61
|
+
});
|
|
62
|
+
if (!response.ok) {
|
|
63
|
+
const body = await response.text();
|
|
64
|
+
throw new Error(`Voyage Rerank API error ${response.status}: ${body}`);
|
|
65
|
+
}
|
|
66
|
+
const data = await response.json();
|
|
67
|
+
return data.data.map((item) => ({
|
|
68
|
+
index: item.index,
|
|
69
|
+
relevanceScore: item.relevance_score
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export {
|
|
74
|
+
generateEmbeddings,
|
|
75
|
+
rerankResults
|
|
76
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// src/indexing/hasher.ts
|
|
2
|
+
import { createHash } from "crypto";
|
|
3
|
+
function hashContent(content) {
|
|
4
|
+
return createHash("sha256").update(content, "utf-8").digest("hex");
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
// src/indexing/diff-resolver.ts
|
|
8
|
+
function resolveChanges(oldEntries, newEntries) {
|
|
9
|
+
const oldMap = /* @__PURE__ */ new Map();
|
|
10
|
+
for (const entry of oldEntries) {
|
|
11
|
+
oldMap.set(entry.filePath, entry);
|
|
12
|
+
}
|
|
13
|
+
const newMap = /* @__PURE__ */ new Map();
|
|
14
|
+
for (const entry of newEntries) {
|
|
15
|
+
newMap.set(entry.filePath, entry);
|
|
16
|
+
}
|
|
17
|
+
const added = [];
|
|
18
|
+
const modified = [];
|
|
19
|
+
const unchanged = [];
|
|
20
|
+
const deleted = [];
|
|
21
|
+
for (const [filePath, newEntry] of newMap) {
|
|
22
|
+
const oldEntry = oldMap.get(filePath);
|
|
23
|
+
if (!oldEntry) {
|
|
24
|
+
added.push(filePath);
|
|
25
|
+
} else if (oldEntry.contentHash !== newEntry.contentHash) {
|
|
26
|
+
modified.push(filePath);
|
|
27
|
+
} else {
|
|
28
|
+
unchanged.push(filePath);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
for (const filePath of oldMap.keys()) {
|
|
32
|
+
if (!newMap.has(filePath)) {
|
|
33
|
+
deleted.push(filePath);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return { added, modified, deleted, unchanged };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export {
|
|
40
|
+
hashContent,
|
|
41
|
+
resolveChanges
|
|
42
|
+
};
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
// src/indexing/file-filter.ts
|
|
2
|
+
var INDEXABLE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
3
|
+
".ts",
|
|
4
|
+
".tsx",
|
|
5
|
+
".js",
|
|
6
|
+
".jsx",
|
|
7
|
+
".mjs",
|
|
8
|
+
".cjs",
|
|
9
|
+
".py",
|
|
10
|
+
".go",
|
|
11
|
+
".rs",
|
|
12
|
+
".java",
|
|
13
|
+
".kt",
|
|
14
|
+
".swift",
|
|
15
|
+
".c",
|
|
16
|
+
".cpp",
|
|
17
|
+
".h",
|
|
18
|
+
".hpp",
|
|
19
|
+
".cs",
|
|
20
|
+
".rb",
|
|
21
|
+
".php",
|
|
22
|
+
".scala",
|
|
23
|
+
".sh",
|
|
24
|
+
".bash",
|
|
25
|
+
".zsh",
|
|
26
|
+
".sql",
|
|
27
|
+
".graphql",
|
|
28
|
+
".gql",
|
|
29
|
+
".css",
|
|
30
|
+
".scss",
|
|
31
|
+
".less",
|
|
32
|
+
".html",
|
|
33
|
+
".svelte",
|
|
34
|
+
".vue",
|
|
35
|
+
".md",
|
|
36
|
+
".mdx",
|
|
37
|
+
".json",
|
|
38
|
+
".yaml",
|
|
39
|
+
".yml",
|
|
40
|
+
".toml",
|
|
41
|
+
".xml",
|
|
42
|
+
".proto",
|
|
43
|
+
".tf",
|
|
44
|
+
".hcl",
|
|
45
|
+
".dockerfile",
|
|
46
|
+
".prisma"
|
|
47
|
+
]);
|
|
48
|
+
var IGNORED_DIRS = [
|
|
49
|
+
"node_modules/",
|
|
50
|
+
"dist/",
|
|
51
|
+
".git/",
|
|
52
|
+
".next/",
|
|
53
|
+
"__pycache__/",
|
|
54
|
+
".cache/",
|
|
55
|
+
"coverage/",
|
|
56
|
+
"build/",
|
|
57
|
+
".turbo/",
|
|
58
|
+
"vendor/",
|
|
59
|
+
".venv/"
|
|
60
|
+
];
|
|
61
|
+
var IGNORED_FILES = [
|
|
62
|
+
"pnpm-lock.yaml",
|
|
63
|
+
"package-lock.json",
|
|
64
|
+
"yarn.lock",
|
|
65
|
+
"bun.lockb",
|
|
66
|
+
"Cargo.lock",
|
|
67
|
+
"go.sum",
|
|
68
|
+
"poetry.lock",
|
|
69
|
+
"Pipfile.lock",
|
|
70
|
+
"composer.lock",
|
|
71
|
+
"Gemfile.lock"
|
|
72
|
+
];
|
|
73
|
+
var MAX_FILE_SIZE = 100 * 1024;
|
|
74
|
+
function shouldIndexFile(path, size) {
|
|
75
|
+
if (size > MAX_FILE_SIZE) return false;
|
|
76
|
+
if (IGNORED_FILES.includes(path.split("/").pop() ?? "")) return false;
|
|
77
|
+
for (const dir of IGNORED_DIRS) {
|
|
78
|
+
if (path.includes(dir)) return false;
|
|
79
|
+
}
|
|
80
|
+
const ext = getExtension(path);
|
|
81
|
+
if (!ext) {
|
|
82
|
+
const basename = path.split("/").pop() ?? "";
|
|
83
|
+
return basename === "Dockerfile" || basename === "Makefile";
|
|
84
|
+
}
|
|
85
|
+
return INDEXABLE_EXTENSIONS.has(ext);
|
|
86
|
+
}
|
|
87
|
+
var LANGUAGE_MAP = {
|
|
88
|
+
".ts": { language: "typescript", grammar: "typescript" },
|
|
89
|
+
".tsx": { language: "typescript", grammar: "tsx" },
|
|
90
|
+
".js": { language: "javascript", grammar: "javascript" },
|
|
91
|
+
".jsx": { language: "javascript", grammar: "javascript" },
|
|
92
|
+
".mjs": { language: "javascript", grammar: "javascript" },
|
|
93
|
+
".cjs": { language: "javascript", grammar: "javascript" },
|
|
94
|
+
".py": { language: "python", grammar: "python" },
|
|
95
|
+
".go": { language: "go", grammar: "go" },
|
|
96
|
+
".rs": { language: "rust", grammar: "rust" },
|
|
97
|
+
".java": { language: "java", grammar: "java" },
|
|
98
|
+
".kt": { language: "kotlin", grammar: "" },
|
|
99
|
+
".swift": { language: "swift", grammar: "" },
|
|
100
|
+
".c": { language: "c", grammar: "" },
|
|
101
|
+
".cpp": { language: "cpp", grammar: "" },
|
|
102
|
+
".h": { language: "c", grammar: "" },
|
|
103
|
+
".hpp": { language: "cpp", grammar: "" },
|
|
104
|
+
".cs": { language: "csharp", grammar: "" },
|
|
105
|
+
".rb": { language: "ruby", grammar: "" },
|
|
106
|
+
".php": { language: "php", grammar: "" },
|
|
107
|
+
".scala": { language: "scala", grammar: "" },
|
|
108
|
+
".sh": { language: "shell", grammar: "" },
|
|
109
|
+
".bash": { language: "shell", grammar: "" },
|
|
110
|
+
".zsh": { language: "shell", grammar: "" },
|
|
111
|
+
".sql": { language: "sql", grammar: "" },
|
|
112
|
+
".graphql": { language: "graphql", grammar: "" },
|
|
113
|
+
".gql": { language: "graphql", grammar: "" },
|
|
114
|
+
".css": { language: "css", grammar: "" },
|
|
115
|
+
".scss": { language: "scss", grammar: "" },
|
|
116
|
+
".less": { language: "less", grammar: "" },
|
|
117
|
+
".html": { language: "html", grammar: "" },
|
|
118
|
+
".svelte": { language: "svelte", grammar: "" },
|
|
119
|
+
".vue": { language: "vue", grammar: "" },
|
|
120
|
+
".md": { language: "markdown", grammar: "" },
|
|
121
|
+
".mdx": { language: "markdown", grammar: "" },
|
|
122
|
+
".json": { language: "json", grammar: "" },
|
|
123
|
+
".yaml": { language: "yaml", grammar: "" },
|
|
124
|
+
".yml": { language: "yaml", grammar: "" },
|
|
125
|
+
".toml": { language: "toml", grammar: "" },
|
|
126
|
+
".xml": { language: "xml", grammar: "" },
|
|
127
|
+
".proto": { language: "protobuf", grammar: "" },
|
|
128
|
+
".tf": { language: "terraform", grammar: "" },
|
|
129
|
+
".hcl": { language: "hcl", grammar: "" },
|
|
130
|
+
".dockerfile": { language: "dockerfile", grammar: "" },
|
|
131
|
+
".prisma": { language: "prisma", grammar: "" }
|
|
132
|
+
};
|
|
133
|
+
var AST_SUPPORTED_LANGUAGES = /* @__PURE__ */ new Set([
|
|
134
|
+
"typescript",
|
|
135
|
+
"tsx",
|
|
136
|
+
"javascript",
|
|
137
|
+
"python",
|
|
138
|
+
"go",
|
|
139
|
+
"rust",
|
|
140
|
+
"java"
|
|
141
|
+
]);
|
|
142
|
+
function detectLanguage(path) {
|
|
143
|
+
const ext = getExtension(path);
|
|
144
|
+
if (ext && ext in LANGUAGE_MAP) return LANGUAGE_MAP[ext].language;
|
|
145
|
+
const basename = path.split("/").pop() ?? "";
|
|
146
|
+
if (basename === "Dockerfile") return "dockerfile";
|
|
147
|
+
if (basename === "Makefile") return "makefile";
|
|
148
|
+
return "unknown";
|
|
149
|
+
}
|
|
150
|
+
function getTreeSitterGrammar(path) {
|
|
151
|
+
const ext = getExtension(path);
|
|
152
|
+
if (ext && ext in LANGUAGE_MAP) return LANGUAGE_MAP[ext].grammar;
|
|
153
|
+
return "";
|
|
154
|
+
}
|
|
155
|
+
function getExtension(path) {
|
|
156
|
+
const basename = path.split("/").pop() ?? "";
|
|
157
|
+
const dotIdx = basename.lastIndexOf(".");
|
|
158
|
+
if (dotIdx <= 0) return "";
|
|
159
|
+
return basename.slice(dotIdx).toLowerCase();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export {
|
|
163
|
+
INDEXABLE_EXTENSIONS,
|
|
164
|
+
shouldIndexFile,
|
|
165
|
+
AST_SUPPORTED_LANGUAGES,
|
|
166
|
+
detectLanguage,
|
|
167
|
+
getTreeSitterGrammar
|
|
168
|
+
};
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
// src/generate/index.ts
|
|
2
|
+
var PLACEHOLDER_PATTERNS = [
|
|
3
|
+
/^\w+ component is needed$/i,
|
|
4
|
+
/^Alternative component is more appropriate$/i,
|
|
5
|
+
/^Use \w+ when you need/i
|
|
6
|
+
];
|
|
7
|
+
function filterPlaceholders(items) {
|
|
8
|
+
if (!items) return [];
|
|
9
|
+
return items.filter(
|
|
10
|
+
(item) => !PLACEHOLDER_PATTERNS.some((pattern) => pattern.test(item.trim()))
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
function generateContext(segments, options = {}, blocks) {
|
|
14
|
+
const format = options.format ?? "markdown";
|
|
15
|
+
const compact = options.compact ?? false;
|
|
16
|
+
const include = {
|
|
17
|
+
props: options.include?.props ?? true,
|
|
18
|
+
variants: options.include?.variants ?? true,
|
|
19
|
+
usage: options.include?.usage ?? true,
|
|
20
|
+
relations: options.include?.relations ?? false,
|
|
21
|
+
code: options.include?.code ?? false
|
|
22
|
+
};
|
|
23
|
+
const sorted = [...segments].sort((a, b) => {
|
|
24
|
+
const catCompare = a.meta.category.localeCompare(b.meta.category);
|
|
25
|
+
if (catCompare !== 0) return catCompare;
|
|
26
|
+
return a.meta.name.localeCompare(b.meta.name);
|
|
27
|
+
});
|
|
28
|
+
if (format === "json") {
|
|
29
|
+
return generateJsonContext(sorted, include, compact, blocks);
|
|
30
|
+
}
|
|
31
|
+
return generateMarkdownContext(sorted, include, compact, blocks);
|
|
32
|
+
}
|
|
33
|
+
function generateMarkdownContext(segments, include, compact, blocks) {
|
|
34
|
+
const lines = [];
|
|
35
|
+
lines.push("# Design System Reference");
|
|
36
|
+
lines.push("");
|
|
37
|
+
lines.push("## Quick Reference");
|
|
38
|
+
lines.push("");
|
|
39
|
+
lines.push("| Component | Category | Use For |");
|
|
40
|
+
lines.push("|-----------|----------|---------|");
|
|
41
|
+
for (const segment of segments) {
|
|
42
|
+
const filteredWhen = filterPlaceholders(segment.usage.when);
|
|
43
|
+
const useFor = filteredWhen.slice(0, 2).join(", ") || segment.meta.description;
|
|
44
|
+
lines.push(`| ${segment.meta.name} | ${segment.meta.category} | ${truncate(useFor, 50)} |`);
|
|
45
|
+
}
|
|
46
|
+
lines.push("");
|
|
47
|
+
if (compact) {
|
|
48
|
+
const content2 = lines.join("\n");
|
|
49
|
+
return { content: content2, tokenEstimate: estimateTokens(content2) };
|
|
50
|
+
}
|
|
51
|
+
lines.push("## Components");
|
|
52
|
+
lines.push("");
|
|
53
|
+
for (const segment of segments) {
|
|
54
|
+
lines.push(`### ${segment.meta.name}`);
|
|
55
|
+
lines.push("");
|
|
56
|
+
const statusParts = [`**Category:** ${segment.meta.category}`];
|
|
57
|
+
if (segment.meta.status) {
|
|
58
|
+
statusParts.push(`**Status:** ${segment.meta.status}`);
|
|
59
|
+
}
|
|
60
|
+
lines.push(statusParts.join(" | "));
|
|
61
|
+
lines.push("");
|
|
62
|
+
if (segment.meta.description) {
|
|
63
|
+
lines.push(segment.meta.description);
|
|
64
|
+
lines.push("");
|
|
65
|
+
}
|
|
66
|
+
const whenFiltered = filterPlaceholders(segment.usage.when);
|
|
67
|
+
const whenNotFiltered = filterPlaceholders(segment.usage.whenNot);
|
|
68
|
+
if (include.usage && (whenFiltered.length > 0 || whenNotFiltered.length > 0)) {
|
|
69
|
+
if (whenFiltered.length > 0) {
|
|
70
|
+
lines.push("**When to use:**");
|
|
71
|
+
for (const when of whenFiltered) {
|
|
72
|
+
lines.push(`- ${when}`);
|
|
73
|
+
}
|
|
74
|
+
lines.push("");
|
|
75
|
+
}
|
|
76
|
+
if (whenNotFiltered.length > 0) {
|
|
77
|
+
lines.push("**When NOT to use:**");
|
|
78
|
+
for (const whenNot of whenNotFiltered) {
|
|
79
|
+
lines.push(`- ${whenNot}`);
|
|
80
|
+
}
|
|
81
|
+
lines.push("");
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (include.props && Object.keys(segment.props).length > 0) {
|
|
85
|
+
lines.push("**Props:**");
|
|
86
|
+
for (const [name, prop] of Object.entries(segment.props)) {
|
|
87
|
+
lines.push(`- \`${name}\`: ${formatPropType(prop)}${prop.required ? " (required)" : ""}`);
|
|
88
|
+
}
|
|
89
|
+
lines.push("");
|
|
90
|
+
}
|
|
91
|
+
if (include.variants && segment.variants.length > 0) {
|
|
92
|
+
const variantNames = segment.variants.map((v) => v.name).join(", ");
|
|
93
|
+
lines.push(`**Variants:** ${variantNames}`);
|
|
94
|
+
lines.push("");
|
|
95
|
+
if (include.code) {
|
|
96
|
+
for (const variant of segment.variants) {
|
|
97
|
+
if (variant.code) {
|
|
98
|
+
lines.push(`*${variant.name}:*`);
|
|
99
|
+
lines.push("```tsx");
|
|
100
|
+
lines.push(variant.code);
|
|
101
|
+
lines.push("```");
|
|
102
|
+
lines.push("");
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (include.relations && segment.relations && segment.relations.length > 0) {
|
|
108
|
+
lines.push("**Related:**");
|
|
109
|
+
for (const relation of segment.relations) {
|
|
110
|
+
lines.push(`- ${relation.component} (${relation.relationship}): ${relation.note}`);
|
|
111
|
+
}
|
|
112
|
+
lines.push("");
|
|
113
|
+
}
|
|
114
|
+
lines.push("---");
|
|
115
|
+
lines.push("");
|
|
116
|
+
}
|
|
117
|
+
if (blocks && blocks.length > 0) {
|
|
118
|
+
lines.push("## Blocks");
|
|
119
|
+
lines.push("");
|
|
120
|
+
lines.push("Composition patterns showing how components wire together.");
|
|
121
|
+
lines.push("");
|
|
122
|
+
for (const block of blocks) {
|
|
123
|
+
lines.push(`### ${block.name}`);
|
|
124
|
+
lines.push("");
|
|
125
|
+
lines.push(block.description);
|
|
126
|
+
lines.push("");
|
|
127
|
+
lines.push(`**Category:** ${block.category}`);
|
|
128
|
+
lines.push(`**Components:** ${block.components.join(", ")}`);
|
|
129
|
+
if (block.tags && block.tags.length > 0) {
|
|
130
|
+
lines.push(`**Tags:** ${block.tags.join(", ")}`);
|
|
131
|
+
}
|
|
132
|
+
lines.push("");
|
|
133
|
+
lines.push("```tsx");
|
|
134
|
+
lines.push(block.code);
|
|
135
|
+
lines.push("```");
|
|
136
|
+
lines.push("");
|
|
137
|
+
lines.push("---");
|
|
138
|
+
lines.push("");
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const content = lines.join("\n");
|
|
142
|
+
return { content, tokenEstimate: estimateTokens(content) };
|
|
143
|
+
}
|
|
144
|
+
function generateJsonContext(segments, include, compact, blocks) {
|
|
145
|
+
const categories = [...new Set(segments.map((s) => s.meta.category))].sort();
|
|
146
|
+
const components = {};
|
|
147
|
+
for (const segment of segments) {
|
|
148
|
+
const component = {
|
|
149
|
+
category: segment.meta.category,
|
|
150
|
+
description: segment.meta.description
|
|
151
|
+
};
|
|
152
|
+
if (segment.meta.status) {
|
|
153
|
+
component.status = segment.meta.status;
|
|
154
|
+
}
|
|
155
|
+
if (!compact) {
|
|
156
|
+
if (include.usage) {
|
|
157
|
+
const whenFiltered = filterPlaceholders(segment.usage.when);
|
|
158
|
+
const whenNotFiltered = filterPlaceholders(segment.usage.whenNot);
|
|
159
|
+
if (whenFiltered.length > 0) component.whenToUse = whenFiltered;
|
|
160
|
+
if (whenNotFiltered.length > 0) component.whenNotToUse = whenNotFiltered;
|
|
161
|
+
}
|
|
162
|
+
if (include.props && Object.keys(segment.props).length > 0) {
|
|
163
|
+
component.props = {};
|
|
164
|
+
for (const [name, prop] of Object.entries(segment.props)) {
|
|
165
|
+
component.props[name] = {
|
|
166
|
+
type: formatPropType(prop),
|
|
167
|
+
description: prop.description
|
|
168
|
+
};
|
|
169
|
+
if (prop.required) component.props[name].required = true;
|
|
170
|
+
if (prop.default !== void 0) component.props[name].default = prop.default;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (include.variants && segment.variants.length > 0) {
|
|
174
|
+
component.variants = segment.variants.map((v) => v.name);
|
|
175
|
+
}
|
|
176
|
+
if (include.relations && segment.relations && segment.relations.length > 0) {
|
|
177
|
+
component.relations = segment.relations.map((r) => ({
|
|
178
|
+
component: r.component,
|
|
179
|
+
relationship: r.relationship,
|
|
180
|
+
note: r.note
|
|
181
|
+
}));
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
components[segment.meta.name] = component;
|
|
185
|
+
}
|
|
186
|
+
const blocksMap = blocks && blocks.length > 0 ? Object.fromEntries(blocks.map((b) => [b.name, {
|
|
187
|
+
description: b.description,
|
|
188
|
+
category: b.category,
|
|
189
|
+
components: b.components,
|
|
190
|
+
code: b.code,
|
|
191
|
+
tags: b.tags
|
|
192
|
+
}])) : void 0;
|
|
193
|
+
const output = {
|
|
194
|
+
version: "1.0",
|
|
195
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
196
|
+
summary: {
|
|
197
|
+
totalComponents: segments.length,
|
|
198
|
+
categories,
|
|
199
|
+
...blocksMap && { totalBlocks: blocks.length }
|
|
200
|
+
},
|
|
201
|
+
components,
|
|
202
|
+
...blocksMap && { blocks: blocksMap }
|
|
203
|
+
};
|
|
204
|
+
const content = JSON.stringify(output, null, 2);
|
|
205
|
+
return { content, tokenEstimate: estimateTokens(content) };
|
|
206
|
+
}
|
|
207
|
+
function formatPropType(prop) {
|
|
208
|
+
if (prop.type === "enum" && prop.values) {
|
|
209
|
+
return prop.values.map((v) => `"${v}"`).join(" | ");
|
|
210
|
+
}
|
|
211
|
+
if (prop.default !== void 0) {
|
|
212
|
+
return `${prop.type} (default: ${JSON.stringify(prop.default)})`;
|
|
213
|
+
}
|
|
214
|
+
return prop.type;
|
|
215
|
+
}
|
|
216
|
+
function truncate(str, maxLength) {
|
|
217
|
+
if (str.length <= maxLength) return str;
|
|
218
|
+
return str.slice(0, maxLength - 3) + "...";
|
|
219
|
+
}
|
|
220
|
+
function estimateTokens(text) {
|
|
221
|
+
return Math.ceil(text.length / 4);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export {
|
|
225
|
+
PLACEHOLDER_PATTERNS,
|
|
226
|
+
filterPlaceholders,
|
|
227
|
+
generateContext
|
|
228
|
+
};
|