Files
smartmate/backend/services/agent/sv/task_class_rpc_adapter.go
Losita d7184b776b Version: 0.9.75.dev.260505
后端:
1.收口阶段 6 agent 结构迁移,将 newAgent 内核与 agentsvc 编排层迁入 services/agent
- 切换 Agent 启动装配与 HTTP handler 直连 agent sv,移除旧 service agent bridge
- 补齐 Agent 对 memory、task、task-class、schedule 的 RPC 适配与契约字段
- 扩展 schedule、task、task-class RPC/contract 支撑 Agent 查询、写入与 provider 切流
- 更新迁移文档、README 与相关注释,明确 agent 当前切流点和剩余 memory 迁移面
2026-05-05 16:00:57 +08:00

122 lines
4.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package sv
import (
"context"
"encoding/json"
"errors"
"strings"
"time"
"github.com/LoveLosita/smartflow/backend/model"
agenttools "github.com/LoveLosita/smartflow/backend/services/agent/tools"
taskclasscontracts "github.com/LoveLosita/smartflow/backend/shared/contracts/taskclass"
)
const taskClassUpsertRPCTimeout = 6 * time.Second
// TaskClassUpsertRPCClient 描述 agent 写入任务类时依赖的 task-class RPC 最小能力。
//
// 职责边界:
// 1. 只覆盖 upsert_task_class 工具需要的新增/更新能力;
// 2. 不暴露 task-class DAO、事务细节或 schedule 迁移期直写语义;
// 3. 读取型能力由 schedule provider 的独立接口承载,避免接口膨胀。
type TaskClassUpsertRPCClient interface {
AddTaskClass(ctx context.Context, req taskclasscontracts.UpsertTaskClassRequest) (json.RawMessage, error)
UpdateTaskClass(ctx context.Context, req taskclasscontracts.UpsertTaskClassRequest) (json.RawMessage, error)
}
type taskClassRPCUpsertAdapter struct {
client TaskClassUpsertRPCClient
}
// NewTaskClassRPCUpsertFunc 把 task-class zrpc client 适配成 agent 工具写入函数。
//
// 职责边界:
// 1. 只替换 agent upsert_task_class 的 DAO 直连路径;
// 2. 入参仍复用 agent 工具层已标准化的 UserAddTaskClassRequest
// 3. client 为空时返回会失败的闭包,让工具层保留既有错误包装语义。
func NewTaskClassRPCUpsertFunc(client TaskClassUpsertRPCClient) func(userID int, input agenttools.TaskClassUpsertInput) (agenttools.TaskClassUpsertPersistResult, error) {
adapter := &taskClassRPCUpsertAdapter{client: client}
return adapter.UpsertTaskClass
}
// UpsertTaskClass 通过 task-class zrpc 新增或更新任务类,并返回稳定 task_class_id。
func (a *taskClassRPCUpsertAdapter) UpsertTaskClass(userID int, input agenttools.TaskClassUpsertInput) (agenttools.TaskClassUpsertPersistResult, error) {
if a == nil || a.client == nil {
return agenttools.TaskClassUpsertPersistResult{}, errors.New("task-class rpc client is nil")
}
req := taskClassUpsertInputToContract(userID, input)
ctx, cancel := context.WithTimeout(context.Background(), taskClassUpsertRPCTimeout)
defer cancel()
var raw json.RawMessage
var err error
created := input.ID == 0
// 调用目的:把 agent 工具产出的任务类写入 task-class 服务,避免 agent 继续直连 task_classes/task_items。
if created {
raw, err = a.client.AddTaskClass(ctx, req)
} else {
raw, err = a.client.UpdateTaskClass(ctx, req)
}
if err != nil {
return agenttools.TaskClassUpsertPersistResult{}, err
}
var resp taskclasscontracts.UpsertTaskClassResponse
if err := json.Unmarshal(raw, &resp); err != nil {
return agenttools.TaskClassUpsertPersistResult{}, err
}
if resp.TaskClassID <= 0 {
return agenttools.TaskClassUpsertPersistResult{}, errors.New("task-class rpc upsert returned invalid task_class_id")
}
return agenttools.TaskClassUpsertPersistResult{
TaskClassID: resp.TaskClassID,
Created: resp.Created,
}, nil
}
func taskClassUpsertInputToContract(userID int, input agenttools.TaskClassUpsertInput) taskclasscontracts.UpsertTaskClassRequest {
req := input.Request
items := make([]taskclasscontracts.UpsertTaskClassItemConfig, 0, len(req.Items))
for _, item := range req.Items {
items = append(items, taskclasscontracts.UpsertTaskClassItemConfig{
ID: item.ID,
Order: item.Order,
Content: strings.TrimSpace(item.Content),
EmbeddedTime: toTaskClassContractTargetTime(item.EmbeddedTime),
})
}
return taskclasscontracts.UpsertTaskClassRequest{
UserID: userID,
TaskClassID: input.ID,
Name: strings.TrimSpace(req.Name),
StartDate: strings.TrimSpace(req.StartDate),
EndDate: strings.TrimSpace(req.EndDate),
Mode: strings.TrimSpace(req.Mode),
SubjectType: strings.TrimSpace(req.SubjectType),
DifficultyLevel: strings.TrimSpace(req.DifficultyLevel),
CognitiveIntensity: strings.TrimSpace(req.CognitiveIntensity),
Config: taskclasscontracts.UpsertTaskClassConfig{
TotalSlots: req.Config.TotalSlots,
AllowFillerCourse: req.Config.AllowFillerCourse,
Strategy: strings.TrimSpace(req.Config.Strategy),
ExcludedSlots: append([]int(nil), req.Config.ExcludedSlots...),
ExcludedDaysOfWeek: append([]int(nil), req.Config.ExcludedDaysOfWeek...),
},
Items: items,
}
}
func toTaskClassContractTargetTime(value *model.TargetTime) *taskclasscontracts.TargetTime {
if value == nil {
return nil
}
return &taskclasscontracts.TargetTime{
Week: value.Week,
DayOfWeek: value.DayOfWeek,
SectionFrom: value.SectionFrom,
SectionTo: value.SectionTo,
}
}