brians resume | brians resume | access web information | Search

The messageFilesystem function is an asynchronous function that retrieves information about available projects and their related files by interacting with the file system and user input. It generates a prompt, filters related projects and files, and logs user responses and project information, although it has some potential performance and logging issues that should be addressed.

Run example

npm run import -- "file system access"

file system access

const path = require('path')
const fs = require('fs')

const PROFILE_PATH = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE || '';

async function messageFilesystem(promptModel, session, prompt) {

  let currentProject = path.basename(path.resolve(__dirname, '..'))
  let availableProjects = fs.readdirSync(PROFILE_PATH)
    .filter(dir => dir[0] != '.')
    .filter(dir => fs.statSync(path.join(PROFILE_PATH, dir)).isDirectory())
    .filter(dir => fs.existsSync(path.join(PROFILE_PATH, dir, '.git')))
  let q1 = 'Current project: ' + currentProject
    + '\nAvailable projects:\n' + availableProjects.join('\n')
    + '\nAre any of these project related to the current prompt:\n'
    + prompt
    + '\nOnly respond with the project name or "No" if none are related.'
  console.log('User: ' + q1)
  let a1 = await promptModel(q1)
  console.log('AI: ' + a1)
  
  let relatedProjects = availableProjects.filter(dir => a1.match(dir))

  if(relatedProjects.length == 0) {
    return 'Current project: ' + currentProject
      + '\nAvailable projects:\n' + availableProjects.join('\n')
  }

  let projectFiles = fs.readdirSync(path.join(PROFILE_PATH, relatedProjects[0]))
    .filter(dir => dir[0] != '.' && dir != 'node_modules')
    .map(file => {
      let currentPath = path.join(PROFILE_PATH, relatedProjects[0], file)
      if(fs.statSync(currentPath).isDirectory()) {
        return [file].concat(fs.readdirSync(currentPath)
          .filter(dir => dir[0] != '.')
          .map(dir => path.join(file, dir)))
      } else {
        return file
      }
    })
    .flat(1)
  let relatedFiles = []
  if(currentProject == relatedProjects[0]) {
    // TODO: use cell lookup instead of notebook files
    let q2 = 'Current project: ' + currentProject
      + '\nRelated projects:\n' + relatedProjects.join('\n')
      + '\nProject files:\n'
    let originalFilePrompt = q2
    let count = 0
    for(let i = 0; i < projectFiles.length; i++) {
      q2 += projectFiles[i] + '\n'
      count++
      if(count == 25 || q2.length > 2048) {
        q2 += '\nAre any of the project files relevant to the prompt:\n'
          + prompt
          + '\nOnly respond with the related file paths or file names, nothing else.'
        console.log('User: ' + q2)
        let a2 = await promptModel(q2)
        console.log('AI: ' + a2)
        relatedFiles = relatedFiles.concat(projectFiles
          .filter(file => a2.match(file) || a2.match(path.basename(file))))
        count = 0
        q2 = originalFilePrompt
      }
    }
    if(q2.length != originalFilePrompt.length || count > 0) {
      q2 += '\nAre any of the project files relevant to the prompt:\n'
        + prompt
        + '\nOnly respond with the related file paths or file names, nothing else.'
      console.log('User: ' + q2)
      let a2 = await promptModel(q2)
      console.log('AI: ' + a2)
      relatedFiles = relatedFiles.concat(projectFiles
        .filter(file => a2.match(file) || a2.match(path.basename(file))))
    }
  }

  if(relatedFiles.length == 0) {
    return 'Current project: ' + currentProject
      + '\nRelated projects:\n' + relatedProjects.join('\n')
      + '\nProject files:\n' + projectFiles.join('\n')
  }

  // TODO: another depth of related files
  
  return 'Current project: ' + currentProject
    + '\nRelated projects:\n' + relatedProjects.join('\n')
    + '\nRelated files:\n' + relatedFiles.join('\n')


}

module.exports = messageFilesystem

What the code could have been:

const path = require('path');
const fs = require('fs');
const { promisify } = require('util');

const PROFILE_PATH = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE || '';

const readdir = promisify(fs.readdir);
const readFile = promisify(fs.readFile);
const stat = promisify(fs.stat);

