Files
smartmate/backend/services/agent/sv/memory_rpc_reader.go
Losita 2a96f4c6f9 Version: 0.9.76.dev.260505
后端:
1.阶段 6 agent / memory 服务化收口
- 新增 cmd/agent 独立进程入口,承载 agent zrpc server、agent outbox relay / consumer 和运行时依赖初始化
- 补齐 services/agent/rpc 的 Chat stream 与 conversation meta/list/timeline、schedule-preview、context-stats、schedule-state unary RPC
- 新增 gateway/client/agent 与 shared/contracts/agent,将 /api/v1/agent chat 和非 chat 门面切到 agent zrpc
- 收缩 gateway 本地 AgentService 装配,双 RPC 开关开启时不再初始化本地 agent 编排、LLM、RAG 和 memory reader fallback
- 将 backend/memory 物理迁入 services/memory,私有实现收入 internal,保留 module/model/observe 作为 memory 服务门面
- 调整 memory outbox、memory reader 和 agent 记忆渲染链路的 import 与服务边界,cmd/memory 独占 memory worker / consumer
- 关闭 gateway 侧 agent outbox worker 所有权,agent relay / consumer 由 cmd/agent 独占,gateway 仅保留 HTTP/SSE 门面与迁移期开关回退
- 更新阶段 6 文档,记录 agent / memory 当前切流点、smoke 结果,以及 backend/client 与 gateway/shared 的目录收口口径
2026-05-05 19:31:39 +08:00

122 lines
4.0 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"
"errors"
memorymodel "github.com/LoveLosita/smartflow/backend/services/memory/model"
memoryobserve "github.com/LoveLosita/smartflow/backend/services/memory/observe"
memorycontracts "github.com/LoveLosita/smartflow/backend/shared/contracts/memory"
)
// MemoryRPCReaderClient 描述 agent 读取 memory zrpc 所需的最小能力。
//
// 职责边界:
// 1. 只读取候选记忆,不暴露管理写接口;
// 2. 不要求调用方知道 gateway/client/memory 的具体实现;
// 3. 错误原样返回给预取链路,由 agent 侧负责软降级和观测记录。
type MemoryRPCReaderClient interface {
Retrieve(ctx context.Context, req memorycontracts.RetrieveRequest) ([]memorycontracts.ItemDTO, error)
}
type memoryRPCReader struct {
client MemoryRPCReaderClient
observer memoryobserve.Observer
metrics memoryobserve.MetricsRecorder
}
// NewMemoryRPCReader 创建跨进程 memory reader 适配器。
//
// 职责边界:
// 1. 只把 agent 内部的 memorymodel.RetrieveRequest 转成共享契约;
// 2. 不持有 memory.Module避免 CP3 后 agent 主链路继续直连本进程记忆服务;
// 3. observer / metrics 只用于 agent 注入观测,不参与 retrieve 业务调用;
// 4. client 为空时返回 nil让 SetMemoryReader 保持既有“无 reader 则不注入”的降级语义。
func NewMemoryRPCReader(
client MemoryRPCReaderClient,
observer memoryobserve.Observer,
metrics memoryobserve.MetricsRecorder,
) MemoryReader {
if client == nil {
return nil
}
if observer == nil {
observer = memoryobserve.NewNopObserver()
}
if metrics == nil {
metrics = memoryobserve.NewNopMetrics()
}
return &memoryRPCReader{
client: client,
observer: observer,
metrics: metrics,
}
}
// Retrieve 通过 memory zrpc 读取候选记忆并转换回 agent 内部 DTO。
func (r *memoryRPCReader) Retrieve(ctx context.Context, req memorymodel.RetrieveRequest) ([]memorymodel.ItemDTO, error) {
if r == nil || r.client == nil {
return nil, errors.New("memory rpc reader client is nil")
}
items, err := r.client.Retrieve(ctx, memorycontracts.RetrieveRequest{
Query: req.Query,
UserID: req.UserID,
ConversationID: req.ConversationID,
AssistantID: req.AssistantID,
RunID: req.RunID,
MemoryTypes: append([]string(nil), req.MemoryTypes...),
Limit: req.Limit,
Now: req.Now,
})
if err != nil {
return nil, err
}
return toMemoryModelItems(items), nil
}
// MemoryObserver 暴露 agent 注入链路使用的 observer保持 CP3 切流前后的注入观测连续。
func (r *memoryRPCReader) MemoryObserver() memoryobserve.Observer {
if r == nil || r.observer == nil {
return memoryobserve.NewNopObserver()
}
return r.observer
}
// MemoryMetrics 暴露 agent 注入链路使用的 metrics避免 RPC reader 切流后指标静默丢失。
func (r *memoryRPCReader) MemoryMetrics() memoryobserve.MetricsRecorder {
if r == nil || r.metrics == nil {
return memoryobserve.NewNopMetrics()
}
return r.metrics
}
// toMemoryModelItems 只做跨层 DTO 字段搬运,不改变排序、过滤和记忆内容。
func toMemoryModelItems(items []memorycontracts.ItemDTO) []memorymodel.ItemDTO {
if len(items) == 0 {
return nil
}
result := make([]memorymodel.ItemDTO, 0, len(items))
for _, item := range items {
result = append(result, memorymodel.ItemDTO{
ID: item.ID,
UserID: item.UserID,
ConversationID: item.ConversationID,
AssistantID: item.AssistantID,
RunID: item.RunID,
MemoryType: item.MemoryType,
Title: item.Title,
Content: item.Content,
ContentHash: item.ContentHash,
Confidence: item.Confidence,
Importance: item.Importance,
SensitivityLevel: item.SensitivityLevel,
IsExplicit: item.IsExplicit,
Status: item.Status,
TTLAt: item.TTLAt,
CreatedAt: item.CreatedAt,
UpdatedAt: item.UpdatedAt,
})
}
return result
}