| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- from __future__ import annotations
- from typing import Any, Literal
- from pydantic import BaseModel, ConfigDict, Field, model_validator
- from content_agent.constants import DEFAULT_STRATEGY_VERSION
- class RunStartRequest(BaseModel):
- model_config = ConfigDict(extra="forbid")
- run_id: str | None = Field(
- default=None,
- description="Optional fixed run_id (V3-M5: deterministic replay for concurrency-consistency tests).",
- )
- source: str | None = Field(
- default=None,
- description="Optional source_context.json or DemandAgent demand_content.json path.",
- )
- demand_content_id: int | None = Field(
- default=None,
- description="Optional content-deconstruction-supply.demand_content id.",
- )
- run_label: str | None = Field(
- default=None,
- description="Optional ext_data.run_label selector in demand_content.",
- )
- platform: str = Field(default="douyin", description="Requested platform.")
- platform_mode: Literal["mock", "real"] = Field(
- default="real",
- description="mock uses deterministic fixtures; real calls the configured platform API.",
- )
- strategy_version: str = Field(default=DEFAULT_STRATEGY_VERSION)
- @model_validator(mode="after")
- def validate_source_selector(self) -> "RunStartRequest":
- selectors = [
- bool(self.source),
- self.demand_content_id is not None,
- bool(self.run_label),
- ]
- if sum(selectors) > 1:
- raise ValueError("source, demand_content_id, and run_label are mutually exclusive")
- return self
- class RunStartResponse(BaseModel):
- run_id: str
- policy_run_id: str
- status: str
- policy_bundle_id: str
- strategy_version: str
- platform: str
- platform_mode: str
- output_dir: str
- class RunSummaryResponse(BaseModel):
- run_id: str
- policy_run_id: str | None = None
- status: str
- current_step: str
- output_dir: str
- files: dict[str, bool]
- validation_status: str
- errors: list[str] = Field(default_factory=list)
- class RecordsResponse(BaseModel):
- run_id: str
- records: list[dict[str, Any]]
- class JsonFileResponse(BaseModel):
- run_id: str
- data: dict[str, Any]
- class ValidationResponse(BaseModel):
- run_id: str
- status: str
- findings: list[dict[str, Any]]
- class RunListItem(BaseModel):
- run_id: str
- policy_run_id: str | None = None
- status: str | None = None
- current_step: str | None = None
- platform: str | None = None
- platform_mode: str | None = None
- content_format: str | None = None
- strategy_version: str | None = None
- demand_name: str | None = None
- demand_desc: str | None = None
- validation_status: str | None = None
- error_code: str | None = None
- started_at: str | None = None
- completed_at: str | None = None
- class RunListResponse(BaseModel):
- items: list[RunListItem]
- page: int
- page_size: int
- total: int
- data_origin: str
- class DashboardResponse(BaseModel):
- run_id: str
- summary: dict[str, Any]
- counts: dict[str, int]
- files: dict[str, bool]
- runtime_files: list[dict[str, Any]]
- validation: dict[str, Any]
- final_output_summary: dict[str, Any]
- strategy_review_status: str
- business_summary: dict[str, Any]
- stage_conclusions: list[dict[str, Any]]
- rule_application_summary: list[dict[str, Any]]
- walk_graph: dict[str, Any]
- primary_failure_reason: dict[str, Any] | None = None
- technical_refs: dict[str, Any]
- data_origin: str
- links: dict[str, str]
- class RuntimeFilesResponse(BaseModel):
- run_id: str
- files: list[dict[str, Any]]
- data_origin: str
- class RuntimeFileResponse(BaseModel):
- run_id: str
- filename: str
- data_origin: str
- data: dict[str, Any] | None = None
- records: list[dict[str, Any]] | None = None
- offset: int | None = None
- limit: int | None = None
- total: int | None = None
- class QueryListResponse(BaseModel):
- run_id: str
- items: list[dict[str, Any]]
- total: int
- data_origin: str
- class ConfigFileResponse(BaseModel):
- source_file: str
- data: dict[str, Any]
- class PlatformDescriptor(BaseModel):
- # 平台展示元数据(从 platform_profiles 派生,前端按此渲染,不再写死抖音)
- platform: str
- label: str
- status: str | None = None
- # 该平台真实可得的互动指标(= profile.heat.signals 的 field,按重要度排序;统一键名)
- heat_fields: list[str] = []
- class PlatformCatalogResponse(BaseModel):
- platforms: dict[str, PlatformDescriptor]
- class TimelineResponse(BaseModel):
- run_id: str
- items: list[dict[str, Any]]
- total: int
- data_origin: str
- summary: dict[str, Any]
- class ContentItemsResponse(BaseModel):
- run_id: str
- items: list[dict[str, Any]]
- total: int
- data_origin: str
|