- 后端:项目/运行 API、上下文服务与数据模型 - 前端:Studio 列表、编辑页(R1/R2 布局)、运行页与节点图 - 编辑页顶部:CSS Grid 统一标签行与控件行对齐,项目按钮独立第三行 - Docker 开发配置与文档脚本 Co-authored-by: Cursor <cursoragent@cursor.com>
217 lines
5.1 KiB
Python
217 lines
5.1 KiB
Python
"""
|
|
Studio workflow editor data models.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from enum import Enum
|
|
from typing import Any, Dict, List, 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 LastToolResponse(BaseModel):
|
|
"""LLM tool-call payload surfaced to the run UI (R2+)."""
|
|
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 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
|
|
|
|
|
|
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)
|
|
|
|
|
|
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 = ""
|