@nanocollective/nanocoder
Version:
A local-first CLI coding agent that brings the power of agentic coding tools like Claude Code and Gemini CLI to local models or controlled APIs like OpenRouter
59 lines • 2.38 kB
JavaScript
import { PlaceholderType, } from '../types/hooks.js';
import { loadFileContent } from './file-content-loader.js';
/**
* Handle @file mention by creating a placeholder
* Called when file is selected from autocomplete or on message submit
*
* Returns null if file doesn't exist (silent failure per spec)
*/
export async function handleFileMention(filePath, currentDisplayValue, currentPlaceholderContent, mentionText, // The original "@src/app.tsx:10-20" text to replace
lineRange) {
// Load file content
const fileResult = await loadFileContent(filePath, lineRange);
// If file doesn't exist or failed to load, return null (silently skip per spec)
if (!fileResult.success) {
return null;
}
// Generate unique ID for this file placeholder
const existingFileCount = Object.values(currentPlaceholderContent).filter(content => content.type === PlaceholderType.FILE).length;
const fileId = `file_${existingFileCount + 1}`;
// Create compact placeholder for display
const placeholder = lineRange
? `[@${filePath}:${lineRange.start}${lineRange.end ? `-${lineRange.end}` : ''}]`
: `[@${filePath}]`;
// Create file placeholder content
// Use the existing FilePlaceholderContent interface
const fileContent = {
type: PlaceholderType.FILE,
displayText: placeholder,
filePath: fileResult.metadata.absolutePath,
content: fileResult.content || '',
lastModified: Date.now(),
encoding: 'utf-8',
fileSize: fileResult.metadata.size,
};
const newPlaceholderContent = {
...currentPlaceholderContent,
[fileId]: fileContent,
};
// Replace the @mention text with placeholder in display
const newDisplayValue = currentDisplayValue.replace(mentionText, placeholder);
return {
displayValue: newDisplayValue,
placeholderContent: newPlaceholderContent,
};
}
/**
* Parse line range from mention text if present
* e.g., "@app.tsx:10-20" -> {start: 10, end: 20}
*/
export function parseLineRangeFromMention(mentionText) {
const match = mentionText.match(/:(\d+)(?:-(\d+))?$/);
if (!match) {
return undefined;
}
const start = parseInt(match[1], 10);
const end = match[2] ? parseInt(match[2], 10) : undefined;
return { start, end };
}
//# sourceMappingURL=file-mention-handler.js.map