feat(aiops): add mcp agent loop foundation
Some checks failed
CD Pipeline / tests (push) Successful in 1m59s
Code Review / ai-code-review (push) Successful in 28s
run-migration / migrate (push) Failing after 24s
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled

This commit is contained in:
Your Name
2026-05-01 13:21:19 +08:00
parent 9db87f177e
commit 7e4d995e4b
15 changed files with 1162 additions and 28 deletions

View File

@@ -19,6 +19,7 @@ from sqlalchemy import (
BigInteger,
Boolean,
CheckConstraint,
Date,
DateTime,
Float,
Index,
@@ -456,6 +457,90 @@ class AuditLog(Base):
)
# =============================================================================
# MCP Audit / Snapshots — 2026-05-01 ghost-loop + MCP governance
# =============================================================================
class MCPAuditLog(Base):
"""Durable audit trail for every MCP tool call."""
__tablename__ = "mcp_audit_log"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
session_id: Mapped[str] = mapped_column(String(36), nullable=False)
flywheel_node: Mapped[str | None] = mapped_column(String(20), nullable=True)
mcp_server: Mapped[str] = mapped_column(String(80), nullable=False)
tool_name: Mapped[str] = mapped_column(String(120), nullable=False)
input_params: Mapped[dict | None] = mapped_column(JSONB, nullable=True)
output_result: Mapped[dict | list | str | None] = mapped_column(JSONB, nullable=True)
duration_ms: Mapped[int | None] = mapped_column(Integer, nullable=True)
success: Mapped[bool | None] = mapped_column(Boolean, nullable=True)
error_message: Mapped[str | None] = mapped_column(Text, nullable=True)
incident_id: Mapped[str | None] = mapped_column(String(64), nullable=True)
agent_role: Mapped[str | None] = mapped_column(String(40), nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=taipei_now)
__table_args__ = (
Index("idx_mcp_audit_session", "session_id"),
Index("idx_mcp_audit_incident", "incident_id"),
Index("idx_mcp_audit_node", "flywheel_node", "created_at"),
Index("idx_mcp_audit_server_tool", "mcp_server", "tool_name", "created_at"),
Index("idx_mcp_audit_agent_role", "agent_role", "created_at"),
)
class MCPDailyStats(Base):
"""Daily aggregate for MCP provider/tool success rate and latency."""
__tablename__ = "mcp_daily_stats"
date: Mapped[datetime] = mapped_column(Date, primary_key=True)
mcp_server: Mapped[str] = mapped_column(String(80), primary_key=True)
tool_name: Mapped[str] = mapped_column(String(120), primary_key=True)
call_count: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
success_count: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
avg_duration_ms: Mapped[float | None] = mapped_column(Float, nullable=True)
class K8sStateSnapshot(Base):
"""Pre/post Kubernetes resource state snapshots for remediation verification."""
__tablename__ = "k8s_state_snapshots"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
incident_id: Mapped[str | None] = mapped_column(String(64), nullable=True)
snapshot_type: Mapped[str] = mapped_column(String(40), nullable=False)
namespace: Mapped[str | None] = mapped_column(String(63), nullable=True)
resource_type: Mapped[str | None] = mapped_column(String(80), nullable=True)
resource_name: Mapped[str | None] = mapped_column(String(253), nullable=True)
state_json: Mapped[dict | None] = mapped_column(JSONB, nullable=True)
captured_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=taipei_now)
__table_args__ = (
Index("idx_k8s_snapshot_incident", "incident_id"),
Index("idx_k8s_snapshot_resource", "namespace", "resource_type", "resource_name"),
Index("idx_k8s_snapshot_captured", "captured_at"),
)
class PrometheusSnapshot(Base):
"""Prometheus query snapshots for detect/verify flywheel stages."""
__tablename__ = "prometheus_snapshots"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
incident_id: Mapped[str | None] = mapped_column(String(64), nullable=True)
query: Mapped[str] = mapped_column(Text, nullable=False)
result_json: Mapped[dict | list | str | None] = mapped_column(JSONB, nullable=True)
snapshot_type: Mapped[str | None] = mapped_column(String(40), nullable=True)
captured_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=taipei_now)
__table_args__ = (
Index("idx_prom_snapshot_incident", "incident_id"),
Index("idx_prom_snapshot_type", "snapshot_type", "captured_at"),
)
# =============================================================================
# AutoRepairExecution - Phase 10 操作記錄
# 2026-04-08 Claude Code: 統帥指令「所有操作都必須被記錄,寫入資料庫」