259 lines
6.4 KiB
Python
259 lines
6.4 KiB
Python
"""
|
|
Studio workflow editor data models.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from enum import Enum
|
|
from typing import Any, Dict, List, Literal, Optional
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class DisplayParam(BaseModel):
|
|
key: str
|
|
label: str
|
|
type: str = "text"
|
|
required: bool = True
|
|
placeholder: str = ""
|
|
|
|
|
|
class InputRef(BaseModel):
|
|
ref: str
|
|
label: Optional[str] = None
|
|
optional: bool = False
|
|
|
|
|
|
class ScoringDimension(BaseModel):
|
|
id: str
|
|
name: str
|
|
criteria: str = ""
|
|
|
|
|
|
class InsertionRagConfig(BaseModel):
|
|
libraryId: str = ""
|
|
threshold: float = 0.5
|
|
maxEntries: int = 3
|
|
|
|
|
|
class InsertionConfig(BaseModel):
|
|
position: int = 1
|
|
activationType: str = "permanent"
|
|
key: str = ""
|
|
keysecondary: str = ""
|
|
comment: str = ""
|
|
ragConfig: Optional[InsertionRagConfig] = None
|
|
|
|
|
|
class ScoringConfig(BaseModel):
|
|
enabled: bool = True
|
|
dimensions: List[ScoringDimension] = Field(default_factory=list)
|
|
rubric: Optional[str] = None
|
|
|
|
|
|
class StudioNode(BaseModel):
|
|
id: str
|
|
skillId: str
|
|
displayName: str
|
|
enabled: bool = True
|
|
niche: Optional[str] = None
|
|
loopUntilSatisfied: bool = False
|
|
config: Dict[str, Any] = Field(default_factory=dict)
|
|
displayParams: List[DisplayParam] = Field(default_factory=list)
|
|
inputs: List[InputRef] = Field(default_factory=list)
|
|
|
|
|
|
class PipelineDefinition(BaseModel):
|
|
workflowGoal: str = ""
|
|
nodes: List[StudioNode] = Field(default_factory=list)
|
|
|
|
|
|
class StudioProjectMeta(BaseModel):
|
|
id: str
|
|
name: str
|
|
description: str = ""
|
|
templateId: Optional[str] = None
|
|
characterId: Optional[str] = None
|
|
worldbookId: Optional[str] = None
|
|
createdAt: str = ""
|
|
updatedAt: str = ""
|
|
|
|
|
|
class StudioProject(BaseModel):
|
|
meta: StudioProjectMeta
|
|
pipeline: PipelineDefinition
|
|
|
|
|
|
class ArtifactDef(BaseModel):
|
|
type: str
|
|
displayName: str = ""
|
|
|
|
|
|
class SkillTemplateDef(BaseModel):
|
|
skillId: str
|
|
displayName: str
|
|
description: str = ""
|
|
displayParams: List[DisplayParam] = Field(default_factory=list)
|
|
configWhitelist: List[str] = Field(default_factory=list)
|
|
artifacts: List[ArtifactDef] = Field(default_factory=list)
|
|
supportsLoopUntilSatisfied: bool = False
|
|
supportsInputs: bool = False
|
|
supportsInsertion: bool = False
|
|
supportsScoring: bool = False
|
|
|
|
|
|
class WorkflowTemplateSummary(BaseModel):
|
|
id: str
|
|
name: str
|
|
description: str = ""
|
|
|
|
|
|
class WorkflowVariableDef(BaseModel):
|
|
ref: str
|
|
label: str
|
|
description: str = ""
|
|
|
|
|
|
class DynamicVariableSuffix(BaseModel):
|
|
suffix: str
|
|
labelPattern: str
|
|
|
|
|
|
class WorkflowVariablesResponse(BaseModel):
|
|
builtIn: List[WorkflowVariableDef] = Field(default_factory=list)
|
|
dynamic: List[WorkflowVariableDef] = Field(default_factory=list)
|
|
|
|
|
|
class SkillTemplatesCatalog(BaseModel):
|
|
templates: List[SkillTemplateDef] = Field(default_factory=list)
|
|
|
|
|
|
class StudioProjectSummary(BaseModel):
|
|
id: str
|
|
name: str
|
|
description: str = ""
|
|
updatedAt: str = ""
|
|
|
|
|
|
class CreateStudioProjectRequest(BaseModel):
|
|
name: str = "新项目"
|
|
template_id: str = "builtin.studio.example"
|
|
project_id: Optional[str] = None
|
|
|
|
|
|
class UpdateStudioProjectRequest(BaseModel):
|
|
name: Optional[str] = Field(None, min_length=1, max_length=120)
|
|
description: Optional[str] = Field(None, max_length=500)
|
|
|
|
|
|
class StudioRunStatus(str, Enum):
|
|
PENDING = "pending"
|
|
RUNNING = "running"
|
|
PAUSED = "paused"
|
|
COMPLETED = "completed"
|
|
FAILED = "failed"
|
|
CANCELLED = "cancelled"
|
|
|
|
|
|
class ToolQuestionOption(BaseModel):
|
|
question: str
|
|
options: List[str] = Field(default_factory=list)
|
|
|
|
|
|
class StepMessage(BaseModel):
|
|
"""Short step-scoped dialogue (not full chat history)."""
|
|
id: str
|
|
role: str # user | assistant
|
|
content: str
|
|
createdAt: Optional[str] = None
|
|
|
|
|
|
class LastToolResponse(BaseModel):
|
|
"""LLM tool-call payload surfaced to the run UI (R2+)."""
|
|
thinking: Optional[str] = None
|
|
evaluation: Optional[str] = None
|
|
questions: List[ToolQuestionOption] = Field(default_factory=list)
|
|
generatedAt: Optional[str] = None
|
|
|
|
|
|
class PromptBlock(BaseModel):
|
|
"""Single assembled context section for LLM prompt (R2 debug / execution)."""
|
|
id: str
|
|
label: str
|
|
content: str
|
|
source: str = "auto" # auto | manual | workflow
|
|
|
|
|
|
class TurnSnapshot(BaseModel):
|
|
"""State captured before each LLM turn (for undo)."""
|
|
lastDraft: Optional[Dict[str, Any]] = None
|
|
lastToolResponse: Optional[LastToolResponse] = None
|
|
stepMessages: List[StepMessage] = Field(default_factory=list)
|
|
timestamp: Optional[str] = None
|
|
|
|
|
|
class StudioNodeRunState(BaseModel):
|
|
nodeId: str
|
|
displayName: str
|
|
skillId: str
|
|
status: str # pending | active | completed | skipped
|
|
loopUntilSatisfied: bool = False
|
|
lastDraft: Optional[Dict[str, Any]] = None
|
|
lastToolResponse: Optional[LastToolResponse] = None
|
|
stepMessages: List[StepMessage] = Field(default_factory=list)
|
|
turnHistory: List[TurnSnapshot] = Field(default_factory=list)
|
|
|
|
|
|
class StudioRun(BaseModel):
|
|
id: str
|
|
projectId: str
|
|
status: StudioRunStatus
|
|
pipelineSnapshot: PipelineDefinition
|
|
pipelineVersionNote: str
|
|
currentNodeId: Optional[str] = None
|
|
nodeStates: List[StudioNodeRunState] = Field(default_factory=list)
|
|
workflowVariables: Dict[str, Any] = Field(default_factory=dict)
|
|
lastPromptBlocks: List[PromptBlock] = Field(default_factory=list)
|
|
title: str = ""
|
|
createdAt: str = ""
|
|
updatedAt: str = ""
|
|
|
|
|
|
class AdvanceRunRequest(BaseModel):
|
|
displayParams: Dict[str, str] = Field(default_factory=dict)
|
|
saveMode: Literal["advance", "append", "overwrite"] = "advance"
|
|
|
|
|
|
class SaveRunRequest(BaseModel):
|
|
mode: Literal["incremental", "overwrite"]
|
|
|
|
|
|
class SwitchRunNodeRequest(BaseModel):
|
|
nodeId: str = Field(..., min_length=1)
|
|
|
|
|
|
class RunMessageRequest(BaseModel):
|
|
content: str = Field(..., min_length=1, max_length=32000)
|
|
stream: bool = False
|
|
profileId: Optional[str] = None
|
|
apiConfig: Optional[Dict[str, str]] = None
|
|
|
|
|
|
class RunRerollRequest(BaseModel):
|
|
stream: bool = False
|
|
profileId: Optional[str] = None
|
|
apiConfig: Optional[Dict[str, str]] = None
|
|
|
|
|
|
class RenameRunRequest(BaseModel):
|
|
title: str = Field(..., min_length=1, max_length=120)
|
|
|
|
|
|
class StudioRunSummary(BaseModel):
|
|
id: str
|
|
projectId: str
|
|
status: StudioRunStatus
|
|
currentNodeId: Optional[str] = None
|
|
title: str = ""
|
|
createdAt: str = ""
|
|
updatedAt: str = ""
|