@gemini-designer/mcp-server 0.1.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/.prettierrc +9 -0
- package/dist/components/catalog.d.ts +24 -0
- package/dist/components/catalog.d.ts.map +1 -0
- package/dist/components/catalog.js +186 -0
- package/dist/components/catalog.js.map +1 -0
- package/dist/config/index.d.ts +60 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +199 -0
- package/dist/config/index.js.map +1 -0
- package/dist/context/builder.d.ts +32 -0
- package/dist/context/builder.d.ts.map +1 -0
- package/dist/context/builder.js +194 -0
- package/dist/context/builder.js.map +1 -0
- package/dist/context/filter.d.ts +28 -0
- package/dist/context/filter.d.ts.map +1 -0
- package/dist/context/filter.js +136 -0
- package/dist/context/filter.js.map +1 -0
- package/dist/context/grounding.d.ts +27 -0
- package/dist/context/grounding.d.ts.map +1 -0
- package/dist/context/grounding.js +162 -0
- package/dist/context/grounding.js.map +1 -0
- package/dist/context/guards.d.ts +31 -0
- package/dist/context/guards.d.ts.map +1 -0
- package/dist/context/guards.js +76 -0
- package/dist/context/guards.js.map +1 -0
- package/dist/context/repo-hints.d.ts +12 -0
- package/dist/context/repo-hints.d.ts.map +1 -0
- package/dist/context/repo-hints.js +40 -0
- package/dist/context/repo-hints.js.map +1 -0
- package/dist/generation/gemini-client.d.ts +27 -0
- package/dist/generation/gemini-client.d.ts.map +1 -0
- package/dist/generation/gemini-client.js +64 -0
- package/dist/generation/gemini-client.js.map +1 -0
- package/dist/generation/litellm-client.d.ts +16 -0
- package/dist/generation/litellm-client.d.ts.map +1 -0
- package/dist/generation/litellm-client.js +98 -0
- package/dist/generation/litellm-client.js.map +1 -0
- package/dist/generation/remote-client.d.ts +20 -0
- package/dist/generation/remote-client.d.ts.map +1 -0
- package/dist/generation/remote-client.js +69 -0
- package/dist/generation/remote-client.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/output/file-writer.d.ts +39 -0
- package/dist/output/file-writer.d.ts.map +1 -0
- package/dist/output/file-writer.js +153 -0
- package/dist/output/file-writer.js.map +1 -0
- package/dist/output/formatter.d.ts +26 -0
- package/dist/output/formatter.d.ts.map +1 -0
- package/dist/output/formatter.js +156 -0
- package/dist/output/formatter.js.map +1 -0
- package/dist/server.d.ts +9 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +22 -0
- package/dist/server.js.map +1 -0
- package/dist/stack/detect.d.ts +49 -0
- package/dist/stack/detect.d.ts.map +1 -0
- package/dist/stack/detect.js +157 -0
- package/dist/stack/detect.js.map +1 -0
- package/dist/tokens/sync.d.ts +32 -0
- package/dist/tokens/sync.d.ts.map +1 -0
- package/dist/tokens/sync.js +188 -0
- package/dist/tokens/sync.js.map +1 -0
- package/dist/tools/analyze-screenshot-ui.d.ts +18 -0
- package/dist/tools/analyze-screenshot-ui.d.ts.map +1 -0
- package/dist/tools/analyze-screenshot-ui.js +133 -0
- package/dist/tools/analyze-screenshot-ui.js.map +1 -0
- package/dist/tools/analyze-tokens.d.ts +10 -0
- package/dist/tools/analyze-tokens.d.ts.map +1 -0
- package/dist/tools/analyze-tokens.js +107 -0
- package/dist/tools/analyze-tokens.js.map +1 -0
- package/dist/tools/catalog-components.d.ts +14 -0
- package/dist/tools/catalog-components.d.ts.map +1 -0
- package/dist/tools/catalog-components.js +85 -0
- package/dist/tools/catalog-components.js.map +1 -0
- package/dist/tools/create-ui.d.ts +10 -0
- package/dist/tools/create-ui.d.ts.map +1 -0
- package/dist/tools/create-ui.js +167 -0
- package/dist/tools/create-ui.js.map +1 -0
- package/dist/tools/detect-ui-stack.d.ts +15 -0
- package/dist/tools/detect-ui-stack.d.ts.map +1 -0
- package/dist/tools/detect-ui-stack.js +52 -0
- package/dist/tools/detect-ui-stack.js.map +1 -0
- package/dist/tools/generate-component-variants.d.ts +15 -0
- package/dist/tools/generate-component-variants.d.ts.map +1 -0
- package/dist/tools/generate-component-variants.js +199 -0
- package/dist/tools/generate-component-variants.js.map +1 -0
- package/dist/tools/generate-vibes.d.ts +10 -0
- package/dist/tools/generate-vibes.d.ts.map +1 -0
- package/dist/tools/generate-vibes.js +145 -0
- package/dist/tools/generate-vibes.js.map +1 -0
- package/dist/tools/index.d.ts +12 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +36 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/modify-ui.d.ts +11 -0
- package/dist/tools/modify-ui.d.ts.map +1 -0
- package/dist/tools/modify-ui.js +207 -0
- package/dist/tools/modify-ui.js.map +1 -0
- package/dist/tools/scaffold-project.d.ts +10 -0
- package/dist/tools/scaffold-project.d.ts.map +1 -0
- package/dist/tools/scaffold-project.js +122 -0
- package/dist/tools/scaffold-project.js.map +1 -0
- package/dist/tools/snippet-ui.d.ts +11 -0
- package/dist/tools/snippet-ui.d.ts.map +1 -0
- package/dist/tools/snippet-ui.js +194 -0
- package/dist/tools/snippet-ui.js.map +1 -0
- package/dist/tools/sync-design-tokens.d.ts +14 -0
- package/dist/tools/sync-design-tokens.d.ts.map +1 -0
- package/dist/tools/sync-design-tokens.js +233 -0
- package/dist/tools/sync-design-tokens.js.map +1 -0
- package/dist/utils/walk.d.ts +15 -0
- package/dist/utils/walk.d.ts.map +1 -0
- package/dist/utils/walk.js +63 -0
- package/dist/utils/walk.js.map +1 -0
- package/eslint.config.js +37 -0
- package/package.json +56 -0
- package/src/__tests__/builder.test.ts +31 -0
- package/src/__tests__/config.test.ts +52 -0
- package/src/__tests__/filter.test.ts +109 -0
- package/src/components/catalog.ts +214 -0
- package/src/config/index.ts +237 -0
- package/src/context/builder.ts +233 -0
- package/src/context/filter.ts +164 -0
- package/src/context/grounding.ts +191 -0
- package/src/context/guards.ts +94 -0
- package/src/context/repo-hints.ts +43 -0
- package/src/generation/gemini-client.ts +94 -0
- package/src/generation/litellm-client.ts +121 -0
- package/src/generation/remote-client.ts +103 -0
- package/src/index.ts +36 -0
- package/src/output/file-writer.ts +181 -0
- package/src/output/formatter.ts +186 -0
- package/src/server.ts +28 -0
- package/src/stack/detect.ts +204 -0
- package/src/tokens/sync.ts +212 -0
- package/src/tools/analyze-screenshot-ui.ts +150 -0
- package/src/tools/analyze-tokens.ts +123 -0
- package/src/tools/catalog-components.ts +99 -0
- package/src/tools/create-ui.ts +194 -0
- package/src/tools/detect-ui-stack.ts +64 -0
- package/src/tools/generate-component-variants.ts +218 -0
- package/src/tools/generate-vibes.ts +177 -0
- package/src/tools/index.ts +42 -0
- package/src/tools/modify-ui.ts +230 -0
- package/src/tools/scaffold-project.ts +138 -0
- package/src/tools/snippet-ui.ts +222 -0
- package/src/tools/sync-design-tokens.ts +256 -0
- package/src/utils/walk.ts +75 -0
- package/tsconfig.json +34 -0
- package/vitest.config.ts +15 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Builder
|
|
3
|
+
*
|
|
4
|
+
* Builds token-optimized context from specified files.
|
|
5
|
+
* Filters out sensitive content and optimizes for relevance.
|
|
6
|
+
* Includes token counting for quota management.
|
|
7
|
+
*/
|
|
8
|
+
import * as fs from 'node:fs';
|
|
9
|
+
import * as path from 'node:path';
|
|
10
|
+
import { isPathAllowed, isSensitiveFile, sanitizeContent } from './filter.js';
|
|
11
|
+
// Token estimation: ~4 characters per token for English text/code
|
|
12
|
+
const CHARS_PER_TOKEN = 4;
|
|
13
|
+
const MAX_CONTEXT_TOKENS = 12500; // ~50k chars
|
|
14
|
+
const MAX_FILE_TOKENS = 2500; // ~10k chars per file
|
|
15
|
+
/**
|
|
16
|
+
* Estimate token count from text
|
|
17
|
+
*/
|
|
18
|
+
export function estimateTokens(text) {
|
|
19
|
+
return Math.ceil(text.length / CHARS_PER_TOKEN);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Build context from specified file paths with token optimization
|
|
23
|
+
*/
|
|
24
|
+
export async function buildContext(paths, config) {
|
|
25
|
+
const result = await buildContextWithMetadata(paths, config);
|
|
26
|
+
return result.content;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Build context with full metadata (tokens, files included, etc.)
|
|
30
|
+
*/
|
|
31
|
+
export async function buildContextWithMetadata(paths, config) {
|
|
32
|
+
const contents = [];
|
|
33
|
+
const filesIncluded = [];
|
|
34
|
+
const filesSkipped = [];
|
|
35
|
+
let totalTokens = 0;
|
|
36
|
+
let truncated = false;
|
|
37
|
+
// Sort paths by likely relevance (design tokens first, then components)
|
|
38
|
+
const sortedPaths = sortByRelevance(paths);
|
|
39
|
+
for (const filePath of sortedPaths) {
|
|
40
|
+
// Resolve to absolute path
|
|
41
|
+
const absPath = path.isAbsolute(filePath) ? filePath : path.resolve(process.cwd(), filePath);
|
|
42
|
+
// Security check: path must be in allowed paths
|
|
43
|
+
if (!isPathAllowed(absPath, config.allowedPaths)) {
|
|
44
|
+
if (config.debug) {
|
|
45
|
+
console.error(`[context] Skipping ${filePath}: outside allowed paths`);
|
|
46
|
+
}
|
|
47
|
+
filesSkipped.push(`${filePath} (outside allowed paths)`);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
// Security check: not a sensitive file
|
|
51
|
+
if (isSensitiveFile(absPath)) {
|
|
52
|
+
if (config.debug) {
|
|
53
|
+
console.error(`[context] Skipping ${filePath}: sensitive file`);
|
|
54
|
+
}
|
|
55
|
+
filesSkipped.push(`${filePath} (sensitive)`);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
// Check if file exists and is a file
|
|
59
|
+
if (!fs.existsSync(absPath)) {
|
|
60
|
+
filesSkipped.push(`${filePath} (not found)`);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const stat = fs.statSync(absPath);
|
|
64
|
+
if (!stat.isFile()) {
|
|
65
|
+
filesSkipped.push(`${filePath} (not a file)`);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
let content = fs.readFileSync(absPath, 'utf-8');
|
|
70
|
+
// Sanitize content to remove any secrets
|
|
71
|
+
content = sanitizeContent(content);
|
|
72
|
+
// Calculate tokens for this file
|
|
73
|
+
let fileTokens = estimateTokens(content);
|
|
74
|
+
const maxFileChars = MAX_FILE_TOKENS * CHARS_PER_TOKEN;
|
|
75
|
+
// Truncate large files
|
|
76
|
+
if (fileTokens > MAX_FILE_TOKENS) {
|
|
77
|
+
content = smartTruncate(content, maxFileChars);
|
|
78
|
+
fileTokens = MAX_FILE_TOKENS;
|
|
79
|
+
}
|
|
80
|
+
// Check if adding this would exceed total limit
|
|
81
|
+
if (totalTokens + fileTokens > MAX_CONTEXT_TOKENS) {
|
|
82
|
+
if (config.debug) {
|
|
83
|
+
console.error(`[context] Stopping: token limit reached`);
|
|
84
|
+
}
|
|
85
|
+
truncated = true;
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
const ext = path.extname(absPath);
|
|
89
|
+
const header = `/* File: ${path.basename(absPath)} (${ext}) - ~${fileTokens} tokens */`;
|
|
90
|
+
contents.push(`${header}\n${content}`);
|
|
91
|
+
filesIncluded.push(filePath);
|
|
92
|
+
totalTokens += fileTokens;
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
if (config.debug) {
|
|
96
|
+
console.error(`[context] Error reading ${filePath}:`, error);
|
|
97
|
+
}
|
|
98
|
+
filesSkipped.push(`${filePath} (read error)`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
content: contents.length > 0 ? contents.join('\n\n---\n\n') : '',
|
|
103
|
+
estimatedTokens: totalTokens,
|
|
104
|
+
filesIncluded,
|
|
105
|
+
filesSkipped,
|
|
106
|
+
truncated,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Sort paths by relevance (design tokens and variables first)
|
|
111
|
+
*/
|
|
112
|
+
function sortByRelevance(paths) {
|
|
113
|
+
const priority = {
|
|
114
|
+
tokens: 0,
|
|
115
|
+
variables: 0,
|
|
116
|
+
theme: 1,
|
|
117
|
+
design: 1,
|
|
118
|
+
colors: 2,
|
|
119
|
+
typography: 2,
|
|
120
|
+
styles: 3,
|
|
121
|
+
css: 4,
|
|
122
|
+
};
|
|
123
|
+
return [...paths].sort((a, b) => {
|
|
124
|
+
const aName = path.basename(a).toLowerCase();
|
|
125
|
+
const bName = path.basename(b).toLowerCase();
|
|
126
|
+
let aPriority = 10;
|
|
127
|
+
let bPriority = 10;
|
|
128
|
+
for (const [key, value] of Object.entries(priority)) {
|
|
129
|
+
if (aName.includes(key))
|
|
130
|
+
aPriority = Math.min(aPriority, value);
|
|
131
|
+
if (bName.includes(key))
|
|
132
|
+
bPriority = Math.min(bPriority, value);
|
|
133
|
+
}
|
|
134
|
+
return aPriority - bPriority;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Smart truncate: keep beginning and end, with clear indicator
|
|
139
|
+
*/
|
|
140
|
+
function smartTruncate(content, maxChars) {
|
|
141
|
+
if (content.length <= maxChars)
|
|
142
|
+
return content;
|
|
143
|
+
const keepStart = Math.floor(maxChars * 0.7);
|
|
144
|
+
const keepEnd = Math.floor(maxChars * 0.2);
|
|
145
|
+
const start = content.slice(0, keepStart);
|
|
146
|
+
const end = content.slice(-keepEnd);
|
|
147
|
+
return `${start}\n\n/* ... [${Math.round((content.length - maxChars) / 1000)}k chars truncated] ... */\n\n${end}`;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Automatically discover relevant UI files in a directory
|
|
151
|
+
*/
|
|
152
|
+
export async function discoverUIFiles(directory, config) {
|
|
153
|
+
const uiPatterns = [
|
|
154
|
+
/\.(css|scss|less|sass)$/,
|
|
155
|
+
/\.(tsx|jsx)$/,
|
|
156
|
+
/\.(vue|svelte)$/,
|
|
157
|
+
/theme\./,
|
|
158
|
+
/design[-_]?tokens?\./,
|
|
159
|
+
/tailwind\.config\./,
|
|
160
|
+
];
|
|
161
|
+
const files = [];
|
|
162
|
+
function scan(dir, depth = 0) {
|
|
163
|
+
if (depth > 3)
|
|
164
|
+
return; // Max depth
|
|
165
|
+
try {
|
|
166
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
167
|
+
for (const entry of entries) {
|
|
168
|
+
const fullPath = path.join(dir, entry.name);
|
|
169
|
+
// Skip node_modules, .git, etc.
|
|
170
|
+
if (entry.isDirectory()) {
|
|
171
|
+
if (['node_modules', '.git', 'dist', 'build', '.next', '.nuxt'].includes(entry.name)) {
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
scan(fullPath, depth + 1);
|
|
175
|
+
}
|
|
176
|
+
else if (entry.isFile()) {
|
|
177
|
+
// Check if matches UI patterns
|
|
178
|
+
if (uiPatterns.some((pattern) => pattern.test(entry.name))) {
|
|
179
|
+
if (isPathAllowed(fullPath, config.allowedPaths) && !isSensitiveFile(fullPath)) {
|
|
180
|
+
files.push(fullPath);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
// Skip directories we can't read
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
scan(directory);
|
|
191
|
+
// Sort by relevance
|
|
192
|
+
return sortByRelevance(files);
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder.js","sourceRoot":"","sources":["../../src/context/builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Filter
|
|
3
|
+
*
|
|
4
|
+
* Security patterns to prevent sensitive data from being shared.
|
|
5
|
+
* Ensures only UI-relevant files are included in context.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* UI-relevant file patterns (for auto-discovery)
|
|
9
|
+
*/
|
|
10
|
+
export declare const UI_INCLUDE_PATTERNS: RegExp[];
|
|
11
|
+
/**
|
|
12
|
+
* Check if a file path matches sensitive patterns
|
|
13
|
+
*/
|
|
14
|
+
export declare function isSensitiveFile(filePath: string): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Check if a file path is within allowed paths
|
|
17
|
+
*/
|
|
18
|
+
export declare function isPathAllowed(filePath: string, allowedPaths: string[]): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Check if a file is UI-relevant
|
|
21
|
+
*/
|
|
22
|
+
export declare function isUIRelevant(filePath: string): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Sanitize file content to remove potential secrets
|
|
25
|
+
* This is a best-effort filter for dynamic content
|
|
26
|
+
*/
|
|
27
|
+
export declare function sanitizeContent(content: string): string;
|
|
28
|
+
//# sourceMappingURL=filter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../src/context/filter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA2DH;;GAEG;AACH,eAAO,MAAM,mBAAmB,UAkB/B,CAAC;AAEF;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAUzD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,OAAO,CAW/E;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAUtD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA0BvD"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Filter
|
|
3
|
+
*
|
|
4
|
+
* Security patterns to prevent sensitive data from being shared.
|
|
5
|
+
* Ensures only UI-relevant files are included in context.
|
|
6
|
+
*/
|
|
7
|
+
import * as path from 'node:path';
|
|
8
|
+
/**
|
|
9
|
+
* Files/directories that should NEVER be included in context
|
|
10
|
+
*/
|
|
11
|
+
const SENSITIVE_PATTERNS = [
|
|
12
|
+
// Environment and secrets
|
|
13
|
+
/\.env/i,
|
|
14
|
+
/secrets?\./i,
|
|
15
|
+
/\.pem$/i,
|
|
16
|
+
/\.key$/i,
|
|
17
|
+
/\.crt$/i,
|
|
18
|
+
/credentials/i,
|
|
19
|
+
/\.htpasswd/i,
|
|
20
|
+
// Private keys and certificates
|
|
21
|
+
/id_rsa/i,
|
|
22
|
+
/id_ed25519/i,
|
|
23
|
+
/\.p12$/i,
|
|
24
|
+
/\.pfx$/i,
|
|
25
|
+
// Config with potential secrets
|
|
26
|
+
/\.npmrc$/i,
|
|
27
|
+
/\.pypirc$/i,
|
|
28
|
+
/kubeconfig/i,
|
|
29
|
+
/\.docker\/config\.json$/i,
|
|
30
|
+
// Database
|
|
31
|
+
/\.sqlite$/i,
|
|
32
|
+
/\.db$/i,
|
|
33
|
+
/migrations?\//i,
|
|
34
|
+
/seeds?\//i,
|
|
35
|
+
// Backend/server code (when isolating UI)
|
|
36
|
+
/\/api\//i,
|
|
37
|
+
/\/server\//i,
|
|
38
|
+
/\/backend\//i,
|
|
39
|
+
/\/functions\//i, // Serverless
|
|
40
|
+
/\/lambda\//i,
|
|
41
|
+
/\/middleware\//i,
|
|
42
|
+
// Auth-related
|
|
43
|
+
/\/auth\//i,
|
|
44
|
+
/passport/i,
|
|
45
|
+
/jwt/i,
|
|
46
|
+
// System and dependencies
|
|
47
|
+
/node_modules\//i,
|
|
48
|
+
/\.git\//i,
|
|
49
|
+
/vendor\//i,
|
|
50
|
+
/\.cache\//i,
|
|
51
|
+
/\.next\//i,
|
|
52
|
+
/\.nuxt\//i,
|
|
53
|
+
/dist\//i,
|
|
54
|
+
/build\//i,
|
|
55
|
+
];
|
|
56
|
+
/**
|
|
57
|
+
* UI-relevant file patterns (for auto-discovery)
|
|
58
|
+
*/
|
|
59
|
+
export const UI_INCLUDE_PATTERNS = [
|
|
60
|
+
// Stylesheets
|
|
61
|
+
/\.(css|scss|less|sass|styl)$/i,
|
|
62
|
+
// Components
|
|
63
|
+
/\.(tsx|jsx)$/i,
|
|
64
|
+
/\.(vue|svelte)$/i,
|
|
65
|
+
// Design tokens
|
|
66
|
+
/theme\./i,
|
|
67
|
+
/tokens?\./i,
|
|
68
|
+
/variables\./i,
|
|
69
|
+
/design[-_]?system/i,
|
|
70
|
+
// Config files for styling
|
|
71
|
+
/tailwind\.config/i,
|
|
72
|
+
/postcss\.config/i,
|
|
73
|
+
/styled-components/i,
|
|
74
|
+
];
|
|
75
|
+
/**
|
|
76
|
+
* Check if a file path matches sensitive patterns
|
|
77
|
+
*/
|
|
78
|
+
export function isSensitiveFile(filePath) {
|
|
79
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
80
|
+
for (const pattern of SENSITIVE_PATTERNS) {
|
|
81
|
+
if (pattern.test(normalized)) {
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Check if a file path is within allowed paths
|
|
89
|
+
*/
|
|
90
|
+
export function isPathAllowed(filePath, allowedPaths) {
|
|
91
|
+
const absPath = path.resolve(filePath);
|
|
92
|
+
for (const allowed of allowedPaths) {
|
|
93
|
+
const absAllowed = path.resolve(allowed);
|
|
94
|
+
if (absPath.startsWith(absAllowed)) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Check if a file is UI-relevant
|
|
102
|
+
*/
|
|
103
|
+
export function isUIRelevant(filePath) {
|
|
104
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
105
|
+
for (const pattern of UI_INCLUDE_PATTERNS) {
|
|
106
|
+
if (pattern.test(normalized)) {
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Sanitize file content to remove potential secrets
|
|
114
|
+
* This is a best-effort filter for dynamic content
|
|
115
|
+
*/
|
|
116
|
+
export function sanitizeContent(content) {
|
|
117
|
+
// Remove common secret patterns
|
|
118
|
+
const patterns = [
|
|
119
|
+
// API keys (generic patterns)
|
|
120
|
+
/(['"`])?(api[_-]?key|apikey|secret|password|token|auth)(['"`])?[\s]*[:=][\s]*['"`][^'"`]+['"`]/gi,
|
|
121
|
+
// Bearer tokens
|
|
122
|
+
/Bearer\s+[A-Za-z0-9\-_=]+\.[A-Za-z0-9\-_=]+\.?[A-Za-z0-9\-_.+/=]*/gi,
|
|
123
|
+
// AWS keys
|
|
124
|
+
/AKIA[0-9A-Z]{16}/g,
|
|
125
|
+
// Private keys
|
|
126
|
+
/-----BEGIN[\s\w]+PRIVATE KEY-----[\s\S]+?-----END[\s\w]+PRIVATE KEY-----/g,
|
|
127
|
+
// Connection strings
|
|
128
|
+
/(mongodb|postgresql|mysql|redis):\/\/[^\s'"]+/gi,
|
|
129
|
+
];
|
|
130
|
+
let result = content;
|
|
131
|
+
for (const pattern of patterns) {
|
|
132
|
+
result = result.replace(pattern, '[REDACTED]');
|
|
133
|
+
}
|
|
134
|
+
return result;
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter.js","sourceRoot":"","sources":["../../src/context/filter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* grounding.ts
|
|
3
|
+
*
|
|
4
|
+
* Deterministic “repo grounding” injected into prompts to improve output quality
|
|
5
|
+
* without burning large context windows.
|
|
6
|
+
*
|
|
7
|
+
* This module is used internally by tools like modify_ui and
|
|
8
|
+
* generate_component_variants to:
|
|
9
|
+
* - auto-detect the UI stack (framework/styling/libs)
|
|
10
|
+
* - catalog available components for reuse
|
|
11
|
+
*
|
|
12
|
+
* The output is intentionally concise and stable.
|
|
13
|
+
*/
|
|
14
|
+
import { Config } from '../config/index.js';
|
|
15
|
+
export interface RepoGroundingOptions {
|
|
16
|
+
focusFileAbs?: string;
|
|
17
|
+
instruction?: string;
|
|
18
|
+
maxComponents?: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Build a concise deterministic “grounding” string.
|
|
22
|
+
*
|
|
23
|
+
* This is safe to include in prompts because it contains only local, deterministic
|
|
24
|
+
* project metadata (no secrets).
|
|
25
|
+
*/
|
|
26
|
+
export declare function buildRepoGrounding(config: Config, options?: RepoGroundingOptions): Promise<string>;
|
|
27
|
+
//# sourceMappingURL=grounding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grounding.d.ts","sourceRoot":"","sources":["../../src/context/grounding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AA+H5C,MAAM,WAAW,oBAAoB;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,MAAM,CAAC,CAoC5G"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* grounding.ts
|
|
3
|
+
*
|
|
4
|
+
* Deterministic “repo grounding” injected into prompts to improve output quality
|
|
5
|
+
* without burning large context windows.
|
|
6
|
+
*
|
|
7
|
+
* This module is used internally by tools like modify_ui and
|
|
8
|
+
* generate_component_variants to:
|
|
9
|
+
* - auto-detect the UI stack (framework/styling/libs)
|
|
10
|
+
* - catalog available components for reuse
|
|
11
|
+
*
|
|
12
|
+
* The output is intentionally concise and stable.
|
|
13
|
+
*/
|
|
14
|
+
import * as path from 'node:path';
|
|
15
|
+
import { detectUiStack } from '../stack/detect.js';
|
|
16
|
+
import { walkFiles, toPosixPath } from '../utils/walk.js';
|
|
17
|
+
import { buildComponentCatalog } from '../components/catalog.js';
|
|
18
|
+
const CACHE_TTL_MS = 60_000;
|
|
19
|
+
const cache = new Map();
|
|
20
|
+
function resolveRootForFile(absFile, config) {
|
|
21
|
+
const allowed = (config.allowedPaths || []).map((p) => path.resolve(p));
|
|
22
|
+
const fallback = allowed[0] || process.cwd();
|
|
23
|
+
if (!absFile)
|
|
24
|
+
return fallback;
|
|
25
|
+
const abs = path.resolve(absFile);
|
|
26
|
+
// pick the deepest allowed root that contains the file
|
|
27
|
+
const matches = allowed
|
|
28
|
+
.filter((root) => abs === root || abs.startsWith(root + path.sep))
|
|
29
|
+
.sort((a, b) => b.length - a.length);
|
|
30
|
+
return matches[0] || fallback;
|
|
31
|
+
}
|
|
32
|
+
function summarizeStack(stack) {
|
|
33
|
+
const summary = {
|
|
34
|
+
framework: stack.framework,
|
|
35
|
+
typescript: stack.language.typescript,
|
|
36
|
+
styling: stack.styling,
|
|
37
|
+
uiLibraries: stack.uiLibraries,
|
|
38
|
+
iconLibraries: stack.iconLibraries,
|
|
39
|
+
tooling: stack.tooling,
|
|
40
|
+
conventions: {
|
|
41
|
+
srcDir: stack.conventions.srcDir,
|
|
42
|
+
hasAppDir: stack.conventions.hasAppDir,
|
|
43
|
+
hasPagesDir: stack.conventions.hasPagesDir,
|
|
44
|
+
tsconfigPaths: stack.conventions.tsconfigPaths ? Object.keys(stack.conventions.tsconfigPaths) : undefined,
|
|
45
|
+
},
|
|
46
|
+
files: {
|
|
47
|
+
tailwindConfig: stack.files.tailwindConfig,
|
|
48
|
+
componentsJson: stack.files.componentsJson,
|
|
49
|
+
storybookDir: stack.files.storybookDir,
|
|
50
|
+
},
|
|
51
|
+
warnings: stack.warnings,
|
|
52
|
+
};
|
|
53
|
+
return JSON.stringify(summary, null, 2);
|
|
54
|
+
}
|
|
55
|
+
function tokenizeInstruction(instruction) {
|
|
56
|
+
const set = new Set();
|
|
57
|
+
if (!instruction)
|
|
58
|
+
return set;
|
|
59
|
+
const tokens = instruction.match(/[A-Za-z_][A-Za-z0-9_]*/g) || [];
|
|
60
|
+
for (const t of tokens)
|
|
61
|
+
set.add(t.toLowerCase());
|
|
62
|
+
return set;
|
|
63
|
+
}
|
|
64
|
+
function scoreComponent(c, focusDirRel, instructionTokens) {
|
|
65
|
+
let score = 0;
|
|
66
|
+
// Mentioned explicitly in instruction
|
|
67
|
+
if (instructionTokens.has(c.name.toLowerCase()))
|
|
68
|
+
score += 8;
|
|
69
|
+
// Same directory as focused file
|
|
70
|
+
if (focusDirRel && c.file.startsWith(focusDirRel + '/'))
|
|
71
|
+
score += 6;
|
|
72
|
+
// Common reusable directories
|
|
73
|
+
if (c.file.includes('/components/') ||
|
|
74
|
+
c.file.startsWith('components/') ||
|
|
75
|
+
c.file.includes('/ui/') ||
|
|
76
|
+
c.file.includes('/shared/')) {
|
|
77
|
+
score += 3;
|
|
78
|
+
}
|
|
79
|
+
// Prefer TSX
|
|
80
|
+
if (c.file.endsWith('.tsx'))
|
|
81
|
+
score += 1;
|
|
82
|
+
return score;
|
|
83
|
+
}
|
|
84
|
+
function formatCatalogSubset(catalog, subset) {
|
|
85
|
+
const lines = [];
|
|
86
|
+
const header = `scanned_files=${catalog.filesScanned}, total_exports=${catalog.components.length}`;
|
|
87
|
+
lines.push(header);
|
|
88
|
+
if (catalog.warnings.length) {
|
|
89
|
+
lines.push(`warnings: ${catalog.warnings.join(' | ')}`);
|
|
90
|
+
}
|
|
91
|
+
lines.push('');
|
|
92
|
+
lines.push('components:');
|
|
93
|
+
for (const c of subset) {
|
|
94
|
+
const extras = [];
|
|
95
|
+
if (c.exportType)
|
|
96
|
+
extras.push(c.exportType);
|
|
97
|
+
if (c.propsType)
|
|
98
|
+
extras.push(`props: ${c.propsType}`);
|
|
99
|
+
if (c.jsDoc)
|
|
100
|
+
extras.push(`doc: ${c.jsDoc}`);
|
|
101
|
+
const extra = extras.length ? ` (${extras.join(', ')})` : '';
|
|
102
|
+
lines.push(`- ${c.name} — ${c.file}${extra}`);
|
|
103
|
+
}
|
|
104
|
+
return lines.join('\n');
|
|
105
|
+
}
|
|
106
|
+
async function getOrBuildRepoData(root) {
|
|
107
|
+
const now = Date.now();
|
|
108
|
+
const hit = cache.get(root);
|
|
109
|
+
if (hit && now - hit.ts < CACHE_TTL_MS)
|
|
110
|
+
return hit;
|
|
111
|
+
const stack = detectUiStack(root);
|
|
112
|
+
const files = walkFiles(root, {
|
|
113
|
+
includeExtensions: ['.tsx', '.jsx'],
|
|
114
|
+
maxFiles: 5000,
|
|
115
|
+
});
|
|
116
|
+
const catalog = await buildComponentCatalog(root, files);
|
|
117
|
+
const fresh = { ts: now, stack, catalog };
|
|
118
|
+
cache.set(root, fresh);
|
|
119
|
+
return fresh;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Build a concise deterministic “grounding” string.
|
|
123
|
+
*
|
|
124
|
+
* This is safe to include in prompts because it contains only local, deterministic
|
|
125
|
+
* project metadata (no secrets).
|
|
126
|
+
*/
|
|
127
|
+
export async function buildRepoGrounding(config, options = {}) {
|
|
128
|
+
const maxComponents = typeof options.maxComponents === 'number' ? options.maxComponents : 120;
|
|
129
|
+
const root = resolveRootForFile(options.focusFileAbs ? path.resolve(options.focusFileAbs) : null, config);
|
|
130
|
+
const data = await getOrBuildRepoData(root);
|
|
131
|
+
const focusRel = options.focusFileAbs ? toPosixPath(path.relative(root, path.resolve(options.focusFileAbs))) : null;
|
|
132
|
+
const focusDirRel = focusRel ? toPosixPath(path.posix.dirname(focusRel)) : null;
|
|
133
|
+
const instructionTokens = tokenizeInstruction(options.instruction);
|
|
134
|
+
// Score and select a small subset for reuse.
|
|
135
|
+
const scored = data.catalog.components
|
|
136
|
+
.map((c) => ({ c, s: scoreComponent(c, focusDirRel, instructionTokens) }))
|
|
137
|
+
.sort((a, b) => b.s - a.s);
|
|
138
|
+
const subset = [];
|
|
139
|
+
const seen = new Set();
|
|
140
|
+
for (const item of scored) {
|
|
141
|
+
if (subset.length >= maxComponents)
|
|
142
|
+
break;
|
|
143
|
+
const key = `${item.c.name}|${item.c.file}|${item.c.exportType}`;
|
|
144
|
+
if (seen.has(key))
|
|
145
|
+
continue;
|
|
146
|
+
// Skip ultra-low relevance if we already have enough
|
|
147
|
+
if (subset.length > 30 && item.s <= 0)
|
|
148
|
+
break;
|
|
149
|
+
subset.push(item.c);
|
|
150
|
+
seen.add(key);
|
|
151
|
+
}
|
|
152
|
+
return [
|
|
153
|
+
'AUTO PROJECT CONTEXT (deterministic):',
|
|
154
|
+
'',
|
|
155
|
+
'STACK (json):',
|
|
156
|
+
summarizeStack(data.stack),
|
|
157
|
+
'',
|
|
158
|
+
'COMPONENT CATALOG (subset for reuse):',
|
|
159
|
+
formatCatalogSubset(data.catalog, subset),
|
|
160
|
+
].join('\n');
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=grounding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grounding.js","sourceRoot":"","sources":["../../src/context/grounding.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path Guards
|
|
3
|
+
*
|
|
4
|
+
* Centralized helpers to validate and resolve file paths for tools.
|
|
5
|
+
*
|
|
6
|
+
* Goals:
|
|
7
|
+
* - Prevent accidental reads/writes outside the workspace
|
|
8
|
+
* - Avoid including sensitive files (e.g. .env, private keys)
|
|
9
|
+
* - Provide consistent absolute-path resolution
|
|
10
|
+
*/
|
|
11
|
+
import { Config } from '../config/index.js';
|
|
12
|
+
/**
|
|
13
|
+
* Resolve a path to an absolute path (relative paths are resolved from process.cwd()).
|
|
14
|
+
*/
|
|
15
|
+
export declare function resolveToAbs(filePath: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Validate that a path is safe to read according to server config.
|
|
18
|
+
* Returns the resolved absolute path.
|
|
19
|
+
*/
|
|
20
|
+
export declare function assertReadablePath(filePath: string, config: Config): string;
|
|
21
|
+
/**
|
|
22
|
+
* Validate that a path is safe to write according to server config.
|
|
23
|
+
* Returns the resolved absolute path.
|
|
24
|
+
*/
|
|
25
|
+
export declare function assertWritablePath(filePath: string, config: Config): string;
|
|
26
|
+
/**
|
|
27
|
+
* Validate that a directory path is safe to read according to server config.
|
|
28
|
+
* Returns the resolved absolute path.
|
|
29
|
+
*/
|
|
30
|
+
export declare function assertReadableDir(dirPath: string, config: Config): string;
|
|
31
|
+
//# sourceMappingURL=guards.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../../src/context/guards.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAG5C;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAqB3E;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAY3E;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAqBzE"}
|