MCPcopy
hub / github.com/Doorman11991/smallcode / resolveReferences

Function resolveReferences

src/session/references.js:29–100  ·  view source on GitHub ↗

* Parse @file references from user input. * Returns the text with references resolved + injected file contents.

(input, cwd)

Source from the content-addressed store, hash-verified

27 * Returns the text with references resolved + injected file contents.
28 */
29function resolveReferences(input, cwd) {
30 const matches = [...input.matchAll(FILE_REGEX)];
31 if (matches.length === 0) return { text: input, files: [] };
32
33 const files = [];
34 const seen = new Set();
35
36 for (const match of matches) {
37 const rawPath = match[1];
38 if (!rawPath || rawPath.length < 2) continue;
39 if (seen.has(rawPath)) continue;
40 seen.add(rawPath);
41
42 // Resolve the path safely. We allow `~/...` but require the resolved
43 // path NOT to be a sensitive credential file (.ssh, .aws, etc.).
44 // For project-relative paths we additionally require containment.
45 const isHome = rawPath.startsWith('~/') || rawPath.startsWith('~\\');
46 const safe = safeResolvePath(rawPath, cwd, {
47 allowHome: isHome,
48 allowOutside: isHome, // a ~/-relative path is by definition outside cwd
49 });
50 if (!safe.ok) continue; // Silently skip unsafe references — model gets nothing
51 const resolvedPath = safe.fullPath;
52
53 if (!fs.existsSync(resolvedPath)) continue;
54
55 let stat;
56 try { stat = fs.statSync(resolvedPath); } catch { continue; }
57
58 if (stat.isFile()) {
59 // Refuse files larger than 5MB up front — prevents DoS via @largebinary
60 if (stat.size > 5 * 1024 * 1024) continue;
61 // Read file content (capped at 500 lines)
62 try {
63 const content = fs.readFileSync(resolvedPath, 'utf-8');
64 const lines = content.split('\n');
65 const truncated = lines.length > 500
66 ? lines.slice(0, 500).join('\n') + `\n... (${lines.length - 500} more lines)`
67 : content;
68
69 files.push({
70 path: rawPath,
71 resolvedPath,
72 type: 'file',
73 // Sanitize before sending into the conversation: strip ANSI/control
74 // chars and redact secrets. A user-typed `@.env` no longer leaks
75 // their API keys to a (possibly remote) model.
76 content: sanitizeToolOutput(truncated),
77 lines: lines.length,
78 });
79 } catch {}
80 } else if (stat.isDirectory()) {
81 // List directory contents
82 try {
83 const entries = fs.readdirSync(resolvedPath, { withFileTypes: true })
84 .filter(e => !e.name.startsWith('.') && e.name !== 'node_modules')
85 .slice(0, 50)
86 .map(e => e.isDirectory() ? `${e.name}/` : e.name);

Callers 1

runAgentLoopFunction · 0.85

Calls 4

safeResolvePathFunction · 0.85
sanitizeToolOutputFunction · 0.85
addMethod · 0.80
hasMethod · 0.45

Tested by

no test coverage detected