#!/usr/bin/env python3 import json import re import urllib.error import urllib.request ASK_API = "https://fission.kube5s.ru/console/api/ai/ask" CHECK_API = "https://fission.kube5s.ru/console/api/ai/check" HEADERS = {"X-Test-Sub": "livetest@test.local", "Content-Type": "application/json"} PROMPT = """Ты генерируешь код одной функции для Fission. Нужно отвечать строго в 3 секциях: 1. Нормализованная задача 2. Один fenced code block 3. Заголовок LLM что делает, затем 2-5 коротких пунктов Правила: - Если ввод кривой, сначала коротко нормализуй задачу. - Если не хватает важного условия, задай один короткий вопрос или опиши допущение. - Не выдумывай лишнюю инфраструктуру, SDK или wrapper-код. - Код должен быть синтаксически корректным и соответствовать runtime выбранного языка. - В секции кода используй ровно один fenced block с языковым идентификатором. - В секции LLM что делает не используй другие заголовки, bold, Explanation или fenced block. Языковые правила: - Node.js: CommonJS без ESM export-обвязки. - Python: обычный entrypoint без лишних импортов. - PHP: обычный PHP-код без выдуманных контрактов. - Ruby: корректный def/end без лишних зависимостей. """ CASES = [ ("nodejs", "Юзер криво сказал: приветствие и не падать если name пустой. Сделай Fission Node.js handler, который читает JSON body, берёт name и отвечает 200 с greeting и default World."), ("nodejs", "Нужна функция для суммы чисел, но формат входа не описан. Сделай Node.js Fission handler: если в JSON есть numbers и это массив, вернуть сумму, иначе 0."), ("python", "Нужна Fission Python функция: если в context есть name, вернуть greeting, иначе default greeting. Ничего лишнего."), ("python", "Юзер просит обработать число и не знает формат. Сделай Python handler для Fission: если в context есть numbers, просуммировать их, иначе вернуть 0."), ("php", "Сделай PHP handler для Fission: name из context, иначе World, ответ JSON 200 с greeting. Без фреймворков."), ("php", "Сделай PHP handler для Fission: если в context есть numbers-массив, вернуть его сумму, иначе 0. Без лишних зависимостей."), ("ruby", "Сделай Ruby handler для Fission: name из context, иначе World, ответ JSON с greeting."), ("ruby", "Сделай Ruby handler для Fission: если в context есть numbers и это массив, вернуть сумму, иначе 0."), ] def post(url: str, payload: dict) -> dict: body = json.dumps(payload).encode() req = urllib.request.Request(url, data=body, headers=HEADERS) try: with urllib.request.urlopen(req, timeout=90) as resp: return json.loads(resp.read()) except urllib.error.HTTPError as exc: return {"http_error": exc.code, "body": exc.read().decode(errors="replace")} def extract_code(answer: str) -> str: match = re.search(r"```(?:[a-zA-Z0-9_+-]+)?\n(.*?)\n```", answer, re.S) return match.group(1).strip() if match else "" def has_exact_heading(answer: str) -> bool: return bool(re.search(r"(^|\n)LLM что делает\s*$", answer, re.M)) def explanation_after_heading(answer: str) -> str: match = re.search(r"(^|\n)LLM что делает\s*\n(.*)$", answer, re.S) return match.group(2).strip() if match else "" for lang, question in CASES: ask_resp = post(ASK_API, {"question": PROMPT + "\n\nЗадача:\n" + question}) print(f"=== {lang} ===") print("QUESTION:") print(question) if ask_resp.get("http_error"): print(f"HTTP {ask_resp['http_error']}") print(ask_resp.get("body", "")) print("\n" + "=" * 72 + "\n") continue answer = ask_resp.get("answer", ask_resp.get("error", "???")) code = extract_code(answer) lint_resp = post(CHECK_API, {"language": lang, "code": code}) if code else {"ok": False, "result": "no code extracted"} print("HAS EXACT HEADING:", has_exact_heading(answer)) print("HAS EXPLANATION:", bool(explanation_after_heading(answer))) print("ANSWER:") print(answer) print("\nEXTRACTED CODE:") print(code) print("\nLINT:") print(json.dumps(lint_resp, ensure_ascii=False, indent=2)[:2000]) print("\n" + "=" * 72 + "\n")