local lang = jarvis.context.language local phrase = (jarvis.context.phrase or ""):lower() local triggers = { "сгенерируй скрипт", "напиши скрипт", "сделай скрипт", "сгенерируй код", "набросай код", "напиши код", "generate code", "write code", "make script", "write script", "згенеруй код", "напиши код", "зроби скрипт", } local request = phrase for _, t in ipairs(triggers) do local s, e = string.find(request, t, 1, true) if s == 1 then request = request:sub(e + 1) break end end request = request:gsub("^%s+", ""):gsub("%s+$", "") if request == "" then jarvis.system.notify( lang == "ru" and "Codegen" or "Codegen", lang == "ru" and "Что писать?" or "What to write?" ) jarvis.audio.play_error() return { chain = false } end local token = jarvis.system.env("GROQ_TOKEN") if not token or token == "" then jarvis.log("error", "GROQ_TOKEN not set") jarvis.system.notify("Codegen", "GROQ_TOKEN не задан") jarvis.audio.play_error() return { chain = false } end local base = jarvis.system.env("GROQ_BASE_URL") if not base or base == "" then base = "https://api.groq.com/openai/v1" end local model = jarvis.system.env("GROQ_MODEL") if not model or model == "" then model = "llama-3.3-70b-versatile" end local system_prompt = lang == "ru" and "Ты Senior Engineer. На запрос пользователя верни ТОЛЬКО исходный код, без обрамления ``` и без объяснений. Если язык не задан — выбери самый подходящий (по умолчанию Python). Не добавляй комментарии-болтовню." or "You are a Senior Engineer. Reply with ONLY source code, no ``` fences, no commentary. Pick the most fitting language if unspecified (Python by default). Skip chatty comments." jarvis.log("info", "codegen request: " .. request) local payload = { model = model, messages = { { role = "system", content = system_prompt }, { role = "user", content = request }, }, max_tokens = 1024, temperature = 0.2, } local headers = { Authorization = "Bearer " .. token } local res = jarvis.http.post_json(base .. "/chat/completions", payload, headers) if not res.ok then jarvis.log("error", "codegen API failed: status=" .. tostring(res.status) .. " body=" .. tostring(res.body):sub(1, 200)) jarvis.system.notify("Codegen", "Ошибка API: " .. tostring(res.status)) jarvis.audio.play_error() return { chain = false } end local body = res.body or "" local content = body:match('"content"%s*:%s*"(.-[^\\])"') if not content then jarvis.log("error", "codegen: could not parse content from " .. body:sub(1, 200)) jarvis.system.notify("Codegen", "Не смог распарсить ответ") jarvis.audio.play_error() return { chain = false } end content = content:gsub('\\n', '\n') content = content:gsub('\\"', '"') content = content:gsub('\\\\', '\\') content = content:gsub('\\t', '\t') content = content:gsub("^```[%w]*\n?", "") content = content:gsub("\n?```%s*$", "") content = content:gsub("^%s+", ""):gsub("%s+$", "") jarvis.system.clipboard.set(content) jarvis.log("info", "codegen result copied to clipboard (" .. #content .. " bytes)") local preview = content:sub(1, 120) if #content > 120 then preview = preview .. "..." end jarvis.system.notify( lang == "ru" and "Код в буфере" or "Code in clipboard", preview ) jarvis.audio.play_ok() return { chain = false }