packfs-core
Version:
Semantic filesystem operations for LLM agent frameworks with natural language understanding. See LLM_AGENT_GUIDE.md for copy-paste examples.
288 lines • 10.6 kB
JavaScript
/**
* Backward compatibility adapter for traditional filesystem operations
* Translates traditional POSIX-style calls to semantic operations
*/
import { FileSystemInterface } from '../core/filesystem.js';
import { TraditionalToSemanticConverter } from './intent-processor.js';
/**
* Adapter that makes semantic filesystem work with traditional interface
* Enables existing code to work with semantic backend without changes
*
* This is the bridge between:
* - Old approach: readFile(), writeFile(), stat(), exists(), etc.
* - New approach: accessFile(), updateContent(), organizeFiles(), etc.
*/
export class SemanticCompatibilityAdapter extends FileSystemInterface {
constructor(semanticBackend) {
super();
this.semanticBackend = semanticBackend;
}
/**
* Traditional readFile() -> semantic accessFile()
*/
async readFile(path, options) {
const intent = TraditionalToSemanticConverter.readFileToIntent(path, options);
const result = await this.semanticBackend.accessFile(intent);
if (!result.success) {
throw new Error(result.message || `Failed to read file: ${path}`);
}
if (result.content === undefined) {
throw new Error(`No content returned for file: ${path}`);
}
return result.content;
}
/**
* Traditional writeFile() -> semantic updateContent()
*/
async writeFile(path, data, options) {
const intent = TraditionalToSemanticConverter.writeFileToIntent(path, data, {
createDirs: options?.createDirs,
mode: options?.mode
});
const result = await this.semanticBackend.updateContent(intent);
if (!result.success) {
throw new Error(result.message || `Failed to write file: ${path}`);
}
}
/**
* Traditional exists() -> semantic accessFile()
*/
async exists(path) {
const intent = TraditionalToSemanticConverter.existsToIntent(path);
const result = await this.semanticBackend.accessFile(intent);
return result.exists;
}
/**
* Traditional stat() -> semantic accessFile()
*/
async stat(path) {
const intent = TraditionalToSemanticConverter.statToIntent(path);
const result = await this.semanticBackend.accessFile(intent);
if (!result.success) {
throw new Error(result.message || `Failed to stat file: ${path}`);
}
if (!result.metadata) {
throw new Error(`No metadata returned for file: ${path}`);
}
return result.metadata;
}
/**
* Traditional readdir() -> semantic discoverFiles()
*/
async readdir(path) {
const intent = TraditionalToSemanticConverter.readdirToIntent(path);
const result = await this.semanticBackend.discoverFiles(intent);
if (!result.success) {
throw new Error(result.message || `Failed to read directory: ${path}`);
}
// Extract just the filenames from the full file objects
return result.files.map(file => {
const fullPath = file.path;
const basePath = path.endsWith('/') ? path : path + '/';
if (fullPath.startsWith(basePath)) {
const relativePath = fullPath.substring(basePath.length);
// Return just the immediate child name (no nested paths)
const parts = relativePath.split('/');
return parts[0] || fullPath;
}
return fullPath;
}).filter(Boolean);
}
/**
* Traditional mkdir() -> semantic organizeFiles()
*/
async mkdir(path, recursive) {
const intent = TraditionalToSemanticConverter.mkdirToIntent(path, { recursive });
const result = await this.semanticBackend.organizeFiles(intent);
if (!result.success) {
throw new Error(result.message || `Failed to create directory: ${path}`);
}
}
/**
* Traditional remove() -> semantic removeFiles()
*/
async remove(path, _recursive) {
const intent = TraditionalToSemanticConverter.unlinkToIntent(path);
const result = await this.semanticBackend.removeFiles(intent);
if (!result.success) {
throw new Error(result.message || `Failed to remove: ${path}`);
}
}
/**
* Traditional copy() -> semantic organizeFiles()
*/
async copy(source, destination) {
const intent = {
purpose: 'copy',
source: { path: source },
destination: { path: destination }
};
const result = await this.semanticBackend.organizeFiles(intent);
if (!result.success) {
throw new Error(result.message || `Failed to copy from ${source} to ${destination}`);
}
}
/**
* Traditional move() -> semantic organizeFiles()
*/
async move(source, destination) {
const intent = {
purpose: 'move',
source: { path: source },
destination: { path: destination }
};
const result = await this.semanticBackend.organizeFiles(intent);
if (!result.success) {
throw new Error(result.message || `Failed to move from ${source} to ${destination}`);
}
}
/**
* Enhanced methods that expose semantic capabilities while maintaining compatibility
*/
/**
* Extended readFile with semantic features
*/
async readFileEnhanced(path, options) {
const intent = {
purpose: options?.purpose || 'read',
target: { path },
preferences: {
encoding: options?.encoding,
chunkingStrategy: options?.chunkingStrategy,
includeMetadata: true
}
};
const result = await this.semanticBackend.accessFile(intent);
if (!result.success) {
throw new Error(result.message || `Failed to read file: ${path}`);
}
return {
content: result.content || '',
metadata: result.metadata,
preview: result.preview,
chunks: result.chunks
};
}
/**
* Semantic file search through traditional interface
*/
async findFiles(query, options) {
const purpose = options?.searchType === 'content' ? 'search_content' :
options?.searchType === 'semantic' ? 'search_semantic' :
'search_integrated';
const intent = {
purpose: purpose,
target: { semanticQuery: query },
options: {
maxResults: options?.maxResults,
includeContent: options?.includeContent
}
};
const result = await this.semanticBackend.discoverFiles(intent);
if (!result.success) {
throw new Error(result.message || `Failed to search files: ${query}`);
}
return result.files;
}
/**
* Natural language file operations
*/
async executeNaturalLanguage(query) {
// First, interpret the natural language
const nlResult = await this.semanticBackend.interpretNaturalLanguage({
query,
context: {
workingDirectory: process.cwd()
}
});
if (!nlResult.success) {
return {
success: false,
result: null,
interpretedIntent: null,
confidence: 0
};
}
// Execute the interpreted intent
const intent = nlResult.interpretedIntent;
let result;
try {
if ('purpose' in intent) {
switch (intent.purpose) {
case 'read':
case 'preview':
case 'metadata':
case 'verify_exists':
case 'create_or_get':
result = await this.semanticBackend.accessFile(intent);
break;
case 'create':
case 'append':
case 'overwrite':
case 'merge':
case 'patch':
result = await this.semanticBackend.updateContent(intent);
break;
case 'create_directory':
case 'move':
case 'copy':
case 'group_semantic':
case 'group_keywords':
result = await this.semanticBackend.organizeFiles(intent);
break;
case 'list':
case 'find':
case 'search_content':
case 'search_semantic':
case 'search_integrated':
result = await this.semanticBackend.discoverFiles(intent);
break;
case 'delete_file':
case 'delete_directory':
case 'delete_by_criteria':
result = await this.semanticBackend.removeFiles(intent);
break;
default:
throw new Error(`Unknown intent purpose: ${intent.purpose}`);
}
}
else {
// Handle workflow intents
result = await this.semanticBackend.executeWorkflow(intent);
}
return {
success: result.success,
result,
interpretedIntent: intent,
confidence: nlResult.confidence
};
}
catch (error) {
return {
success: false,
result: { error: error instanceof Error ? error.message : 'Unknown error' },
interpretedIntent: intent,
confidence: nlResult.confidence
};
}
}
/**
* Get access to the underlying semantic backend for advanced operations
*/
getSemanticBackend() {
return this.semanticBackend;
}
}
/**
* Factory function to create a semantic filesystem with traditional interface
*/
export function createSemanticFileSystem(semanticBackend) {
return new SemanticCompatibilityAdapter(semanticBackend);
}
/**
* Factory function to create enhanced filesystem with both traditional and semantic methods
*/
export function createEnhancedFileSystem(semanticBackend) {
return new SemanticCompatibilityAdapter(semanticBackend);
}
//# sourceMappingURL=compatibility-adapter.js.map