Feat: Continued conversion on data models

This commit is contained in:
2025-11-30 13:47:47 -05:00
parent bdf566c385
commit 5bc36579f5
5 changed files with 467 additions and 2 deletions
+5 -2
View File
@@ -3792,8 +3792,11 @@ If you can do all of the above by end of Day 1, you're on track!
- [X] Convert ai_models_custom.py (5 models): CustomModel, CustomProvider, ModelsInput, ClientModelPackSchema, ClientModelsInput — implemented in `src/cleveragents/domain/models/aimodels_custom/__init__.py` with shared enums from `aimodelscommon`.
- [X] Convert ai_models_data_models.py (17 models): ModelCompatibility, BaseModelShared, BaseModelProviderConfig, BaseModelConfig, BaseModelUsesProvider, BaseModelConfigSchema, BaseModelConfigVariant, AvailableModel, PlannerModelConfig, ModelRoleConfig, ModelRoleModelConfig, ModelRoleConfigSchema, PlannerRoleConfig, ClientModelPackSchemaRoles, ModelPackSchemaRoles, ModelPackSchema, ModelPack — now live in `src/cleveragents/domain/models/aimodelsdatamodels/__init__.py` with populate-by-name config support.
- [X] Convert context.py (2 models): ContextUpdateResult, SummaryForUpdateContextParams
- [ ] Convert data_models.py (25 models): Org, User, OrgUser, Invite, Project (stub), Plan (stub), Branch, Context (stub), CurrentStage, ConvoMessageFlags, Subtask, ConvoMessage, ConvoSummary, Operation (stub), ConvoMessageDescription (stub), PlanBuild (stub), Replacement, PlanFileResult, CurrentPlanFiles, PlanResult (stub), PlanApply, CurrentPlanState, OrgRole, CloudBillingFields, CreditsTransaction
- [ ] Convert plan_model_settings.py (1 model): PlanSettings
- [X] Convert data_models.py conversation models (7 models): CurrentStage, ConvoMessageFlags, Subtask, ConvoMessage, ConvoSummary, TellStage, PlanningPhase — implemented in `src/cleveragents/domain/models/conversation/__init__.py`
- [X] Convert data_models.py plan file models (7 models): Branch, Replacement, PlanFileResult, CurrentPlanFiles, PlanApply, CurrentPlanState, PlanStateStatus — implemented in `src/cleveragents/domain/models/planfiles/__init__.py`
- [X] Convert data_models.py core stubs (6 models): Project, Plan, Context, Operation, PlanBuild, PlanResult — already exist in `src/cleveragents/domain/models/core/`
- [ ] Convert data_models.py cloud/billing models (7 models): Org, User, OrgUser, Invite, OrgRole, CloudBillingFields, CreditsTransaction — deferred, not needed for standalone mode
- [X] Convert plan_model_settings.py (1 model): PlanSettings — implemented in `src/cleveragents/domain/models/plansettings/__init__.py` with proper type hints and Pydantic validation.
- [ ] Convert req_res.py (53 API models) - defer to Phase 5 when implementing server endpoints
- [ ] CreateEmailVerificationRequest
- [ ] CreateEmailVerificationResponse
@@ -1,5 +1,14 @@
"""Domain models for CleverAgents."""
from .conversation import (
ConvoMessage,
ConvoMessageFlags,
ConvoSummary,
CurrentStage,
PlanningPhase,
Subtask,
TellStage,
)
from .core import (
Change,
ChangeSet,
@@ -19,23 +28,48 @@ from .core import (
ProjectStats,
SummaryForUpdateContextParams,
)
from .planfiles import (
Branch,
CurrentPlanFiles,
CurrentPlanState,
PlanApply,
PlanFileResult,
PlanStateStatus,
Replacement,
)
from .plansettings import PlanSettings
__all__ = [
"Branch",
"Change",
"ChangeSet",
"Context",
"ContextFile",
"ContextType",
"ContextUpdateResult",
"ConvoMessage",
"ConvoMessageFlags",
"ConvoSummary",
"CurrentPlanFiles",
"CurrentPlanState",
"CurrentStage",
"MaxContextCount",
"Operation",
"OperationType",
"Plan",
"PlanApply",
"PlanBuild",
"PlanFileResult",
"PlanResult",
"PlanSettings",
"PlanStateStatus",
"PlanStatus",
"PlanningPhase",
"Project",
"ProjectSettings",
"ProjectStats",
"Replacement",
"Subtask",
"SummaryForUpdateContextParams",
"TellStage",
]
@@ -0,0 +1,167 @@
"""Conversation domain models for CleverAgents.
Based on Phase 0 discovery stubs from data_models.py.
These models represent the conversation state and history for plans.
"""
from __future__ import annotations
from datetime import datetime
from enum import Enum
from pydantic import BaseModel, ConfigDict, Field
def _empty_string_list() -> list[str]:
return []
def _empty_subtask_list() -> list[Subtask]:
return []
def _default_convo_message_flags() -> ConvoMessageFlags:
return ConvoMessageFlags(
didMakePlan=False,
didRemoveTasks=False,
didMakeDebuggingPlan=False,
didLoadContext=False,
currentStage=None,
isChat=False,
didWriteCode=False,
didCompleteTask=False,
didCompletePlan=False,
hasUnfinishedSubtasks=False,
isApplyDebug=False,
isUserDebug=False,
hasError=False,
)
__all__ = [
"ConvoMessage",
"ConvoMessageFlags",
"ConvoSummary",
"CurrentStage",
"PlanningPhase",
"Subtask",
"TellStage",
]
class TellStage(str, Enum):
"""Stage of the tell operation."""
PLANNING = "planning"
IMPLEMENTATION = "implementation"
class PlanningPhase(str, Enum):
"""Phase of the planning stage."""
CONTEXT = "context"
TASKS = "tasks"
class CurrentStage(BaseModel):
"""Current stage of plan execution."""
tell_stage: TellStage = Field(TellStage.PLANNING, alias="tellStage")
planning_phase: PlanningPhase = Field(PlanningPhase.CONTEXT, alias="planningPhase")
model_config = ConfigDict(
str_strip_whitespace=True,
validate_assignment=True,
populate_by_name=True,
use_enum_values=True,
)
class ConvoMessageFlags(BaseModel):
"""Flags indicating what happened during a conversation message."""
did_make_plan: bool = Field(False, alias="didMakePlan")
did_remove_tasks: bool = Field(False, alias="didRemoveTasks")
did_make_debugging_plan: bool = Field(False, alias="didMakeDebuggingPlan")
did_load_context: bool = Field(False, alias="didLoadContext")
current_stage: CurrentStage | None = Field(default=None, alias="currentStage")
is_chat: bool = Field(False, alias="isChat")
did_write_code: bool = Field(False, alias="didWriteCode")
did_complete_task: bool = Field(False, alias="didCompleteTask")
did_complete_plan: bool = Field(False, alias="didCompletePlan")
has_unfinished_subtasks: bool = Field(False, alias="hasUnfinishedSubtasks")
is_apply_debug: bool = Field(False, alias="isApplyDebug")
is_user_debug: bool = Field(False, alias="isUserDebug")
has_error: bool = Field(False, alias="hasError")
model_config = ConfigDict(
str_strip_whitespace=True,
validate_assignment=True,
populate_by_name=True,
use_enum_values=True,
)
class Subtask(BaseModel):
"""A subtask within a plan."""
title: str = Field(...)
description: str = Field(...)
uses_files: list[str] = Field(default_factory=_empty_string_list, alias="usesFiles")
is_finished: bool = Field(False, alias="isFinished")
model_config = ConfigDict(
str_strip_whitespace=True,
validate_assignment=True,
populate_by_name=True,
)
class ConvoMessage(BaseModel):
"""A single message in a conversation."""
id: str = Field(...)
user_id: str = Field(..., alias="userId")
role: str = Field(...)
tokens: int = Field(0, ge=0)
num: int = Field(0, ge=0)
message: str = Field(...)
stopped: bool = Field(False)
flags: ConvoMessageFlags = Field(default_factory=_default_convo_message_flags)
subtask: Subtask | None = Field(None)
added_subtasks: list[Subtask] = Field(
default_factory=_empty_subtask_list, alias="addedSubtasks"
)
removed_subtasks: list[str] = Field(
default_factory=_empty_string_list, alias="removedSubtasks"
)
active_context_ids: list[str] = Field(
default_factory=_empty_string_list, alias="activeContextIds"
)
created_at: datetime = Field(default_factory=datetime.now, alias="createdAt")
model_config = ConfigDict(
str_strip_whitespace=True,
validate_assignment=True,
populate_by_name=True,
)
class ConvoSummary(BaseModel):
"""Summary of a conversation."""
id: str = Field(...)
latest_convo_message_created_at: datetime = Field(
..., alias="latestConvoMessageCreatedAt"
)
latest_convo_message_id: str = Field(..., alias="latestConvoMessageId")
summary: str = Field(...)
tokens: int = Field(0, ge=0)
num_messages: int = Field(0, ge=0, alias="numMessages")
created_at: datetime = Field(default_factory=datetime.now, alias="createdAt")
model_config = ConfigDict(
str_strip_whitespace=True,
validate_assignment=True,
populate_by_name=True,
)
@@ -0,0 +1,184 @@
"""Plan file domain models for CleverAgents.
Based on Phase 0 discovery stubs from data_models.py.
These models represent plan file operations, results, and state.
"""
from __future__ import annotations
from datetime import datetime
from enum import Enum
from pydantic import BaseModel, ConfigDict, Field
def _empty_string_list() -> list[str]:
return []
def _empty_replacement_list() -> list[Replacement]:
return []
def _empty_plan_file_result_dict() -> dict[str, PlanFileResult]:
return {}
__all__ = [
"Branch",
"CurrentPlanFiles",
"CurrentPlanState",
"PlanApply",
"PlanFileResult",
"Replacement",
]
class Replacement(BaseModel):
"""A single text replacement within a file.
Represents an old->new text replacement operation.
"""
id: str = Field(...)
old: str = Field(..., description="Text to be replaced")
new: str = Field(..., description="Replacement text")
stream_id: str = Field("", alias="streamId")
failed: bool = Field(False, description="Whether the replacement failed")
reason: str | None = Field(None, description="Reason for failure if failed")
is_pending: bool = Field(False, alias="isPending")
model_config = ConfigDict(
str_strip_whitespace=True,
validate_assignment=True,
populate_by_name=True,
)
class PlanFileResult(BaseModel):
"""Result of plan operations on a single file.
Tracks all replacements and the resulting content for a file.
"""
replacements: list[Replacement] = Field(
default_factory=_empty_replacement_list,
description="List of replacements applied to file",
)
content: str = Field("", description="Current file content after replacements")
path: str = Field(..., description="File path")
will_be_deleted: bool = Field(False, alias="willBeDeleted")
model_config = ConfigDict(
str_strip_whitespace=True,
validate_assignment=True,
populate_by_name=True,
)
class CurrentPlanFiles(BaseModel):
"""Current state of all files in a plan.
Maps file paths to their current result state.
"""
files: dict[str, PlanFileResult] = Field(
default_factory=_empty_plan_file_result_dict,
description="Map of file paths to their plan file results",
)
model_config = ConfigDict(
str_strip_whitespace=True,
validate_assignment=True,
populate_by_name=True,
)
class PlanApply(BaseModel):
"""State of applying a plan.
Tracks which files have been applied and any errors.
"""
id: str = Field(...)
plan_id: str = Field(..., alias="planId")
commit_msg: str = Field("", alias="commitMsg")
applied_at: datetime = Field(default_factory=datetime.now, alias="appliedAt")
files_applied: list[str] = Field(
default_factory=_empty_string_list, alias="filesApplied"
)
files_failed: list[str] = Field(
default_factory=_empty_string_list, alias="filesFailed"
)
error_message: str | None = Field(None, alias="errorMessage")
model_config = ConfigDict(
str_strip_whitespace=True,
validate_assignment=True,
populate_by_name=True,
)
class PlanStateStatus(str, Enum):
"""Status of the current plan state."""
IDLE = "idle"
BUILDING = "building"
BUILT = "built"
APPLYING = "applying"
APPLIED = "applied"
ERROR = "error"
class CurrentPlanState(BaseModel):
"""Current overall state of a plan.
Aggregates file states and overall plan status.
"""
plan_id: str = Field(..., alias="planId")
status: PlanStateStatus = Field(PlanStateStatus.IDLE)
current_plan_files: CurrentPlanFiles = Field(
default_factory=lambda: CurrentPlanFiles(),
alias="currentPlanFiles",
)
pending_builds: int = Field(0, ge=0, alias="pendingBuilds")
context_updated_at: datetime | None = Field(None, alias="contextUpdatedAt")
built_at: datetime | None = Field(None, alias="builtAt")
applied_at: datetime | None = Field(None, alias="appliedAt")
error_message: str | None = Field(None, alias="errorMessage")
model_config = ConfigDict(
str_strip_whitespace=True,
validate_assignment=True,
populate_by_name=True,
use_enum_values=True,
)
class Branch(BaseModel):
"""A branch in a plan's version history.
Supports plan branching/versioning where users can create
alternate versions of a plan.
"""
id: str = Field(...)
org_id: str = Field(..., alias="orgId")
plan_id: str = Field(..., alias="planId")
parent_branch_id: str | None = Field(None, alias="parentBranchId")
name: str = Field(..., min_length=1, max_length=255)
status: PlanStateStatus = Field(PlanStateStatus.IDLE)
context_tokens: int = Field(0, ge=0, alias="contextTokens")
convo_tokens: int = Field(0, ge=0, alias="convoTokens")
shared: bool = Field(False)
archived: bool = Field(False)
created_at: datetime = Field(default_factory=datetime.now, alias="createdAt")
updated_at: datetime = Field(default_factory=datetime.now, alias="updatedAt")
model_config = ConfigDict(
str_strip_whitespace=True,
validate_assignment=True,
populate_by_name=True,
use_enum_values=True,
)
@@ -0,0 +1,77 @@
"""Plan settings domain models for CleverAgents.
Based on Phase 0 discovery stubs from plan_model_settings.py.
"""
from __future__ import annotations
from datetime import datetime
from pydantic import BaseModel, ConfigDict, Field
from ..aimodels_custom import CustomModel, CustomProvider
from ..aimodelsdatamodels import BaseModelUsesProvider, ModelPack
def _empty_model_pack_list() -> list[ModelPack]:
return []
def _empty_custom_model_list() -> list[CustomModel]:
return []
def _empty_custom_provider_list() -> list[CustomProvider]:
return []
def _empty_custom_models_by_id() -> dict[str, CustomModel]:
return {}
def _empty_uses_custom_provider_by_model_id() -> dict[str, list[BaseModelUsesProvider]]:
return {}
__all__ = ["PlanSettings"]
class PlanSettings(BaseModel):
"""Data contract for PlanSettings.
Tracks the model configuration for a plan, including:
- The active model pack
- Custom model packs defined by the user
- Custom models and providers
- Whether this is a cloud deployment
"""
model_pack_name: str = Field(..., alias="modelPackName")
model_pack: ModelPack | None = Field(default=None, alias="modelPack")
custom_model_packs: list[ModelPack] = Field(
default_factory=_empty_model_pack_list, alias="customModelPacks"
)
custom_models: list[CustomModel] = Field(
default_factory=_empty_custom_model_list, alias="customModels"
)
custom_models_by_id: dict[str, CustomModel] = Field(
default_factory=_empty_custom_models_by_id, alias="customModelsById"
)
custom_providers: list[CustomProvider] = Field(
default_factory=_empty_custom_provider_list, alias="customProviders"
)
uses_custom_provider_by_model_id: dict[str, list[BaseModelUsesProvider]] = Field(
default_factory=_empty_uses_custom_provider_by_model_id,
alias="usesCustomProviderByModelId",
)
is_cloud: bool = Field(False, alias="isCloud")
configured: bool = Field(False)
updated_at: datetime | None = Field(default=None, alias="updatedAt")
model_config = ConfigDict(
str_strip_whitespace=True,
validate_assignment=True,
arbitrary_types_allowed=False,
populate_by_name=True,
use_enum_values=True,
)