Skip to content

Commit

Permalink
improvement boiletplate, fix sendChat endpoint, wip
Browse files Browse the repository at this point in the history
  • Loading branch information
r4zendev committed Jul 17, 2024
1 parent 2d6a555 commit 83cbf30
Show file tree
Hide file tree
Showing 11 changed files with 283 additions and 216 deletions.
117 changes: 88 additions & 29 deletions apps/cli/src/commands/learn.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
import * as fs from "node:fs";
import { readFile } from "node:fs/promises";
import { dirname, extname, resolve, sep } from "node:path";
import { type PrinterBlueprint, chalk } from "@codemod-com/printer";
import { type KnownEngines, doubleQuotify } from "@codemod-com/utilities";
import { parseCodemodSettings, transpile } from "@codemod-com/runner";
import {
type KnownEngines,
TarService,
doubleQuotify,
} from "@codemod-com/utilities";
import { AxiosError } from "axios";
import inquirer from "inquirer";
import open from "open";
import { createCodeDiff } from "../apis.js";
import { createCodeDiff, sendAIRequest } from "../apis.js";
import { buildSourcedCodemodOptions } from "../buildCodemodOptions.js";
import {
findModifiedFiles,
getFileFromCommit,
getGitDiffForFile,
getLatestCommitHash,
isFileInGitDirectory,
} from "../gitCommands.js";
import { getCodemodPrompt, getCurrentUserOrLogin } from "../utils.js";

