Первый коммит

This commit is contained in:
2026-02-25 14:47:19 +03:00
commit 1e376aff24
170 changed files with 4893 additions and 0 deletions

0
app/schemas/__init__.py Normal file
View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

34
app/schemas/changeset.py Normal file
View File

@@ -0,0 +1,34 @@
from enum import Enum
from typing import Optional
from pydantic import BaseModel, Field, model_validator
class ChangeOp(str, Enum):
CREATE = "create"
UPDATE = "update"
DELETE = "delete"
class ChangeItem(BaseModel):
op: ChangeOp
path: str = Field(min_length=1)
base_hash: Optional[str] = None
proposed_content: Optional[str] = None
reason: str = Field(min_length=1, max_length=500)
@model_validator(mode="after")
def validate_op_fields(self) -> "ChangeItem":
if self.op in (ChangeOp.UPDATE, ChangeOp.DELETE) and not self.base_hash:
raise ValueError("base_hash is required for update/delete")
if self.op in (ChangeOp.CREATE, ChangeOp.UPDATE) and self.proposed_content is None:
raise ValueError("proposed_content is required for create/update")
if self.op == ChangeOp.DELETE and self.proposed_content is not None:
raise ValueError("proposed_content is forbidden for delete")
return self
class ChangeSetPayload(BaseModel):
schema_version: str
task_id: str
changeset: list[ChangeItem]

80
app/schemas/chat.py Normal file
View File

@@ -0,0 +1,80 @@
from enum import Enum
from typing import Optional
from pydantic import BaseModel, Field, HttpUrl
from app.schemas.changeset import ChangeItem
from app.schemas.common import ErrorPayload
class AttachmentType(str, Enum):
CONFLUENCE_URL = "confluence_url"
class ChatMode(str, Enum):
AUTO = "auto"
PROJECT_QA = "project_qa"
PROJECT_EDITS = "project_edits"
DOCS_GENERATION = "docs_generation"
# Legacy alias preserved for backward compatibility.
CODE_CHANGE = "code_change"
# Legacy alias preserved for backward compatibility.
ANALYTICS_REVIEW = "analytics_review"
QA = "qa"
class Attachment(BaseModel):
type: AttachmentType
url: HttpUrl
class ChatFileContext(BaseModel):
path: str = Field(min_length=1)
content: str
content_hash: str = Field(min_length=1)
class ChatMessageRequest(BaseModel):
mode: ChatMode = ChatMode.AUTO
dialog_session_id: str | None = Field(default=None, min_length=1)
rag_session_id: str | None = Field(default=None, min_length=1)
session_id: str | None = Field(default=None, min_length=1)
project_id: str | None = Field(default=None, min_length=1)
message: str = Field(min_length=1)
attachments: list[Attachment] = Field(default_factory=list)
files: list[ChatFileContext] = Field(default_factory=list)
class TaskQueuedResponse(BaseModel):
task_id: str
status: str
class TaskStatus(str, Enum):
QUEUED = "queued"
RUNNING = "running"
DONE = "done"
ERROR = "error"
class TaskResultType(str, Enum):
ANSWER = "answer"
CHANGESET = "changeset"
class TaskResultResponse(BaseModel):
task_id: str
status: TaskStatus
result_type: Optional[TaskResultType] = None
answer: Optional[str] = None
changeset: list[ChangeItem] = Field(default_factory=list)
error: Optional[ErrorPayload] = None
class DialogCreateRequest(BaseModel):
rag_session_id: str = Field(min_length=1)
class DialogCreateResponse(BaseModel):
dialog_session_id: str
rag_session_id: str

17
app/schemas/common.py Normal file
View File

@@ -0,0 +1,17 @@
from enum import Enum
from pydantic import BaseModel
class ModuleName(str, Enum):
BACKEND = "backend"
AGENT = "agent"
RAG = "rag"
CONFLUENCE = "confluence"
FRONTEND = "frontend"
class ErrorPayload(BaseModel):
code: str
desc: str
module: ModuleName

54
app/schemas/indexing.py Normal file
View File

@@ -0,0 +1,54 @@
from enum import Enum
from typing import Optional
from pydantic import BaseModel, Field
from app.schemas.common import ErrorPayload
class FileSnapshot(BaseModel):
path: str = Field(min_length=1)
content: str
content_hash: str = Field(min_length=1)
class IndexSnapshotRequest(BaseModel):
project_id: str = Field(min_length=1)
files: list[FileSnapshot]
class ChangeOp(str, Enum):
UPSERT = "upsert"
DELETE = "delete"
class ChangedFile(BaseModel):
op: ChangeOp
path: str = Field(min_length=1)
content: Optional[str] = None
content_hash: Optional[str] = None
class IndexChangesRequest(BaseModel):
project_id: str = Field(min_length=1)
changed_files: list[ChangedFile]
class IndexJobQueuedResponse(BaseModel):
index_job_id: str
status: str
class IndexJobStatus(str, Enum):
QUEUED = "queued"
RUNNING = "running"
DONE = "done"
ERROR = "error"
class IndexJobResponse(BaseModel):
index_job_id: str
status: IndexJobStatus
indexed_files: int = 0
failed_files: int = 0
error: Optional[ErrorPayload] = None

View File

@@ -0,0 +1,27 @@
from pydantic import BaseModel, Field
from app.schemas.indexing import ChangedFile, FileSnapshot, IndexJobStatus
class RagSessionCreateRequest(BaseModel):
project_id: str = Field(min_length=1)
files: list[FileSnapshot]
class RagSessionCreateResponse(BaseModel):
rag_session_id: str
index_job_id: str
status: IndexJobStatus
class RagSessionChangesRequest(BaseModel):
changed_files: list[ChangedFile]
class RagSessionJobResponse(BaseModel):
rag_session_id: str
index_job_id: str
status: IndexJobStatus
indexed_files: int = 0
failed_files: int = 0
error: dict | None = None