"""Declarative workspace contributions; no plugin JavaScript or model execution.""" from typing import Literal from pydantic import BaseModel, ConfigDict, Field, model_validator class WorkspaceModel(BaseModel): model_config = ConfigDict(extra="forbid") class PanelWidth(WorkspaceModel): preferred: int = Field(default=340, ge=200, le=1000) minimum: int = Field(default=240, ge=160, le=800) maximum: int = Field(default=480, ge=200, le=1200) @model_validator(mode="after") def ordered(self): if not self.minimum <= self.preferred <= self.maximum: raise ValueError("面板宽度必须满足 minimum ≤ preferred ≤ maximum") return self class WorkspaceField(WorkspaceModel): id: str = Field(pattern=r"^[a-z][a-z0-9_]{0,47}$") label: str = Field(min_length=1, max_length=100) description: str = Field(default="", max_length=1000) kind: Literal["choice", "text"] options: list[str] = Field(default_factory=list, max_length=12) max_length: int = Field(default=2000, ge=1, le=10000) report: bool = True @model_validator(mode="after") def valid_options(self): if self.kind == "choice" and not self.options: raise ValueError("选择字段必须声明 options") if self.kind == "text" and self.options: raise ValueError("文本字段不接受 options") if len(set(self.options)) != len(self.options) or any( not option.strip() or len(option) > min(100, self.max_length) for option in self.options ): raise ValueError("选项必须非空、唯一且不超过长度限制") return self class WorkspacePanel(WorkspaceModel): id: str = Field(pattern=r"^[a-z][a-z0-9_]{0,47}$") title: str = Field(min_length=1, max_length=100) side: Literal["left", "right"] kind: Literal["initial_prompt", "original_case", "form"] width: PanelWidth = Field(default_factory=PanelWidth) class WorkspaceContribution(WorkspaceModel): panels: list[WorkspacePanel] = Field(min_length=1, max_length=2) fields: list[WorkspaceField] = Field(default_factory=list, max_length=20) @model_validator(mode="after") def unique_contributions(self): if len({panel.id for panel in self.panels}) != len(self.panels) or len( {panel.kind for panel in self.panels} ) != len(self.panels): raise ValueError("面板 id 和 kind 不得重复") if len({field.id for field in self.fields}) != len(self.fields): raise ValueError("工作区字段 id 不得重复") if bool(self.fields) != any(panel.kind == "form" for panel in self.panels): raise ValueError("表单面板与 fields 必须同时声明") return self