Spaces:
Runtime error
Runtime error
File size: 4,297 Bytes
b6cd280 b5e4648 801e523 fc99222 b6cd280 b5e4648 b6cd280 b5e4648 fc99222 b5e4648 fc99222 b5e4648 b6cd280 b5e4648 fc99222 b5e4648 fc99222 b5e4648 fc99222 b5e4648 fc99222 b5e4648 fc99222 b5e4648 fc99222 b5e4648 b6cd280 b5e4648 b6cd280 b5e4648 b6cd280 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | import { END, type GraphNode, START, StateGraph } from "@langchain/langgraph";
import { CoderState } from "./state.ts";
import { solidityCoderPrompt, solidityFixPrompt, solidityReviewPrompt } from "./prompts.ts";
import { compileSolidityTool } from "./tools/compile-solidity.ts";
import { createLLM } from "../../config/llm.ts";
import { emitStep } from "../../logger.ts";
const MAX_FIX_ATTEMPTS = 3;
/**
* Extrai apenas o bloco de c贸digo Solidity de uma resposta do LLM.
*/
function extractSolidityCode(text: string): string {
const match = text.match(/```(?:solidity)?\s*\n([\s\S]*?)```/);
if (match) return match[1].trim();
// Se n茫o tem bloco de c贸digo, assume que a resposta inteira 茅 c贸digo
return text.trim();
}
/**
* N贸 1: Gera o smart contract a partir dos requisitos.
*/
const generateContract: GraphNode<typeof CoderState> = async (state) => {
emitStep({ agent: "coder", step: "gen", status: "running" });
const llm = createLLM();
const chain = solidityCoderPrompt.pipe(llm);
const requirementsText = state.requirements
.map((r, i) => `${i + 1}. ${r}`)
.join("\n");
const result = await chain.invoke({ requirements: requirementsText });
const code = extractSolidityCode(
typeof result.content === "string" ? result.content : JSON.stringify(result.content),
);
emitStep({ agent: "coder", step: "gen", status: "done" });
return { contract: code, compilationErrors: [] };
};
/**
* N贸 2: Compila o contrato e armazena erros (se houver).
*/
const compileContract: GraphNode<typeof CoderState> = async (state) => {
emitStep({ agent: "coder", step: "compile", status: "running" });
const result = await compileSolidityTool.invoke({
sourceCode: state.contract,
filename: "Contract.sol",
});
if (result.errors.length === 0) {
emitStep({ agent: "coder", step: "compile", status: "done" });
}
return { compilationErrors: result.errors };
};
/**
* N贸 3: Corrige o contrato com base nos erros de compila莽茫o.
*/
const fixContract: GraphNode<typeof CoderState> = async (state) => {
emitStep({ agent: "coder", step: "compile", status: "running", detail: `fix ${fixAttempts}/${MAX_FIX_ATTEMPTS}` });
const llm = createLLM();
const chain = solidityFixPrompt.pipe(llm);
const errorsText = state.compilationErrors.join("\n\n");
const result = await chain.invoke({
contract: state.contract,
errors: errorsText,
});
const code = extractSolidityCode(
typeof result.content === "string" ? result.content : JSON.stringify(result.content),
);
return { contract: code, compilationErrors: [] };
};
/**
* N贸 4: Revisa o contrato compilado quanto a seguran莽a e boas pr谩ticas.
*/
const reviewContract: GraphNode<typeof CoderState> = async (state) => {
emitStep({ agent: "coder", step: "review", status: "running" });
const llm = createLLM();
const chain = solidityReviewPrompt.pipe(llm);
const requirementsText = state.requirements.join(", ");
const result = await chain.invoke({
requirements: requirementsText,
contract: state.contract,
});
const summary =
typeof result.content === "string" ? result.content : JSON.stringify(result.content);
emitStep({ agent: "coder", step: "review", status: "done" });
return { reviewSummary: summary };
};
/**
* Roteador: decide se precisa corrigir ou se pode seguir para revis茫o.
* Controla o n煤mero de tentativas de corre莽茫o.
*/
let fixAttempts = 0;
function shouldFix(state: { compilationErrors: string[] }): "fixContract" | "reviewContract" {
if (state.compilationErrors.length > 0 && fixAttempts < MAX_FIX_ATTEMPTS) {
fixAttempts++;
return "fixContract";
}
if (state.compilationErrors.length > 0) {
emitStep({ agent: "coder", step: "compile", status: "error" });
}
fixAttempts = 0;
return "reviewContract";
}
export const coderAgent = new StateGraph(CoderState)
.addNode("generateContract", generateContract)
.addNode("compileContract", compileContract)
.addNode("fixContract", fixContract)
.addNode("reviewContract", reviewContract)
.addEdge(START, "generateContract")
.addEdge("generateContract", "compileContract")
.addConditionalEdges("compileContract", shouldFix)
.addEdge("fixContract", "compileContract")
.addEdge("reviewContract", END)
.compile();
|