Prechádzať zdrojové kódy

feat:AI角色模块代码提交

jimmyyem 7 mesiacov pred
rodič
commit
3f2d6732c4

+ 2 - 1
desc/all.api

@@ -12,4 +12,5 @@ import "./wechat/sop_node.api"
 import "./wechat/message_records.api"
 import "./wechat/chatroom_member.api"
 import "./openapi/contact.api"
-import "./wechat/batch_msg.api"
+import "./wechat/batch_msg.api"
+import "./wechat/agent.api"

+ 89 - 0
desc/wechat/agent.api

@@ -0,0 +1,89 @@
+import "../base.api"
+
+type (
+    // The data of agent information | Agent信息
+    AgentInfo {
+        BaseIDInfo
+
+        // name | 角色名称 
+        Name  *string `json:"name,optional"`
+
+        // role | 角色设定 
+        Role  *string `json:"role,optional"`
+
+        // status | 状态 1-正常 2-禁用 
+        Status  *int `json:"status,optional"`
+
+        // background | 背景介绍 
+        Background  *string `json:"background,optional"`
+
+        // examples | 对话案例 
+        Examples  *string `json:"examples,optional"`
+    }
+
+    // The response data of agent list | Agent列表数据
+    AgentListResp {
+        BaseDataInfo
+
+        // Agent list data | Agent列表数据
+        Data AgentListInfo `json:"data"`
+    }
+
+    // Agent list data | Agent列表数据
+    AgentListInfo {
+        BaseListInfo
+
+        // The API list data | Agent列表数据
+        Data  []AgentInfo  `json:"data"`
+    }
+
+    // Get agent list request params | Agent列表请求参数
+    AgentListReq {
+        PageInfo
+
+        // name | 角色名称 
+        Name  *string `json:"name,optional"`
+
+        // role | 角色设定 
+        Role  *string `json:"role,optional"`
+
+        // background | 背景介绍 
+        Background  *string `json:"background,optional"`
+    }
+
+    // Agent information response | Agent信息返回体
+    AgentInfoResp {
+        BaseDataInfo
+
+        // Agent information | Agent数据
+        Data AgentInfo `json:"data"`
+    }
+)
+
+@server(
+    jwt: Auth
+    group: agent
+    middleware: Authority
+)
+
+service Wechat {
+    // Create agent information | 创建Agent
+    @handler createAgent
+    post /agent/create (AgentInfo) returns (BaseMsgResp)
+
+    // Update agent information | 更新Agent
+    @handler updateAgent
+    post /agent/update (AgentInfo) returns (BaseMsgResp)
+
+    // Delete agent information | 删除Agent信息
+    @handler deleteAgent
+    post /agent/delete (IDsReq) returns (BaseMsgResp)
+
+    // Get agent list | 获取Agent列表
+    @handler getAgentList
+    post /agent/list (AgentListReq) returns (AgentListResp)
+
+    // Get agent by ID | 通过ID获取Agent
+    @handler getAgentById
+    post /agent (IDReq) returns (AgentInfoResp)
+}

+ 183 - 0
ent/agent.go

@@ -0,0 +1,183 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"fmt"
+	"strings"
+	"time"
+	"wechat-api/ent/agent"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/sql"
+)
+
+// Agent is the model entity for the Agent schema.
+type Agent struct {
+	config `json:"-"`
+	// ID of the ent.
+	ID uint64 `json:"id,omitempty"`
+	// Create Time | 创建日期
+	CreatedAt time.Time `json:"created_at,omitempty"`
+	// Update Time | 修改日期
+	UpdatedAt time.Time `json:"updated_at,omitempty"`
+	// Delete Time | 删除日期
+	DeletedAt time.Time `json:"deleted_at,omitempty"`
+	// name | 角色名称
+	Name string `json:"name,omitempty"`
+	// role | 角色设定
+	Role string `json:"role,omitempty"`
+	// status | 状态 1-正常 2-禁用
+	Status int `json:"status,omitempty"`
+	// background | 背景介绍
+	Background string `json:"background,omitempty"`
+	// examples | 对话案例
+	Examples     string `json:"examples,omitempty"`
+	selectValues sql.SelectValues
+}
+
+// scanValues returns the types for scanning values from sql.Rows.
+func (*Agent) scanValues(columns []string) ([]any, error) {
+	values := make([]any, len(columns))
+	for i := range columns {
+		switch columns[i] {
+		case agent.FieldID, agent.FieldStatus:
+			values[i] = new(sql.NullInt64)
+		case agent.FieldName, agent.FieldRole, agent.FieldBackground, agent.FieldExamples:
+			values[i] = new(sql.NullString)
+		case agent.FieldCreatedAt, agent.FieldUpdatedAt, agent.FieldDeletedAt:
+			values[i] = new(sql.NullTime)
+		default:
+			values[i] = new(sql.UnknownType)
+		}
+	}
+	return values, nil
+}
+
+// assignValues assigns the values that were returned from sql.Rows (after scanning)
+// to the Agent fields.
+func (a *Agent) assignValues(columns []string, values []any) error {
+	if m, n := len(values), len(columns); m < n {
+		return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
+	}
+	for i := range columns {
+		switch columns[i] {
+		case agent.FieldID:
+			value, ok := values[i].(*sql.NullInt64)
+			if !ok {
+				return fmt.Errorf("unexpected type %T for field id", value)
+			}
+			a.ID = uint64(value.Int64)
+		case agent.FieldCreatedAt:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field created_at", values[i])
+			} else if value.Valid {
+				a.CreatedAt = value.Time
+			}
+		case agent.FieldUpdatedAt:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field updated_at", values[i])
+			} else if value.Valid {
+				a.UpdatedAt = value.Time
+			}
+		case agent.FieldDeletedAt:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field deleted_at", values[i])
+			} else if value.Valid {
+				a.DeletedAt = value.Time
+			}
+		case agent.FieldName:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field name", values[i])
+			} else if value.Valid {
+				a.Name = value.String
+			}
+		case agent.FieldRole:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field role", values[i])
+			} else if value.Valid {
+				a.Role = value.String
+			}
+		case agent.FieldStatus:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field status", values[i])
+			} else if value.Valid {
+				a.Status = int(value.Int64)
+			}
+		case agent.FieldBackground:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field background", values[i])
+			} else if value.Valid {
+				a.Background = value.String
+			}
+		case agent.FieldExamples:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field examples", values[i])
+			} else if value.Valid {
+				a.Examples = value.String
+			}
+		default:
+			a.selectValues.Set(columns[i], values[i])
+		}
+	}
+	return nil
+}
+
+// Value returns the ent.Value that was dynamically selected and assigned to the Agent.
+// This includes values selected through modifiers, order, etc.
+func (a *Agent) Value(name string) (ent.Value, error) {
+	return a.selectValues.Get(name)
+}
+
+// Update returns a builder for updating this Agent.
+// Note that you need to call Agent.Unwrap() before calling this method if this Agent
+// was returned from a transaction, and the transaction was committed or rolled back.
+func (a *Agent) Update() *AgentUpdateOne {
+	return NewAgentClient(a.config).UpdateOne(a)
+}
+
+// Unwrap unwraps the Agent entity that was returned from a transaction after it was closed,
+// so that all future queries will be executed through the driver which created the transaction.
+func (a *Agent) Unwrap() *Agent {
+	_tx, ok := a.config.driver.(*txDriver)
+	if !ok {
+		panic("ent: Agent is not a transactional entity")
+	}
+	a.config.driver = _tx.drv
+	return a
+}
+
+// String implements the fmt.Stringer.
+func (a *Agent) String() string {
+	var builder strings.Builder
+	builder.WriteString("Agent(")
+	builder.WriteString(fmt.Sprintf("id=%v, ", a.ID))
+	builder.WriteString("created_at=")
+	builder.WriteString(a.CreatedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("updated_at=")
+	builder.WriteString(a.UpdatedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("deleted_at=")
+	builder.WriteString(a.DeletedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("name=")
+	builder.WriteString(a.Name)
+	builder.WriteString(", ")
+	builder.WriteString("role=")
+	builder.WriteString(a.Role)
+	builder.WriteString(", ")
+	builder.WriteString("status=")
+	builder.WriteString(fmt.Sprintf("%v", a.Status))
+	builder.WriteString(", ")
+	builder.WriteString("background=")
+	builder.WriteString(a.Background)
+	builder.WriteString(", ")
+	builder.WriteString("examples=")
+	builder.WriteString(a.Examples)
+	builder.WriteByte(')')
+	return builder.String()
+}
+
+// Agents is a parsable slice of Agent.
+type Agents []*Agent

+ 132 - 0
ent/agent/agent.go

@@ -0,0 +1,132 @@
+// Code generated by ent, DO NOT EDIT.
+
+package agent
+
+import (
+	"time"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/sql"
+)
+
+const (
+	// Label holds the string label denoting the agent type in the database.
+	Label = "agent"
+	// FieldID holds the string denoting the id field in the database.
+	FieldID = "id"
+	// FieldCreatedAt holds the string denoting the created_at field in the database.
+	FieldCreatedAt = "created_at"
+	// FieldUpdatedAt holds the string denoting the updated_at field in the database.
+	FieldUpdatedAt = "updated_at"
+	// FieldDeletedAt holds the string denoting the deleted_at field in the database.
+	FieldDeletedAt = "deleted_at"
+	// FieldName holds the string denoting the name field in the database.
+	FieldName = "name"
+	// FieldRole holds the string denoting the role field in the database.
+	FieldRole = "role"
+	// FieldStatus holds the string denoting the status field in the database.
+	FieldStatus = "status"
+	// FieldBackground holds the string denoting the background field in the database.
+	FieldBackground = "background"
+	// FieldExamples holds the string denoting the examples field in the database.
+	FieldExamples = "examples"
+	// Table holds the table name of the agent in the database.
+	Table = "agent"
+)
+
+// Columns holds all SQL columns for agent fields.
+var Columns = []string{
+	FieldID,
+	FieldCreatedAt,
+	FieldUpdatedAt,
+	FieldDeletedAt,
+	FieldName,
+	FieldRole,
+	FieldStatus,
+	FieldBackground,
+	FieldExamples,
+}
+
+// ValidColumn reports if the column name is valid (part of the table columns).
+func ValidColumn(column string) bool {
+	for i := range Columns {
+		if column == Columns[i] {
+			return true
+		}
+	}
+	return false
+}
+
+// Note that the variables below are initialized by the runtime
+// package on the initialization of the application. Therefore,
+// it should be imported in the main as follows:
+//
+//	import _ "wechat-api/ent/runtime"
+var (
+	Hooks        [1]ent.Hook
+	Interceptors [1]ent.Interceptor
+	// DefaultCreatedAt holds the default value on creation for the "created_at" field.
+	DefaultCreatedAt func() time.Time
+	// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
+	DefaultUpdatedAt func() time.Time
+	// UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field.
+	UpdateDefaultUpdatedAt func() time.Time
+	// NameValidator is a validator for the "name" field. It is called by the builders before save.
+	NameValidator func(string) error
+	// RoleValidator is a validator for the "role" field. It is called by the builders before save.
+	RoleValidator func(string) error
+	// DefaultStatus holds the default value on creation for the "status" field.
+	DefaultStatus int
+	// BackgroundValidator is a validator for the "background" field. It is called by the builders before save.
+	BackgroundValidator func(string) error
+	// ExamplesValidator is a validator for the "examples" field. It is called by the builders before save.
+	ExamplesValidator func(string) error
+)
+
+// OrderOption defines the ordering options for the Agent queries.
+type OrderOption func(*sql.Selector)
+
+// ByID orders the results by the id field.
+func ByID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldID, opts...).ToFunc()
+}
+
+// ByCreatedAt orders the results by the created_at field.
+func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
+}
+
+// ByUpdatedAt orders the results by the updated_at field.
+func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc()
+}
+
+// ByDeletedAt orders the results by the deleted_at field.
+func ByDeletedAt(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldDeletedAt, opts...).ToFunc()
+}
+
+// ByName orders the results by the name field.
+func ByName(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldName, opts...).ToFunc()
+}
+
+// ByRole orders the results by the role field.
+func ByRole(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldRole, opts...).ToFunc()
+}
+
+// ByStatus orders the results by the status field.
+func ByStatus(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldStatus, opts...).ToFunc()
+}
+
+// ByBackground orders the results by the background field.
+func ByBackground(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldBackground, opts...).ToFunc()
+}
+
+// ByExamples orders the results by the examples field.
+func ByExamples(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldExamples, opts...).ToFunc()
+}

+ 550 - 0
ent/agent/where.go

