add low-code

This commit is contained in:
2026-04-10 00:47:53 +03:00
parent d30b5614f4
commit 2d30fe258b
3 changed files with 298 additions and 6 deletions

View File

@@ -5,7 +5,7 @@ import os
import requests
import yaml
from fastapi import Depends, FastAPI, HTTPException
from pydantic import BaseModel
from pydantic import BaseModel, Field
from sqlalchemy import delete, select
from sqlalchemy.orm import Session
from sqlalchemy.exc import SQLAlchemyError
@@ -39,7 +39,7 @@ from backend.auth import ( # noqa: E402
verify_password,
)
from backend.db import engine, get_db # noqa: E402
from backend.models import Base, User, UserChatMessage # noqa: E402
from backend.models import AutonomousPipeline, Base, User, UserChatMessage # noqa: E402
class GenerationRequest(BaseModel):
@@ -58,6 +58,24 @@ class ChatRequest(BaseModel):
messages: list[ChatMessageIn]
class JenkinsPhaseConfigIn(BaseModel):
job: str = ""
server_url: str = ""
parameters: dict[str, str] = Field(default_factory=dict)
class LowCodePhaseIn(BaseModel):
id: str
name: str = ""
description: str = ""
jenkins: JenkinsPhaseConfigIn = Field(default_factory=JenkinsPhaseConfigIn)
class AutonomousPipelineSave(BaseModel):
title: str = ""
phases: list[LowCodePhaseIn] = Field(default_factory=list)
def validate_config(config_text: str):
try:
yaml.safe_load(config_text)
@@ -169,6 +187,58 @@ def me(user: User = Depends(get_current_user)):
return {"id": str(user.id), "email": user.email, "full_name": user.full_name, "is_admin": user.is_admin}
@app.get("/pipelines/autonomous")
def get_autonomous_pipeline(
db: Session = Depends(get_db),
user: User | None = Depends(get_current_user) if REQUIRE_AUTH_FOR_GENERATE else None,
):
if user is None:
return {"title": "", "phases": [], "updated_at": None}
row = db.get(AutonomousPipeline, user.id)
if row is None:
return {"title": "", "phases": [], "updated_at": None}
defn = row.definition if isinstance(row.definition, dict) else {}
phases = defn.get("phases", [])
return {
"title": row.title,
"phases": phases,
"updated_at": row.updated_at.isoformat() if row.updated_at else None,
}
@app.put("/pipelines/autonomous")
def put_autonomous_pipeline(
body: AutonomousPipelineSave,
db: Session = Depends(get_db),
user: User | None = Depends(get_current_user) if REQUIRE_AUTH_FOR_GENERATE else None,
):
if user is None:
raise HTTPException(status_code=401, detail="Authentication required")
try:
row = db.get(AutonomousPipeline, user.id)
dumped = [p.model_dump() for p in body.phases]
if row is None:
row = AutonomousPipeline(
user_id=user.id,
title=body.title,
definition={"schema_version": 1, "phases": dumped},
)
db.add(row)
else:
row.title = body.title
row.definition = {"schema_version": 1, "phases": dumped}
db.commit()
db.refresh(row)
return {
"title": row.title,
"phases": row.definition.get("phases", []),
"updated_at": row.updated_at.isoformat() if row.updated_at else None,
}
except SQLAlchemyError as e:
db.rollback()
raise HTTPException(status_code=500, detail=f"Database error: {str(e)}")
@app.get("/chat/history")
def chat_history(
limit: int = 500,

View File

@@ -4,7 +4,7 @@ import uuid
from datetime import datetime, timezone
from sqlalchemy import Boolean, DateTime, ForeignKey, String, Text
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.dialects.postgresql import JSONB, UUID
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
@@ -43,3 +43,26 @@ class UserChatMessage(Base):
content: Mapped[str] = mapped_column(Text, nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_now, nullable=False)
class AutonomousPipeline(Base):
"""Low-code конвейер: фазы и вызов Jenkins с параметрами (один черновик на пользователя)."""
__tablename__ = "autonomous_pipelines"
user_id: Mapped[uuid.UUID] = mapped_column(
ForeignKey("users.id", ondelete="CASCADE"),
primary_key=True,
)
title: Mapped[str] = mapped_column(String(500), default="", nullable=False)
definition: Mapped[dict] = mapped_column(
JSONB,
nullable=False,
default=lambda: {"schema_version": 1, "phases": []},
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=_now,
onupdate=_now,
nullable=False,
)