#pragma once #include "PrimitivesRegistry.h" #include "ast/Function.h" #include "ast/Parameter.h" #include "ast/Statement.h" #include "ast/Expression.h" #include #include #include struct AgentCodeGenResult { ASTNode* node = nullptr; std::string note; std::vector usedSymbols; }; class AgentCodeGen { public: AgentCodeGenResult generate(const std::string& spec, PrimitivesRegistry& registry, const std::string& language, bool preferImports) const { AgentCodeGenResult result; auto functions = registry.getAvailableFunctions(); if (functions.empty()) { result.note = "No available functions; returning empty stub."; result.node = makeEmptyFunction("generated"); return result; } PrimitiveSymbol chosen = chooseFunction(functions, preferImports); result.usedSymbols.push_back(chosen.name); auto* fn = new Function(nextId("fn"), "generated"); auto* param = new Parameter(nextId("param"), "input"); fn->addChild("parameters", param); auto* call = new FunctionCall(); call->id = nextId("call"); call->functionName = chosen.name; call->addChild("arguments", new VariableReference(nextId("var"), "input")); auto* stmt = new ExpressionStatement(); stmt->id = nextId("exprstmt"); stmt->setChild("expression", call); fn->addChild("body", stmt); result.node = fn; result.note = buildNote(spec, chosen, language); return result; } private: static PrimitiveSymbol chooseFunction(const std::vector& funcs, bool preferImports) { if (preferImports) { for (const auto& sym : funcs) { if (sym.source == "import" && !sym.vulnerable) return sym; } for (const auto& sym : funcs) { if (sym.source == "import") return sym; } } for (const auto& sym : funcs) { if (sym.source == "builtin") return sym; } return funcs.front(); } static Function* makeEmptyFunction(const std::string& name) { auto* fn = new Function(nextId("fn"), name); return fn; } static std::string buildNote(const std::string& spec, const PrimitiveSymbol& sym, const std::string& language) { std::string note = "Generated using " + sym.name + " (" + sym.source + ")"; if (!spec.empty()) note += " for spec: " + spec; if (!language.empty()) note += " in " + language; if (!sym.tags.empty()) { note += " | tags: "; for (size_t i = 0; i < sym.tags.size(); ++i) { if (i > 0) note += ", "; note += sym.tags[i]; } } return note; } static std::string nextId(const std::string& prefix) { static int counter = 0; return prefix + "_" + std::to_string(counter++); } };