@@ -0,0 +1,550 @@
+// Code generated by ent, DO NOT EDIT.
+
+package agent
+
+import (
+	"time"
+	"wechat-api/ent/predicate"
+
+	"entgo.io/ent/dialect/sql"
+)
+
+// ID filters vertices based on their ID field.
+func ID(id uint64) predicate.Agent {
+	return predicate.Agent(sql.FieldEQ(FieldID, id))
+}
+
+// IDEQ applies the EQ predicate on the ID field.
+func IDEQ(id uint64) predicate.Agent {
+	return predicate.Agent(sql.FieldEQ(FieldID, id))
+}
+
+// IDNEQ applies the NEQ predicate on the ID field.
+func IDNEQ(id uint64) predicate.Agent {
+	return predicate.Agent(sql.FieldNEQ(FieldID, id))
+}
+
+// IDIn applies the In predicate on the ID field.
+func IDIn(ids ...uint64) predicate.Agent {
+	return predicate.Agent(sql.FieldIn(FieldID, ids...))
+}
+
+// IDNotIn applies the NotIn predicate on the ID field.
+func IDNotIn(ids ...uint64) predicate.Agent {
+	return predicate.Agent(sql.FieldNotIn(FieldID, ids...))
+}
+
+// IDGT applies the GT predicate on the ID field.
+func IDGT(id uint64) predicate.Agent {
+	return predicate.Agent(sql.FieldGT(FieldID, id))
+}
+
+// IDGTE applies the GTE predicate on the ID field.
+func IDGTE(id uint64) predicate.Agent {
+	return predicate.Agent(sql.FieldGTE(FieldID, id))
+}
+
+// IDLT applies the LT predicate on the ID field.
+func IDLT(id uint64) predicate.Agent {
+	return predicate.Agent(sql.FieldLT(FieldID, id))
+}
+
+// IDLTE applies the LTE predicate on the ID field.
+func IDLTE(id uint64) predicate.Agent {
+	return predicate.Agent(sql.FieldLTE(FieldID, id))
+}
+
+// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
+func CreatedAt(v time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldEQ(FieldCreatedAt, v))
+}
+
+// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
+func UpdatedAt(v time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldEQ(FieldUpdatedAt, v))
+}
+
+// DeletedAt applies equality check predicate on the "deleted_at" field. It's identical to DeletedAtEQ.
+func DeletedAt(v time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldEQ(FieldDeletedAt, v))
+}
+
+// Name applies equality check predicate on the "name" field. It's identical to NameEQ.
+func Name(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldEQ(FieldName, v))
+}
+
+// Role applies equality check predicate on the "role" field. It's identical to RoleEQ.
+func Role(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldEQ(FieldRole, v))
+}
+
+// Status applies equality check predicate on the "status" field. It's identical to StatusEQ.
+func Status(v int) predicate.Agent {
+	return predicate.Agent(sql.FieldEQ(FieldStatus, v))
+}
+
+// Background applies equality check predicate on the "background" field. It's identical to BackgroundEQ.
+func Background(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldEQ(FieldBackground, v))
+}
+
+// Examples applies equality check predicate on the "examples" field. It's identical to ExamplesEQ.
+func Examples(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldEQ(FieldExamples, v))
+}
+
+// CreatedAtEQ applies the EQ predicate on the "created_at" field.
+func CreatedAtEQ(v time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldEQ(FieldCreatedAt, v))
+}
+
+// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
+func CreatedAtNEQ(v time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldNEQ(FieldCreatedAt, v))
+}
+
+// CreatedAtIn applies the In predicate on the "created_at" field.
+func CreatedAtIn(vs ...time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldIn(FieldCreatedAt, vs...))
+}
+
+// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
+func CreatedAtNotIn(vs ...time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldNotIn(FieldCreatedAt, vs...))
+}
+
+// CreatedAtGT applies the GT predicate on the "created_at" field.
+func CreatedAtGT(v time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldGT(FieldCreatedAt, v))
+}
+
+// CreatedAtGTE applies the GTE predicate on the "created_at" field.
+func CreatedAtGTE(v time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldGTE(FieldCreatedAt, v))
+}
+
+// CreatedAtLT applies the LT predicate on the "created_at" field.
+func CreatedAtLT(v time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldLT(FieldCreatedAt, v))
+}
+
+// CreatedAtLTE applies the LTE predicate on the "created_at" field.
+func CreatedAtLTE(v time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldLTE(FieldCreatedAt, v))
+}
+
+// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
+func UpdatedAtEQ(v time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldEQ(FieldUpdatedAt, v))
+}
+
+// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
+func UpdatedAtNEQ(v time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldNEQ(FieldUpdatedAt, v))
+}
+
+// UpdatedAtIn applies the In predicate on the "updated_at" field.
+func UpdatedAtIn(vs ...time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldIn(FieldUpdatedAt, vs...))
+}
+
+// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
+func UpdatedAtNotIn(vs ...time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldNotIn(FieldUpdatedAt, vs...))
+}
+
+// UpdatedAtGT applies the GT predicate on the "updated_at" field.
+func UpdatedAtGT(v time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldGT(FieldUpdatedAt, v))
+}
+
+// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
+func UpdatedAtGTE(v time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldGTE(FieldUpdatedAt, v))
+}
+
+// UpdatedAtLT applies the LT predicate on the "updated_at" field.
+func UpdatedAtLT(v time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldLT(FieldUpdatedAt, v))
+}
+
+// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
+func UpdatedAtLTE(v time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldLTE(FieldUpdatedAt, v))
+}
+
+// DeletedAtEQ applies the EQ predicate on the "deleted_at" field.
+func DeletedAtEQ(v time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldEQ(FieldDeletedAt, v))
+}
+
+// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field.
+func DeletedAtNEQ(v time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldNEQ(FieldDeletedAt, v))
+}
+
+// DeletedAtIn applies the In predicate on the "deleted_at" field.
+func DeletedAtIn(vs ...time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldIn(FieldDeletedAt, vs...))
+}
+
+// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field.
+func DeletedAtNotIn(vs ...time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldNotIn(FieldDeletedAt, vs...))
+}
+
+// DeletedAtGT applies the GT predicate on the "deleted_at" field.
+func DeletedAtGT(v time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldGT(FieldDeletedAt, v))
+}
+
+// DeletedAtGTE applies the GTE predicate on the "deleted_at" field.
+func DeletedAtGTE(v time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldGTE(FieldDeletedAt, v))
+}
+
+// DeletedAtLT applies the LT predicate on the "deleted_at" field.
+func DeletedAtLT(v time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldLT(FieldDeletedAt, v))
+}
+
+// DeletedAtLTE applies the LTE predicate on the "deleted_at" field.
+func DeletedAtLTE(v time.Time) predicate.Agent {
+	return predicate.Agent(sql.FieldLTE(FieldDeletedAt, v))
+}
+
+// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field.
+func DeletedAtIsNil() predicate.Agent {
+	return predicate.Agent(sql.FieldIsNull(FieldDeletedAt))
+}
+
+// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field.
+func DeletedAtNotNil() predicate.Agent {
+	return predicate.Agent(sql.FieldNotNull(FieldDeletedAt))
+}
+
+// NameEQ applies the EQ predicate on the "name" field.
+func NameEQ(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldEQ(FieldName, v))
+}
+
+// NameNEQ applies the NEQ predicate on the "name" field.
+func NameNEQ(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldNEQ(FieldName, v))
+}
+
+// NameIn applies the In predicate on the "name" field.
+func NameIn(vs ...string) predicate.Agent {
+	return predicate.Agent(sql.FieldIn(FieldName, vs...))
+}
+
+// NameNotIn applies the NotIn predicate on the "name" field.
+func NameNotIn(vs ...string) predicate.Agent {
+	return predicate.Agent(sql.FieldNotIn(FieldName, vs...))
+}
+
+// NameGT applies the GT predicate on the "name" field.
+func NameGT(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldGT(FieldName, v))
+}
+
+// NameGTE applies the GTE predicate on the "name" field.
+func NameGTE(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldGTE(FieldName, v))
+}
+
+// NameLT applies the LT predicate on the "name" field.
+func NameLT(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldLT(FieldName, v))
+}
+
+// NameLTE applies the LTE predicate on the "name" field.
+func NameLTE(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldLTE(FieldName, v))
+}
+
+// NameContains applies the Contains predicate on the "name" field.
+func NameContains(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldContains(FieldName, v))
+}
+
+// NameHasPrefix applies the HasPrefix predicate on the "name" field.
+func NameHasPrefix(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldHasPrefix(FieldName, v))
+}
+
+// NameHasSuffix applies the HasSuffix predicate on the "name" field.
+func NameHasSuffix(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldHasSuffix(FieldName, v))
+}
+
+// NameEqualFold applies the EqualFold predicate on the "name" field.
+func NameEqualFold(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldEqualFold(FieldName, v))
+}
+
+// NameContainsFold applies the ContainsFold predicate on the "name" field.
+func NameContainsFold(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldContainsFold(FieldName, v))
+}
+
+// RoleEQ applies the EQ predicate on the "role" field.
+func RoleEQ(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldEQ(FieldRole, v))
+}
+
+// RoleNEQ applies the NEQ predicate on the "role" field.
+func RoleNEQ(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldNEQ(FieldRole, v))
+}
+
+// RoleIn applies the In predicate on the "role" field.
+func RoleIn(vs ...string) predicate.Agent {
+	return predicate.Agent(sql.FieldIn(FieldRole, vs...))
+}
+
+// RoleNotIn applies the NotIn predicate on the "role" field.
+func RoleNotIn(vs ...string) predicate.Agent {
+	return predicate.Agent(sql.FieldNotIn(FieldRole, vs...))
+}
+
+// RoleGT applies the GT predicate on the "role" field.
+func RoleGT(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldGT(FieldRole, v))
+}
+
+// RoleGTE applies the GTE predicate on the "role" field.
+func RoleGTE(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldGTE(FieldRole, v))
+}
+
+// RoleLT applies the LT predicate on the "role" field.
+func RoleLT(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldLT(FieldRole, v))
+}
+
+// RoleLTE applies the LTE predicate on the "role" field.
+func RoleLTE(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldLTE(FieldRole, v))
+}
+
+// RoleContains applies the Contains predicate on the "role" field.
+func RoleContains(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldContains(FieldRole, v))
+}
+
+// RoleHasPrefix applies the HasPrefix predicate on the "role" field.
+func RoleHasPrefix(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldHasPrefix(FieldRole, v))
+}
+
+// RoleHasSuffix applies the HasSuffix predicate on the "role" field.
+func RoleHasSuffix(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldHasSuffix(FieldRole, v))
+}
+
+// RoleEqualFold applies the EqualFold predicate on the "role" field.
+func RoleEqualFold(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldEqualFold(FieldRole, v))
+}
+
+// RoleContainsFold applies the ContainsFold predicate on the "role" field.
+func RoleContainsFold(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldContainsFold(FieldRole, v))
+}
+
+// StatusEQ applies the EQ predicate on the "status" field.
+func StatusEQ(v int) predicate.Agent {
+	return predicate.Agent(sql.FieldEQ(FieldStatus, v))
+}
+
+// StatusNEQ applies the NEQ predicate on the "status" field.
+func StatusNEQ(v int) predicate.Agent {
+	return predicate.Agent(sql.FieldNEQ(FieldStatus, v))
+}
+
+// StatusIn applies the In predicate on the "status" field.
+func StatusIn(vs ...int) predicate.Agent {
+	return predicate.Agent(sql.FieldIn(FieldStatus, vs...))
+}
+
+// StatusNotIn applies the NotIn predicate on the "status" field.
+func StatusNotIn(vs ...int) predicate.Agent {
+	return predicate.Agent(sql.FieldNotIn(FieldStatus, vs...))
+}
+
+// StatusGT applies the GT predicate on the "status" field.
+func StatusGT(v int) predicate.Agent {
+	return predicate.Agent(sql.FieldGT(FieldStatus, v))
+}
+
+// StatusGTE applies the GTE predicate on the "status" field.
+func StatusGTE(v int) predicate.Agent {
+	return predicate.Agent(sql.FieldGTE(FieldStatus, v))
+}
+
+// StatusLT applies the LT predicate on the "status" field.
+func StatusLT(v int) predicate.Agent {
+	return predicate.Agent(sql.FieldLT(FieldStatus, v))
+}
+
+// StatusLTE applies the LTE predicate on the "status" field.
+func StatusLTE(v int) predicate.Agent {
+	return predicate.Agent(sql.FieldLTE(FieldStatus, v))
+}
+
+// StatusIsNil applies the IsNil predicate on the "status" field.
+func StatusIsNil() predicate.Agent {
+	return predicate.Agent(sql.FieldIsNull(FieldStatus))
+}
+
+// StatusNotNil applies the NotNil predicate on the "status" field.
+func StatusNotNil() predicate.Agent {
+	return predicate.Agent(sql.FieldNotNull(FieldStatus))
+}
+
+// BackgroundEQ applies the EQ predicate on the "background" field.
+func BackgroundEQ(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldEQ(FieldBackground, v))
+}
+
+// BackgroundNEQ applies the NEQ predicate on the "background" field.
+func BackgroundNEQ(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldNEQ(FieldBackground, v))
+}
+
+// BackgroundIn applies the In predicate on the "background" field.
+func BackgroundIn(vs ...string) predicate.Agent {
+	return predicate.Agent(sql.FieldIn(FieldBackground, vs...))
+}
+
+// BackgroundNotIn applies the NotIn predicate on the "background" field.
+func BackgroundNotIn(vs ...string) predicate.Agent {
+	return predicate.Agent(sql.FieldNotIn(FieldBackground, vs...))
+}
+
+// BackgroundGT applies the GT predicate on the "background" field.
+func BackgroundGT(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldGT(FieldBackground, v))
+}
+
+// BackgroundGTE applies the GTE predicate on the "background" field.
+func BackgroundGTE(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldGTE(FieldBackground, v))
+}
+
+// BackgroundLT applies the LT predicate on the "background" field.
+func BackgroundLT(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldLT(FieldBackground, v))
+}
+
+// BackgroundLTE applies the LTE predicate on the "background" field.
+func BackgroundLTE(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldLTE(FieldBackground, v))
+}
+
+// BackgroundContains applies the Contains predicate on the "background" field.
+func BackgroundContains(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldContains(FieldBackground, v))
+}
+
+// BackgroundHasPrefix applies the HasPrefix predicate on the "background" field.
+func BackgroundHasPrefix(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldHasPrefix(FieldBackground, v))
+}
+
+// BackgroundHasSuffix applies the HasSuffix predicate on the "background" field.
+func BackgroundHasSuffix(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldHasSuffix(FieldBackground, v))
+}
+
+// BackgroundEqualFold applies the EqualFold predicate on the "background" field.
+func BackgroundEqualFold(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldEqualFold(FieldBackground, v))
+}
+
+// BackgroundContainsFold applies the ContainsFold predicate on the "background" field.
+func BackgroundContainsFold(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldContainsFold(FieldBackground, v))
+}
+
+// ExamplesEQ applies the EQ predicate on the "examples" field.
+func ExamplesEQ(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldEQ(FieldExamples, v))
+}
+
+// ExamplesNEQ applies the NEQ predicate on the "examples" field.
+func ExamplesNEQ(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldNEQ(FieldExamples, v))
+}
+
+// ExamplesIn applies the In predicate on the "examples" field.
+func ExamplesIn(vs ...string) predicate.Agent {
+	return predicate.Agent(sql.FieldIn(FieldExamples, vs...))
+}
+
+// ExamplesNotIn applies the NotIn predicate on the "examples" field.
+func ExamplesNotIn(vs ...string) predicate.Agent {
+	return predicate.Agent(sql.FieldNotIn(FieldExamples, vs...))
+}
+
+// ExamplesGT applies the GT predicate on the "examples" field.
+func ExamplesGT(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldGT(FieldExamples, v))
+}
+
+// ExamplesGTE applies the GTE predicate on the "examples" field.
+func ExamplesGTE(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldGTE(FieldExamples, v))
+}
+
+// ExamplesLT applies the LT predicate on the "examples" field.
+func ExamplesLT(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldLT(FieldExamples, v))
+}
+
+// ExamplesLTE applies the LTE predicate on the "examples" field.
+func ExamplesLTE(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldLTE(FieldExamples, v))
+}
+
+// ExamplesContains applies the Contains predicate on the "examples" field.
+func ExamplesContains(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldContains(FieldExamples, v))
+}
+
+// ExamplesHasPrefix applies the HasPrefix predicate on the "examples" field.
+func ExamplesHasPrefix(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldHasPrefix(FieldExamples, v))
+}
+
+// ExamplesHasSuffix applies the HasSuffix predicate on the "examples" field.
+func ExamplesHasSuffix(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldHasSuffix(FieldExamples, v))
+}
+
+// ExamplesEqualFold applies the EqualFold predicate on the "examples" field.
+func ExamplesEqualFold(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldEqualFold(FieldExamples, v))
+}
+
+// ExamplesContainsFold applies the ContainsFold predicate on the "examples" field.
+func ExamplesContainsFold(v string) predicate.Agent {
+	return predicate.Agent(sql.FieldContainsFold(FieldExamples, v))
+}
+
+// And groups predicates with the AND operator between them.
+func And(predicates ...predicate.Agent) predicate.Agent {
+	return predicate.Agent(sql.AndPredicates(predicates...))
+}
+
+// Or groups predicates with the OR operator between them.
+func Or(predicates ...predicate.Agent) predicate.Agent {
+	return predicate.Agent(sql.OrPredicates(predicates...))
+}
+
+// Not applies the not operator on the given predicate.
+func Not(p predicate.Agent) predicate.Agent {
+	return predicate.Agent(sql.NotPredicates(p))
+}

+ 955 - 0
ent/agent_create.go

