90 lines
3.6 KiB
Python
90 lines
3.6 KiB
Python
"""Skill:双执行器(龙虾 / 脚本)注册 + 参数 schema + 产品范围绑定。"""
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy import (
|
|
JSON,
|
|
Column,
|
|
DateTime,
|
|
ForeignKey,
|
|
Integer,
|
|
String,
|
|
Table,
|
|
Text,
|
|
func,
|
|
)
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from app.db.base import Base, TimestampMixin
|
|
|
|
skill_product_scope = Table(
|
|
"skill_product_scope",
|
|
Base.metadata,
|
|
Column("skill_id", Integer, ForeignKey("skill.id", ondelete="CASCADE"), primary_key=True),
|
|
Column("product_id", Integer, ForeignKey("product.id", ondelete="CASCADE"), primary_key=True),
|
|
)
|
|
|
|
|
|
class Skill(Base, TimestampMixin):
|
|
__tablename__ = "skill"
|
|
|
|
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
|
code: Mapped[str] = mapped_column(String(64), nullable=False, unique=True)
|
|
name: Mapped[str] = mapped_column(String(128), nullable=False)
|
|
category: Mapped[str | None] = mapped_column(String(32), nullable=True)
|
|
# LOBSTER / SCRIPT
|
|
executor_type: Mapped[str] = mapped_column(String(16), nullable=False, default="LOBSTER")
|
|
description: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
|
|
|
# 输入参数 JSON Schema(展示给用户填写)
|
|
input_schema: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
# 参数映射表达式:{ "lobster_param_key": "{{input.field}}" } 之类
|
|
param_mapping: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
|
|
# 龙虾模板 ID / 脚本模板 ID (二选一,由 executor_type 决定)
|
|
lobster_template_id: Mapped[str | None] = mapped_column(String(128), nullable=True)
|
|
script_template_id: Mapped[int | None] = mapped_column(
|
|
ForeignKey("script_template.id", ondelete="SET NULL"), nullable=True
|
|
)
|
|
|
|
status: Mapped[str] = mapped_column(String(16), default="ACTIVE", nullable=False)
|
|
|
|
# 执行示例 / 说明文档(可选)
|
|
doc: Mapped[str | None] = mapped_column(Text, nullable=True)
|
|
|
|
product_scope: Mapped[list["Product"]] = relationship( # type: ignore[name-defined] # noqa: F821
|
|
"Product", secondary=skill_product_scope, lazy="selectin"
|
|
)
|
|
|
|
|
|
class SkillCallLog(Base):
|
|
"""Skill 调用审计(由测试台 / 任务执行器写入)。"""
|
|
|
|
__tablename__ = "skill_call_log"
|
|
|
|
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
|
skill_id: Mapped[int] = mapped_column(
|
|
ForeignKey("skill.id", ondelete="CASCADE"), nullable=False, index=True
|
|
)
|
|
skill_code: Mapped[str] = mapped_column(String(64), nullable=False)
|
|
operator_id: Mapped[int | None] = mapped_column(
|
|
ForeignKey("user.id", ondelete="SET NULL"), nullable=True, index=True
|
|
)
|
|
operator_name: Mapped[str | None] = mapped_column(String(64), nullable=True)
|
|
executor_type: Mapped[str] = mapped_column(String(16), nullable=False)
|
|
product_id: Mapped[int | None] = mapped_column(
|
|
ForeignKey("product.id", ondelete="SET NULL"), nullable=True
|
|
)
|
|
input_data: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
output_data: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
# ok / failed
|
|
result: Mapped[str] = mapped_column(String(16), nullable=False, default="ok")
|
|
message: Mapped[str | None] = mapped_column(String(512), nullable=True)
|
|
cost_ms: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
|
|
# 是测试台调用还是真实任务调用
|
|
source: Mapped[str] = mapped_column(String(16), default="test", nullable=False)
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), server_default=func.now(), nullable=False, index=True
|
|
)
|