Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

home env for OPENAI_API_KEY with interactive init #174

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .env.template
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
OPENAI_API_KEY=<your-api-key>
# Path to your code, defaults to itself.
# Even if you are on windows this is POSIX style path.
# For example C:\Users\user\code\project
Expand Down
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,9 @@ Note: This project is currently operating autonomously on a server. Whenever an
2. Do `cd autopilot` to install dependencies: `npm ci`
3. Create the `.env` file and set up the environment variables:
1. Copy the .env.template file to .env: `cp .env.template .env`
2. Set up an OpenAI API key and file with the key: `OPENAI_API_KEY=<your-api-key>`. [Create openAI API key](https://platform.openai.com/account/api-keys)
3. Set the path to your code `CODE_DIR=<path-to-your-code>` (or use `-d path-to-your-code` later)
4. Update `IGNORE_LIST=node_modules,coverage,public,__tests__`
5. Update `FILE_EXTENSIONS_TO_PROCESS=.js,.tsx,.ts,.jsx`
2. Set the path to your code `CODE_DIR=<path-to-your-code>` (or use `-d path-to-your-code` later)
3. Update `IGNORE_LIST=node_modules,coverage,public,__tests__`
4. Update `FILE_EXTENSIONS_TO_PROCESS=.js,.tsx,.ts,.jsx`

## Running
* `node ui -t "YOUR_TASK"` - is the easiest way to start.
Expand Down
4 changes: 3 additions & 1 deletion agents/getFiles.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const getRelevantFiles = require('./getFiles');
const dotenv = require('dotenv');

require('dotenv').config();
dotenv.config();
dotenv.config({ path: path.posix.join(os.homedir(), '.autopilot', '.env') });

describe('getRelevantFiles', () => {
const summaries = `
Expand Down
6 changes: 3 additions & 3 deletions modules/fsInput.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
const fs = require('fs');
const path = require('path');
require('dotenv').config();
const hashFile = require('./hashing');
const { countTokens } = require('./tokenHelper');

const ignoreList = process.env.IGNORE_LIST.split(',');
const fileExtensionsToProcess = process.env.FILE_EXTENSIONS_TO_PROCESS.split(',');

/**
* Recursively scans the directory specified by 'dir', searching for project files.
Expand All @@ -17,6 +14,9 @@ const fileExtensionsToProcess = process.env.FILE_EXTENSIONS_TO_PROCESS.split(','
* @returns {string[]} An array of absolute file paths for all project files found.
*/
function getFilePaths(dir) {
const ignoreList = process.env.IGNORE_LIST.split(',');
const fileExtensionsToProcess = process.env.FILE_EXTENSIONS_TO_PROCESS.split(',');

const files = fs.readdirSync(dir);
const projectFiles = [];

Expand Down
1 change: 0 additions & 1 deletion modules/gpt.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
const chalk = require('chalk');
require('dotenv').config()
const { Configuration, OpenAIApi } = require("openai");
const {saveLog} = require('./fsOutput');

Expand Down
74 changes: 55 additions & 19 deletions modules/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,70 @@ const { createDB } = require('./db');
const fs = require('fs');
const { codeBaseFullIndex, codeBaseFullIndexInteractive } = require('./codeBase');
const { getCodeBaseAutopilotDirectory } = require('./autopilotConfig');
const chalk = require('chalk');
const openAIApiKeyLength = 51;

/**
*
* @returns {Promise<string>} OpenAIKey
*/
async function askForOpenAIKey(){
const prompts = require('prompts');

const openAIApiKey = await prompts({
type: 'password',
name: 'value',
require: true,
message: 'OpenAIKey (https://platform.openai.com/account/api-keys)',
validate: value => value.length == openAIApiKeyLength ? true : 'Please enter an OpenAIKey'
});
return openAIApiKey.value;
}

/**
*
* @param {string} codeBaseDirectory
*/
async function initCodeBase(codeBaseDirectory, interactive){
model = process.env.INDEXER_MODEL;
// Create directory `__CODEBASE__/.autopilot`
codeBaseAutopilotDirectory = getCodeBaseAutopilotDirectory(codeBaseDirectory);

if (!fs.existsSync(codeBaseAutopilotDirectory)){
fs.mkdirSync(codeBaseAutopilotDirectory);
if (!process.env.OPENAI_API_KEY || process.env.OPENAI_API_KEY.length < openAIApiKeyLength) {
const os = require('os');
const openAIApiKey = await askForOpenAIKey();
const homeAutopilotDirectory = path.join(os.homedir(), '.autopilot');
if (!fs.existsSync(homeAutopilotDirectory)){
fs.mkdirSync(homeAutopilotDirectory);
}
const homeEnvPath = path.join(homeAutopilotDirectory, '.env');
const homeEnvContent = `OPENAI_API_KEY=${openAIApiKey}`;

fs.writeFileSync(homeEnvPath, homeEnvContent);
console.log(chalk.green(`OpenAIKey saved to ${homeEnvPath}`));

const dotenv = require('dotenv');
dotenv.config({ path: path.posix.join(os.homedir(), '.autopilot', '.env') });
}

model = process.env.INDEXER_MODEL;
// Create directory `__CODEBASE__/.autopilot`
codeBaseAutopilotDirectory = getCodeBaseAutopilotDirectory(codeBaseDirectory);

if (!fs.existsSync(codeBaseAutopilotDirectory)){
fs.mkdirSync(codeBaseAutopilotDirectory);
}

// Create config file `__CODEBASE__/.autopilot/config.json`
// TODO: Refactor include/exclude lists into codebase config file

// Create config file `__CODEBASE__/.autopilot/config.json`
// TODO: Refactor include/exclude lists into codebase config file

const { getDBFilePath } = require('./db');
// Bootstrap DB
if (!fs.existsSync(getDBFilePath(codeBaseDirectory))){
createDB(codeBaseDirectory);
// Trigger codeBase indexing
if (interactive){
await codeBaseFullIndexInteractive(codeBaseDirectory, model);
} else {
await codeBaseFullIndex(codeBaseDirectory);
}
const { getDBFilePath } = require('./db');
// Bootstrap DB
if (!fs.existsSync(getDBFilePath(codeBaseDirectory))){
createDB(codeBaseDirectory);
// Trigger codeBase indexing
if (interactive){
await codeBaseFullIndexInteractive(codeBaseDirectory, model);
} else {
await codeBaseFullIndex(codeBaseDirectory);
}
}
}

module.exports = { initCodeBase }
12 changes: 6 additions & 6 deletions modules/interactiveTask.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ async function getTaskInput() {
const prompts = require('prompts');

const response = await prompts({
type: 'text',
name: 'task',
message: 'Please enter your TASK (multiline supported):',
multiline: true,
validate: value => value.length > 0 ? true : 'Please enter a task'
});
type: 'text',
name: 'task',
message: 'Please enter your TASK (multiline supported):',
multiline: true,
validate: value => value.length > 0 ? true : 'Please enter a task'
});

return response.task;
}
Expand Down
5 changes: 4 additions & 1 deletion modules/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ const { OpenAI } = require('langchain/llms');
function getModel(modelType){
let model
if (['gpt-3.5-turbo', 'gpt-4'].includes(modelType)) {
if (!process.env.OPENAI_API_KEY) {
throw new Error('OPENAI_API_KEY not found.');
}
model = new OpenAI({
modelName: modelType,
maxTokens: parseInt(process.env.OPENAI_MAX_TOKEN_REPLY),
Expand All @@ -26,4 +29,4 @@ function getModel(modelType){
return model
}

module.exports = { getModel }
module.exports = { getModel };
15 changes: 11 additions & 4 deletions modules/summaries.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
require('dotenv').config()
const { countTokens } = require('./tokenHelper')
const chalk = require('chalk');
const path = require('path');
const { parseFileContent } = require('./fsInput');
const { getDB, insertOrUpdateFile } = require('./db');

const summaryStringDelimiter = "\n---\n";
const maxTokenSingleFile = process.env.MAX_TOKEN_COUNT_SINGLE_FILE;
const maxSummaryTokenCount = process.env.MAX_TOKEN_COUNT_SUMMARIES_CHUNK;

function getMaxTokenSingleFile(){
return process.env.MAX_TOKEN_COUNT_SINGLE_FILE;
}

function getMaxSummaryTokenCount(){
return process.env.MAX_TOKEN_COUNT_SUMMARIES_CHUNK;
}

const types = {
FileObject: {
Expand Down Expand Up @@ -113,7 +118,9 @@ async function getSummaries(codeBaseDirectory){
* @param {string} fileContent - The content of the file being processed.
*/
async function generateAndWriteFileSummary(codeBaseDirectory, filePathRelative, fileContent) {
const maxTokenSingleFile = getMaxTokenSingleFile();
const { fileSummary } = require('../agents/indexer');


const filePathFull = path.join(codeBaseDirectory, filePathRelative);
const parsedFile = parseFileContent(codeBaseDirectory, filePathFull, fileContent);
Expand Down Expand Up @@ -162,6 +169,6 @@ module.exports = {
types,
getSummaries,
chunkSummaries,
maxSummaryTokenCount,
getMaxSummaryTokenCount,
generateAndWriteFileSummary
}
8 changes: 7 additions & 1 deletion ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
const chalk = require('chalk');
const path = require('path');
const fs = require('fs');
const dotenv = require('dotenv');
const os = require('os');

const { getSummaries, chunkSummaries, maxSummaryTokenCount } = require('./modules/summaries');
const { getSummaries, chunkSummaries, getMaxSummaryTokenCount } = require('./modules/summaries');
const { saveOutput, logPath, updateFile, newLog } = require('./modules/fsOutput');
const { printGitDiff } = require('./modules/gitHelper');
const { getFiles } = require('./modules/fsInput');
Expand All @@ -24,6 +26,8 @@ const { getRelevantFiles } = require('./agents/getFiles');
* @returns {Array} - Array with file and code
*/
async function main(task, test=false, suggestionMode) {
dotenv.config();
dotenv.config({ path: path.posix.join(os.homedir(), '.autopilot', '.env') });
newLog();
const options = getOptions(task, test);
let codeBaseDirectory = options.dir;
Expand All @@ -45,6 +49,7 @@ async function main(task, test=false, suggestionMode) {
// init, reindex, or gap fill
const { initCodeBase } = require('./modules/init');
await initCodeBase(codeBaseDirectory, interactive);
dotenv.config({ path: path.posix.join(os.homedir(), '.autopilot', '.env') });
if (reindex){
await reindexCodeBase(codeBaseDirectory, process.env.INDEXER_MODEL, interactive);
}
Expand All @@ -57,6 +62,7 @@ async function main(task, test=false, suggestionMode) {
task = await getTask(task, options);

// Get the summaries of the files in the directory
const maxSummaryTokenCount = getMaxSummaryTokenCount();
const summaries = await getSummaries(codeBaseDirectory);
const chunkedSummaries = chunkSummaries(summaries, maxSummaryTokenCount);
console.log(`Split summaries into ${chalk.yellow(chunkedSummaries.length)} chunks of up to ${chalk.yellow(maxSummaryTokenCount)} tokens each. (an agent would run for each)`)
Expand Down