feat: initial TaskPulse release
AI Agent 定时任务跟踪、监控、状态看板系统。 - FastAPI + Vue3 单体应用 - AI Agent 一键接入(批量注册 API) - 暗色主题 Dashboard - 后台调度器 + 超时告警 - 飞书/邮件/Webhook 多渠道通知 - Base URL 可配置 - Gunicorn 生产部署
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
"""Pydantic schema registry."""
|
||||
|
||||
from app.schemas.agent import AgentBatchRegister, AgentBatchRegisterResult, AgentCreate, AgentHeartbeat, AgentOut, AgentUpdate # noqa: F401
|
||||
from app.schemas.execution import ExecutionOut, ExecutionReport # noqa: F401
|
||||
from app.schemas.notification import ( # noqa: F401
|
||||
AlertAcknowledge,
|
||||
AlertOut,
|
||||
AlertRuleCreate,
|
||||
AlertRuleOut,
|
||||
NotificationChannelCreate,
|
||||
NotificationChannelOut,
|
||||
NotificationChannelUpdate,
|
||||
)
|
||||
from app.schemas.task import TaskCreate, TaskOut, TaskUpdate # noqa: F401
|
||||
|
||||
__all__ = [
|
||||
"AgentCreate", "AgentUpdate", "AgentOut", "AgentHeartbeat",
|
||||
"TaskCreate", "TaskUpdate", "TaskOut",
|
||||
"ExecutionReport", "ExecutionOut",
|
||||
"NotificationChannelCreate", "NotificationChannelUpdate", "NotificationChannelOut",
|
||||
"AlertRuleCreate", "AlertRuleOut",
|
||||
"AlertOut", "AlertAcknowledge",
|
||||
]
|
||||
@@ -0,0 +1,57 @@
|
||||
"""Pydantic schemas — Agent."""
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class AgentCreate(BaseModel):
|
||||
name: str = Field(..., max_length=128)
|
||||
description: str = Field(default="")
|
||||
|
||||
|
||||
class AgentUpdate(BaseModel):
|
||||
name: str | None = Field(None, max_length=128)
|
||||
description: str | None = None
|
||||
status: str | None = None # active / inactive
|
||||
|
||||
|
||||
class AgentOut(BaseModel):
|
||||
id: int
|
||||
name: str
|
||||
description: str
|
||||
api_key: str
|
||||
status: str
|
||||
last_heartbeat_at: datetime | None = None
|
||||
task_count: int = 0
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
class AgentHeartbeat(BaseModel):
|
||||
pass
|
||||
|
||||
|
||||
# ── Batch registration (AI agent self-registers with tasks) ───────
|
||||
|
||||
class TaskRegistrationItem(BaseModel):
|
||||
"""A single task an agent wants to register."""
|
||||
name: str = Field(..., max_length=256)
|
||||
description: str = Field(default="")
|
||||
cron_expression: str = Field(..., max_length=64)
|
||||
grace_period: int = Field(default=300, ge=0)
|
||||
|
||||
|
||||
class AgentBatchRegister(BaseModel):
|
||||
"""AI agent sends this to register itself + all its tasks in one call."""
|
||||
name: str = Field(..., max_length=128)
|
||||
description: str = Field(default="")
|
||||
tasks: list[TaskRegistrationItem] = Field(default_factory=list)
|
||||
|
||||
|
||||
class AgentBatchRegisterResult(BaseModel):
|
||||
"""Response for batch registration."""
|
||||
agent: AgentOut
|
||||
tasks_created: int
|
||||
@@ -0,0 +1,31 @@
|
||||
"""Pydantic schemas — TaskExecution."""
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class ExecutionReport(BaseModel):
|
||||
"""Agent 汇报执行结果"""
|
||||
status: str = Field(..., pattern=r"^(success|failed)$", description="success 或 failed")
|
||||
finished_at: datetime | None = None
|
||||
duration_ms: int | None = None
|
||||
result: str | None = Field(None, description="执行结果摘要 (JSON)")
|
||||
log: str | None = Field(None, description="执行日志文本")
|
||||
error_message: str | None = None
|
||||
|
||||
|
||||
class ExecutionOut(BaseModel):
|
||||
id: int
|
||||
task_id: int
|
||||
agent_id: int
|
||||
status: str
|
||||
started_at: datetime
|
||||
finished_at: datetime | None = None
|
||||
duration_ms: int | None = None
|
||||
result: str | None = None
|
||||
log: str | None = None
|
||||
error_message: str | None = None
|
||||
created_at: datetime
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
@@ -0,0 +1,70 @@
|
||||
"""Pydantic schemas — Notifications & Alerts."""
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
# ── Notification Channel ──────────────────────────────────────────────
|
||||
|
||||
class NotificationChannelCreate(BaseModel):
|
||||
name: str = Field(..., max_length=128)
|
||||
channel_type: str = Field(..., pattern=r"^(feishu_cli|email|webhook)$")
|
||||
config: str = Field(..., description="JSON 配置字符串")
|
||||
|
||||
|
||||
class NotificationChannelUpdate(BaseModel):
|
||||
name: str | None = Field(None, max_length=128)
|
||||
config: str | None = None
|
||||
enabled: bool | None = None
|
||||
|
||||
|
||||
class NotificationChannelOut(BaseModel):
|
||||
id: int
|
||||
name: str
|
||||
channel_type: str
|
||||
config: str
|
||||
enabled: bool
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
# ── Alert Rule ────────────────────────────────────────────────────────
|
||||
|
||||
class AlertRuleCreate(BaseModel):
|
||||
task_id: int
|
||||
channel_id: int
|
||||
alert_type: str = Field(default="missed_run", pattern=r"^(missed_run|failure)$")
|
||||
|
||||
|
||||
class AlertRuleOut(BaseModel):
|
||||
id: int
|
||||
task_id: int
|
||||
channel_id: int
|
||||
channel_name: str = ""
|
||||
alert_type: str
|
||||
enabled: bool
|
||||
created_at: datetime
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
# ── Alert ─────────────────────────────────────────────────────────────
|
||||
|
||||
class AlertOut(BaseModel):
|
||||
id: int
|
||||
task_id: int | None = None
|
||||
task_name: str = ""
|
||||
alert_type: str
|
||||
message: str
|
||||
status: str
|
||||
acknowledged_at: datetime | None = None
|
||||
created_at: datetime
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
class AlertAcknowledge(BaseModel):
|
||||
pass
|
||||
@@ -0,0 +1,39 @@
|
||||
"""Pydantic schemas — ScheduledTask."""
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class TaskCreate(BaseModel):
|
||||
name: str = Field(..., max_length=256)
|
||||
description: str = Field(default="")
|
||||
cron_expression: str = Field(..., max_length=64)
|
||||
grace_period: int = Field(default=300, ge=0)
|
||||
|
||||
|
||||
class TaskUpdate(BaseModel):
|
||||
name: str | None = Field(None, max_length=256)
|
||||
description: str | None = None
|
||||
cron_expression: str | None = None
|
||||
grace_period: int | None = None
|
||||
status: str | None = None # active / paused / stopped
|
||||
|
||||
|
||||
class TaskOut(BaseModel):
|
||||
id: int
|
||||
agent_id: int
|
||||
agent_name: str = ""
|
||||
name: str
|
||||
description: str
|
||||
cron_expression: str
|
||||
grace_period: int
|
||||
status: str
|
||||
last_run_at: datetime | None = None
|
||||
last_run_result: str | None = None
|
||||
next_run_at: datetime | None = None
|
||||
total_run_count: int = 0
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
Reference in New Issue
Block a user