@@ -0,0 +1,955 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"time"
+	"wechat-api/ent/agent"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// AgentCreate is the builder for creating a Agent entity.
+type AgentCreate struct {
+	config
+	mutation *AgentMutation
+	hooks    []Hook
+	conflict []sql.ConflictOption
+}
+
+// SetCreatedAt sets the "created_at" field.
+func (ac *AgentCreate) SetCreatedAt(t time.Time) *AgentCreate {
+	ac.mutation.SetCreatedAt(t)
+	return ac
+}
+
+// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
+func (ac *AgentCreate) SetNillableCreatedAt(t *time.Time) *AgentCreate {
+	if t != nil {
+		ac.SetCreatedAt(*t)
+	}
+	return ac
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (ac *AgentCreate) SetUpdatedAt(t time.Time) *AgentCreate {
+	ac.mutation.SetUpdatedAt(t)
+	return ac
+}
+
+// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil.
+func (ac *AgentCreate) SetNillableUpdatedAt(t *time.Time) *AgentCreate {
+	if t != nil {
+		ac.SetUpdatedAt(*t)
+	}
+	return ac
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (ac *AgentCreate) SetDeletedAt(t time.Time) *AgentCreate {
+	ac.mutation.SetDeletedAt(t)
+	return ac
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (ac *AgentCreate) SetNillableDeletedAt(t *time.Time) *AgentCreate {
+	if t != nil {
+		ac.SetDeletedAt(*t)
+	}
+	return ac
+}
+
+// SetName sets the "name" field.
+func (ac *AgentCreate) SetName(s string) *AgentCreate {
+	ac.mutation.SetName(s)
+	return ac
+}
+
+// SetRole sets the "role" field.
+func (ac *AgentCreate) SetRole(s string) *AgentCreate {
+	ac.mutation.SetRole(s)
+	return ac
+}
+
+// SetStatus sets the "status" field.
+func (ac *AgentCreate) SetStatus(i int) *AgentCreate {
+	ac.mutation.SetStatus(i)
+	return ac
+}
+
+// SetNillableStatus sets the "status" field if the given value is not nil.
+func (ac *AgentCreate) SetNillableStatus(i *int) *AgentCreate {
+	if i != nil {
+		ac.SetStatus(*i)
+	}
+	return ac
+}
+
+// SetBackground sets the "background" field.
+func (ac *AgentCreate) SetBackground(s string) *AgentCreate {
+	ac.mutation.SetBackground(s)
+	return ac
+}
+
+// SetExamples sets the "examples" field.
+func (ac *AgentCreate) SetExamples(s string) *AgentCreate {
+	ac.mutation.SetExamples(s)
+	return ac
+}
+
+// SetID sets the "id" field.
+func (ac *AgentCreate) SetID(u uint64) *AgentCreate {
+	ac.mutation.SetID(u)
+	return ac
+}
+
+// Mutation returns the AgentMutation object of the builder.
+func (ac *AgentCreate) Mutation() *AgentMutation {
+	return ac.mutation
+}
+
+// Save creates the Agent in the database.
+func (ac *AgentCreate) Save(ctx context.Context) (*Agent, error) {
+	if err := ac.defaults(); err != nil {
+		return nil, err
+	}
+	return withHooks(ctx, ac.sqlSave, ac.mutation, ac.hooks)
+}
+
+// SaveX calls Save and panics if Save returns an error.
+func (ac *AgentCreate) SaveX(ctx context.Context) *Agent {
+	v, err := ac.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return v
+}
+
+// Exec executes the query.
+func (ac *AgentCreate) Exec(ctx context.Context) error {
+	_, err := ac.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (ac *AgentCreate) ExecX(ctx context.Context) {
+	if err := ac.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (ac *AgentCreate) defaults() error {
+	if _, ok := ac.mutation.CreatedAt(); !ok {
+		if agent.DefaultCreatedAt == nil {
+			return fmt.Errorf("ent: uninitialized agent.DefaultCreatedAt (forgotten import ent/runtime?)")
+		}
+		v := agent.DefaultCreatedAt()
+		ac.mutation.SetCreatedAt(v)
+	}
+	if _, ok := ac.mutation.UpdatedAt(); !ok {
+		if agent.DefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized agent.DefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := agent.DefaultUpdatedAt()
+		ac.mutation.SetUpdatedAt(v)
+	}
+	if _, ok := ac.mutation.Status(); !ok {
+		v := agent.DefaultStatus
+		ac.mutation.SetStatus(v)
+	}
+	return nil
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (ac *AgentCreate) check() error {
+	if _, ok := ac.mutation.CreatedAt(); !ok {
+		return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "Agent.created_at"`)}
+	}
+	if _, ok := ac.mutation.UpdatedAt(); !ok {
+		return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "Agent.updated_at"`)}
+	}
+	if _, ok := ac.mutation.Name(); !ok {
+		return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "Agent.name"`)}
+	}
+	if v, ok := ac.mutation.Name(); ok {
+		if err := agent.NameValidator(v); err != nil {
+			return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "Agent.name": %w`, err)}
+		}
+	}
+	if _, ok := ac.mutation.Role(); !ok {
+		return &ValidationError{Name: "role", err: errors.New(`ent: missing required field "Agent.role"`)}
+	}
+	if v, ok := ac.mutation.Role(); ok {
+		if err := agent.RoleValidator(v); err != nil {
+			return &ValidationError{Name: "role", err: fmt.Errorf(`ent: validator failed for field "Agent.role": %w`, err)}
+		}
+	}
+	if _, ok := ac.mutation.Background(); !ok {
+		return &ValidationError{Name: "background", err: errors.New(`ent: missing required field "Agent.background"`)}
+	}
+	if v, ok := ac.mutation.Background(); ok {
+		if err := agent.BackgroundValidator(v); err != nil {
+			return &ValidationError{Name: "background", err: fmt.Errorf(`ent: validator failed for field "Agent.background": %w`, err)}
+		}
+	}
+	if _, ok := ac.mutation.Examples(); !ok {
+		return &ValidationError{Name: "examples", err: errors.New(`ent: missing required field "Agent.examples"`)}
+	}
+	if v, ok := ac.mutation.Examples(); ok {
+		if err := agent.ExamplesValidator(v); err != nil {
+			return &ValidationError{Name: "examples", err: fmt.Errorf(`ent: validator failed for field "Agent.examples": %w`, err)}
+		}
+	}
+	return nil
+}
+
+func (ac *AgentCreate) sqlSave(ctx context.Context) (*Agent, error) {
+	if err := ac.check(); err != nil {
+		return nil, err
+	}
+	_node, _spec := ac.createSpec()
+	if err := sqlgraph.CreateNode(ctx, ac.driver, _spec); err != nil {
+		if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return nil, err
+	}
+	if _spec.ID.Value != _node.ID {
+		id := _spec.ID.Value.(int64)
+		_node.ID = uint64(id)
+	}
+	ac.mutation.id = &_node.ID
+	ac.mutation.done = true
+	return _node, nil
+}
+
+func (ac *AgentCreate) createSpec() (*Agent, *sqlgraph.CreateSpec) {
+	var (
+		_node = &Agent{config: ac.config}
+		_spec = sqlgraph.NewCreateSpec(agent.Table, sqlgraph.NewFieldSpec(agent.FieldID, field.TypeUint64))
+	)
+	_spec.OnConflict = ac.conflict
+	if id, ok := ac.mutation.ID(); ok {
+		_node.ID = id
+		_spec.ID.Value = id
+	}
+	if value, ok := ac.mutation.CreatedAt(); ok {
+		_spec.SetField(agent.FieldCreatedAt, field.TypeTime, value)
+		_node.CreatedAt = value
+	}
+	if value, ok := ac.mutation.UpdatedAt(); ok {
+		_spec.SetField(agent.FieldUpdatedAt, field.TypeTime, value)
+		_node.UpdatedAt = value
+	}
+	if value, ok := ac.mutation.DeletedAt(); ok {
+		_spec.SetField(agent.FieldDeletedAt, field.TypeTime, value)
+		_node.DeletedAt = value
+	}
+	if value, ok := ac.mutation.Name(); ok {
+		_spec.SetField(agent.FieldName, field.TypeString, value)
+		_node.Name = value
+	}
+	if value, ok := ac.mutation.Role(); ok {
+		_spec.SetField(agent.FieldRole, field.TypeString, value)
+		_node.Role = value
+	}
+	if value, ok := ac.mutation.Status(); ok {
+		_spec.SetField(agent.FieldStatus, field.TypeInt, value)
+		_node.Status = value
+	}
+	if value, ok := ac.mutation.Background(); ok {
+		_spec.SetField(agent.FieldBackground, field.TypeString, value)
+		_node.Background = value
+	}
+	if value, ok := ac.mutation.Examples(); ok {
+		_spec.SetField(agent.FieldExamples, field.TypeString, value)
+		_node.Examples = value
+	}
+	return _node, _spec
+}
+
+// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
+// of the `INSERT` statement. For example:
+//
+//	client.Agent.Create().
+//		SetCreatedAt(v).
+//		OnConflict(
+//			// Update the row with the new values
+//			// the was proposed for insertion.
+//			sql.ResolveWithNewValues(),
+//		).
+//		// Override some of the fields with custom
+//		// update values.
+//		Update(func(u *ent.AgentUpsert) {
+//			SetCreatedAt(v+v).
+//		}).
+//		Exec(ctx)
+func (ac *AgentCreate) OnConflict(opts ...sql.ConflictOption) *AgentUpsertOne {
+	ac.conflict = opts
+	return &AgentUpsertOne{
+		create: ac,
+	}
+}
+
+// OnConflictColumns calls `OnConflict` and configures the columns
+// as conflict target. Using this option is equivalent to using:
+//
+//	client.Agent.Create().
+//		OnConflict(sql.ConflictColumns(columns...)).
+//		Exec(ctx)
+func (ac *AgentCreate) OnConflictColumns(columns ...string) *AgentUpsertOne {
+	ac.conflict = append(ac.conflict, sql.ConflictColumns(columns...))
+	return &AgentUpsertOne{
+		create: ac,
+	}
+}
+
+type (
+	// AgentUpsertOne is the builder for "upsert"-ing
+	//  one Agent node.
+	AgentUpsertOne struct {
+		create *AgentCreate
+	}
+
+	// AgentUpsert is the "OnConflict" setter.
+	AgentUpsert struct {
+		*sql.UpdateSet
+	}
+)
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *AgentUpsert) SetUpdatedAt(v time.Time) *AgentUpsert {
+	u.Set(agent.FieldUpdatedAt, v)
+	return u
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *AgentUpsert) UpdateUpdatedAt() *AgentUpsert {
+	u.SetExcluded(agent.FieldUpdatedAt)
+	return u
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *AgentUpsert) SetDeletedAt(v time.Time) *AgentUpsert {
+	u.Set(agent.FieldDeletedAt, v)
+	return u
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *AgentUpsert) UpdateDeletedAt() *AgentUpsert {
+	u.SetExcluded(agent.FieldDeletedAt)
+	return u
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *AgentUpsert) ClearDeletedAt() *AgentUpsert {
+	u.SetNull(agent.FieldDeletedAt)
+	return u
+}
+
+// SetName sets the "name" field.
+func (u *AgentUpsert) SetName(v string) *AgentUpsert {
+	u.Set(agent.FieldName, v)
+	return u
+}
+
+// UpdateName sets the "name" field to the value that was provided on create.
+func (u *AgentUpsert) UpdateName() *AgentUpsert {
+	u.SetExcluded(agent.FieldName)
+	return u
+}
+
+// SetRole sets the "role" field.
+func (u *AgentUpsert) SetRole(v string) *AgentUpsert {
+	u.Set(agent.FieldRole, v)
+	return u
+}
+
+// UpdateRole sets the "role" field to the value that was provided on create.
+func (u *AgentUpsert) UpdateRole() *AgentUpsert {
+	u.SetExcluded(agent.FieldRole)
+	return u
+}
+
+// SetStatus sets the "status" field.
+func (u *AgentUpsert) SetStatus(v int) *AgentUpsert {
+	u.Set(agent.FieldStatus, v)
+	return u
+}
+
+// UpdateStatus sets the "status" field to the value that was provided on create.
+func (u *AgentUpsert) UpdateStatus() *AgentUpsert {
+	u.SetExcluded(agent.FieldStatus)
+	return u
+}
+
+// AddStatus adds v to the "status" field.
+func (u *AgentUpsert) AddStatus(v int) *AgentUpsert {
+	u.Add(agent.FieldStatus, v)
+	return u
+}
+
+// ClearStatus clears the value of the "status" field.
+func (u *AgentUpsert) ClearStatus() *AgentUpsert {
+	u.SetNull(agent.FieldStatus)
+	return u
+}
+
+// SetBackground sets the "background" field.
+func (u *AgentUpsert) SetBackground(v string) *AgentUpsert {
+	u.Set(agent.FieldBackground, v)
+	return u
+}
+
+// UpdateBackground sets the "background" field to the value that was provided on create.
+func (u *AgentUpsert) UpdateBackground() *AgentUpsert {
+	u.SetExcluded(agent.FieldBackground)
+	return u
+}
+
+// SetExamples sets the "examples" field.
+func (u *AgentUpsert) SetExamples(v string) *AgentUpsert {
+	u.Set(agent.FieldExamples, v)
+	return u
+}
+
+// UpdateExamples sets the "examples" field to the value that was provided on create.
+func (u *AgentUpsert) UpdateExamples() *AgentUpsert {
+	u.SetExcluded(agent.FieldExamples)
+	return u
+}
+
+// UpdateNewValues updates the mutable fields using the new values that were set on create except the ID field.
+// Using this option is equivalent to using:
+//
+//	client.Agent.Create().
+//		OnConflict(
+//			sql.ResolveWithNewValues(),
+//			sql.ResolveWith(func(u *sql.UpdateSet) {
+//				u.SetIgnore(agent.FieldID)
+//			}),
+//		).
+//		Exec(ctx)
+func (u *AgentUpsertOne) UpdateNewValues() *AgentUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
+		if _, exists := u.create.mutation.ID(); exists {
+			s.SetIgnore(agent.FieldID)
+		}
+		if _, exists := u.create.mutation.CreatedAt(); exists {
+			s.SetIgnore(agent.FieldCreatedAt)
+		}
+	}))
+	return u
+}
+
+// Ignore sets each column to itself in case of conflict.
+// Using this option is equivalent to using:
+//
+//	client.Agent.Create().
+//	    OnConflict(sql.ResolveWithIgnore()).
+//	    Exec(ctx)
+func (u *AgentUpsertOne) Ignore() *AgentUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
+	return u
+}
+
+// DoNothing configures the conflict_action to `DO NOTHING`.
+// Supported only by SQLite and PostgreSQL.
+func (u *AgentUpsertOne) DoNothing() *AgentUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.DoNothing())
+	return u
+}
+
+// Update allows overriding fields `UPDATE` values. See the AgentCreate.OnConflict
+// documentation for more info.
+func (u *AgentUpsertOne) Update(set func(*AgentUpsert)) *AgentUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
+		set(&AgentUpsert{UpdateSet: update})
+	}))
+	return u
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *AgentUpsertOne) SetUpdatedAt(v time.Time) *AgentUpsertOne {
+	return u.Update(func(s *AgentUpsert) {
+		s.SetUpdatedAt(v)
+	})
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *AgentUpsertOne) UpdateUpdatedAt() *AgentUpsertOne {
+	return u.Update(func(s *AgentUpsert) {
+		s.UpdateUpdatedAt()
+	})
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *AgentUpsertOne) SetDeletedAt(v time.Time) *AgentUpsertOne {
+	return u.Update(func(s *AgentUpsert) {
+		s.SetDeletedAt(v)
+	})
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *AgentUpsertOne) UpdateDeletedAt() *AgentUpsertOne {
+	return u.Update(func(s *AgentUpsert) {
+		s.UpdateDeletedAt()
+	})
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *AgentUpsertOne) ClearDeletedAt() *AgentUpsertOne {
+	return u.Update(func(s *AgentUpsert) {
+		s.ClearDeletedAt()
+	})
+}
+
+// SetName sets the "name" field.
+func (u *AgentUpsertOne) SetName(v string) *AgentUpsertOne {
+	return u.Update(func(s *AgentUpsert) {
+		s.SetName(v)
+	})
+}
+
+// UpdateName sets the "name" field to the value that was provided on create.
+func (u *AgentUpsertOne) UpdateName() *AgentUpsertOne {
+	return u.Update(func(s *AgentUpsert) {
+		s.UpdateName()
+	})
+}
+
+// SetRole sets the "role" field.
+func (u *AgentUpsertOne) SetRole(v string) *AgentUpsertOne {
+	return u.Update(func(s *AgentUpsert) {
+		s.SetRole(v)
+	})
+}
+
+// UpdateRole sets the "role" field to the value that was provided on create.
+func (u *AgentUpsertOne) UpdateRole() *AgentUpsertOne {
+	return u.Update(func(s *AgentUpsert) {
+		s.UpdateRole()
+	})
+}
+
+// SetStatus sets the "status" field.
+func (u *AgentUpsertOne) SetStatus(v int) *AgentUpsertOne {
+	return u.Update(func(s *AgentUpsert) {
+		s.SetStatus(v)
+	})
+}
+
+// AddStatus adds v to the "status" field.
+func (u *AgentUpsertOne) AddStatus(v int) *AgentUpsertOne {
+	return u.Update(func(s *AgentUpsert) {
+		s.AddStatus(v)
+	})
+}
+
+// UpdateStatus sets the "status" field to the value that was provided on create.
+func (u *AgentUpsertOne) UpdateStatus() *AgentUpsertOne {
+	return u.Update(func(s *AgentUpsert) {
+		s.UpdateStatus()
+	})
+}
+
+// ClearStatus clears the value of the "status" field.
+func (u *AgentUpsertOne) ClearStatus() *AgentUpsertOne {
+	return u.Update(func(s *AgentUpsert) {
+		s.ClearStatus()
+	})
+}
+
+// SetBackground sets the "background" field.
+func (u *AgentUpsertOne) SetBackground(v string) *AgentUpsertOne {
+	return u.Update(func(s *AgentUpsert) {
+		s.SetBackground(v)
+	})
+}
+
+// UpdateBackground sets the "background" field to the value that was provided on create.
+func (u *AgentUpsertOne) UpdateBackground() *AgentUpsertOne {
+	return u.Update(func(s *AgentUpsert) {
+		s.UpdateBackground()
+	})
+}
+
+// SetExamples sets the "examples" field.
+func (u *AgentUpsertOne) SetExamples(v string) *AgentUpsertOne {
+	return u.Update(func(s *AgentUpsert) {
+		s.SetExamples(v)
+	})
+}
+
+// UpdateExamples sets the "examples" field to the value that was provided on create.
+func (u *AgentUpsertOne) UpdateExamples() *AgentUpsertOne {
+	return u.Update(func(s *AgentUpsert) {
+		s.UpdateExamples()
+	})
+}
+
+// Exec executes the query.
+func (u *AgentUpsertOne) Exec(ctx context.Context) error {
+	if len(u.create.conflict) == 0 {
+		return errors.New("ent: missing options for AgentCreate.OnConflict")
+	}
+	return u.create.Exec(ctx)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (u *AgentUpsertOne) ExecX(ctx context.Context) {
+	if err := u.create.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// Exec executes the UPSERT query and returns the inserted/updated ID.
+func (u *AgentUpsertOne) ID(ctx context.Context) (id uint64, err error) {
+	node, err := u.create.Save(ctx)
+	if err != nil {
+		return id, err
+	}
+	return node.ID, nil
+}
+
+// IDX is like ID, but panics if an error occurs.
+func (u *AgentUpsertOne) IDX(ctx context.Context) uint64 {
+	id, err := u.ID(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return id
+}
+
+// AgentCreateBulk is the builder for creating many Agent entities in bulk.
+type AgentCreateBulk struct {
+	config
+	err      error
+	builders []*AgentCreate
+	conflict []sql.ConflictOption
+}
+
+// Save creates the Agent entities in the database.
+func (acb *AgentCreateBulk) Save(ctx context.Context) ([]*Agent, error) {
+	if acb.err != nil {
+		return nil, acb.err
+	}
+	specs := make([]*sqlgraph.CreateSpec, len(acb.builders))
+	nodes := make([]*Agent, len(acb.builders))
+	mutators := make([]Mutator, len(acb.builders))
+	for i := range acb.builders {
+		func(i int, root context.Context) {
+			builder := acb.builders[i]
+			builder.defaults()
+			var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
+				mutation, ok := m.(*AgentMutation)
+				if !ok {
+					return nil, fmt.Errorf("unexpected mutation type %T", m)
+				}
+				if err := builder.check(); err != nil {
+					return nil, err
+				}
+				builder.mutation = mutation
+				var err error
+				nodes[i], specs[i] = builder.createSpec()
+				if i < len(mutators)-1 {
+					_, err = mutators[i+1].Mutate(root, acb.builders[i+1].mutation)
+				} else {
+					spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
+					spec.OnConflict = acb.conflict
+					// Invoke the actual operation on the latest mutation in the chain.
+					if err = sqlgraph.BatchCreate(ctx, acb.driver, spec); err != nil {
+						if sqlgraph.IsConstraintError(err) {
+							err = &ConstraintError{msg: err.Error(), wrap: err}
+						}
+					}
+				}
+				if err != nil {
+					return nil, err
+				}
+				mutation.id = &nodes[i].ID
+				if specs[i].ID.Value != nil && nodes[i].ID == 0 {
+					id := specs[i].ID.Value.(int64)
+					nodes[i].ID = uint64(id)
+				}
+				mutation.done = true
+				return nodes[i], nil
+			})
+			for i := len(builder.hooks) - 1; i >= 0; i-- {
+				mut = builder.hooks[i](mut)
+			}
+			mutators[i] = mut
+		}(i, ctx)
+	}
+	if len(mutators) > 0 {
+		if _, err := mutators[0].Mutate(ctx, acb.builders[0].mutation); err != nil {
+			return nil, err
+		}
+	}
+	return nodes, nil
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (acb *AgentCreateBulk) SaveX(ctx context.Context) []*Agent {
+	v, err := acb.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return v
+}
+
+// Exec executes the query.
+func (acb *AgentCreateBulk) Exec(ctx context.Context) error {
+	_, err := acb.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (acb *AgentCreateBulk) ExecX(ctx context.Context) {
+	if err := acb.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
+// of the `INSERT` statement. For example:
+//
+//	client.Agent.CreateBulk(builders...).
+//		OnConflict(
+//			// Update the row with the new values
+//			// the was proposed for insertion.
+//			sql.ResolveWithNewValues(),
+//		).
+//		// Override some of the fields with custom
+//		// update values.
+//		Update(func(u *ent.AgentUpsert) {
+//			SetCreatedAt(v+v).
+//		}).
+//		Exec(ctx)
+func (acb *AgentCreateBulk) OnConflict(opts ...sql.ConflictOption) *AgentUpsertBulk {
+	acb.conflict = opts
+	return &AgentUpsertBulk{
+		create: acb,
+	}
+}
+
+// OnConflictColumns calls `OnConflict` and configures the columns
+// as conflict target. Using this option is equivalent to using:
+//
+//	client.Agent.Create().
+//		OnConflict(sql.ConflictColumns(columns...)).
+//		Exec(ctx)
+func (acb *AgentCreateBulk) OnConflictColumns(columns ...string) *AgentUpsertBulk {
+	acb.conflict = append(acb.conflict, sql.ConflictColumns(columns...))
+	return &AgentUpsertBulk{
+		create: acb,
+	}
+}
+
+// AgentUpsertBulk is the builder for "upsert"-ing
+// a bulk of Agent nodes.
+type AgentUpsertBulk struct {
+	create *AgentCreateBulk
+}
+
+// UpdateNewValues updates the mutable fields using the new values that
+// were set on create. Using this option is equivalent to using:
+//
+//	client.Agent.Create().
+//		OnConflict(
+//			sql.ResolveWithNewValues(),
+//			sql.ResolveWith(func(u *sql.UpdateSet) {
+//				u.SetIgnore(agent.FieldID)
+//			}),
+//		).
+//		Exec(ctx)
+func (u *AgentUpsertBulk) UpdateNewValues() *AgentUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
+		for _, b := range u.create.builders {
+			if _, exists := b.mutation.ID(); exists {
+				s.SetIgnore(agent.FieldID)
+			}
+			if _, exists := b.mutation.CreatedAt(); exists {
+				s.SetIgnore(agent.FieldCreatedAt)
+			}
+		}
+	}))
+	return u
+}
+
+// Ignore sets each column to itself in case of conflict.
+// Using this option is equivalent to using:
+//
+//	client.Agent.Create().
+//		OnConflict(sql.ResolveWithIgnore()).
+//		Exec(ctx)
+func (u *AgentUpsertBulk) Ignore() *AgentUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
+	return u
+}
+
+// DoNothing configures the conflict_action to `DO NOTHING`.
+// Supported only by SQLite and PostgreSQL.
+func (u *AgentUpsertBulk) DoNothing() *AgentUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.DoNothing())
+	return u
+}
+
+// Update allows overriding fields `UPDATE` values. See the AgentCreateBulk.OnConflict
+// documentation for more info.
+func (u *AgentUpsertBulk) Update(set func(*AgentUpsert)) *AgentUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
+		set(&AgentUpsert{UpdateSet: update})
+	}))
+	return u
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *AgentUpsertBulk) SetUpdatedAt(v time.Time) *AgentUpsertBulk {
+	return u.Update(func(s *AgentUpsert) {
+		s.SetUpdatedAt(v)
+	})
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *AgentUpsertBulk) UpdateUpdatedAt() *AgentUpsertBulk {
+	return u.Update(func(s *AgentUpsert) {
+		s.UpdateUpdatedAt()
+	})
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *AgentUpsertBulk) SetDeletedAt(v time.Time) *AgentUpsertBulk {
+	return u.Update(func(s *AgentUpsert) {
+		s.SetDeletedAt(v)
+	})
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *AgentUpsertBulk) UpdateDeletedAt() *AgentUpsertBulk {
+	return u.Update(func(s *AgentUpsert) {
+		s.UpdateDeletedAt()
+	})
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *AgentUpsertBulk) ClearDeletedAt() *AgentUpsertBulk {
+	return u.Update(func(s *AgentUpsert) {
+		s.ClearDeletedAt()
+	})
+}
+
+// SetName sets the "name" field.
+func (u *AgentUpsertBulk) SetName(v string) *AgentUpsertBulk {
+	return u.Update(func(s *AgentUpsert) {
+		s.SetName(v)
+	})
+}
+
+// UpdateName sets the "name" field to the value that was provided on create.
+func (u *AgentUpsertBulk) UpdateName() *AgentUpsertBulk {
+	return u.Update(func(s *AgentUpsert) {
+		s.UpdateName()
+	})
+}
+
+// SetRole sets the "role" field.
+func (u *AgentUpsertBulk) SetRole(v string) *AgentUpsertBulk {
+	return u.Update(func(s *AgentUpsert) {
+		s.SetRole(v)
+	})
+}
+
+// UpdateRole sets the "role" field to the value that was provided on create.
+func (u *AgentUpsertBulk) UpdateRole() *AgentUpsertBulk {
+	return u.Update(func(s *AgentUpsert) {
+		s.UpdateRole()
+	})
+}
+
+// SetStatus sets the "status" field.
+func (u *AgentUpsertBulk) SetStatus(v int) *AgentUpsertBulk {
+	return u.Update(func(s *AgentUpsert) {
+		s.SetStatus(v)
+	})
+}
+
+// AddStatus adds v to the "status" field.
+func (u *AgentUpsertBulk) AddStatus(v int) *AgentUpsertBulk {
+	return u.Update(func(s *AgentUpsert) {
+		s.AddStatus(v)
+	})
+}
+
+// UpdateStatus sets the "status" field to the value that was provided on create.
+func (u *AgentUpsertBulk) UpdateStatus() *AgentUpsertBulk {
+	return u.Update(func(s *AgentUpsert) {
+		s.UpdateStatus()
+	})
+}
+
+// ClearStatus clears the value of the "status" field.
+func (u *AgentUpsertBulk) ClearStatus() *AgentUpsertBulk {
+	return u.Update(func(s *AgentUpsert) {
+		s.ClearStatus()
+	})
+}
+
+// SetBackground sets the "background" field.
+func (u *AgentUpsertBulk) SetBackground(v string) *AgentUpsertBulk {
+	return u.Update(func(s *AgentUpsert) {
+		s.SetBackground(v)
+	})
+}
+
+// UpdateBackground sets the "background" field to the value that was provided on create.
+func (u *AgentUpsertBulk) UpdateBackground() *AgentUpsertBulk {
+	return u.Update(func(s *AgentUpsert) {
+		s.UpdateBackground()
+	})
+}
+
+// SetExamples sets the "examples" field.
+func (u *AgentUpsertBulk) SetExamples(v string) *AgentUpsertBulk {
+	return u.Update(func(s *AgentUpsert) {
+		s.SetExamples(v)
+	})
+}
+
+// UpdateExamples sets the "examples" field to the value that was provided on create.
+func (u *AgentUpsertBulk) UpdateExamples() *AgentUpsertBulk {
+	return u.Update(func(s *AgentUpsert) {
+		s.UpdateExamples()
+	})
+}
+
+// Exec executes the query.
+func (u *AgentUpsertBulk) Exec(ctx context.Context) error {
+	if u.create.err != nil {
+		return u.create.err
+	}
+	for i, b := range u.create.builders {
+		if len(b.conflict) != 0 {
+			return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the AgentCreateBulk instead", i)
+		}
+	}
+	if len(u.create.conflict) == 0 {
+		return errors.New("ent: missing options for AgentCreateBulk.OnConflict")
+	}
+	return u.create.Exec(ctx)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (u *AgentUpsertBulk) ExecX(ctx context.Context) {
+	if err := u.create.Exec(ctx); err != nil {
+		panic(err)
+	}
+}

+ 88 - 0
ent/agent_delete.go

@@ -0,0 +1,88 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"wechat-api/ent/agent"
+	"wechat-api/ent/predicate"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// AgentDelete is the builder for deleting a Agent entity.
+type AgentDelete struct {
+	config
+	hooks    []Hook
+	mutation *AgentMutation
+}
+
+// Where appends a list predicates to the AgentDelete builder.
+func (ad *AgentDelete) Where(ps ...predicate.Agent) *AgentDelete {
+	ad.mutation.Where(ps...)
+	return ad
+}
+
+// Exec executes the deletion query and returns how many vertices were deleted.
+func (ad *AgentDelete) Exec(ctx context.Context) (int, error) {
+	return withHooks(ctx, ad.sqlExec, ad.mutation, ad.hooks)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (ad *AgentDelete) ExecX(ctx context.Context) int {
+	n, err := ad.Exec(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return n
+}
+
+func (ad *AgentDelete) sqlExec(ctx context.Context) (int, error) {
+	_spec := sqlgraph.NewDeleteSpec(agent.Table, sqlgraph.NewFieldSpec(agent.FieldID, field.TypeUint64))
+	if ps := ad.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	affected, err := sqlgraph.DeleteNodes(ctx, ad.driver, _spec)
+	if err != nil && sqlgraph.IsConstraintError(err) {
+		err = &ConstraintError{msg: err.Error(), wrap: err}
+	}
+	ad.mutation.done = true
+	return affected, err
+}
+
+// AgentDeleteOne is the builder for deleting a single Agent entity.
+type AgentDeleteOne struct {
+	ad *AgentDelete
+}
+
+// Where appends a list predicates to the AgentDelete builder.
+func (ado *AgentDeleteOne) Where(ps ...predicate.Agent) *AgentDeleteOne {
+	ado.ad.mutation.Where(ps...)
+	return ado
+}
+
+// Exec executes the deletion query.
+func (ado *AgentDeleteOne) Exec(ctx context.Context) error {
+	n, err := ado.ad.Exec(ctx)
+	switch {
+	case err != nil:
+		return err
+	case n == 0:
+		return &NotFoundError{agent.Label}
+	default:
+		return nil
+	}
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (ado *AgentDeleteOne) ExecX(ctx context.Context) {
+	if err := ado.Exec(ctx); err != nil {
+		panic(err)
+	}
+}

+ 526 - 0
ent/agent_query.go

@@ -0,0 +1,526 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"fmt"
+	"math"
+	"wechat-api/ent/agent"
+	"wechat-api/ent/predicate"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// AgentQuery is the builder for querying Agent entities.
+type AgentQuery struct {
+	config
+	ctx        *QueryContext
+	order      []agent.OrderOption
+	inters     []Interceptor
+	predicates []predicate.Agent
+	// intermediate query (i.e. traversal path).
+	sql  *sql.Selector
+	path func(context.Context) (*sql.Selector, error)
+}
+
+// Where adds a new predicate for the AgentQuery builder.
+func (aq *AgentQuery) Where(ps ...predicate.Agent) *AgentQuery {
+	aq.predicates = append(aq.predicates, ps...)
+	return aq
+}
+
+// Limit the number of records to be returned by this query.
+func (aq *AgentQuery) Limit(limit int) *AgentQuery {
+	aq.ctx.Limit = &limit
+	return aq
+}
+
+// Offset to start from.
+func (aq *AgentQuery) Offset(offset int) *AgentQuery {
+	aq.ctx.Offset = &offset
+	return aq
+}
+
+// Unique configures the query builder to filter duplicate records on query.
+// By default, unique is set to true, and can be disabled using this method.
+func (aq *AgentQuery) Unique(unique bool) *AgentQuery {
+	aq.ctx.Unique = &unique
+	return aq
+}
+
+// Order specifies how the records should be ordered.
+func (aq *AgentQuery) Order(o ...agent.OrderOption) *AgentQuery {
+	aq.order = append(aq.order, o...)
+	return aq
+}
+
+// First returns the first Agent entity from the query.
+// Returns a *NotFoundError when no Agent was found.
+func (aq *AgentQuery) First(ctx context.Context) (*Agent, error) {
+	nodes, err := aq.Limit(1).All(setContextOp(ctx, aq.ctx, "First"))
+	if err != nil {
+		return nil, err
+	}
+	if len(nodes) == 0 {
+		return nil, &NotFoundError{agent.Label}
+	}
+	return nodes[0], nil
+}
+
+// FirstX is like First, but panics if an error occurs.
+func (aq *AgentQuery) FirstX(ctx context.Context) *Agent {
+	node, err := aq.First(ctx)
+	if err != nil && !IsNotFound(err) {
+		panic(err)
+	}
+	return node
+}
+
+// FirstID returns the first Agent ID from the query.
+// Returns a *NotFoundError when no Agent ID was found.
+func (aq *AgentQuery) FirstID(ctx context.Context) (id uint64, err error) {
+	var ids []uint64
+	if ids, err = aq.Limit(1).IDs(setContextOp(ctx, aq.ctx, "FirstID")); err != nil {
+		return
+	}
+	if len(ids) == 0 {
+		err = &NotFoundError{agent.Label}
+		return
+	}
+	return ids[0], nil
+}
+
+// FirstIDX is like FirstID, but panics if an error occurs.
+func (aq *AgentQuery) FirstIDX(ctx context.Context) uint64 {
+	id, err := aq.FirstID(ctx)
+	if err != nil && !IsNotFound(err) {
+		panic(err)
+	}
+	return id
+}
+
+// Only returns a single Agent entity found by the query, ensuring it only returns one.
+// Returns a *NotSingularError when more than one Agent entity is found.
+// Returns a *NotFoundError when no Agent entities are found.
+func (aq *AgentQuery) Only(ctx context.Context) (*Agent, error) {
+	nodes, err := aq.Limit(2).All(setContextOp(ctx, aq.ctx, "Only"))
+	if err != nil {
+		return nil, err
+	}
+	switch len(nodes) {
+	case 1:
+		return nodes[0], nil
+	case 0:
+		return nil, &NotFoundError{agent.Label}
+	default:
+		return nil, &NotSingularError{agent.Label}
+	}
+}
+
+// OnlyX is like Only, but panics if an error occurs.
+func (aq *AgentQuery) OnlyX(ctx context.Context) *Agent {
+	node, err := aq.Only(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return node
+}
+
+// OnlyID is like Only, but returns the only Agent ID in the query.
+// Returns a *NotSingularError when more than one Agent ID is found.
+// Returns a *NotFoundError when no entities are found.
+func (aq *AgentQuery) OnlyID(ctx context.Context) (id uint64, err error) {
+	var ids []uint64
+	if ids, err = aq.Limit(2).IDs(setContextOp(ctx, aq.ctx, "OnlyID")); err != nil {
+		return
+	}
+	switch len(ids) {
+	case 1:
+		id = ids[0]
+	case 0:
+		err = &NotFoundError{agent.Label}
+	default:
+		err = &NotSingularError{agent.Label}
+	}
+	return
+}
+
+// OnlyIDX is like OnlyID, but panics if an error occurs.
+func (aq *AgentQuery) OnlyIDX(ctx context.Context) uint64 {
+	id, err := aq.OnlyID(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return id
+}
+
+// All executes the query and returns a list of Agents.
+func (aq *AgentQuery) All(ctx context.Context) ([]*Agent, error) {
+	ctx = setContextOp(ctx, aq.ctx, "All")
+	if err := aq.prepareQuery(ctx); err != nil {
+		return nil, err
+	}
+	qr := querierAll[[]*Agent, *AgentQuery]()
+	return withInterceptors[[]*Agent](ctx, aq, qr, aq.inters)
+}
+
+// AllX is like All, but panics if an error occurs.
+func (aq *AgentQuery) AllX(ctx context.Context) []*Agent {
+	nodes, err := aq.All(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return nodes
+}
+
+// IDs executes the query and returns a list of Agent IDs.
+func (aq *AgentQuery) IDs(ctx context.Context) (ids []uint64, err error) {
+	if aq.ctx.Unique == nil && aq.path != nil {
+		aq.Unique(true)
+	}
+	ctx = setContextOp(ctx, aq.ctx, "IDs")
+	if err = aq.Select(agent.FieldID).Scan(ctx, &ids); err != nil {
+		return nil, err
+	}
+	return ids, nil
+}
+
+// IDsX is like IDs, but panics if an error occurs.
+func (aq *AgentQuery) IDsX(ctx context.Context) []uint64 {
+	ids, err := aq.IDs(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return ids
+}
+
+// Count returns the count of the given query.
+func (aq *AgentQuery) Count(ctx context.Context) (int, error) {
+	ctx = setContextOp(ctx, aq.ctx, "Count")
+	if err := aq.prepareQuery(ctx); err != nil {
+		return 0, err
+	}
+	return withInterceptors[int](ctx, aq, querierCount[*AgentQuery](), aq.inters)
+}
+
+// CountX is like Count, but panics if an error occurs.
+func (aq *AgentQuery) CountX(ctx context.Context) int {
+	count, err := aq.Count(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return count
+}
+
+// Exist returns true if the query has elements in the graph.
+func (aq *AgentQuery) Exist(ctx context.Context) (bool, error) {
+	ctx = setContextOp(ctx, aq.ctx, "Exist")
+	switch _, err := aq.FirstID(ctx); {
+	case IsNotFound(err):
+		return false, nil
+	case err != nil:
+		return false, fmt.Errorf("ent: check existence: %w", err)
+	default:
+		return true, nil
+	}
+}
+
+// ExistX is like Exist, but panics if an error occurs.
+func (aq *AgentQuery) ExistX(ctx context.Context) bool {
+	exist, err := aq.Exist(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return exist
+}
+
+// Clone returns a duplicate of the AgentQuery builder, including all associated steps. It can be
+// used to prepare common query builders and use them differently after the clone is made.
+func (aq *AgentQuery) Clone() *AgentQuery {
+	if aq == nil {
+		return nil
+	}
+	return &AgentQuery{
+		config:     aq.config,
+		ctx:        aq.ctx.Clone(),
+		order:      append([]agent.OrderOption{}, aq.order...),
+		inters:     append([]Interceptor{}, aq.inters...),
+		predicates: append([]predicate.Agent{}, aq.predicates...),
+		// clone intermediate query.
+		sql:  aq.sql.Clone(),
+		path: aq.path,
+	}
+}
+
+// GroupBy is used to group vertices by one or more fields/columns.
+// It is often used with aggregate functions, like: count, max, mean, min, sum.
+//
+// Example:
+//
+//	var v []struct {
+//		CreatedAt time.Time `json:"created_at,omitempty"`
+//		Count int `json:"count,omitempty"`
+//	}
+//
+//	client.Agent.Query().
+//		GroupBy(agent.FieldCreatedAt).
+//		Aggregate(ent.Count()).
+//		Scan(ctx, &v)
+func (aq *AgentQuery) GroupBy(field string, fields ...string) *AgentGroupBy {
+	aq.ctx.Fields = append([]string{field}, fields...)
+	grbuild := &AgentGroupBy{build: aq}
+	grbuild.flds = &aq.ctx.Fields
+	grbuild.label = agent.Label
+	grbuild.scan = grbuild.Scan
+	return grbuild
+}
+
+// Select allows the selection one or more fields/columns for the given query,
+// instead of selecting all fields in the entity.
+//
+// Example:
+//
+//	var v []struct {
+//		CreatedAt time.Time `json:"created_at,omitempty"`
+//	}
+//
+//	client.Agent.Query().
+//		Select(agent.FieldCreatedAt).
+//		Scan(ctx, &v)
+func (aq *AgentQuery) Select(fields ...string) *AgentSelect {
+	aq.ctx.Fields = append(aq.ctx.Fields, fields...)
+	sbuild := &AgentSelect{AgentQuery: aq}
+	sbuild.label = agent.Label
+	sbuild.flds, sbuild.scan = &aq.ctx.Fields, sbuild.Scan
+	return sbuild
+}
+
+// Aggregate returns a AgentSelect configured with the given aggregations.
+func (aq *AgentQuery) Aggregate(fns ...AggregateFunc) *AgentSelect {
+	return aq.Select().Aggregate(fns...)
+}
+
+func (aq *AgentQuery) prepareQuery(ctx context.Context) error {
+	for _, inter := range aq.inters {
+		if inter == nil {
+			return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
+		}
+		if trv, ok := inter.(Traverser); ok {
+			if err := trv.Traverse(ctx, aq); err != nil {
+				return err
+			}
+		}
+	}
+	for _, f := range aq.ctx.Fields {
+		if !agent.ValidColumn(f) {
+			return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+		}
+	}
+	if aq.path != nil {
+		prev, err := aq.path(ctx)
+		if err != nil {
+			return err
+		}
+		aq.sql = prev
+	}
+	return nil
+}
+
+func (aq *AgentQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Agent, error) {
+	var (
+		nodes = []*Agent{}
+		_spec = aq.querySpec()
+	)
+	_spec.ScanValues = func(columns []string) ([]any, error) {
+		return (*Agent).scanValues(nil, columns)
+	}
+	_spec.Assign = func(columns []string, values []any) error {
+		node := &Agent{config: aq.config}
+		nodes = append(nodes, node)
+		return node.assignValues(columns, values)
+	}
+	for i := range hooks {
+		hooks[i](ctx, _spec)
+	}
+	if err := sqlgraph.QueryNodes(ctx, aq.driver, _spec); err != nil {
+		return nil, err
+	}
+	if len(nodes) == 0 {
+		return nodes, nil
+	}
+	return nodes, nil
+}
+
+func (aq *AgentQuery) sqlCount(ctx context.Context) (int, error) {
+	_spec := aq.querySpec()
+	_spec.Node.Columns = aq.ctx.Fields
+	if len(aq.ctx.Fields) > 0 {
+		_spec.Unique = aq.ctx.Unique != nil && *aq.ctx.Unique
+	}
+	return sqlgraph.CountNodes(ctx, aq.driver, _spec)
+}
+
+func (aq *AgentQuery) querySpec() *sqlgraph.QuerySpec {
+	_spec := sqlgraph.NewQuerySpec(agent.Table, agent.Columns, sqlgraph.NewFieldSpec(agent.FieldID, field.TypeUint64))
+	_spec.From = aq.sql
+	if unique := aq.ctx.Unique; unique != nil {
+		_spec.Unique = *unique
+	} else if aq.path != nil {
+		_spec.Unique = true
+	}
+	if fields := aq.ctx.Fields; len(fields) > 0 {
+		_spec.Node.Columns = make([]string, 0, len(fields))
+		_spec.Node.Columns = append(_spec.Node.Columns, agent.FieldID)
+		for i := range fields {
+			if fields[i] != agent.FieldID {
+				_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
+			}
+		}
+	}
+	if ps := aq.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if limit := aq.ctx.Limit; limit != nil {
+		_spec.Limit = *limit
+	}
+	if offset := aq.ctx.Offset; offset != nil {
+		_spec.Offset = *offset
+	}
+	if ps := aq.order; len(ps) > 0 {
+		_spec.Order = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	return _spec
+}
+
+func (aq *AgentQuery) sqlQuery(ctx context.Context) *sql.Selector {
+	builder := sql.Dialect(aq.driver.Dialect())
+	t1 := builder.Table(agent.Table)
+	columns := aq.ctx.Fields
+	if len(columns) == 0 {
+		columns = agent.Columns
+	}
+	selector := builder.Select(t1.Columns(columns...)...).From(t1)
+	if aq.sql != nil {
+		selector = aq.sql
+		selector.Select(selector.Columns(columns...)...)
+	}
+	if aq.ctx.Unique != nil && *aq.ctx.Unique {
+		selector.Distinct()
+	}
+	for _, p := range aq.predicates {
+		p(selector)
+	}
+	for _, p := range aq.order {
+		p(selector)
+	}
+	if offset := aq.ctx.Offset; offset != nil {
+		// limit is mandatory for offset clause. We start
+		// with default value, and override it below if needed.
+		selector.Offset(*offset).Limit(math.MaxInt32)
+	}
+	if limit := aq.ctx.Limit; limit != nil {
+		selector.Limit(*limit)
+	}
+	return selector
+}
+
+// AgentGroupBy is the group-by builder for Agent entities.
+type AgentGroupBy struct {
+	selector
+	build *AgentQuery
+}
+
+// Aggregate adds the given aggregation functions to the group-by query.
+func (agb *AgentGroupBy) Aggregate(fns ...AggregateFunc) *AgentGroupBy {
+	agb.fns = append(agb.fns, fns...)
+	return agb
+}
+
+// Scan applies the selector query and scans the result into the given value.
+func (agb *AgentGroupBy) Scan(ctx context.Context, v any) error {
+	ctx = setContextOp(ctx, agb.build.ctx, "GroupBy")
+	if err := agb.build.prepareQuery(ctx); err != nil {
+		return err
+	}
+	return scanWithInterceptors[*AgentQuery, *AgentGroupBy](ctx, agb.build, agb, agb.build.inters, v)
+}
+
+func (agb *AgentGroupBy) sqlScan(ctx context.Context, root *AgentQuery, v any) error {
+	selector := root.sqlQuery(ctx).Select()
+	aggregation := make([]string, 0, len(agb.fns))
+	for _, fn := range agb.fns {
+		aggregation = append(aggregation, fn(selector))
+	}
+	if len(selector.SelectedColumns()) == 0 {
+		columns := make([]string, 0, len(*agb.flds)+len(agb.fns))
+		for _, f := range *agb.flds {
+			columns = append(columns, selector.C(f))
+		}
+		columns = append(columns, aggregation...)
+		selector.Select(columns...)
+	}
+	selector.GroupBy(selector.Columns(*agb.flds...)...)
+	if err := selector.Err(); err != nil {
+		return err
+	}
+	rows := &sql.Rows{}
+	query, args := selector.Query()
+	if err := agb.build.driver.Query(ctx, query, args, rows); err != nil {
+		return err
+	}
+	defer rows.Close()
+	return sql.ScanSlice(rows, v)
+}
+
+// AgentSelect is the builder for selecting fields of Agent entities.
+type AgentSelect struct {
+	*AgentQuery
+	selector
+}
+
+// Aggregate adds the given aggregation functions to the selector query.
+func (as *AgentSelect) Aggregate(fns ...AggregateFunc) *AgentSelect {
+	as.fns = append(as.fns, fns...)
+	return as
+}
+
+// Scan applies the selector query and scans the result into the given value.
+func (as *AgentSelect) Scan(ctx context.Context, v any) error {
+	ctx = setContextOp(ctx, as.ctx, "Select")
+	if err := as.prepareQuery(ctx); err != nil {
+		return err
+	}
+	return scanWithInterceptors[*AgentQuery, *AgentSelect](ctx, as.AgentQuery, as, as.inters, v)
+}
+
+func (as *AgentSelect) sqlScan(ctx context.Context, root *AgentQuery, v any) error {
+	selector := root.sqlQuery(ctx)
+	aggregation := make([]string, 0, len(as.fns))
+	for _, fn := range as.fns {
+		aggregation = append(aggregation, fn(selector))
+	}
+	switch n := len(*as.selector.flds); {
+	case n == 0 && len(aggregation) > 0:
+		selector.Select(aggregation...)
+	case n != 0 && len(aggregation) > 0:
+		selector.AppendSelect(aggregation...)
+	}
+	rows := &sql.Rows{}
+	query, args := selector.Query()
+	if err := as.driver.Query(ctx, query, args, rows); err != nil {
+		return err
+	}
+	defer rows.Close()
+	return sql.ScanSlice(rows, v)
+}

+ 540 - 0
ent/agent_update.go

@@ -0,0 +1,540 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"time"
+	"wechat-api/ent/agent"
+	"wechat-api/ent/predicate"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// AgentUpdate is the builder for updating Agent entities.
+type AgentUpdate struct {
+	config
+	hooks    []Hook
+	mutation *AgentMutation
+}
+
+// Where appends a list predicates to the AgentUpdate builder.
+func (au *AgentUpdate) Where(ps ...predicate.Agent) *AgentUpdate {
+	au.mutation.Where(ps...)
+	return au
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (au *AgentUpdate) SetUpdatedAt(t time.Time) *AgentUpdate {
+	au.mutation.SetUpdatedAt(t)
+	return au
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (au *AgentUpdate) SetDeletedAt(t time.Time) *AgentUpdate {
+	au.mutation.SetDeletedAt(t)
+	return au
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (au *AgentUpdate) SetNillableDeletedAt(t *time.Time) *AgentUpdate {
+	if t != nil {
+		au.SetDeletedAt(*t)
+	}
+	return au
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (au *AgentUpdate) ClearDeletedAt() *AgentUpdate {
+	au.mutation.ClearDeletedAt()
+	return au
+}
+
+// SetName sets the "name" field.
+func (au *AgentUpdate) SetName(s string) *AgentUpdate {
+	au.mutation.SetName(s)
+	return au
+}
+
+// SetNillableName sets the "name" field if the given value is not nil.
+func (au *AgentUpdate) SetNillableName(s *string) *AgentUpdate {
+	if s != nil {
+		au.SetName(*s)
+	}
+	return au
+}
+
+// SetRole sets the "role" field.
+func (au *AgentUpdate) SetRole(s string) *AgentUpdate {
+	au.mutation.SetRole(s)
+	return au
+}
+
+// SetNillableRole sets the "role" field if the given value is not nil.
+func (au *AgentUpdate) SetNillableRole(s *string) *AgentUpdate {
+	if s != nil {
+		au.SetRole(*s)
+	}
+	return au
+}
+
+// SetStatus sets the "status" field.
+func (au *AgentUpdate) SetStatus(i int) *AgentUpdate {
+	au.mutation.ResetStatus()
+	au.mutation.SetStatus(i)
+	return au
+}
+
+// SetNillableStatus sets the "status" field if the given value is not nil.
+func (au *AgentUpdate) SetNillableStatus(i *int) *AgentUpdate {
+	if i != nil {
+		au.SetStatus(*i)
+	}
+	return au
+}
+
+// AddStatus adds i to the "status" field.
+func (au *AgentUpdate) AddStatus(i int) *AgentUpdate {
+	au.mutation.AddStatus(i)
+	return au
+}
+
+// ClearStatus clears the value of the "status" field.
+func (au *AgentUpdate) ClearStatus() *AgentUpdate {
+	au.mutation.ClearStatus()
+	return au
+}
+
+// SetBackground sets the "background" field.
+func (au *AgentUpdate) SetBackground(s string) *AgentUpdate {
+	au.mutation.SetBackground(s)
+	return au
+}
+
+// SetNillableBackground sets the "background" field if the given value is not nil.
+func (au *AgentUpdate) SetNillableBackground(s *string) *AgentUpdate {
+	if s != nil {
+		au.SetBackground(*s)
+	}
+	return au
+}
+
+// SetExamples sets the "examples" field.
+func (au *AgentUpdate) SetExamples(s string) *AgentUpdate {
+	au.mutation.SetExamples(s)
+	return au
+}
+
+// SetNillableExamples sets the "examples" field if the given value is not nil.
+func (au *AgentUpdate) SetNillableExamples(s *string) *AgentUpdate {
+	if s != nil {
+		au.SetExamples(*s)
+	}
+	return au
+}
+
+// Mutation returns the AgentMutation object of the builder.
+func (au *AgentUpdate) Mutation() *AgentMutation {
+	return au.mutation
+}
+
+// Save executes the query and returns the number of nodes affected by the update operation.
+func (au *AgentUpdate) Save(ctx context.Context) (int, error) {
+	if err := au.defaults(); err != nil {
+		return 0, err
+	}
+	return withHooks(ctx, au.sqlSave, au.mutation, au.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (au *AgentUpdate) SaveX(ctx context.Context) int {
+	affected, err := au.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return affected
+}
+
+// Exec executes the query.
+func (au *AgentUpdate) Exec(ctx context.Context) error {
+	_, err := au.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (au *AgentUpdate) ExecX(ctx context.Context) {
+	if err := au.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (au *AgentUpdate) defaults() error {
+	if _, ok := au.mutation.UpdatedAt(); !ok {
+		if agent.UpdateDefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized agent.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := agent.UpdateDefaultUpdatedAt()
+		au.mutation.SetUpdatedAt(v)
+	}
+	return nil
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (au *AgentUpdate) check() error {
+	if v, ok := au.mutation.Name(); ok {
+		if err := agent.NameValidator(v); err != nil {
+			return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "Agent.name": %w`, err)}
+		}
+	}
+	if v, ok := au.mutation.Role(); ok {
+		if err := agent.RoleValidator(v); err != nil {
+			return &ValidationError{Name: "role", err: fmt.Errorf(`ent: validator failed for field "Agent.role": %w`, err)}
+		}
+	}
+	if v, ok := au.mutation.Background(); ok {
+		if err := agent.BackgroundValidator(v); err != nil {
+			return &ValidationError{Name: "background", err: fmt.Errorf(`ent: validator failed for field "Agent.background": %w`, err)}
+		}
+	}
+	if v, ok := au.mutation.Examples(); ok {
+		if err := agent.ExamplesValidator(v); err != nil {
+			return &ValidationError{Name: "examples", err: fmt.Errorf(`ent: validator failed for field "Agent.examples": %w`, err)}
+		}
+	}
+	return nil
+}
+
+func (au *AgentUpdate) sqlSave(ctx context.Context) (n int, err error) {
+	if err := au.check(); err != nil {
+		return n, err
+	}
+	_spec := sqlgraph.NewUpdateSpec(agent.Table, agent.Columns, sqlgraph.NewFieldSpec(agent.FieldID, field.TypeUint64))
+	if ps := au.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if value, ok := au.mutation.UpdatedAt(); ok {
+		_spec.SetField(agent.FieldUpdatedAt, field.TypeTime, value)
+	}
+	if value, ok := au.mutation.DeletedAt(); ok {
+		_spec.SetField(agent.FieldDeletedAt, field.TypeTime, value)
+	}
+	if au.mutation.DeletedAtCleared() {
+		_spec.ClearField(agent.FieldDeletedAt, field.TypeTime)
+	}
+	if value, ok := au.mutation.Name(); ok {
+		_spec.SetField(agent.FieldName, field.TypeString, value)
+	}
+	if value, ok := au.mutation.Role(); ok {
+		_spec.SetField(agent.FieldRole, field.TypeString, value)
+	}
+	if value, ok := au.mutation.Status(); ok {
+		_spec.SetField(agent.FieldStatus, field.TypeInt, value)
+	}
+	if value, ok := au.mutation.AddedStatus(); ok {
+		_spec.AddField(agent.FieldStatus, field.TypeInt, value)
+	}
+	if au.mutation.StatusCleared() {
+		_spec.ClearField(agent.FieldStatus, field.TypeInt)
+	}
+	if value, ok := au.mutation.Background(); ok {
+		_spec.SetField(agent.FieldBackground, field.TypeString, value)
+	}
+	if value, ok := au.mutation.Examples(); ok {
+		_spec.SetField(agent.FieldExamples, field.TypeString, value)
+	}
+	if n, err = sqlgraph.UpdateNodes(ctx, au.driver, _spec); err != nil {
+		if _, ok := err.(*sqlgraph.NotFoundError); ok {
+			err = &NotFoundError{agent.Label}
+		} else if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return 0, err
+	}
+	au.mutation.done = true
+	return n, nil
+}
+
+// AgentUpdateOne is the builder for updating a single Agent entity.
+type AgentUpdateOne struct {
+	config
+	fields   []string
+	hooks    []Hook
+	mutation *AgentMutation
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (auo *AgentUpdateOne) SetUpdatedAt(t time.Time) *AgentUpdateOne {
+	auo.mutation.SetUpdatedAt(t)
+	return auo
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (auo *AgentUpdateOne) SetDeletedAt(t time.Time) *AgentUpdateOne {
+	auo.mutation.SetDeletedAt(t)
+	return auo
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (auo *AgentUpdateOne) SetNillableDeletedAt(t *time.Time) *AgentUpdateOne {
+	if t != nil {
+		auo.SetDeletedAt(*t)
+	}
+	return auo
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (auo *AgentUpdateOne) ClearDeletedAt() *AgentUpdateOne {
+	auo.mutation.ClearDeletedAt()
+	return auo
+}
+
+// SetName sets the "name" field.
+func (auo *AgentUpdateOne) SetName(s string) *AgentUpdateOne {
+	auo.mutation.SetName(s)
+	return auo
+}
+
+// SetNillableName sets the "name" field if the given value is not nil.
+func (auo *AgentUpdateOne) SetNillableName(s *string) *AgentUpdateOne {
+	if s != nil {
+		auo.SetName(*s)
+	}
+	return auo
+}
+
+// SetRole sets the "role" field.
+func (auo *AgentUpdateOne) SetRole(s string) *AgentUpdateOne {
+	auo.mutation.SetRole(s)
+	return auo
+}
+
+// SetNillableRole sets the "role" field if the given value is not nil.
+func (auo *AgentUpdateOne) SetNillableRole(s *string) *AgentUpdateOne {
+	if s != nil {
+		auo.SetRole(*s)
+	}
+	return auo
+}
+
+// SetStatus sets the "status" field.
+func (auo *AgentUpdateOne) SetStatus(i int) *AgentUpdateOne {
+	auo.mutation.ResetStatus()
+	auo.mutation.SetStatus(i)
+	return auo
+}
+
+// SetNillableStatus sets the "status" field if the given value is not nil.
+func (auo *AgentUpdateOne) SetNillableStatus(i *int) *AgentUpdateOne {
+	if i != nil {
+		auo.SetStatus(*i)
+	}
+	return auo
+}
+
+// AddStatus adds i to the "status" field.
+func (auo *AgentUpdateOne) AddStatus(i int) *AgentUpdateOne {
+	auo.mutation.AddStatus(i)
+	return auo
+}
+
+// ClearStatus clears the value of the "status" field.
+func (auo *AgentUpdateOne) ClearStatus() *AgentUpdateOne {
+	auo.mutation.ClearStatus()
+	return auo
+}
+
+// SetBackground sets the "background" field.
+func (auo *AgentUpdateOne) SetBackground(s string) *AgentUpdateOne {
+	auo.mutation.SetBackground(s)
+	return auo
+}
+
+// SetNillableBackground sets the "background" field if the given value is not nil.
+func (auo *AgentUpdateOne) SetNillableBackground(s *string) *AgentUpdateOne {
+	if s != nil {
+		auo.SetBackground(*s)
+	}
+	return auo
+}
+
+// SetExamples sets the "examples" field.
+func (auo *AgentUpdateOne) SetExamples(s string) *AgentUpdateOne {
+	auo.mutation.SetExamples(s)
+	return auo
+}
+
+// SetNillableExamples sets the "examples" field if the given value is not nil.
+func (auo *AgentUpdateOne) SetNillableExamples(s *string) *AgentUpdateOne {
+	if s != nil {
+		auo.SetExamples(*s)
+	}
+	return auo
+}
+
+// Mutation returns the AgentMutation object of the builder.
+func (auo *AgentUpdateOne) Mutation() *AgentMutation {
+	return auo.mutation
+}
+
+// Where appends a list predicates to the AgentUpdate builder.
+func (auo *AgentUpdateOne) Where(ps ...predicate.Agent) *AgentUpdateOne {
+	auo.mutation.Where(ps...)
+	return auo
+}
+
+// Select allows selecting one or more fields (columns) of the returned entity.
+// The default is selecting all fields defined in the entity schema.
+func (auo *AgentUpdateOne) Select(field string, fields ...string) *AgentUpdateOne {
+	auo.fields = append([]string{field}, fields...)
+	return auo
+}
+
+// Save executes the query and returns the updated Agent entity.
+func (auo *AgentUpdateOne) Save(ctx context.Context) (*Agent, error) {
+	if err := auo.defaults(); err != nil {
+		return nil, err
+	}
+	return withHooks(ctx, auo.sqlSave, auo.mutation, auo.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (auo *AgentUpdateOne) SaveX(ctx context.Context) *Agent {
+	node, err := auo.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return node
+}
+
+// Exec executes the query on the entity.
+func (auo *AgentUpdateOne) Exec(ctx context.Context) error {
+	_, err := auo.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (auo *AgentUpdateOne) ExecX(ctx context.Context) {
+	if err := auo.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (auo *AgentUpdateOne) defaults() error {
+	if _, ok := auo.mutation.UpdatedAt(); !ok {
+		if agent.UpdateDefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized agent.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := agent.UpdateDefaultUpdatedAt()
+		auo.mutation.SetUpdatedAt(v)
+	}
+	return nil
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (auo *AgentUpdateOne) check() error {
+	if v, ok := auo.mutation.Name(); ok {
+		if err := agent.NameValidator(v); err != nil {
+			return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "Agent.name": %w`, err)}
+		}
+	}
+	if v, ok := auo.mutation.Role(); ok {
+		if err := agent.RoleValidator(v); err != nil {
+			return &ValidationError{Name: "role", err: fmt.Errorf(`ent: validator failed for field "Agent.role": %w`, err)}
+		}
+	}
+	if v, ok := auo.mutation.Background(); ok {
+		if err := agent.BackgroundValidator(v); err != nil {
+			return &ValidationError{Name: "background", err: fmt.Errorf(`ent: validator failed for field "Agent.background": %w`, err)}
+		}
+	}
+	if v, ok := auo.mutation.Examples(); ok {
+		if err := agent.ExamplesValidator(v); err != nil {
+			return &ValidationError{Name: "examples", err: fmt.Errorf(`ent: validator failed for field "Agent.examples": %w`, err)}
+		}
+	}
+	return nil
+}
+
+func (auo *AgentUpdateOne) sqlSave(ctx context.Context) (_node *Agent, err error) {
+	if err := auo.check(); err != nil {
+		return _node, err
+	}
+	_spec := sqlgraph.NewUpdateSpec(agent.Table, agent.Columns, sqlgraph.NewFieldSpec(agent.FieldID, field.TypeUint64))
+	id, ok := auo.mutation.ID()
+	if !ok {
+		return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Agent.id" for update`)}
+	}
+	_spec.Node.ID.Value = id
+	if fields := auo.fields; len(fields) > 0 {
+		_spec.Node.Columns = make([]string, 0, len(fields))
+		_spec.Node.Columns = append(_spec.Node.Columns, agent.FieldID)
+		for _, f := range fields {
+			if !agent.ValidColumn(f) {
+				return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+			}
+			if f != agent.FieldID {
+				_spec.Node.Columns = append(_spec.Node.Columns, f)
+			}
+		}
+	}
+	if ps := auo.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if value, ok := auo.mutation.UpdatedAt(); ok {
+		_spec.SetField(agent.FieldUpdatedAt, field.TypeTime, value)
+	}
+	if value, ok := auo.mutation.DeletedAt(); ok {
+		_spec.SetField(agent.FieldDeletedAt, field.TypeTime, value)
+	}
+	if auo.mutation.DeletedAtCleared() {
+		_spec.ClearField(agent.FieldDeletedAt, field.TypeTime)
+	}
+	if value, ok := auo.mutation.Name(); ok {
+		_spec.SetField(agent.FieldName, field.TypeString, value)
+	}
+	if value, ok := auo.mutation.Role(); ok {
+		_spec.SetField(agent.FieldRole, field.TypeString, value)
+	}
+	if value, ok := auo.mutation.Status(); ok {
+		_spec.SetField(agent.FieldStatus, field.TypeInt, value)
+	}
+	if value, ok := auo.mutation.AddedStatus(); ok {
+		_spec.AddField(agent.FieldStatus, field.TypeInt, value)
+	}
+	if auo.mutation.StatusCleared() {
+		_spec.ClearField(agent.FieldStatus, field.TypeInt)
+	}
+	if value, ok := auo.mutation.Background(); ok {
+		_spec.SetField(agent.FieldBackground, field.TypeString, value)
+	}
+	if value, ok := auo.mutation.Examples(); ok {
+		_spec.SetField(agent.FieldExamples, field.TypeString, value)
+	}
+	_node = &Agent{config: auo.config}
+	_spec.Assign = _node.assignValues
+	_spec.ScanValues = _node.scanValues
+	if err = sqlgraph.UpdateNode(ctx, auo.driver, _spec); err != nil {
+		if _, ok := err.(*sqlgraph.NotFoundError); ok {
+			err = &NotFoundError{agent.Label}
+		} else if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return nil, err
+	}
+	auo.mutation.done = true
+	return _node, nil
+}

+ 150 - 7
ent/client.go

@@ -11,6 +11,7 @@ import (
 
 	"wechat-api/ent/migrate"
 
+	"wechat-api/ent/agent"
 	"wechat-api/ent/batchmsg"
 	"wechat-api/ent/contact"
 	"wechat-api/ent/label"
@@ -37,6 +38,8 @@ type Client struct {
 	config
 	// Schema is the client for creating, migrating and dropping schema.
 	Schema *migrate.Schema
+	// Agent is the client for interacting with the Agent builders.
+	Agent *AgentClient
 	// BatchMsg is the client for interacting with the BatchMsg builders.
 	BatchMsg *BatchMsgClient
 	// Contact is the client for interacting with the Contact builders.
@@ -72,6 +75,7 @@ func NewClient(opts ...Option) *Client {
 
 func (c *Client) init() {
 	c.Schema = migrate.NewSchema(c.driver)
+	c.Agent = NewAgentClient(c.config)
 	c.BatchMsg = NewBatchMsgClient(c.config)
 	c.Contact = NewContactClient(c.config)
 	c.Label = NewLabelClient(c.config)
@@ -176,6 +180,7 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) {
 	return &Tx{
 		ctx:               ctx,
 		config:            cfg,
+		Agent:             NewAgentClient(cfg),
 		BatchMsg:          NewBatchMsgClient(cfg),
 		Contact:           NewContactClient(cfg),
 		Label:             NewLabelClient(cfg),
@@ -207,6 +212,7 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
 	return &Tx{
 		ctx:               ctx,
 		config:            cfg,
+		Agent:             NewAgentClient(cfg),
 		BatchMsg:          NewBatchMsgClient(cfg),
 		Contact:           NewContactClient(cfg),
 		Label:             NewLabelClient(cfg),
@@ -225,7 +231,7 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
 // Debug returns a new debug-client. It's used to get verbose logging on specific operations.
 //
 //	client.Debug().
-//		BatchMsg.
+//		Agent.
 //		Query().
 //		Count(ctx)
 func (c *Client) Debug() *Client {
@@ -248,7 +254,7 @@ func (c *Client) Close() error {
 // In order to add hooks to a specific client, call: `client.Node.Use(...)`.
 func (c *Client) Use(hooks ...Hook) {
 	for _, n := range []interface{ Use(...Hook) }{
-		c.BatchMsg, c.Contact, c.Label, c.LabelRelationship, c.Message,
+		c.Agent, c.BatchMsg, c.Contact, c.Label, c.LabelRelationship, c.Message,
 		c.MessageRecords, c.Msg, c.Server, c.SopNode, c.SopStage, c.SopTask, c.Wx,
 	} {
 		n.Use(hooks...)
@@ -259,7 +265,7 @@ func (c *Client) Use(hooks ...Hook) {
 // In order to add interceptors to a specific client, call: `client.Node.Intercept(...)`.
 func (c *Client) Intercept(interceptors ...Interceptor) {
 	for _, n := range []interface{ Intercept(...Interceptor) }{
-		c.BatchMsg, c.Contact, c.Label, c.LabelRelationship, c.Message,
+		c.Agent, c.BatchMsg, c.Contact, c.Label, c.LabelRelationship, c.Message,
 		c.MessageRecords, c.Msg, c.Server, c.SopNode, c.SopStage, c.SopTask, c.Wx,
 	} {
 		n.Intercept(interceptors...)
@@ -269,6 +275,8 @@ func (c *Client) Intercept(interceptors ...Interceptor) {
 // Mutate implements the ent.Mutator interface.
 func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
 	switch m := m.(type) {
+	case *AgentMutation:
+		return c.Agent.mutate(ctx, m)
 	case *BatchMsgMutation:
 		return c.BatchMsg.mutate(ctx, m)
 	case *ContactMutation:
@@ -298,6 +306,141 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
 	}
 }
 
+// AgentClient is a client for the Agent schema.
+type AgentClient struct {
+	config
+}
+
+// NewAgentClient returns a client for the Agent from the given config.
+func NewAgentClient(c config) *AgentClient {
+	return &AgentClient{config: c}
+}
+
+// Use adds a list of mutation hooks to the hooks stack.
+// A call to `Use(f, g, h)` equals to `agent.Hooks(f(g(h())))`.
+func (c *AgentClient) Use(hooks ...Hook) {
+	c.hooks.Agent = append(c.hooks.Agent, hooks...)
+}
+
+// Intercept adds a list of query interceptors to the interceptors stack.
+// A call to `Intercept(f, g, h)` equals to `agent.Intercept(f(g(h())))`.
+func (c *AgentClient) Intercept(interceptors ...Interceptor) {
+	c.inters.Agent = append(c.inters.Agent, interceptors...)
+}
+
+// Create returns a builder for creating a Agent entity.
+func (c *AgentClient) Create() *AgentCreate {
+	mutation := newAgentMutation(c.config, OpCreate)
+	return &AgentCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// CreateBulk returns a builder for creating a bulk of Agent entities.
+func (c *AgentClient) CreateBulk(builders ...*AgentCreate) *AgentCreateBulk {
+	return &AgentCreateBulk{config: c.config, builders: builders}
+}
+
+// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates
+// a builder and applies setFunc on it.
+func (c *AgentClient) MapCreateBulk(slice any, setFunc func(*AgentCreate, int)) *AgentCreateBulk {
+	rv := reflect.ValueOf(slice)
+	if rv.Kind() != reflect.Slice {
+		return &AgentCreateBulk{err: fmt.Errorf("calling to AgentClient.MapCreateBulk with wrong type %T, need slice", slice)}
+	}
+	builders := make([]*AgentCreate, rv.Len())
+	for i := 0; i < rv.Len(); i++ {
+		builders[i] = c.Create()
+		setFunc(builders[i], i)
+	}
+	return &AgentCreateBulk{config: c.config, builders: builders}
+}
+
+// Update returns an update builder for Agent.
+func (c *AgentClient) Update() *AgentUpdate {
+	mutation := newAgentMutation(c.config, OpUpdate)
+	return &AgentUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOne returns an update builder for the given entity.
+func (c *AgentClient) UpdateOne(a *Agent) *AgentUpdateOne {
+	mutation := newAgentMutation(c.config, OpUpdateOne, withAgent(a))
+	return &AgentUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOneID returns an update builder for the given id.
+func (c *AgentClient) UpdateOneID(id uint64) *AgentUpdateOne {
+	mutation := newAgentMutation(c.config, OpUpdateOne, withAgentID(id))
+	return &AgentUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// Delete returns a delete builder for Agent.
+func (c *AgentClient) Delete() *AgentDelete {
+	mutation := newAgentMutation(c.config, OpDelete)
+	return &AgentDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// DeleteOne returns a builder for deleting the given entity.
+func (c *AgentClient) DeleteOne(a *Agent) *AgentDeleteOne {
+	return c.DeleteOneID(a.ID)
+}
+
+// DeleteOneID returns a builder for deleting the given entity by its id.
+func (c *AgentClient) DeleteOneID(id uint64) *AgentDeleteOne {
+	builder := c.Delete().Where(agent.ID(id))
+	builder.mutation.id = &id
+	builder.mutation.op = OpDeleteOne
+	return &AgentDeleteOne{builder}
+}
+
+// Query returns a query builder for Agent.
+func (c *AgentClient) Query() *AgentQuery {
+	return &AgentQuery{
+		config: c.config,
+		ctx:    &QueryContext{Type: TypeAgent},
+		inters: c.Interceptors(),
+	}
+}
+
+// Get returns a Agent entity by its id.
+func (c *AgentClient) Get(ctx context.Context, id uint64) (*Agent, error) {
+	return c.Query().Where(agent.ID(id)).Only(ctx)
+}
+
+// GetX is like Get, but panics if an error occurs.
+func (c *AgentClient) GetX(ctx context.Context, id uint64) *Agent {
+	obj, err := c.Get(ctx, id)
+	if err != nil {
+		panic(err)
+	}
+	return obj
+}
+
+// Hooks returns the client hooks.
+func (c *AgentClient) Hooks() []Hook {
+	hooks := c.hooks.Agent
+	return append(hooks[:len(hooks):len(hooks)], agent.Hooks[:]...)
+}
+
+// Interceptors returns the client interceptors.
+func (c *AgentClient) Interceptors() []Interceptor {
+	inters := c.inters.Agent
+	return append(inters[:len(inters):len(inters)], agent.Interceptors[:]...)
+}
+
+func (c *AgentClient) mutate(ctx context.Context, m *AgentMutation) (Value, error) {
+	switch m.Op() {
+	case OpCreate:
+		return (&AgentCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpUpdate:
+		return (&AgentUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpUpdateOne:
+		return (&AgentUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpDelete, OpDeleteOne:
+		return (&AgentDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
+	default:
+		return nil, fmt.Errorf("ent: unknown Agent mutation op: %q", m.Op())
+	}
+}
+
 // BatchMsgClient is a client for the BatchMsg schema.
 type BatchMsgClient struct {
 	config
@@ -2173,12 +2316,12 @@ func (c *WxClient) mutate(ctx context.Context, m *WxMutation) (Value, error) {
 // hooks and interceptors per client, for fast access.
 type (
 	hooks struct {
-		BatchMsg, Contact, Label, LabelRelationship, Message, MessageRecords, Msg,
-		Server, SopNode, SopStage, SopTask, Wx []ent.Hook
+		Agent, BatchMsg, Contact, Label, LabelRelationship, Message, MessageRecords,
+		Msg, Server, SopNode, SopStage, SopTask, Wx []ent.Hook
 	}
 	inters struct {
-		BatchMsg, Contact, Label, LabelRelationship, Message, MessageRecords, Msg,
-		Server, SopNode, SopStage, SopTask, Wx []ent.Interceptor
+		Agent, BatchMsg, Contact, Label, LabelRelationship, Message, MessageRecords,
+		Msg, Server, SopNode, SopStage, SopTask, Wx []ent.Interceptor
 	}
 )
 

+ 2 - 0
ent/ent.go

@@ -8,6 +8,7 @@ import (
 	"fmt"
 	"reflect"
 	"sync"
+	"wechat-api/ent/agent"
 	"wechat-api/ent/batchmsg"
 	"wechat-api/ent/contact"
 	"wechat-api/ent/label"
@@ -84,6 +85,7 @@ var (
 func checkColumn(table, column string) error {
 	initCheck.Do(func() {
 		columnCheck = sql.NewColumnCheck(map[string]func(string) bool{
+			agent.Table:             agent.ValidColumn,
 			batchmsg.Table:          batchmsg.ValidColumn,
 			contact.Table:           contact.ValidColumn,
 			label.Table:             label.ValidColumn,

+ 12 - 0
ent/hook/hook.go

@@ -8,6 +8,18 @@ import (
 	"wechat-api/ent"
 )
 
+// The AgentFunc type is an adapter to allow the use of ordinary
+// function as Agent mutator.
+type AgentFunc func(context.Context, *ent.AgentMutation) (ent.Value, error)
+
+// Mutate calls f(ctx, m).
+func (f AgentFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
+	if mv, ok := m.(*ent.AgentMutation); ok {
+		return f(ctx, mv)
+	}
+	return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.AgentMutation", m)
+}
+
 // The BatchMsgFunc type is an adapter to allow the use of ordinary
 // function as BatchMsg mutator.
 type BatchMsgFunc func(context.Context, *ent.BatchMsgMutation) (ent.Value, error)

+ 30 - 0
ent/intercept/intercept.go

@@ -6,6 +6,7 @@ import (
 	"context"
 	"fmt"
 	"wechat-api/ent"
+	"wechat-api/ent/agent"
 	"wechat-api/ent/batchmsg"
 	"wechat-api/ent/contact"
 	"wechat-api/ent/label"
@@ -79,6 +80,33 @@ func (f TraverseFunc) Traverse(ctx context.Context, q ent.Query) error {
 	return f(ctx, query)
 }
 
+// The AgentFunc type is an adapter to allow the use of ordinary function as a Querier.
+type AgentFunc func(context.Context, *ent.AgentQuery) (ent.Value, error)
+
+// Query calls f(ctx, q).
+func (f AgentFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
+	if q, ok := q.(*ent.AgentQuery); ok {
+		return f(ctx, q)
+	}
+	return nil, fmt.Errorf("unexpected query type %T. expect *ent.AgentQuery", q)
+}
+
+// The TraverseAgent type is an adapter to allow the use of ordinary function as Traverser.
+type TraverseAgent func(context.Context, *ent.AgentQuery) error
+
+// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
+func (f TraverseAgent) Intercept(next ent.Querier) ent.Querier {
+	return next
+}
+
+// Traverse calls f(ctx, q).
+func (f TraverseAgent) Traverse(ctx context.Context, q ent.Query) error {
+	if q, ok := q.(*ent.AgentQuery); ok {
+		return f(ctx, q)
+	}
+	return fmt.Errorf("unexpected query type %T. expect *ent.AgentQuery", q)
+}
+
 // The BatchMsgFunc type is an adapter to allow the use of ordinary function as a Querier.
 type BatchMsgFunc func(context.Context, *ent.BatchMsgQuery) (ent.Value, error)
 
@@ -406,6 +434,8 @@ func (f TraverseWx) Traverse(ctx context.Context, q ent.Query) error {
 // NewQuery returns the generic Query interface for the given typed query.
 func NewQuery(q ent.Query) (Query, error) {
 	switch q := q.(type) {
+	case *ent.AgentQuery:
+		return &query[*ent.AgentQuery, predicate.Agent, agent.OrderOption]{typ: ent.TypeAgent, tq: q}, nil
 	case *ent.BatchMsgQuery:
 		return &query[*ent.BatchMsgQuery, predicate.BatchMsg, batchmsg.OrderOption]{typ: ent.TypeBatchMsg, tq: q}, nil
 	case *ent.ContactQuery:

+ 22 - 0
ent/migrate/schema.go

@@ -9,6 +9,24 @@ import (
 )
 
 var (
+	// AgentColumns holds the columns for the "agent" table.
+	AgentColumns = []*schema.Column{
+		{Name: "id", Type: field.TypeUint64, Increment: true},
+		{Name: "created_at", Type: field.TypeTime, Comment: "Create Time | 创建日期"},
+		{Name: "updated_at", Type: field.TypeTime, Comment: "Update Time | 修改日期"},
+		{Name: "deleted_at", Type: field.TypeTime, Nullable: true, Comment: "Delete Time | 删除日期"},
+		{Name: "name", Type: field.TypeString, Size: 20, Comment: "name | 角色名称"},
+		{Name: "role", Type: field.TypeString, Size: 1000, Comment: "role | 角色设定"},
+		{Name: "status", Type: field.TypeInt, Nullable: true, Comment: "status | 状态 1-正常 2-禁用", Default: 1},
+		{Name: "background", Type: field.TypeString, Size: 1000, Comment: "background | 背景介绍"},
+		{Name: "examples", Type: field.TypeString, Size: 5000, Comment: "examples | 对话案例"},
+	}
+	// AgentTable holds the schema information for the "agent" table.
+	AgentTable = &schema.Table{
+		Name:       "agent",
+		Columns:    AgentColumns,
+		PrimaryKey: []*schema.Column{AgentColumns[0]},
+	}
 	// BatchMsgColumns holds the columns for the "batch_msg" table.
 	BatchMsgColumns = []*schema.Column{
 		{Name: "id", Type: field.TypeUint64, Increment: true},
@@ -461,6 +479,7 @@ var (
 	}
 	// Tables holds all the tables in the schema.
 	Tables = []*schema.Table{
+		AgentTable,
 		BatchMsgTable,
 		ContactTable,
 		LabelTable,
@@ -477,6 +496,9 @@ var (
 )
 
 func init() {
+	AgentTable.Annotation = &entsql.Annotation{
+		Table: "agent",
+	}
 	BatchMsgTable.Annotation = &entsql.Annotation{
 		Table: "batch_msg",
 	}

+ 790 - 0
ent/mutation.go

@@ -8,6 +8,7 @@ import (
 	"fmt"
 	"sync"
 	"time"
+	"wechat-api/ent/agent"
 	"wechat-api/ent/batchmsg"
 	"wechat-api/ent/contact"
 	"wechat-api/ent/custom_types"
@@ -36,6 +37,7 @@ const (
 	OpUpdateOne = ent.OpUpdateOne
 
 	// Node types.
+	TypeAgent             = "Agent"
 	TypeBatchMsg          = "BatchMsg"
 	TypeContact           = "Contact"
 	TypeLabel             = "Label"
@@ -50,6 +52,794 @@ const (
 	TypeWx                = "Wx"
 )
 
+// AgentMutation represents an operation that mutates the Agent nodes in the graph.
+type AgentMutation struct {
+	config
+	op            Op
+	typ           string
+	id            *uint64
+	created_at    *time.Time
+	updated_at    *time.Time
+	deleted_at    *time.Time
+	name          *string
+	role          *string
+	status        *int
+	addstatus     *int
+	background    *string
+	examples      *string
+	clearedFields map[string]struct{}
+	done          bool
+	oldValue      func(context.Context) (*Agent, error)
+	predicates    []predicate.Agent
+}
+
+var _ ent.Mutation = (*AgentMutation)(nil)
+
+// agentOption allows management of the mutation configuration using functional options.
+type agentOption func(*AgentMutation)
+
+// newAgentMutation creates new mutation for the Agent entity.
+func newAgentMutation(c config, op Op, opts ...agentOption) *AgentMutation {
+	m := &AgentMutation{
+		config:        c,
+		op:            op,
+		typ:           TypeAgent,
+		clearedFields: make(map[string]struct{}),
+	}
+	for _, opt := range opts {
+		opt(m)
+	}
+	return m
+}
+
+// withAgentID sets the ID field of the mutation.
+func withAgentID(id uint64) agentOption {
+	return func(m *AgentMutation) {
+		var (
+			err   error
+			once  sync.Once
+			value *Agent
+		)
+		m.oldValue = func(ctx context.Context) (*Agent, error) {
+			once.Do(func() {
+				if m.done {
+					err = errors.New("querying old values post mutation is not allowed")
+				} else {
+					value, err = m.Client().Agent.Get(ctx, id)
+				}
+			})
+			return value, err
+		}
+		m.id = &id
+	}
+}
+
+// withAgent sets the old Agent of the mutation.
+func withAgent(node *Agent) agentOption {
+	return func(m *AgentMutation) {
+		m.oldValue = func(context.Context) (*Agent, error) {
+			return node, nil
+		}
+		m.id = &node.ID
+	}
+}
+
+// Client returns a new `ent.Client` from the mutation. If the mutation was
+// executed in a transaction (ent.Tx), a transactional client is returned.
+func (m AgentMutation) Client() *Client {
+	client := &Client{config: m.config}
+	client.init()
+	return client
+}
+
+// Tx returns an `ent.Tx` for mutations that were executed in transactions;
+// it returns an error otherwise.
+func (m AgentMutation) Tx() (*Tx, error) {
+	if _, ok := m.driver.(*txDriver); !ok {
+		return nil, errors.New("ent: mutation is not running in a transaction")
+	}
+	tx := &Tx{config: m.config}
+	tx.init()
+	return tx, nil
+}
+
+// SetID sets the value of the id field. Note that this
+// operation is only accepted on creation of Agent entities.
+func (m *AgentMutation) SetID(id uint64) {
+	m.id = &id
+}
+
+// ID returns the ID value in the mutation. Note that the ID is only available
+// if it was provided to the builder or after it was returned from the database.
+func (m *AgentMutation) ID() (id uint64, exists bool) {
+	if m.id == nil {
+		return
+	}
+	return *m.id, true
+}
+
+// IDs queries the database and returns the entity ids that match the mutation's predicate.
+// That means, if the mutation is applied within a transaction with an isolation level such
+// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated
+// or updated by the mutation.
+func (m *AgentMutation) IDs(ctx context.Context) ([]uint64, error) {
+	switch {
+	case m.op.Is(OpUpdateOne | OpDeleteOne):
+		id, exists := m.ID()
+		if exists {
+			return []uint64{id}, nil
+		}
+		fallthrough
+	case m.op.Is(OpUpdate | OpDelete):
+		return m.Client().Agent.Query().Where(m.predicates...).IDs(ctx)
+	default:
+		return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op)
+	}
+}
+
+// SetCreatedAt sets the "created_at" field.
+func (m *AgentMutation) SetCreatedAt(t time.Time) {
+	m.created_at = &t
+}
+
+// CreatedAt returns the value of the "created_at" field in the mutation.
+func (m *AgentMutation) CreatedAt() (r time.Time, exists bool) {
+	v := m.created_at
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldCreatedAt returns the old "created_at" field's value of the Agent entity.
+// If the Agent object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *AgentMutation) OldCreatedAt(ctx context.Context) (v time.Time, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldCreatedAt is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldCreatedAt requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldCreatedAt: %w", err)
+	}
+	return oldValue.CreatedAt, nil
+}
+
+// ResetCreatedAt resets all changes to the "created_at" field.
+func (m *AgentMutation) ResetCreatedAt() {
+	m.created_at = nil
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (m *AgentMutation) SetUpdatedAt(t time.Time) {
+	m.updated_at = &t
+}
+
+// UpdatedAt returns the value of the "updated_at" field in the mutation.
+func (m *AgentMutation) UpdatedAt() (r time.Time, exists bool) {
+	v := m.updated_at
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldUpdatedAt returns the old "updated_at" field's value of the Agent entity.
+// If the Agent object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *AgentMutation) OldUpdatedAt(ctx context.Context) (v time.Time, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldUpdatedAt is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldUpdatedAt requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldUpdatedAt: %w", err)
+	}
+	return oldValue.UpdatedAt, nil
+}
+
+// ResetUpdatedAt resets all changes to the "updated_at" field.
+func (m *AgentMutation) ResetUpdatedAt() {
+	m.updated_at = nil
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (m *AgentMutation) SetDeletedAt(t time.Time) {
+	m.deleted_at = &t
+}
+
+// DeletedAt returns the value of the "deleted_at" field in the mutation.
+func (m *AgentMutation) DeletedAt() (r time.Time, exists bool) {
+	v := m.deleted_at
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldDeletedAt returns the old "deleted_at" field's value of the Agent entity.
+// If the Agent object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *AgentMutation) OldDeletedAt(ctx context.Context) (v time.Time, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldDeletedAt is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldDeletedAt requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldDeletedAt: %w", err)
+	}
+	return oldValue.DeletedAt, nil
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (m *AgentMutation) ClearDeletedAt() {
+	m.deleted_at = nil
+	m.clearedFields[agent.FieldDeletedAt] = struct{}{}
+}
+
+// DeletedAtCleared returns if the "deleted_at" field was cleared in this mutation.
+func (m *AgentMutation) DeletedAtCleared() bool {
+	_, ok := m.clearedFields[agent.FieldDeletedAt]
+	return ok
+}
+
+// ResetDeletedAt resets all changes to the "deleted_at" field.
+func (m *AgentMutation) ResetDeletedAt() {
+	m.deleted_at = nil
+	delete(m.clearedFields, agent.FieldDeletedAt)
+}
+
+// SetName sets the "name" field.
+func (m *AgentMutation) SetName(s string) {
+	m.name = &s
+}
+
+// Name returns the value of the "name" field in the mutation.
+func (m *AgentMutation) Name() (r string, exists bool) {
+	v := m.name
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldName returns the old "name" field's value of the Agent entity.
+// If the Agent object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *AgentMutation) OldName(ctx context.Context) (v string, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldName is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldName requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldName: %w", err)
+	}
+	return oldValue.Name, nil
+}
+
+// ResetName resets all changes to the "name" field.
+func (m *AgentMutation) ResetName() {
+	m.name = nil
+}
+
+// SetRole sets the "role" field.
+func (m *AgentMutation) SetRole(s string) {
+	m.role = &s
+}
+
+// Role returns the value of the "role" field in the mutation.
+func (m *AgentMutation) Role() (r string, exists bool) {
+	v := m.role
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldRole returns the old "role" field's value of the Agent entity.
+// If the Agent object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *AgentMutation) OldRole(ctx context.Context) (v string, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldRole is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldRole requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldRole: %w", err)
+	}
+	return oldValue.Role, nil
+}
+
+// ResetRole resets all changes to the "role" field.
+func (m *AgentMutation) ResetRole() {
+	m.role = nil
+}
+
+// SetStatus sets the "status" field.
+func (m *AgentMutation) SetStatus(i int) {
+	m.status = &i
+	m.addstatus = nil
+}
+
+// Status returns the value of the "status" field in the mutation.
+func (m *AgentMutation) Status() (r int, exists bool) {
+	v := m.status
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldStatus returns the old "status" field's value of the Agent entity.
+// If the Agent object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *AgentMutation) OldStatus(ctx context.Context) (v int, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldStatus is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldStatus requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldStatus: %w", err)
+	}
+	return oldValue.Status, nil
+}
+
+// AddStatus adds i to the "status" field.
+func (m *AgentMutation) AddStatus(i int) {
+	if m.addstatus != nil {
+		*m.addstatus += i
+	} else {
+		m.addstatus = &i
+	}
+}
+
+// AddedStatus returns the value that was added to the "status" field in this mutation.
+func (m *AgentMutation) AddedStatus() (r int, exists bool) {
+	v := m.addstatus
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// ClearStatus clears the value of the "status" field.
+func (m *AgentMutation) ClearStatus() {
+	m.status = nil
+	m.addstatus = nil
+	m.clearedFields[agent.FieldStatus] = struct{}{}
+}
+
+// StatusCleared returns if the "status" field was cleared in this mutation.
+func (m *AgentMutation) StatusCleared() bool {
+	_, ok := m.clearedFields[agent.FieldStatus]
+	return ok
+}
+
+// ResetStatus resets all changes to the "status" field.
+func (m *AgentMutation) ResetStatus() {
+	m.status = nil
+	m.addstatus = nil
+	delete(m.clearedFields, agent.FieldStatus)
+}
+
+// SetBackground sets the "background" field.
+func (m *AgentMutation) SetBackground(s string) {
+	m.background = &s
+}
+
+// Background returns the value of the "background" field in the mutation.
+func (m *AgentMutation) Background() (r string, exists bool) {
+	v := m.background
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldBackground returns the old "background" field's value of the Agent entity.
+// If the Agent object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *AgentMutation) OldBackground(ctx context.Context) (v string, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldBackground is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldBackground requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldBackground: %w", err)
+	}
+	return oldValue.Background, nil
+}
+
+// ResetBackground resets all changes to the "background" field.
+func (m *AgentMutation) ResetBackground() {
+	m.background = nil
+}
+
+// SetExamples sets the "examples" field.
+func (m *AgentMutation) SetExamples(s string) {
+	m.examples = &s
+}
+
+// Examples returns the value of the "examples" field in the mutation.
+func (m *AgentMutation) Examples() (r string, exists bool) {
+	v := m.examples
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldExamples returns the old "examples" field's value of the Agent entity.
+// If the Agent object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *AgentMutation) OldExamples(ctx context.Context) (v string, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldExamples is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldExamples requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldExamples: %w", err)
+	}
+	return oldValue.Examples, nil
+}
+
+// ResetExamples resets all changes to the "examples" field.
+func (m *AgentMutation) ResetExamples() {
+	m.examples = nil
+}
+
+// Where appends a list predicates to the AgentMutation builder.
+func (m *AgentMutation) Where(ps ...predicate.Agent) {
+	m.predicates = append(m.predicates, ps...)
+}
+
+// WhereP appends storage-level predicates to the AgentMutation builder. Using this method,
+// users can use type-assertion to append predicates that do not depend on any generated package.
+func (m *AgentMutation) WhereP(ps ...func(*sql.Selector)) {
+	p := make([]predicate.Agent, len(ps))
+	for i := range ps {
+		p[i] = ps[i]
+	}
+	m.Where(p...)
+}
+
+// Op returns the operation name.
+func (m *AgentMutation) Op() Op {
+	return m.op
+}
+
+// SetOp allows setting the mutation operation.
+func (m *AgentMutation) SetOp(op Op) {
+	m.op = op
+}
+
+// Type returns the node type of this mutation (Agent).
+func (m *AgentMutation) Type() string {
+	return m.typ
+}
+
+// Fields returns all fields that were changed during this mutation. Note that in
+// order to get all numeric fields that were incremented/decremented, call
+// AddedFields().
+func (m *AgentMutation) Fields() []string {
+	fields := make([]string, 0, 8)
+	if m.created_at != nil {
+		fields = append(fields, agent.FieldCreatedAt)
+	}
+	if m.updated_at != nil {
+		fields = append(fields, agent.FieldUpdatedAt)
+	}
+	if m.deleted_at != nil {
+		fields = append(fields, agent.FieldDeletedAt)
+	}
+	if m.name != nil {
+		fields = append(fields, agent.FieldName)
+	}
+	if m.role != nil {
+		fields = append(fields, agent.FieldRole)
+	}
+	if m.status != nil {
+		fields = append(fields, agent.FieldStatus)
+	}
+	if m.background != nil {
+		fields = append(fields, agent.FieldBackground)
+	}
+	if m.examples != nil {
+		fields = append(fields, agent.FieldExamples)
+	}
+	return fields
+}
+
+// Field returns the value of a field with the given name. The second boolean
+// return value indicates that this field was not set, or was not defined in the
+// schema.
+func (m *AgentMutation) Field(name string) (ent.Value, bool) {
+	switch name {
+	case agent.FieldCreatedAt:
+		return m.CreatedAt()
+	case agent.FieldUpdatedAt:
+		return m.UpdatedAt()
+	case agent.FieldDeletedAt:
+		return m.DeletedAt()
+	case agent.FieldName:
+		return m.Name()
+	case agent.FieldRole:
+		return m.Role()
+	case agent.FieldStatus:
+		return m.Status()
+	case agent.FieldBackground:
+		return m.Background()
+	case agent.FieldExamples:
+		return m.Examples()
+	}
+	return nil, false
+}
+
+// OldField returns the old value of the field from the database. An error is
+// returned if the mutation operation is not UpdateOne, or the query to the
+// database failed.
+func (m *AgentMutation) OldField(ctx context.Context, name string) (ent.Value, error) {
+	switch name {
+	case agent.FieldCreatedAt:
+		return m.OldCreatedAt(ctx)
+	case agent.FieldUpdatedAt:
+		return m.OldUpdatedAt(ctx)
+	case agent.FieldDeletedAt:
+		return m.OldDeletedAt(ctx)
+	case agent.FieldName:
+		return m.OldName(ctx)
+	case agent.FieldRole:
+		return m.OldRole(ctx)
+	case agent.FieldStatus:
+		return m.OldStatus(ctx)
+	case agent.FieldBackground:
+		return m.OldBackground(ctx)
+	case agent.FieldExamples:
+		return m.OldExamples(ctx)
+	}
+	return nil, fmt.Errorf("unknown Agent field %s", name)
+}
+
+// SetField sets the value of a field with the given name. It returns an error if
+// the field is not defined in the schema, or if the type mismatched the field
+// type.
+func (m *AgentMutation) SetField(name string, value ent.Value) error {
+	switch name {
+	case agent.FieldCreatedAt:
+		v, ok := value.(time.Time)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetCreatedAt(v)
+		return nil
+	case agent.FieldUpdatedAt:
+		v, ok := value.(time.Time)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetUpdatedAt(v)
+		return nil
+	case agent.FieldDeletedAt:
+		v, ok := value.(time.Time)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetDeletedAt(v)
+		return nil
+	case agent.FieldName:
+		v, ok := value.(string)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetName(v)
+		return nil
+	case agent.FieldRole:
+		v, ok := value.(string)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetRole(v)
+		return nil
+	case agent.FieldStatus:
+		v, ok := value.(int)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetStatus(v)
+		return nil
+	case agent.FieldBackground:
+		v, ok := value.(string)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetBackground(v)
+		return nil
+	case agent.FieldExamples:
+		v, ok := value.(string)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetExamples(v)
+		return nil
+	}
+	return fmt.Errorf("unknown Agent field %s", name)
+}
+
+// AddedFields returns all numeric fields that were incremented/decremented during
+// this mutation.
+func (m *AgentMutation) AddedFields() []string {
+	var fields []string
+	if m.addstatus != nil {
+		fields = append(fields, agent.FieldStatus)
+	}
+	return fields
+}
+
+// AddedField returns the numeric value that was incremented/decremented on a field
+// with the given name. The second boolean return value indicates that this field
+// was not set, or was not defined in the schema.
+func (m *AgentMutation) AddedField(name string) (ent.Value, bool) {
+	switch name {
+	case agent.FieldStatus:
+		return m.AddedStatus()
+	}
+	return nil, false
+}
+
+// AddField adds the value to the field with the given name. It returns an error if
+// the field is not defined in the schema, or if the type mismatched the field
+// type.
+func (m *AgentMutation) AddField(name string, value ent.Value) error {
+	switch name {
+	case agent.FieldStatus:
+		v, ok := value.(int)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.AddStatus(v)
+		return nil
+	}
+	return fmt.Errorf("unknown Agent numeric field %s", name)
+}
+
+// ClearedFields returns all nullable fields that were cleared during this
+// mutation.
+func (m *AgentMutation) ClearedFields() []string {
+	var fields []string
+	if m.FieldCleared(agent.FieldDeletedAt) {
+		fields = append(fields, agent.FieldDeletedAt)
+	}
+	if m.FieldCleared(agent.FieldStatus) {
+		fields = append(fields, agent.FieldStatus)
+	}
+	return fields
+}
+
+// FieldCleared returns a boolean indicating if a field with the given name was
+// cleared in this mutation.
+func (m *AgentMutation) FieldCleared(name string) bool {
+	_, ok := m.clearedFields[name]
+	return ok
+}
+
+// ClearField clears the value of the field with the given name. It returns an
+// error if the field is not defined in the schema.
+func (m *AgentMutation) ClearField(name string) error {
+	switch name {
+	case agent.FieldDeletedAt:
+		m.ClearDeletedAt()
+		return nil
+	case agent.FieldStatus:
+		m.ClearStatus()
+		return nil
+	}
+	return fmt.Errorf("unknown Agent nullable field %s", name)
+}
+
+// ResetField resets all changes in the mutation for the field with the given name.
+// It returns an error if the field is not defined in the schema.
+func (m *AgentMutation) ResetField(name string) error {
+	switch name {
+	case agent.FieldCreatedAt:
+		m.ResetCreatedAt()
+		return nil
+	case agent.FieldUpdatedAt:
+		m.ResetUpdatedAt()
+		return nil
+	case agent.FieldDeletedAt:
+		m.ResetDeletedAt()
+		return nil
+	case agent.FieldName:
+		m.ResetName()
+		return nil
+	case agent.FieldRole:
+		m.ResetRole()
+		return nil
+	case agent.FieldStatus:
+		m.ResetStatus()
+		return nil
+	case agent.FieldBackground:
+		m.ResetBackground()
+		return nil
+	case agent.FieldExamples:
+		m.ResetExamples()
+		return nil
+	}
+	return fmt.Errorf("unknown Agent field %s", name)
+}
+
+// AddedEdges returns all edge names that were set/added in this mutation.
+func (m *AgentMutation) AddedEdges() []string {
+	edges := make([]string, 0, 0)
+	return edges
+}
+
+// AddedIDs returns all IDs (to other nodes) that were added for the given edge
+// name in this mutation.
+func (m *AgentMutation) AddedIDs(name string) []ent.Value {
+	return nil
+}
+
+// RemovedEdges returns all edge names that were removed in this mutation.
+func (m *AgentMutation) RemovedEdges() []string {
+	edges := make([]string, 0, 0)
+	return edges
+}
+
+// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with
+// the given name in this mutation.
+func (m *AgentMutation) RemovedIDs(name string) []ent.Value {
+	return nil
+}
+
+// ClearedEdges returns all edge names that were cleared in this mutation.
+func (m *AgentMutation) ClearedEdges() []string {
+	edges := make([]string, 0, 0)
+	return edges
+}
+
+// EdgeCleared returns a boolean which indicates if the edge with the given name
+// was cleared in this mutation.
+func (m *AgentMutation) EdgeCleared(name string) bool {
+	return false
+}
+
+// ClearEdge clears the value of the edge with the given name. It returns an error
+// if that edge is not defined in the schema.
+func (m *AgentMutation) ClearEdge(name string) error {
+	return fmt.Errorf("unknown Agent unique edge %s", name)
+}
+
+// ResetEdge resets all changes to the edge with the given name in this mutation.
+// It returns an error if the edge is not defined in the schema.
+func (m *AgentMutation) ResetEdge(name string) error {
+	return fmt.Errorf("unknown Agent edge %s", name)
+}
+
 // BatchMsgMutation represents an operation that mutates the BatchMsg nodes in the graph.
 type BatchMsgMutation struct {
 	config

+ 82 - 0
ent/pagination.go

@@ -5,6 +5,7 @@ package ent
 import (
 	"context"
 	"fmt"
+	"wechat-api/ent/agent"
 	"wechat-api/ent/batchmsg"
 	"wechat-api/ent/contact"
 	"wechat-api/ent/label"
@@ -65,6 +66,87 @@ func (o OrderDirection) reverse() OrderDirection {
 
 const errInvalidPagination = "INVALID_PAGINATION"
 
+type AgentPager struct {
+	Order  agent.OrderOption
+	Filter func(*AgentQuery) (*AgentQuery, error)
+}
+
+// AgentPaginateOption enables pagination customization.
+type AgentPaginateOption func(*AgentPager)
+
+// DefaultAgentOrder is the default ordering of Agent.
+var DefaultAgentOrder = Desc(agent.FieldID)
+
+func newAgentPager(opts []AgentPaginateOption) (*AgentPager, error) {
+	pager := &AgentPager{}
+	for _, opt := range opts {
+		opt(pager)
+	}
+	if pager.Order == nil {
+		pager.Order = DefaultAgentOrder
+	}
+	return pager, nil
+}
+
+func (p *AgentPager) ApplyFilter(query *AgentQuery) (*AgentQuery, error) {
+	if p.Filter != nil {
+		return p.Filter(query)
+	}
+	return query, nil
+}
+
+// AgentPageList is Agent PageList result.
+type AgentPageList struct {
+	List        []*Agent     `json:"list"`
+	PageDetails *PageDetails `json:"pageDetails"`
+}
+
+func (a *AgentQuery) Page(
+	ctx context.Context, pageNum uint64, pageSize uint64, opts ...AgentPaginateOption,
+) (*AgentPageList, error) {
+
+	pager, err := newAgentPager(opts)
+	if err != nil {
+		return nil, err
+	}
+
+	if a, err = pager.ApplyFilter(a); err != nil {
+		return nil, err
+	}
+
+	ret := &AgentPageList{}
+
+	ret.PageDetails = &PageDetails{
+		Page: pageNum,
+		Size: pageSize,
+	}
+
+	query := a.Clone()
+	query.ctx.Fields = nil
+	count, err := query.Count(ctx)
+
+	if err != nil {
+		return nil, err
+	}
+
+	ret.PageDetails.Total = uint64(count)
+
+	if pager.Order != nil {
+		a = a.Order(pager.Order)
+	} else {
+		a = a.Order(DefaultAgentOrder)
+	}
+
+	a = a.Offset(int((pageNum - 1) * pageSize)).Limit(int(pageSize))
+	list, err := a.All(ctx)
+	if err != nil {
+		return nil, err
+	}
+	ret.List = list
+
+	return ret, nil
+}
+
 type BatchMsgPager struct {
 	Order  batchmsg.OrderOption
 	Filter func(*BatchMsgQuery) (*BatchMsgQuery, error)

+ 3 - 0
ent/predicate/predicate.go

@@ -6,6 +6,9 @@ import (
 	"entgo.io/ent/dialect/sql"
 )
 
+// Agent is the predicate function for agent builders.
+type Agent func(*sql.Selector)
+
 // BatchMsg is the predicate function for batchmsg builders.
 type BatchMsg func(*sql.Selector)
 

+ 40 - 0
ent/runtime/runtime.go

@@ -4,6 +4,7 @@ package runtime
 
 import (
 	"time"
+	"wechat-api/ent/agent"
 	"wechat-api/ent/batchmsg"
 	"wechat-api/ent/contact"
 	"wechat-api/ent/label"
@@ -23,6 +24,45 @@ import (
 // (default values, validators, hooks and policies) and stitches it
 // to their package variables.
 func init() {
+	agentMixin := schema.Agent{}.Mixin()
+	agentMixinHooks1 := agentMixin[1].Hooks()
+	agent.Hooks[0] = agentMixinHooks1[0]
+	agentMixinInters1 := agentMixin[1].Interceptors()
+	agent.Interceptors[0] = agentMixinInters1[0]
+	agentMixinFields0 := agentMixin[0].Fields()
+	_ = agentMixinFields0
+	agentFields := schema.Agent{}.Fields()
+	_ = agentFields
+	// agentDescCreatedAt is the schema descriptor for created_at field.
+	agentDescCreatedAt := agentMixinFields0[1].Descriptor()
+	// agent.DefaultCreatedAt holds the default value on creation for the created_at field.
+	agent.DefaultCreatedAt = agentDescCreatedAt.Default.(func() time.Time)
+	// agentDescUpdatedAt is the schema descriptor for updated_at field.
+	agentDescUpdatedAt := agentMixinFields0[2].Descriptor()
+	// agent.DefaultUpdatedAt holds the default value on creation for the updated_at field.
+	agent.DefaultUpdatedAt = agentDescUpdatedAt.Default.(func() time.Time)
+	// agent.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
+	agent.UpdateDefaultUpdatedAt = agentDescUpdatedAt.UpdateDefault.(func() time.Time)
+	// agentDescName is the schema descriptor for name field.
+	agentDescName := agentFields[0].Descriptor()
+	// agent.NameValidator is a validator for the "name" field. It is called by the builders before save.
+	agent.NameValidator = agentDescName.Validators[0].(func(string) error)
+	// agentDescRole is the schema descriptor for role field.
+	agentDescRole := agentFields[1].Descriptor()
+	// agent.RoleValidator is a validator for the "role" field. It is called by the builders before save.
+	agent.RoleValidator = agentDescRole.Validators[0].(func(string) error)
+	// agentDescStatus is the schema descriptor for status field.
+	agentDescStatus := agentFields[2].Descriptor()
+	// agent.DefaultStatus holds the default value on creation for the status field.
+	agent.DefaultStatus = agentDescStatus.Default.(int)
+	// agentDescBackground is the schema descriptor for background field.
+	agentDescBackground := agentFields[3].Descriptor()
+	// agent.BackgroundValidator is a validator for the "background" field. It is called by the builders before save.
+	agent.BackgroundValidator = agentDescBackground.Validators[0].(func(string) error)
+	// agentDescExamples is the schema descriptor for examples field.
+	agentDescExamples := agentFields[4].Descriptor()
+	// agent.ExamplesValidator is a validator for the "examples" field. It is called by the builders before save.
+	agent.ExamplesValidator = agentDescExamples.Validators[0].(func(string) error)
 	batchmsgMixin := schema.BatchMsg{}.Mixin()
 	batchmsgMixinHooks1 := batchmsgMixin[1].Hooks()
 	batchmsg.Hooks[0] = batchmsgMixinHooks1[0]

+ 47 - 0
ent/schema/agent.go

@@ -0,0 +1,47 @@
+package schema
+
+import (
+	"wechat-api/ent/schema/localmixin"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/entsql"
+	"entgo.io/ent/schema"
+	"entgo.io/ent/schema/field"
+	"github.com/suyuan32/simple-admin-common/orm/ent/mixins"
+)
+
+type Agent struct {
+	ent.Schema
+}
+
+func (Agent) Fields() []ent.Field {
+	return []ent.Field{
+		field.String("name").MaxLen(20).Comment("name | 角色名称"),
+		field.String("role").MaxLen(1000).Comment("role | 角色设定"),
+		field.Int("status").Optional().Default(1).Comment("status | 状态 1-正常 2-禁用"),
+		field.String("background").MaxLen(1000).Comment("background | 背景介绍"),
+		field.String("examples").MaxLen(5000).Comment("examples | 对话案例"),
+	}
+}
+
+func (Agent) Mixin() []ent.Mixin {
+	return []ent.Mixin{
+		mixins.IDMixin{},
+		localmixin.SoftDeleteMixin{},
+	}
+}
+
+func (Agent) Edges() []ent.Edge {
+	return nil
+}
+
+func (Agent) Indexes() []ent.Index {
+	return []ent.Index{}
+}
+
+func (Agent) Annotations() []schema.Annotation {
+	return []schema.Annotation{
+		entsql.WithComments(true),
+		entsql.Annotation{Table: "agent"},
+	}
+}

+ 168 - 0
ent/set_not_nil.go

@@ -8,6 +8,174 @@ import (
 )
 
 // set field if value's pointer is not nil.
+func (a *AgentUpdate) SetNotNilUpdatedAt(value *time.Time) *AgentUpdate {
+	if value != nil {
+		return a.SetUpdatedAt(*value)
+	}
+	return a
+}
+
+// set field if value's pointer is not nil.
+func (a *AgentUpdateOne) SetNotNilUpdatedAt(value *time.Time) *AgentUpdateOne {
+	if value != nil {
+		return a.SetUpdatedAt(*value)
+	}
+	return a
+}
+
+// set field if value's pointer is not nil.
+func (a *AgentCreate) SetNotNilUpdatedAt(value *time.Time) *AgentCreate {
+	if value != nil {
+		return a.SetUpdatedAt(*value)
+	}
+	return a
+}
+
+// set field if value's pointer is not nil.
+func (a *AgentUpdate) SetNotNilDeletedAt(value *time.Time) *AgentUpdate {
+	if value != nil {
+		return a.SetDeletedAt(*value)
+	}
+	return a
+}
+
+// set field if value's pointer is not nil.
+func (a *AgentUpdateOne) SetNotNilDeletedAt(value *time.Time) *AgentUpdateOne {
+	if value != nil {
+		return a.SetDeletedAt(*value)
+	}
+	return a
+}
+
+// set field if value's pointer is not nil.
+func (a *AgentCreate) SetNotNilDeletedAt(value *time.Time) *AgentCreate {
+	if value != nil {
+		return a.SetDeletedAt(*value)
+	}
+	return a
+}
+
+// set field if value's pointer is not nil.
+func (a *AgentUpdate) SetNotNilName(value *string) *AgentUpdate {
+	if value != nil {
+		return a.SetName(*value)
+	}
+	return a
+}
+
+// set field if value's pointer is not nil.
+func (a *AgentUpdateOne) SetNotNilName(value *string) *AgentUpdateOne {
+	if value != nil {
+		return a.SetName(*value)
+	}
+	return a
+}
+
+// set field if value's pointer is not nil.
+func (a *AgentCreate) SetNotNilName(value *string) *AgentCreate {
+	if value != nil {
+		return a.SetName(*value)
+	}
+	return a
+}
+
+// set field if value's pointer is not nil.
+func (a *AgentUpdate) SetNotNilRole(value *string) *AgentUpdate {
+	if value != nil {
+		return a.SetRole(*value)
+	}
+	return a
+}
+
+// set field if value's pointer is not nil.
+func (a *AgentUpdateOne) SetNotNilRole(value *string) *AgentUpdateOne {
+	if value != nil {
+		return a.SetRole(*value)
+	}
+	return a
+}
+
+// set field if value's pointer is not nil.
+func (a *AgentCreate) SetNotNilRole(value *string) *AgentCreate {
+	if value != nil {
+		return a.SetRole(*value)
+	}
+	return a
+}
+
+// set field if value's pointer is not nil.
+func (a *AgentUpdate) SetNotNilStatus(value *int) *AgentUpdate {
+	if value != nil {
+		return a.SetStatus(*value)
+	}
+	return a
+}
+
+// set field if value's pointer is not nil.
+func (a *AgentUpdateOne) SetNotNilStatus(value *int) *AgentUpdateOne {
+	if value != nil {
+		return a.SetStatus(*value)
+	}
+	return a
+}
+
+// set field if value's pointer is not nil.
+func (a *AgentCreate) SetNotNilStatus(value *int) *AgentCreate {
+	if value != nil {
+		return a.SetStatus(*value)
+	}
+	return a
+}
+
+// set field if value's pointer is not nil.
+func (a *AgentUpdate) SetNotNilBackground(value *string) *AgentUpdate {
+	if value != nil {
+		return a.SetBackground(*value)
+	}
+	return a
+}
+
+// set field if value's pointer is not nil.
+func (a *AgentUpdateOne) SetNotNilBackground(value *string) *AgentUpdateOne {
+	if value != nil {
+		return a.SetBackground(*value)
+	}
+	return a
+}
+
+// set field if value's pointer is not nil.
+func (a *AgentCreate) SetNotNilBackground(value *string) *AgentCreate {
+	if value != nil {
+		return a.SetBackground(*value)
+	}
+	return a
+}
+
+// set field if value's pointer is not nil.
+func (a *AgentUpdate) SetNotNilExamples(value *string) *AgentUpdate {
+	if value != nil {
+		return a.SetExamples(*value)
+	}
+	return a
+}
+
+// set field if value's pointer is not nil.
+func (a *AgentUpdateOne) SetNotNilExamples(value *string) *AgentUpdateOne {
+	if value != nil {
+		return a.SetExamples(*value)
+	}
+	return a
+}
+
+// set field if value's pointer is not nil.
+func (a *AgentCreate) SetNotNilExamples(value *string) *AgentCreate {
+	if value != nil {
+		return a.SetExamples(*value)
+	}
+	return a
+}
+
+// set field if value's pointer is not nil.
 func (bm *BatchMsgUpdate) SetNotNilUpdatedAt(value *time.Time) *BatchMsgUpdate {
 	if value != nil {
 		return bm.SetUpdatedAt(*value)

+ 4 - 1
ent/tx.go

@@ -14,6 +14,8 @@ import (
 // Tx is a transactional client that is created by calling Client.Tx().
 type Tx struct {
 	config
+	// Agent is the client for interacting with the Agent builders.
+	Agent *AgentClient
 	// BatchMsg is the client for interacting with the BatchMsg builders.
 	BatchMsg *BatchMsgClient
 	// Contact is the client for interacting with the Contact builders.
@@ -169,6 +171,7 @@ func (tx *Tx) Client() *Client {
 }
 
 func (tx *Tx) init() {
+	tx.Agent = NewAgentClient(tx.config)
 	tx.BatchMsg = NewBatchMsgClient(tx.config)
 	tx.Contact = NewContactClient(tx.config)
 	tx.Label = NewLabelClient(tx.config)
@@ -190,7 +193,7 @@ func (tx *Tx) init() {
 // of them in order to commit or rollback the transaction.
 //
 // If a closed transaction is embedded in one of the generated entities, and the entity
-// applies a query, for example: BatchMsg.QueryXXX(), the query will be executed
+// applies a query, for example: Agent.QueryXXX(), the query will be executed
 // through the driver which created this transaction.
 //
 // Note that txDriver is not goroutine safe.

+ 44 - 0
internal/handler/agent/create_agent_handler.go

@@ -0,0 +1,44 @@
+package agent
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/agent"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /agent/create agent CreateAgent
+//
+// Create agent information | 创建Agent
+//
+// Create agent information | 创建Agent
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: AgentInfo
+//
+// Responses:
+//  200: BaseMsgResp
+
+func CreateAgentHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.AgentInfo
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := agent.NewCreateAgentLogic(r.Context(), svcCtx)
+		resp, err := l.CreateAgent(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/agent/delete_agent_handler.go

@@ -0,0 +1,44 @@
+package agent
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/agent"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /agent/delete agent DeleteAgent
+//
+// Delete agent information | 删除Agent信息
+//
+// Delete agent information | 删除Agent信息
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: IDsReq
+//
+// Responses:
+//  200: BaseMsgResp
+
+func DeleteAgentHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.IDsReq
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := agent.NewDeleteAgentLogic(r.Context(), svcCtx)
+		resp, err := l.DeleteAgent(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/agent/get_agent_by_id_handler.go

@@ -0,0 +1,44 @@
+package agent
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/agent"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /agent agent GetAgentById
+//
+// Get agent by ID | 通过ID获取Agent
+//
+// Get agent by ID | 通过ID获取Agent
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: IDReq
+//
+// Responses:
+//  200: AgentInfoResp
+
+func GetAgentByIdHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.IDReq
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := agent.NewGetAgentByIdLogic(r.Context(), svcCtx)
+		resp, err := l.GetAgentById(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/agent/get_agent_list_handler.go

@@ -0,0 +1,44 @@
+package agent
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/agent"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /agent/list agent GetAgentList
+//
+// Get agent list | 获取Agent列表
+//
+// Get agent list | 获取Agent列表
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: AgentListReq
+//
+// Responses:
+//  200: AgentListResp
+
+func GetAgentListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.AgentListReq
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := agent.NewGetAgentListLogic(r.Context(), svcCtx)
+		resp, err := l.GetAgentList(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/agent/update_agent_handler.go

@@ -0,0 +1,44 @@
+package agent
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/agent"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /agent/update agent UpdateAgent
+//
+// Update agent information | 更新Agent
+//
+// Update agent information | 更新Agent
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: AgentInfo
+//
+// Responses:
+//  200: BaseMsgResp
+
+func UpdateAgentHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.AgentInfo
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := agent.NewUpdateAgentLogic(r.Context(), svcCtx)
+		resp, err := l.UpdateAgent(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 35 - 0
internal/handler/routes.go

@@ -9,6 +9,7 @@ import (
 	WechatServer "wechat-api/internal/handler/WechatServer"
 	Wx "wechat-api/internal/handler/Wx"
 	Wxhook "wechat-api/internal/handler/Wxhook"
+	agent "wechat-api/internal/handler/agent"
 	base "wechat-api/internal/handler/base"
 	batch_msg "wechat-api/internal/handler/batch_msg"
 	contact "wechat-api/internal/handler/contact"
@@ -537,4 +538,38 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 		),
 		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
 	)
+
+	server.AddRoutes(
+		rest.WithMiddlewares(
+			[]rest.Middleware{serverCtx.Authority},
+			[]rest.Route{
+				{
+					Method:  http.MethodPost,
+					Path:    "/agent/create",
+					Handler: agent.CreateAgentHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/agent/update",
+					Handler: agent.UpdateAgentHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/agent/delete",
+					Handler: agent.DeleteAgentHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/agent/list",
+					Handler: agent.GetAgentListHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/agent",
+					Handler: agent.GetAgentByIdHandler(serverCtx),
+				},
+			}...,
+		),
+		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
+	)
 }

+ 57 - 0
internal/logic/agent/create_agent_logic.go

@@ -0,0 +1,57 @@
+package agent
+
+import (
+	"context"
+	"errors"
+	"wechat-api/ent/agent"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type CreateAgentLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewCreateAgentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateAgentLogic {
+	return &CreateAgentLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *CreateAgentLogic) CreateAgent(req *types.AgentInfo) (*types.BaseMsgResp, error) {
+	item, err := l.svcCtx.DB.Agent.Query().Where(agent.Name(*req.Name)).First(l.ctx)
+
+	if err != nil {
+		l.Error("DB查询失败")
+		return nil, err
+	}
+
+	if item != nil && item.ID > 0 {
+		l.Error("角色名字已经存在")
+		return nil, errors.New("角色名字已经存在")
+	}
+
+	_, err = l.svcCtx.DB.Agent.Create().
+		SetNotNilName(req.Name).
+		SetNotNilRole(req.Role).
+		//SetNotNilStatus(req.Status).
+		SetNotNilBackground(req.Background).
+		SetNotNilExamples(req.Examples).
+		Save(l.ctx)
+
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	return &types.BaseMsgResp{Msg: errormsg.CreateSuccess}, nil
+}

+ 42 - 0
internal/logic/agent/delete_agent_logic.go

@@ -0,0 +1,42 @@
+package agent
+
+import (
+	"context"
+	"errors"
+
+	"wechat-api/ent/agent"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type DeleteAgentLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewDeleteAgentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteAgentLogic {
+	return &DeleteAgentLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *DeleteAgentLogic) DeleteAgent(req *types.IDsReq) (*types.BaseMsgResp, error) {
+	if len(req.Ids) == 0 {
+		return nil, errors.New("ids参数不能为空")
+	}
+
+	_, err := l.svcCtx.DB.Agent.Delete().Where(agent.IDIn(req.Ids...)).Exec(l.ctx)
+
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	return &types.BaseMsgResp{Msg: errormsg.DeleteSuccess}, nil
+}

+ 55 - 0
internal/logic/agent/get_agent_by_id_logic.go

@@ -0,0 +1,55 @@
+package agent
+
+import (
+	"context"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+	"wechat-api/internal/utils/dberrorhandler"
+
+    "github.com/suyuan32/simple-admin-common/msg/errormsg"
+
+	"github.com/suyuan32/simple-admin-common/utils/pointy"
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetAgentByIdLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewGetAgentByIdLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentByIdLogic {
+	return &GetAgentByIdLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *GetAgentByIdLogic) GetAgentById(req *types.IDReq) (*types.AgentInfoResp, error) {
+	data, err := l.svcCtx.DB.Agent.Get(l.ctx, req.Id)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	return &types.AgentInfoResp{
+	    BaseDataInfo: types.BaseDataInfo{
+            Code: 0,
+            Msg:  errormsg.Success,
+        },
+        Data: types.AgentInfo{
+            BaseIDInfo:    types.BaseIDInfo{
+				Id:          &data.ID,
+				CreatedAt:    pointy.GetPointer(data.CreatedAt.UnixMilli()),
+				UpdatedAt:    pointy.GetPointer(data.UpdatedAt.UnixMilli()),
+            },
+			Name:	&data.Name,
+			Role:	&data.Role,
+			Status:	&data.Status,
+			Background:	&data.Background,
+			Examples:	&data.Examples,
+        },
+	}, nil
+}
+

+ 70 - 0
internal/logic/agent/get_agent_list_logic.go

@@ -0,0 +1,70 @@
+package agent
+
+import (
+	"context"
+
+	"wechat-api/ent/agent"
+	"wechat-api/ent/predicate"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+	"wechat-api/internal/utils/dberrorhandler"
+
+    "github.com/suyuan32/simple-admin-common/msg/errormsg"
+
+	"github.com/suyuan32/simple-admin-common/utils/pointy"
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetAgentListLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewGetAgentListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentListLogic {
+	return &GetAgentListLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *GetAgentListLogic) GetAgentList(req *types.AgentListReq) (*types.AgentListResp, error) {
+	var predicates []predicate.Agent
+	if req.Name != nil {
+		predicates = append(predicates, agent.NameContains(*req.Name))
+	}
+	if req.Role != nil {
+		predicates = append(predicates, agent.RoleContains(*req.Role))
+	}
+	if req.Background != nil {
+		predicates = append(predicates, agent.BackgroundContains(*req.Background))
+	}
+	data, err := l.svcCtx.DB.Agent.Query().Where(predicates...).Page(l.ctx, req.Page, req.PageSize)
+
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	resp := &types.AgentListResp{}
+	resp.Msg = errormsg.Success
+	resp.Data.Total = data.PageDetails.Total
+
+	for _, v := range data.List {
+		resp.Data.Data = append(resp.Data.Data,
+		types.AgentInfo{
+			BaseIDInfo:    types.BaseIDInfo{
+				Id:          &v.ID,
+				CreatedAt:    pointy.GetPointer(v.CreatedAt.UnixMilli()),
+				UpdatedAt:    pointy.GetPointer(v.UpdatedAt.UnixMilli()),
+            },
+			Name:	&v.Name,
+			Role:	&v.Role,
+			Status:	&v.Status,
+			Background:	&v.Background,
+			Examples:	&v.Examples,
+		})
+	}
+
+	return resp, nil
+}

+ 53 - 0
internal/logic/agent/update_agent_logic.go

@@ -0,0 +1,53 @@
+package agent
+
+import (
+	"context"
+	"errors"
+	"wechat-api/ent/agent"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type UpdateAgentLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewUpdateAgentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateAgentLogic {
+	return &UpdateAgentLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *UpdateAgentLogic) UpdateAgent(req *types.AgentInfo) (*types.BaseMsgResp, error) {
+	item, err := l.svcCtx.DB.Agent.Query().Where(agent.Name(*req.Name)).Where(agent.IDNEQ(*req.Id)).First(l.ctx)
+	if err != nil {
+		l.Error("DB查询失败")
+		return nil, err
+	}
+	if item != nil && item.ID > 0 {
+		return nil, errors.New("已有相同名字的角色")
+	}
+
+	err = l.svcCtx.DB.Agent.UpdateOneID(*req.Id).
+		SetNotNilName(req.Name).
+		SetNotNilRole(req.Role).
+		SetNotNilStatus(req.Status).
+		SetNotNilBackground(req.Background).
+		SetNotNilExamples(req.Examples).
+		Exec(l.ctx)
+
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	return &types.BaseMsgResp{Msg: errormsg.UpdateSuccess}, nil
+}

+ 62 - 0
internal/logic/base/init_api_data.go

@@ -6,6 +6,68 @@ import (
 )
 
 func (l *InitDatabaseLogic) insertApiData() (err error) {
+	// Agent
+
+	_, err = l.svcCtx.CoreRpc.CreateApi(l.ctx, &core.ApiInfo{
+		ServiceName: pointy.GetPointer("Wechat"),
+		Path:        pointy.GetPointer("/agent/create"),
+		Description: pointy.GetPointer("apiDesc.createAgent"),
+		ApiGroup:    pointy.GetPointer("agent"),
+		Method:      pointy.GetPointer("POST"),
+	})
+
+	if err != nil {
+		return err
+	}
+
+	_, err = l.svcCtx.CoreRpc.CreateApi(l.ctx, &core.ApiInfo{
+		ServiceName: pointy.GetPointer("Wechat"),
+		Path:        pointy.GetPointer("/agent/update"),
+		Description: pointy.GetPointer("apiDesc.updateAgent"),
+		ApiGroup:    pointy.GetPointer("agent"),
+		Method:      pointy.GetPointer("POST"),
+	})
+
+	if err != nil {
+		return err
+	}
+
+	_, err = l.svcCtx.CoreRpc.CreateApi(l.ctx, &core.ApiInfo{
+		ServiceName: pointy.GetPointer("Wechat"),
+		Path:        pointy.GetPointer("/agent/delete"),
+		Description: pointy.GetPointer("apiDesc.deleteAgent"),
+		ApiGroup:    pointy.GetPointer("agent"),
+		Method:      pointy.GetPointer("POST"),
+	})
+
+	if err != nil {
+		return err
+	}
+
+	_, err = l.svcCtx.CoreRpc.CreateApi(l.ctx, &core.ApiInfo{
+		ServiceName: pointy.GetPointer("Wechat"),
+		Path:        pointy.GetPointer("/agent/list"),
+		Description: pointy.GetPointer("apiDesc.getAgentList"),
+		ApiGroup:    pointy.GetPointer("agent"),
+		Method:      pointy.GetPointer("POST"),
+	})
+
+	if err != nil {
+		return err
+	}
+
+	_, err = l.svcCtx.CoreRpc.CreateApi(l.ctx, &core.ApiInfo{
+		ServiceName: pointy.GetPointer("Wechat"),
+		Path:        pointy.GetPointer("/agent"),
+		Description: pointy.GetPointer("apiDesc.getAgentById"),
+		ApiGroup:    pointy.GetPointer("agent"),
+		Method:      pointy.GetPointer("POST"),
+	})
+
+	if err != nil {
+		return err
+	}
+
 	// BatchMsg
 
 	_, err = l.svcCtx.CoreRpc.CreateApi(l.ctx, &core.ApiInfo{

+ 52 - 0
internal/types/types.go

@@ -1128,3 +1128,55 @@ type BatchMsgInfoResp struct {
 	// BatchMsg information | BatchMsg数据
 	Data BatchMsgInfo `json:"data"`
 }
+
+// The data of agent information | Agent信息
+// swagger:model AgentInfo
+type AgentInfo struct {
+	BaseIDInfo
+	// name | 角色名称
+	Name *string `json:"name,optional"`
+	// role | 角色设定
+	Role *string `json:"role,optional"`
+	// status | 状态 1-正常 2-禁用
+	Status *int `json:"status,optional"`
+	// background | 背景介绍
+	Background *string `json:"background,optional"`
+	// examples | 对话案例
+	Examples *string `json:"examples,optional"`
+}
+
+// The response data of agent list | Agent列表数据
+// swagger:model AgentListResp
+type AgentListResp struct {
+	BaseDataInfo
+	// Agent list data | Agent列表数据
+	Data AgentListInfo `json:"data"`
+}
+
+// Agent list data | Agent列表数据
+// swagger:model AgentListInfo
+type AgentListInfo struct {
+	BaseListInfo
+	// The API list data | Agent列表数据
+	Data []AgentInfo `json:"data"`
+}
+
+// Get agent list request params | Agent列表请求参数
+// swagger:model AgentListReq
+type AgentListReq struct {
+	PageInfo
+	// name | 角色名称
+	Name *string `json:"name,optional"`
+	// role | 角色设定
+	Role *string `json:"role,optional"`
+	// background | 背景介绍
+	Background *string `json:"background,optional"`
+}
+
+// Agent information response | Agent信息返回体
+// swagger:model AgentInfoResp
+type AgentInfoResp struct {
+	BaseDataInfo
+	// Agent information | Agent数据
+	Data AgentInfo `json:"data"`
+}