diff --git a/.gitignore b/.gitignore index 9fabb39..bf6a354 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,49 @@ -node_modules -bin -.vscode -vscode/out \ No newline at end of file +# Dépendances +node_modules/ +package-lock.json + +# Builds et fichiers compilés +dist/ +build/ +out/ +*.tsbuildinfo + +# Résultats de test +coverage/ +test-results/ +jest-html-reporters-*.html +*.log + +# Configuration locale (VS Code, IDE...) +.vscode/ +.idea/ +*.swp +*.swo + +# Fichiers temporaires +tmp/ +temp/ +*.tmp +*.bak + +# Fichiers médias et captures +*.gif +*.mp4 +*.avi +*.mov + +# Configs système/OS +.DS_Store +Thumbs.db + +# Secrets (à ne jamais versionner !) +.env +.env.* +secret.* +credentials.json + +# Ignorer les fichiers de debug +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/bin/command.js b/bin/command.js new file mode 100644 index 0000000..78569cd --- /dev/null +++ b/bin/command.js @@ -0,0 +1,147 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.executeForFile = exports.executeCommand = exports.parseCommand = void 0; +const fs_1 = __importDefault(require("fs")); +const path_1 = __importDefault(require("path")); +const commander_1 = require("commander"); +const chalk_1 = __importDefault(require("chalk")); +const const_1 = require("./const"); +const types_1 = require("./types"); +const utils_1 = require("./utils"); +const ajv_1 = __importDefault(require("ajv")); +const parseCommand = () => { + commander_1.program + .option("-i, --inputFile ") + .option("-o, --outputFile ") + .option("-k, --apiKey ") + .option("-m, --model ") + .option("-p, --promptTemplate ") + .option("-y, --systemMessage ") + .option("-t, --techs ") + .option("-n, --instructions ") + .option("-x, --examples ") + .option("-c, --config ") + .option("-s, --stream") + .option("-e, --modelEndpoint ") + .option("-h, --help"); + commander_1.program.parse(); + const options = commander_1.program.opts(); + if (options.help) { + console.log(chalk_1.default.blue(`Usage: testgpt -i -o -k -m -t -p -c `)); + console.log(chalk_1.default.green("\r\nAll fields are optional except for the input file. If no output file is provided, the default will be used.")); + // exit the program + process.exit(0); + } + return options; +}; +exports.parseCommand = parseCommand; +const executeCommand = (args) => __awaiter(void 0, void 0, void 0, function* () { + const { help, inputFile, outputFile } = args; + if (help) { + console.log(chalk_1.default.blue(`Usage: testgpt -i -o -k -m -t -p -c `)); + console.log(chalk_1.default.green("\r\nAll fields are optional except inputFile. If no inputFile is provided, the default will be used.")); + // exit the program + process.exit(0); + } + const isInputDirectory = (0, utils_1.getFileType)(inputFile) === utils_1.EFileType.Directory; + const isOutputDirectory = outputFile && (0, utils_1.getFileType)(outputFile) === utils_1.EFileType.Directory; + if (isInputDirectory && outputFile && !isOutputDirectory) { + console.error(chalk_1.default.red("If inputFile is a directory, outputFile must also be a directory")); + process.exit(1); + } + if (isInputDirectory) { + // if outputDirectory is not provided, use the inputDirectory + const outputDirectory = outputFile || inputFile; + const files = fs_1.default.readdirSync(inputFile); + for (const file of files) { + const inputFilePath = path_1.default.join(inputFile, file); + const { name: inputFileName, extension } = (0, utils_1.divideFileName)(inputFilePath); + const outputFilePath = path_1.default.join(outputDirectory, `${inputFileName}.test${extension}`); + yield (0, exports.executeForFile)(Object.assign(Object.assign({}, args), { inputFile: inputFilePath, outputFile: outputFilePath })); + } + } + else { + yield (0, exports.executeForFile)(args); + } + process.exit(0); +}); +exports.executeCommand = executeCommand; +const executeForFile = (_a) => __awaiter(void 0, [_a], void 0, function* ({ inputFile, outputFile, apiKey, model, systemMessage, promptTemplate, techs, instructions, examples, config, stream, modelEndpoint, }) { + var _b, _c, _d; + if (examples && typeof examples === "string") { + const ajv = new ajv_1.default(); + const validate = ajv.compile(types_1.examplesSchema); + examples = JSON.parse(examples); + const valid = validate(examples); + if (!valid) { + console.error(chalk_1.default.red("Invalid examples format")); + console.error(chalk_1.default.red(JSON.stringify(validate.errors, null, 2))); + process.exit(1); + } + } + let { extension: inputFileExtension } = (0, utils_1.divideFileName)(inputFile); + if (!inputFile) { + console.error(chalk_1.default.red("Please provide an input file")); + process.exit(1); + } + console.log(chalk_1.default.blue(`Reading ${const_1.CONFIG_FILE_NAME}...`)); + const configFilePath = path_1.default.join(process.cwd(), `${const_1.CONFIG_FILE_NAME}`); + let testGPTConfig = {}; + if (fs_1.default.existsSync(configFilePath)) { + console.log(chalk_1.default.green("Config file found, using..")); + testGPTConfig = (0, utils_1.readYamlFile)(config || path_1.default.join(process.cwd(), `${const_1.CONFIG_FILE_NAME}`)); + } + else { + if (techs) { + console.log(chalk_1.default.blue(`Config file not found, using passed config`)); + testGPTConfig = { + [inputFileExtension]: { + techs: (techs === null || techs === void 0 ? void 0 : techs.split(",")) || [], + instructions: (instructions === null || instructions === void 0 ? void 0 : instructions.split(",")) || [], + examples: [], + }, + }; + } + else { + console.log(chalk_1.default.blue(`Config file not found, continuing with default config`)); + } + } + if (!outputFile) { + const inputFileWithoutExtension = inputFile.replace(inputFileExtension, ""); + outputFile = `${inputFileWithoutExtension}.test${inputFileExtension}`; + console.log(chalk_1.default.blue("No output file provided, using default.")); + console.log(chalk_1.default.yellow(`Output file: ${outputFile}`)); + } + const parsedTechs = (_b = testGPTConfig === null || testGPTConfig === void 0 ? void 0 : testGPTConfig[inputFileExtension]) === null || _b === void 0 ? void 0 : _b.techs; + const parsedInstructions = (_c = testGPTConfig === null || testGPTConfig === void 0 ? void 0 : testGPTConfig[inputFileExtension]) === null || _c === void 0 ? void 0 : _c.instructions; + examples !== null && examples !== void 0 ? examples : (examples = (_d = testGPTConfig === null || testGPTConfig === void 0 ? void 0 : testGPTConfig[inputFileExtension]) === null || _d === void 0 ? void 0 : _d.examples); + apiKey !== null && apiKey !== void 0 ? apiKey : (apiKey = process.env.HUGGINGFACE_API_KEY); + model !== null && model !== void 0 ? model : (model = const_1.DEFAULT_MODEL); + yield (0, utils_1.autoTest)({ + inputFile, + outputFile, + apiKey, + model: model, + systemMessage, + promptTemplate, + examples, + techs: parsedTechs, + instructions: parsedInstructions, + stream, + modelEndpoint, + }); +}); +exports.executeForFile = executeForFile; +//# sourceMappingURL=command.js.map \ No newline at end of file diff --git a/bin/command.js.map b/bin/command.js.map new file mode 100644 index 0000000..26112a8 --- /dev/null +++ b/bin/command.js.map @@ -0,0 +1 @@ +{"version":3,"file":"command.js","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/bin/const.js b/bin/const.js new file mode 100644 index 0000000..969388a --- /dev/null +++ b/bin/const.js @@ -0,0 +1,6 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.DEFAULT_MODEL = exports.CONFIG_FILE_NAME = void 0; +exports.CONFIG_FILE_NAME = "testgpt.config.yaml"; +exports.DEFAULT_MODEL = "HuggingFaceH4/zephyr-7b-beta"; +//# sourceMappingURL=const.js.map \ No newline at end of file diff --git a/bin/const.js.map b/bin/const.js.map new file mode 100644 index 0000000..642e070 --- /dev/null +++ b/bin/const.js.map @@ -0,0 +1 @@ +{"version":3,"file":"const.js","sourceRoot":"","sources":["../src/const.ts"],"names":[],"mappings":";;;AAAa,QAAA,gBAAgB,GAAG,qBAAqB,CAAC;AACzC,QAAA,aAAa,GAAG,8BAA8B,CAAC"} \ No newline at end of file diff --git a/bin/index.js b/bin/index.js new file mode 100644 index 0000000..0c0f3ad --- /dev/null +++ b/bin/index.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const command_1 = require("./command"); +const options = (0, command_1.parseCommand)(); +(0, command_1.executeCommand)(options); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/bin/index.js.map b/bin/index.js.map new file mode 100644 index 0000000..742d5e1 --- /dev/null +++ b/bin/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,uCAAyD;AAEzD,MAAM,OAAO,GAAG,IAAA,sBAAY,GAAE,CAAC;AAE/B,IAAA,wBAAc,EAAC,OAAO,CAAC,CAAC"} \ No newline at end of file diff --git a/bin/types.js b/bin/types.js new file mode 100644 index 0000000..3f0bb62 --- /dev/null +++ b/bin/types.js @@ -0,0 +1,28 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ERole = exports.examplesSchema = void 0; +exports.examplesSchema = { + type: "array", + items: { + type: "object", + required: ["fileName", "code", "tests"], + properties: { + fileName: { + type: "string", + }, + code: { + type: "string", + }, + tests: { + type: "string", + }, + }, + }, +}; +var ERole; +(function (ERole) { + ERole["User"] = "user"; + ERole["System"] = "system"; + ERole["Assistant"] = "assistant"; +})(ERole || (exports.ERole = ERole = {})); +//# sourceMappingURL=types.js.map \ No newline at end of file diff --git a/bin/types.js.map b/bin/types.js.map new file mode 100644 index 0000000..8f915de --- /dev/null +++ b/bin/types.js.map @@ -0,0 +1 @@ +{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;AAwBa,QAAA,cAAc,GAA+B;IACxD,IAAI,EAAE,OAAO;IACb,KAAK,EAAE;QACL,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC;QACvC,UAAU,EAAE;YACV,QAAQ,EAAE;gBACR,IAAI,EAAE,QAAQ;aACf;YACD,IAAI,EAAE;gBACJ,IAAI,EAAE,QAAQ;aACf;YACD,KAAK,EAAE;gBACL,IAAI,EAAE,QAAQ;aACf;SACF;KACF;CACF,CAAC;AAEF,IAAY,KAIX;AAJD,WAAY,KAAK;IACf,sBAAa,CAAA;IACb,0BAAiB,CAAA;IACjB,gCAAuB,CAAA;AACzB,CAAC,EAJW,KAAK,qBAAL,KAAK,QAIhB"} \ No newline at end of file diff --git a/bin/utils.js b/bin/utils.js new file mode 100644 index 0000000..5785bf9 --- /dev/null +++ b/bin/utils.js @@ -0,0 +1,236 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.autoTest = exports.streamTestContent = exports.getTestContent = exports.getMessages = exports.initHuggingFace = exports.readYamlFile = exports.getExampleMessages = exports.getPrompt = exports.parseTemplatePrompt = exports.toList = exports.getFileType = exports.EFileType = exports.divideFileName = exports.writeToFile = exports.readFile = void 0; +const chalk_1 = __importDefault(require("chalk")); +const fs_1 = __importDefault(require("fs")); +const path_1 = __importDefault(require("path")); +const inference_1 = require("@huggingface/inference"); +const yaml_1 = require("yaml"); +const types_1 = require("./types"); +const readFile = (path) => { + try { + const fileContent = fs_1.default.readFileSync(path, "utf-8"); + return fileContent; + } + catch (err) { + console.error(`Error reading file: ${err}`); + return ""; + } +}; +exports.readFile = readFile; +const writeToFile = (path, content, append) => { + try { + fs_1.default.writeFileSync(path, content, { + flag: append ? "a" : "w", + }); + console.log(chalk_1.default.green(`Successfully wrote to file: ${path}`)); + } + catch (err) { + console.error(`Error writing to file: ${err}`); + } +}; +exports.writeToFile = writeToFile; +const divideFileName = (fileName) => { + const extension = path_1.default.extname(fileName); + const name = path_1.default.basename(fileName, extension); + return { name, extension }; +}; +exports.divideFileName = divideFileName; +var EFileType; +(function (EFileType) { + EFileType[EFileType["File"] = 0] = "File"; + EFileType[EFileType["Directory"] = 1] = "Directory"; +})(EFileType || (exports.EFileType = EFileType = {})); +const getFileType = (path) => { + try { + const isDirectory = fs_1.default.lstatSync(path).isDirectory(); + return isDirectory ? EFileType.Directory : EFileType.File; + } + catch (err) { + console.error(`Error getting file type: ${err}`); + return EFileType.File; + } +}; +exports.getFileType = getFileType; +const toList = (arr) => arr.map((tip, index) => `${index + 1}. ${tip}`).join("\r\n"); +exports.toList = toList; +const parseTemplatePrompt = (template, args) => { + const regex = /{(\w+)}/g; + return template.replace(regex, (_, key) => { + return args[key]; + }); +}; +exports.parseTemplatePrompt = parseTemplatePrompt; +const getPrompt = ({ content, fileName, techs, instructions, promptTemplate, }) => { + let prompt = promptTemplate !== null && promptTemplate !== void 0 ? promptTemplate : `Please provide unit tests for the file {fileName} using {techs} +{instructions} + +Please begin your response with \`\`\` and end it with \`\`\` directly. + +Here is the file content: +\`\`\`{content}\`\`\``; + const techsCotent = (techs === null || techs === void 0 ? void 0 : techs.length) ? (0, exports.toList)(techs) : "same techs as the file"; + const instructionsContent = (instructions === null || instructions === void 0 ? void 0 : instructions.join("\r\n")) || ""; + const resultPrompt = (0, exports.parseTemplatePrompt)(prompt, { + content, + fileName, + techs: techsCotent, + instructions: instructionsContent, + }); + return resultPrompt; +}; +exports.getPrompt = getPrompt; +const getExampleMessages = (promptArgs, examples) => { + if (!examples) { + return []; + } + const messages = examples + .map((g) => { + const prompt = (0, exports.getPrompt)(Object.assign(Object.assign({}, promptArgs), { content: g.code, fileName: g.fileName })); + return [ + { + role: types_1.ERole.User, + content: prompt, + }, + { + role: types_1.ERole.Assistant, + content: g.tests, + }, + ]; + }) + .flat(); + return messages; +}; +exports.getExampleMessages = getExampleMessages; +const readYamlFile = (path) => { + const content = (0, exports.readFile)(path); + return (0, yaml_1.parse)(content); +}; +exports.readYamlFile = readYamlFile; +const initHuggingFace = (apiKey) => { + return new inference_1.HfInference(apiKey); +}; +exports.initHuggingFace = initHuggingFace; +const getMessages = (systemMessage, prompt, examples) => { + systemMessage !== null && systemMessage !== void 0 ? systemMessage : (systemMessage = "You are my unit testing assistant, you will help me write unit tests for the files I provide, your reply will only include the unit tests without any additional information, starting your response with ``` and ending it with ``` directly will help me understand your response better."); + return [ + { + role: types_1.ERole.System, + content: systemMessage, + }, + ...examples, + { + role: types_1.ERole.User, + content: prompt, + }, + ]; +}; +exports.getMessages = getMessages; +const getTestContent = (_a) => __awaiter(void 0, [_a], void 0, function* ({ model, messages, openai, }) { + const fullPrompt = messages.map(m => `${m.role}: ${m.content}`).join("\n"); + const response = yield openai.textGeneration({ + model, + inputs: fullPrompt, + parameters: { + max_new_tokens: 1024, + return_full_text: false, + }, + }); + const regex = /^```.*$/gm; + return response.generated_text.replace(regex, "").trim(); +}); +exports.getTestContent = getTestContent; +const streamTestContent = (_a) => __awaiter(void 0, [_a], void 0, function* ({ model, messages, openai, onToken, }) { + const fullPrompt = messages.map(m => `${m.role}: ${m.content}`).join("\n"); + const response = yield openai.textGeneration({ + model, + inputs: fullPrompt, + parameters: { + max_new_tokens: 1024, + return_full_text: false, + }, + }); + const text = response.generated_text; + // Simulation du streaming : on envoie un token � la fois (ou par mot) + for (const token of text.split(" ")) { + onToken(token + " "); // espace pour garder la forme du texte + yield new Promise(resolve => setTimeout(resolve, 30)); // d�lai optionnel + } +}); +exports.streamTestContent = streamTestContent; +const autoTest = (_a) => __awaiter(void 0, [_a], void 0, function* ({ inputFile, outputFile, apiKey, model, systemMessage, promptTemplate, examples, techs, instructions, stream, modelEndpoint, }) { + console.log(chalk_1.default.blue("Reading input file...")); + let content; + try { + content = (0, exports.readFile)(inputFile); + } + catch (err) { + console.error(chalk_1.default.red(`Error reading file: ${err}`)); + process.exit(1); + } + console.log(chalk_1.default.blue("Generating tests...")); + const promptArgs = { + content, + fileName: inputFile, + techs, + instructions, + promptTemplate, + }; + const prompt = (0, exports.getPrompt)(promptArgs); + const exampleMessages = (0, exports.getExampleMessages)(promptArgs, examples); + if (modelEndpoint) { + console.log("Found model endpoint, using it instead of OpenAI API"); + const response = yield fetch(modelEndpoint, { + method: "POST", + body: JSON.stringify({ + prompt, + examples: exampleMessages, + }), + headers: { + "Content-Type": "application/json", + }, + }); + const text = yield response.text(); + (0, exports.writeToFile)(outputFile, text); + return; + } + const messages = (0, exports.getMessages)(systemMessage, prompt, exampleMessages); + const huggingface = yield (0, exports.initHuggingFace)(apiKey); + if (stream) { + const onToken = (token) => { + (0, exports.writeToFile)(outputFile, token, true); + }; + yield (0, exports.streamTestContent)({ + openai: huggingface, + model, + messages, + onToken, + }); + } + else { + const testContent = yield (0, exports.getTestContent)({ + openai: huggingface, + model, + messages, + }); + if (!testContent) { + console.error(chalk_1.default.red("Error generating tests - No tests content")); + process.exit(1); + } + (0, exports.writeToFile)(outputFile, testContent); + } +}); +exports.autoTest = autoTest; +//# sourceMappingURL=utils.js.map \ No newline at end of file diff --git a/bin/utils.js.map b/bin/utils.js.map new file mode 100644 index 0000000..aaf76da --- /dev/null +++ b/bin/utils.js.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/utils.ts b/src/utils.ts index ac9bec9..30b75f9 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -180,7 +180,7 @@ export const getTestContent = async ({ // remove lines that start with ``` (markdown code block) const regex = /^```.*$/gm; - return response.choices[0].message?.content?.replace(regex, ""); + return response.generated_text.replace(regex, "").trim(); }; export interface IStreamTestContentArgs {