Spaces:
Running
Running
| """Pydantic schemas for the /v1 Continuous Build workflow API (Batch C2). | |
| Wire vocabularies are hyphenated and stored verbatim (``approved``/``needs-repair``/``rejected`` | |
| /``not-run``). The UI copy ("Passed" / "Needs repair" / "Rejected") is derived in the response | |
| via ``ui_label`` so the engine's status is never re-spelled on the way through. | |
| """ | |
| from __future__ import annotations | |
| from datetime import datetime | |
| from enum import StrEnum | |
| from pydantic import Field | |
| from app.schemas.common import CoderId, StrictModel | |
| # --- status vocabulary --------------------------------------------------------------------- | |
| class BatchChangeType(StrEnum): | |
| SMALL_UPDATE = "small-update" | |
| ADD_FEATURE = "add-feature" | |
| FIX_ISSUE = "fix-issue" | |
| _UI_LABELS = { | |
| "approved": "Passed", | |
| "needs-repair": "Needs repair", | |
| "rejected": "Rejected", | |
| "not-run": "Not run", | |
| "running": "Running", | |
| } | |
| def ui_label(status: str) -> str: | |
| return _UI_LABELS.get(status, status) | |
| # --- projects ------------------------------------------------------------------------------ | |
| class ProjectCreate(StrictModel): | |
| title: str = Field(min_length=1) | |
| slug: str = Field(min_length=1, max_length=120) | |
| description: str = "" | |
| class ProjectResponse(StrictModel): | |
| id: str | |
| owner_id: str | |
| title: str | |
| slug: str | |
| description: str | |
| status: str | |
| privacy: str | |
| created_at: datetime | |
| # --- versions ------------------------------------------------------------------------------ | |
| class VersionCreate(StrictModel): | |
| project_id: str | |
| version_label: str = Field(default="v1.0.0", max_length=32) | |
| title: str = Field(min_length=1) | |
| requirements_md: str = "" | |
| parent_version_id: str | None = None | |
| class VersionResponse(StrictModel): | |
| id: str | |
| project_id: str | |
| parent_version_id: str | None | |
| version_label: str | |
| title: str | |
| requirements_md: str | |
| status: str | |
| created_at: datetime | |
| # --- batches ------------------------------------------------------------------------------- | |
| class BatchCreate(StrictModel): | |
| version_id: str | |
| title: str = "" | |
| goal_md: str = Field(min_length=1) | |
| change_type: BatchChangeType = BatchChangeType.ADD_FEATURE | |
| class BatchResponse(StrictModel): | |
| id: str | |
| version_id: str | |
| ordinal: int | |
| title: str | |
| goal_md: str | |
| change_type: str | |
| status: str | |
| parent_commit_id: str | None | |
| created_at: datetime | |
| class PromptPackRequest(StrictModel): | |
| coder: CoderId = CoderId.GENERIC_AI_CODER | |
| class PromptPackResponse(StrictModel): | |
| batch_id: str | |
| prompt_version_id: str | |
| coder: str | |
| prompt_text: str | |
| constraints: dict | |
| batch_status: str | |
| # --- executions / validation --------------------------------------------------------------- | |
| class ChangedFile(StrictModel): | |
| path: str = Field(min_length=1) | |
| change_type: str = "modified" # added|modified|deleted | |
| class DependencyChange(StrictModel): | |
| name: str | |
| version: str | None = None | |
| action: str = "add" # add|remove|update | |
| class ExecutionRequest(StrictModel): | |
| coder: CoderId = CoderId.GENERIC_AI_CODER | |
| changed_files: list[ChangedFile] = Field(default_factory=list) | |
| dependency_changes: list[DependencyChange] = Field(default_factory=list) | |
| patch: str | None = None | |
| summary: str = "" | |
| class ValidationFindingResponse(StrictModel): | |
| id: str | |
| severity: str | |
| status: str | |
| check_name: str | |
| file_path: str | None | |
| message: str | |
| remediation: str | None | |
| class ValidationRunResponse(StrictModel): | |
| id: str | |
| commit_id: str | |
| status: str | |
| ui_label: str | |
| score: int | None | |
| runner: str | |
| findings: list[ValidationFindingResponse] = Field(default_factory=list) | |
| class CommitResponse(StrictModel): | |
| id: str | |
| version_id: str | |
| batch_id: str | |
| commit_no: int | |
| summary: str | |
| tree_hash: str | |
| validation_status: str | |
| ui_label: str | |
| parent_commit_id: str | None | |
| created_at: datetime | |
| class ExecutionResponse(StrictModel): | |
| """Result of submitting a batch's changes: the commit + its validation outcome.""" | |
| commit: CommitResponse | |
| validation_run: ValidationRunResponse | |
| outcome: str # committed|needs-repair|rejected | |
| next_action: str | |
| class CommitDiffResponse(StrictModel): | |
| base_commit_id: str | None | |
| head_commit_id: str | |
| patch: str | |
| class ArtifactResponse(StrictModel): | |
| id: str | |
| artifact_type: str | |
| storage_key: str | |
| sha256: str | |
| size_bytes: int | |
| # --- async runs + events (Batch C3) -------------------------------------------------------- | |
| class RunEnqueueResponse(StrictModel): | |
| run_id: str | |
| status: str | |
| ui_label: str | |
| events_url: str | |
| ws_url: str | |
| class RunResponse(StrictModel): | |
| id: str | |
| batch_id: str | None | |
| commit_id: str | None | |
| status: str | |
| ui_label: str | |
| score: int | None | |
| runner: str | |
| class RunEventResponse(StrictModel): | |
| seq: int | |
| run_id: str | |
| event_type: str | |
| payload: dict | |
| created_at: datetime | None = None | |
| # --- repair batches ------------------------------------------------------------------------ | |
| class RepairBatchRequest(StrictModel): | |
| validation_run_id: str | |
| coder: CoderId = CoderId.GENERIC_AI_CODER | |
| # --- timeline ------------------------------------------------------------------------------ | |
| class TimelineEntry(StrictModel): | |
| kind: str # batch|commit | |
| id: str | |
| ordinal: int | None = None | |
| commit_no: int | None = None | |
| title: str = "" | |
| status: str = "" | |
| ui_label: str | None = None | |
| created_at: datetime | |
| class TimelineResponse(StrictModel): | |
| version_id: str | |
| version_label: str | |
| entries: list[TimelineEntry] | |
| # --- sync (Track L2: mb sync ↔ /v1) -------------------------------------------------------- | |
| # The local .mb/ store and the server tables share shapes and an id space (content-addressed | |
| # ids fit String(36)), so sync is upsert-by-id. | |
| class SyncProject(StrictModel): | |
| id: str | |
| slug: str | |
| title: str = "" | |
| description: str = "" | |
| class SyncVersion(StrictModel): | |
| id: str | |
| project_id: str | |
| version_label: str = "v1.0.0" | |
| title: str = "" | |
| requirements_md: str = "" | |
| class SyncBatch(StrictModel): | |
| id: str | |
| version_id: str | |
| ordinal: int = Field(ge=1) | |
| title: str = "" | |
| goal_md: str = "" | |
| change_type: str = "add-feature" | |
| status: str = "draft" | |
| parent_commit_id: str | None = None | |
| class SyncCommit(StrictModel): | |
| id: str | |
| batch_id: str | |
| version_id: str | |
| commit_no: int = Field(ge=1) | |
| summary: str = "" | |
| tree_hash: str | |
| validation_status: str = "not-run" | |
| parent_commit_id: str | None = None | |
| manifest: dict = Field(default_factory=dict) | |
| class SyncRequest(StrictModel): | |
| project: SyncProject | |
| version: SyncVersion | |
| batches: list[SyncBatch] = Field(default_factory=list) | |
| commits: list[SyncCommit] = Field(default_factory=list) | |
| class SyncResponse(StrictModel): | |
| project_id: str | |
| version_id: str | |
| applied: dict | |
| timeline: TimelineResponse | |