async function messageFilesystem(promptModel, session, prompt) {
  const currentProject = path.basename(path.resolve(__dirname, '..'));
  const availableProjects = await getAvailableProjects();

  const relatedProjects = await getRelatedProjects(promptModel, availableProjects, prompt);
  if (relatedProjects.length === 0) {
    return getProjectInfo(currentProject, availableProjects);
  }

  const projectFiles = await getProjectFiles(relatedProjects[0]);
  const relatedFiles = await getRelatedFiles(promptModel, projectFiles, prompt, currentProject);

  return getProjectInfo(currentProject, availableProjects, relatedProjects, relatedFiles);
}

async function getAvailableProjects() {
  return (await readdir(PROFILE_PATH))
   .filter(dir => dir[0]!== '.')
   .filter(dir => (await stat(path.join(PROFILE_PATH, dir))).isDirectory())
   .filter(dir => (await fs.existsSync(path.join(PROFILE_PATH, dir, '.git'))));
}

async function getRelatedProjects(promptModel, availableProjects, prompt) {
  const q1 = `Current project: ${path.basename(path.resolve(__dirname, '..'))}
Available projects:\n${availableProjects.join('\n')}
Are any of these project related to the current prompt:\n${prompt}
Only respond with the project name or "No" if none are related.`;
  console.log('User:'+ q1);
  const a1 = await promptModel(q1);
  console.log('AI:'+ a1);

  return availableProjects.filter(dir => a1.match(dir));
}

async function getProjectInfo(currentProject, availableProjects, relatedProjects = [], relatedFiles = []) {
  return `Current project: ${currentProject}
Available projects:\n${availableProjects.join('\n')}
Related projects:\n${relatedProjects.join('\n')}
Related files:\n${relatedFiles.join('\n')}`;
}

async function getProjectFiles(projectName) {
  return (await readdir(path.join(PROFILE_PATH, projectName)))
   .filter(dir => dir[0]!== '.' && dir!== 'node_modules')
   .map(file => {
      const currentPath = path.join(PROFILE_PATH, projectName, file);
      if ((await stat(currentPath)).isDirectory()) {
        return [file].concat((await getProjectFiles(currentPath)));
      } else {
        return file;
      }
    })
   .flat(1);
}

async function getRelatedFiles(promptModel, projectFiles, prompt, currentProject) {
  const relatedFiles = [];
  if (currentProject === relatedProjects[0]) {
    let q2 = `Current project: ${currentProject}
Related projects:\n${relatedProjects.join('\n')}
Project files:\n`;
    let originalFilePrompt = q2;
    let count = 0;
    for (let i = 0; i < projectFiles.length; i++) {
      q2 += projectFiles[i] + '\n';
      count++;
      if (count === 25 || q2.length > 2048) {
        q2 += `\nAre any of the project files relevant to the prompt:\n${prompt}
Only respond with the related file paths or file names, nothing else.`;
        console.log('User:'+ q2);
        let a2 = await promptModel(q2);
        console.log('AI:'+ a2);
        relatedFiles = relatedFiles.concat(projectFiles
         .filter(file => a2.match(file) || a2.match(path.basename(file))));
        count = 0;
        q2 = originalFilePrompt;
      }
    }
    if (q2.length!== originalFilePrompt.length || count > 0) {
      q2 += `\nAre any of the project files relevant to the prompt:\n${prompt}
Only respond with the related file paths or file names, nothing else.`;
      console.log('User:'+ q2);
      let a2 = await promptModel(q2);
      console.log('AI:'+ a2);
      relatedFiles = relatedFiles.concat(projectFiles
       .filter(file => a2.match(file) || a2.match(path.basename(file))));
    }
  }

  return relatedFiles;
}

module.exports = messageFilesystem;

Function Breakdown: messageFilesystem

This is an asynchronous function that interacts with the file system to provide information about available projects and their related files. It takes in three parameters:

Here's a step-by-step breakdown of the function:

  1. Get current project directory: It uses the path module to get the current working directory and its parent directory (the project root).
  2. Get available projects: It uses the fs module to read the contents of the user's home directory and filter out directories that are hidden or not Git repositories.
  3. Generate prompt: It generates a prompt asking if any of the available projects are related to the current prompt.
  4. Get user response: It uses the promptModel to generate a response to the prompt and logs the user's response.
  5. Filter related projects: It filters the available projects to those that match the user's response.
  6. Get project files: If there are related projects, it gets a list of files in that project directory and its subdirectories.
  7. Generate response: It generates a response that includes the current project, available projects, related projects, and project files.

Notes