// remove all special characters and whitespaces
const removeSpecialCharacters = (str: string) =>
Expand Down Expand Up @@ -63,8 +71,9 @@ export const handleLearnCliCommand = async (options: {
printer: PrinterBlueprint;
target: string | null;
source: string | null;
engine: string | null;
}) => {
const { printer, target, source } = options;
const { printer, target, source, engine } = options;

if (target !== null && !isFileInGitDirectory(target)) {
printer.printOperationMessage({
Expand Down Expand Up @@ -252,35 +261,85 @@ export const handleLearnCliCommand = async (options: {
);

if (source !== null) {
const userData = await getCurrentUserOrLogin({
message: "Please login to continue.",
printer,
});

const codemodSettings = parseCodemodSettings({ source, engine });
if (codemodSettings.kind !== "runSourced") {
return printer.printOperationMessage({
kind: "error",
message: "Unexpected codemod settings parsing result.",
});
}

const tarService = new TarService(fs);

// Improve existing codemod
await Promise.all(
Object.entries(diffs).map(async ([path, fileDiffs]) =>
fileDiffs.map(({ before, after }, i) => {
const spinner = printer.withLoaderMessage(
`Processing diff #${i + 1}`,
);

try {
// 1. send request to AI service
// 2. update the codemod in the source by adding the test fixture and updating the source code
spinner.succeed();
} catch (err) {
spinner.fail();
const error = err as AxiosError<{ message: string }> | Error;
printer.printConsoleMessage(
"error",
`Failed to process diff for file: ${path} - ${
error instanceof AxiosError
? error.response?.data.message
: error.message
}`,
);
return;
}
}),
),
const codemod = await buildSourcedCodemodOptions(
fs,
printer,
codemodSettings,
{ download: () => void 0 as any },
tarService,
);

if (codemod.engine !== "jscodeshift") {
return printer.printOperationMessage({
kind: "error",
message: "Recipe codemods are not supported for improving.",
});
}

let existingCodemodSource: string;
try {
const codemodSource = await readFile(codemod.indexPath, {
encoding: "utf8",
});

existingCodemodSource = codemod.indexPath.endsWith(".ts")
? transpile(codemodSource.toString())
: codemodSource.toString();
} catch (err) {
return printer.printOperationMessage({
kind: "error",
message: "Unexpected error occurred while reading the codemod source.",
});
}

const prompt = getCodemodPrompt({
type: "improve",
testCases: Object.values(diffs).flat(),
existingCodemodSource,
});

const chatSpinner = printer.withLoaderMessage("Improving your codemod...");

try {
// 1. send request to AI service
const response = await sendAIRequest({
accessToken: userData.token,
prompt,
});

console.log(response);
// 2. update the codemod in the source by adding the test fixture and updating the source code
chatSpinner.succeed();
} catch (err) {
chatSpinner.fail();
const error = err as AxiosError<{ message: string }> | Error;

return printer.printConsoleMessage(
"error",
`Failed to send an API request to the AI service:\n ${
error instanceof AxiosError
? error.response?.data.errorText
: error.message
}`,
);
}

return;
}

Expand Down
6 changes: 6 additions & 0 deletions apps/cli/src/executeMainThread.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,11 @@ export const executeMainThread = async () => {
alias: "s",
type: "string",
description: "path to the codemod to improve on top of",
})
.option("engine", {
type: "string",
description: "the engine to use with the standalone codemod",
hidden: true,
}),
async (args) => {
const { executeCliCommand, printer } =
Expand All @@ -243,6 +248,7 @@ export const executeMainThread = async () => {
printer,
target: args.target ?? null,
source: args.source ?? null,
engine: args.engine ?? null,
}),
);
},
Expand Down
33 changes: 18 additions & 15 deletions apps/cli/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,12 @@ const generateCodemodContext = `### Context

const improveCodemodContext = `### Context
- You will be provided with BEFORE and AFTER code snippet pairs and an existing codemod that might or might not satisfy them.
- An existing codemod is located in a zip archive sent to you.
- Use the provided jscodeshift codemod and see whether it would turn each BEFORE snippet into corresponding AFTER snippet.
- Identify common patterns and improve the codemod to handle all cases.
- Use only jscodeshift and TypeScript.
- If comments in AFTER snippets describe the transformation, do not preserve them.
- Only include the generated codemod in your response, no extra explanations.
- Only include the download link for the archive with updated code in your response, no extra explanations or text.
- Comment your code following best practices.
- Do not import 'namedTypes' or 'builders' from jscodeshift.
- Always narrow node types using typeguards before accessing their properties.
Expand Down Expand Up @@ -380,20 +381,22 @@ const isVariableDeclarator = root.find(j.VariableDeclarator).at(0).isOfType('Var
\`\`\`
`;

export function getCodemodPrompt(
type: "generate",
testCases: { before: string; after: string }[],
): string;
export function getCodemodPrompt(
type: "improve",
testCases: { before: string; after: string }[],
existingCodemodSource: string,
): string;
export function getCodemodPrompt(
type: "improve" | "generate",
testCases: { before: string; after: string }[],
existingCodemodSource?: string,
) {
export function getCodemodPrompt(options: {
type: "generate";
testCases: { before: string; after: string }[];
}): string;
export function getCodemodPrompt(options: {
type: "improve";
testCases: { before: string; after: string }[];
existingCodemodSource: string;
}): string;
export function getCodemodPrompt(options: {
type: "improve" | "generate";
testCases: { before: string; after: string }[];
existingCodemodSource?: string;
}) {
const { type, testCases, existingCodemodSource } = options;

return `${type === "generate" ? generateCodemodContext : improveCodemodContext}
${
Expand Down
1 change: 1 addition & 0 deletions apps/modgpt/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ RUN pnpm install

# Copy the remaining application files
COPY apps/modgpt/tsconfig.json apps/modgpt/
COPY apps/modgpt/reset.d.ts apps/modgpt/
COPY apps/modgpt/esbuild.config.js apps/modgpt/
COPY apps/modgpt/src apps/modgpt/src/

Expand Down
2 changes: 2 additions & 0 deletions apps/modgpt/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"author": "Codemod inc.",
"license": "ISC",
"dependencies": {
"@codemod-com/api-types": "workspace:*",
"@codemod-com/auth": "workspace:*",
"@fastify/cors": "catalog:",
"@fastify/multipart": "catalog:",
Expand All @@ -19,6 +20,7 @@
"chatgpt": "catalog:",
"dotenv": "catalog:",
"fastify": "catalog:",
"openai": "catalog:",
"openai-edge": "catalog:",
"replicate": "catalog:",
"ts-node": "^10.9.2",
Expand Down
2 changes: 2 additions & 0 deletions apps/modgpt/reset.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Do not add any other lines of code to this file!
import "@total-typescript/ts-reset";
Loading

0 comments on commit 83cbf30

Please sign in to comment.