agent

package
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 31, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package agent 定义 AI Agent 调用的统一抽象层。

它屏蔽了具体第三方 Agent(Claude Code / Codex / Copilot)与后续自研 Agent 的差异, 向上层业务(AISummaryWorker、LLMHandler 等)统一暴露两种调用语义:

  • Invoke:一次性任务调用,同步等待最终结果。适合 AI 摘要、后台任务等场景。
  • Stream:流式调用,通过 Runtime.Emit 逐块输出事件。适合前端聊天等场景。

除“调用”本身外,本包还实现了 design.md 中描述的“执行架构”:

  • Agent:执行层,负责产生文本 / 推理 / 工具调用等事件,并在需要时请求权限。
  • Runtime:Agent 执行期的运行时环境(Emit / RequestPermission / WaitPermission)。
  • Operation / PermissionPolicy:描述“要做什么”以及“能不能做”。
  • PermissionManager / PermissionRequest:持久化的权限请求与批准 / 拒绝。
  • Task / TaskManager(AgentService):任务状态机与编排。
  • EventBus / AgentEvent:实时通知层(带 sequence,可恢复)。
  • Repository:持久化抽象(默认提供内存实现,后续可替换为 DB)。

各 Provider 通过 Registry 注册,运行时按名称解析;Client 是统一门面,负责 解析请求应使用的 Provider 并转发 Invoke / Stream。

Package agent 中的 memory 层:Agent 的「长期记忆」子系统。

与 conversation.go 中的「短期上下文」(单次会话的多轮历史)不同,memory 负责跨轮次、 跨会话、跨任务的持久化记忆,例如用户偏好、已确认的事实、任务摘要等。它遵循与权限 子系统一致的架构原则:Repository 是状态源,Manager 负责编排,检索 / 提取可插拔。

Index

Constants

View Source
const (
	ProviderMock       = "mock"        // 自研 mock,用于保证链路可跑通
	ProviderClaudeCode = "claude_code" // Anthropic Claude Code CLI
	ProviderCodex      = "codex"       // OpenAI Codex CLI
	ProviderCopilot    = "copilot"     // GitHub Copilot CLI
	ProviderCustom     = "custom"      // 预留:后续自研 Agent
)

Provider 名称常量。新增第三方 Agent 或自研 Agent 时在此登记一个唯一名称。

View Source
const (
	RoleSystem    = "system"
	RoleUser      = "user"
	RoleAssistant = "assistant"
	RoleTool      = "tool"
)

MessageRole 常量。

View Source
const (
	DefaultProfileName   = "default"        // 系统默认 Profile
	ProfileAnalysisCoder = "analysis_coder" // 撰写分析代码
	ProfileArticleWriter = "article_writer" // 撰写科研文章 / 报告
)

内置 AgentProfile 名称常量。新增内置 Profile 时在此登记唯一名称。

View Source
const DefaultProvider = ProviderMock

DefaultProvider 是未配置时的兜底 Provider。

Variables

View Source
var (
	// ErrMemoryNotFound 表示记忆不存在。
	ErrMemoryNotFound = errors.New("agent: memory not found")
	// ErrMemoryNotConfigured 表示 AgentService 未配置记忆管理器。
	ErrMemoryNotConfigured = errors.New("agent: memory manager not configured")
)

记忆相关错误。

View Source
var (
	// ErrPermissionDenied 表示权限请求被拒绝,或策略直接判定为 deny。
	ErrPermissionDenied = errors.New("agent: permission denied")
	// ErrPermissionNotFound 表示权限请求不存在。
	ErrPermissionNotFound = errors.New("agent: permission request not found")
	// ErrPermissionNotPending 表示尝试对非 pending 状态的权限请求做批准 / 拒绝。
	ErrPermissionNotPending = errors.New("agent: permission request is not pending")
	// ErrPermissionExpired 表示等待的权限请求已过期。
	ErrPermissionExpired = errors.New("agent: permission request expired")
	// ErrPermissionCanceled 表示等待的权限请求已取消。
	ErrPermissionCanceled = errors.New("agent: permission request canceled")
	// ErrInvalidPermissionTransition 表示非法的权限状态迁移。
	ErrInvalidPermissionTransition = errors.New("agent: invalid permission state transition")
)

权限相关错误。

View Source
var (
	// ErrProfileNotFound 表示 Profile 不存在。
	ErrProfileNotFound = errors.New("agent: profile not found")
	// ErrProfileNameRequired 表示 Profile 名称缺失。
	ErrProfileNameRequired = errors.New("agent: profile name is required")
)

Profile 相关错误。

View Source
var (
	// ErrTaskNotFound 表示任务不存在。
	ErrTaskNotFound = errors.New("agent: task not found")
	// ErrTaskAlreadyRunning 表示任务已经在执行中。
	ErrTaskAlreadyRunning = errors.New("agent: task already running")
	// ErrInvalidTaskTransition 表示非法的任务状态迁移。
	ErrInvalidTaskTransition = errors.New("agent: invalid task state transition")
)

任务相关错误。

View Source
var (
	// ErrConversationNotFound 表示会话不存在。
	ErrConversationNotFound = errors.New("agent: conversation not found")
)

会话相关错误。

View Source
var ErrNoPermissionResolver = errors.New("agent: no permission resolver in runtime")

ErrNoPermissionResolver 表示当前 Runtime 没有绑定权限解析器(无法等待人工决策)。

View Source
var ErrNotImplemented = errors.New("agent: provider not implemented yet")

ErrNotImplemented 表示某个 Provider 尚未实现真实调用。

Functions

func BuildMemoryContext

func BuildMemoryContext(memories []*Memory) string

BuildMemoryContext 把检索到的记忆格式化为注入上下文的文本块。

用于 AgentService 在调用前把相关记忆注入 SystemPrompt,让 Agent「记得」相关背景。 无记忆时返回空字符串。

Types

type Agent

type Agent interface {
	// Name 返回 Provider 唯一标识。
	Name() string
	// Invoke 执行一次性任务并同步返回最终结果。
	Invoke(ctx context.Context, req Request, rt Runtime) (*Result, error)
	// Stream 执行流式请求,通过 rt.Emit 逐块输出事件,返回最终聚合结果。
	Stream(ctx context.Context, req Request, rt Runtime) (*Result, error)
}

Agent 是统一 Agent 调用接口。 每个 Provider(claude_code / codex / copilot / custom ...)都需要实现该接口。

type AgentEvent

type AgentEvent struct {
	ID        string         `json:"id" gorm:"column:id;primaryKey;type:varchar(64)"`
	TaskID    string         `json:"task_id" gorm:"column:task_id;type:varchar(64);index:idx_agent_events_task_seq,priority:1"`
	Sequence  int64          `json:"sequence" gorm:"column:sequence;index:idx_agent_events_task_seq,priority:2"`
	Type      AgentEventType `json:"type" gorm:"column:type;type:varchar(32)"`
	Payload   any            `json:"payload,omitempty" gorm:"serializer:json"`
	CreatedAt time.Time      `json:"created_at" gorm:"column:created_at"`
}

AgentEvent 是发布到 EventBus 的单个事件,带单调递增的 sequence。

sequence 使事件可被“增量拉取”(如 GET /tasks/{id}/events?after=3), 因此浏览器刷新后无需依赖 WS 历史即可恢复。

func (AgentEvent) TableName

func (AgentEvent) TableName() string

TableName 返回任务事件表的表名。

type AgentEventType

type AgentEventType string

AgentEventType 枚举任务生命周期与实时通知事件。

流式内容事件统一使用 EventStream,具体细分见 StreamEvent.Type; 权限与任务状态变化使用独立类型,便于前端按类型订阅与恢复。

const (
	EventTaskCreated        AgentEventType = "task.created"        // 任务已创建
	EventTaskStarted        AgentEventType = "task.started"        // 任务开始执行
	EventTaskWaiting        AgentEventType = "task.waiting"        // 任务进入等待权限状态
	EventTaskCompleted      AgentEventType = "task.completed"      // 任务完成
	EventTaskFailed         AgentEventType = "task.failed"         // 任务失败
	EventTaskCanceled       AgentEventType = "task.canceled"       // 任务取消
	EventPermissionCreated  AgentEventType = "permission.created"  // 新增待确认权限
	EventPermissionResolved AgentEventType = "permission.resolved" // 权限已被批准 / 拒绝
	EventMemorySaved        AgentEventType = "memory.saved"        // 记忆已保存(Payload 为 Memory)
	EventMemoryDeleted      AgentEventType = "memory.deleted"      // 记忆已删除(Payload 为 Memory)
	EventStream             AgentEventType = "stream"              // 透传的流式事件(Payload 为 StreamEvent)
)

type AgentService

type AgentService struct {
	// contains filtered or unexported fields
}

AgentService 是 Agent 执行架构的编排层(即 design.md 中的 AgentTaskManager)。

它把 Client(Provider 门面)、TaskRepository、PermissionManager、EventRepository、 EventBus 与 PermissionPolicy 组合成一条完整的调用链路:

RunTask 创建任务 → 启动 goroutine 执行 Agent
  → Agent 通过 Runtime.Emit 输出事件(持久化 + 广播)
  → Agent 通过 Runtime.RequestPermission 请求权限(持久化 pending + 任务置为 waiting)
  → UI 调用 ApprovePermission / DenyPermission(更新 DB + 唤醒 Agent)
  → Agent 恢复执行,直至 completed / failed

Recover 用于后端重启后重建运行态。

func NewService

func NewService(cfg ServiceConfig) *AgentService

NewService 创建 AgentService,未提供的依赖使用安全的默认值。

func (*AgentService) ApprovePermission

func (s *AgentService) ApprovePermission(ctx context.Context, id, by string) error

ApprovePermission 批准权限请求(供 UI / HTTP 层调用)。

func (*AgentService) CancelTask

func (s *AgentService) CancelTask(ctx context.Context, taskID string) error

CancelTask 取消任务:取消执行上下文并置为 canceled。

func (*AgentService) CreateTask

func (s *AgentService) CreateTask(ctx context.Context, req Request) (*Task, error)

CreateTask 创建任务(不启动执行)。

供 HTTP 层使用:先拿到 taskID 订阅事件,再调用 StartTask 启动,避免错过 task.created 等早期事件。

func (*AgentService) DeleteMemory

func (s *AgentService) DeleteMemory(ctx context.Context, id string) error

DeleteMemory 删除记忆,并广播记忆事件。

func (*AgentService) DeleteProfile

func (s *AgentService) DeleteProfile(ctx context.Context, userID, id string) error

DeleteProfile 删除用户自定义 Profile(内置 Profile 不可删除)。

func (*AgentService) DenyPermission

func (s *AgentService) DenyPermission(ctx context.Context, id, by string) error

DenyPermission 拒绝权限请求(供 UI / HTTP 层调用)。

func (*AgentService) GetEvents

func (s *AgentService) GetEvents(ctx context.Context, taskID string, after int64) ([]*AgentEvent, error)

GetEvents 增量拉取任务事件(after 为上次收到的最大 sequence)。

func (*AgentService) GetMemory

func (s *AgentService) GetMemory(ctx context.Context, id string) (*Memory, error)

GetMemory 按 ID 查询单条记忆。

func (*AgentService) GetPendingPermissions

func (s *AgentService) GetPendingPermissions(ctx context.Context, taskID string) ([]*PermissionRequest, error)

GetPendingPermissions 查询任务当前待确认的权限请求。

func (*AgentService) GetProfile

func (s *AgentService) GetProfile(ctx context.Context, userID, id string) (*Profile, error)

GetProfile 按 ID 返回当前用户的自定义 Profile(内置 Profile 按 ID 不可取)。

func (*AgentService) GetTask

func (s *AgentService) GetTask(ctx context.Context, id string) (*Task, error)

GetTask 查询任务。

func (*AgentService) ListMemory

func (s *AgentService) ListMemory(ctx context.Context, userID string, offset, limit int, kinds ...MemoryKind) ([]*Memory, int64, error)

ListMemory 分页查询某用户的记忆;kinds 为空表示全部类别。

func (*AgentService) ListProfiles

func (s *AgentService) ListProfiles(ctx context.Context, userID string) ([]*Profile, error)

ListProfiles 返回内置与当前用户自定义的 Profile 列表(合并视图)。

func (*AgentService) PageEvents

func (s *AgentService) PageEvents(ctx context.Context, offset, limit int, taskID string) ([]*AgentEvent, int64, error)

PageEvents 分页查询事件;taskID 为空表示全部任务。

func (*AgentService) PagePermissions

func (s *AgentService) PagePermissions(ctx context.Context, offset, limit int, taskID string, statuses ...PermissionStatus) ([]*PermissionRequest, int64, error)

PagePermissions 分页查询权限请求;taskID 为空表示全部任务,statuses 为空表示全部状态。

func (*AgentService) PageTasks

func (s *AgentService) PageTasks(ctx context.Context, offset, limit int, statuses ...TaskStatus) ([]*Task, int64, error)

PageTasks 分页查询任务(offset/limit 由上层根据 types.Pagination 计算)。

func (*AgentService) ProjectContext

func (s *AgentService) ProjectContext(ctx context.Context, userID string) (string, error)

ProjectContext 返回当前用户激活项目下的上下文文本块(例如已完成的分析节点)。

未配置项目上下文提供者或用户为空时返回空串;查询失败时返回错误。 供 HTTP 层直接向用户展示注入 Agent 系统提示词的项目背景。

func (*AgentService) Recover

func (s *AgentService) Recover(ctx context.Context) error

Recover 在后端重启后重建运行态(见 design.md 第 6 / 19 节)。

当前内存实现下:

  • 没有活跃 goroutine 的 running 任务:无法恢复执行,标记为 failed(interrupted)。
  • 没有活跃 goroutine 的 waiting_permission 任务:pending 权限已持久化, UI 仍可通过 GetPendingPermissions 拉取并批准 / 拒绝(更新 DB); 但 Agent 进程已丢失,真正“恢复执行”依赖各 Provider 的 checkpoint / resume 能力。

func (*AgentService) RetrieveMemory

func (s *AgentService) RetrieveMemory(ctx context.Context, userID, query string, limit int) ([]*Memory, error)

RetrieveMemory 检索与 query 相关的记忆。

func (*AgentService) RunTask

func (s *AgentService) RunTask(ctx context.Context, req Request, handler StreamHandler) (*Task, error)

RunTask 创建任务并异步执行(流式语义)。

执行与调用方 ctx 解耦:任务在独立 goroutine 中运行,可跨多次 HTTP 请求存活, 通过权限确认 / 取消 / 恢复驱动其生命周期。返回的任务对象用于前端轮询 / 订阅。

func (*AgentService) RunTaskSync

func (s *AgentService) RunTaskSync(ctx context.Context, req Request) (*Result, error)

RunTaskSync 同步执行一次性任务:创建 → 运行 → 返回聚合结果。

供需要一次性拿到结果的业务(如 AISummaryWorker)使用,替代直接调用 agent.Client.Invoke。 与 RunTask / StartTask 不同,它不启动 goroutine,直接在调用方同步执行。

func (*AgentService) SaveMemory

func (s *AgentService) SaveMemory(ctx context.Context, memory *Memory) error

SaveMemory 创建或更新一条记忆,并广播记忆事件(实时通知层)。

func (*AgentService) SaveProfile

func (s *AgentService) SaveProfile(ctx context.Context, profile *Profile) error

SaveProfile 创建或更新用户自定义 Profile。

func (*AgentService) StartTask

func (s *AgentService) StartTask(ctx context.Context, taskID string, handler StreamHandler) error

StartTask 启动已创建任务的异步执行。

func (*AgentService) Subscribe

func (s *AgentService) Subscribe(taskID string, handler EventHandler) func()

Subscribe 订阅任务事件(taskID 为空表示订阅全部任务),返回取消订阅函数。 供 WS / SSE 实时推送层使用;刷新恢复历史请使用 GetEvents。

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client 是 Agent 调用的统一门面(Facade)。

上层业务(AISummaryWorker、LLMHandler 等)只依赖 Client,不直接感知具体 Provider。 Client 负责:按请求中的 Provider(或默认 Provider)解析 Agent 实例,并转发 Invoke / Stream。

func NewClient

func NewClient(registry *Registry, defaultProvider string, opts Options) *Client

NewClient 创建 Client。 defaultProvider 为空时使用 DefaultProvider(mock)。

func (*Client) InvokeRuntime

func (c *Client) InvokeRuntime(ctx context.Context, req Request, rt Runtime) (*Result, error)

InvokeRuntime 使用调用方提供的 Runtime 执行一次性任务(供 AgentService 任务模式使用)。

func (*Client) SetDefault

func (c *Client) SetDefault(provider string, opts Options)

SetDefault 动态切换默认 Provider 与默认 Options(用于后续运行时切换能力)。

func (*Client) Stream

func (c *Client) Stream(ctx context.Context, req Request, handler StreamHandler) (*Result, error)

Stream 执行流式请求:解析 Provider → Agent.Stream。 内部使用 standalone Runtime,其 Emit 直接把事件交给 handler。

func (*Client) StreamRuntime

func (c *Client) StreamRuntime(ctx context.Context, req Request, rt Runtime) (*Result, error)

StreamRuntime 使用调用方提供的 Runtime 执行流式请求(供 AgentService 任务模式使用)。

type ContextConfig

type ContextConfig struct {
	InjectMemory  bool `json:"inject_memory"`
	InjectProject bool `json:"inject_project"`
}

ContextConfig 控制 AgentService 在调用前注入哪些背景。

  • InjectMemory:检索长期记忆并拼进 SystemPrompt;
  • InjectProject:把当前项目已完成的分析节点等背景拼进 SystemPrompt。 (只有撰写文章 / 报告一类的任务才需要项目背景,因此默认关闭。)

type Conversation

type Conversation struct {
	ID       string `json:"id" gorm:"column:id;primaryKey;type:varchar(64)"`
	UserID   string `json:"user_id" gorm:"column:user_id;type:varchar(64);index"`
	Provider string `json:"provider" gorm:"column:provider;type:varchar(64)"`
	Model    string `json:"model" gorm:"column:model;type:varchar(128)"`
	// Messages 保存完整历史(system 提示词之外的 user/assistant 消息)。
	// 关系由 Repository 自行维护(独立表 agent_conversation_messages),
	// 不使用 GORM 的 HasMany 关联,因此标记为 gorm:"-"。
	Messages []Message `json:"messages" gorm:"-"`
	// CurrentTaskID 记录当前活跃轮次(running / waiting_permission)的任务 ID;
	// 轮次结束时置空。供前端刷新 / 切换会话时恢复实时流。
	CurrentTaskID string    `json:"current_task_id,omitempty" gorm:"column:current_task_id;type:varchar(64)"`
	CreatedAt     time.Time `json:"created_at" gorm:"column:created_at"`
	UpdatedAt     time.Time `json:"updated_at" gorm:"column:updated_at"`
}

Conversation 是一次多轮对话的持久化对象。

Messages 保存完整历史(system 提示词之外的 user/assistant 消息), 每一轮执行前把历史拼进 Request.Messages,执行结束后把 assistant 回复写回历史。

func NewConversation

func NewConversation(userID, provider, model string) *Conversation

NewConversation 创建一个空的会话。

func (Conversation) TableName

func (Conversation) TableName() string

TableName 返回会话表的表名。

type ConversationMessage

type ConversationMessage struct {
	ID             string    `json:"id" gorm:"column:id;primaryKey;type:varchar(64)"`
	ConversationID string    `json:"conversation_id" gorm:"column:conversation_id;type:varchar(64);index"`
	Seq            int       `json:"seq" gorm:"column:seq;index"`
	Role           string    `json:"role" gorm:"column:role;type:varchar(32)"`
	Content        string    `json:"content" gorm:"column:content;type:text"`
	CreatedAt      time.Time `json:"created_at" gorm:"column:created_at"`
}

ConversationMessage 是会话中的一条消息,以独立表持久化。

与 Conversation 的关系(ConversationID 外键)由 Repository 自行维护, 不使用 GORM 的 HasMany / Preload 关联机制。

func (ConversationMessage) TableName

func (ConversationMessage) TableName() string

TableName 返回会话消息表的表名。

type ConversationRepository

type ConversationRepository interface {
	Get(ctx context.Context, id string) (*Conversation, error)
	Create(ctx context.Context, conv *Conversation) error
	Update(ctx context.Context, conv *Conversation) error
	// Page 分页查询会话(按 UpdatedAt 降序);userID 为空表示全部用户。
	Page(ctx context.Context, userID string, offset, limit int) ([]*Conversation, int64, error)
}

ConversationRepository 持久化会话。

与 TaskRepository 一致:当前提供内存实现保证链路可跑通,后续可替换为 DB 实现。

func NewGormConversationRepository

func NewGormConversationRepository(db *gorm.DB) ConversationRepository

NewGormConversationRepository 创建基于数据库的会话 Repository。

会话与其消息(agent_conversation_messages 表)的关系由本实现自行维护, 不使用 GORM 的 HasMany 关联。

func NewMemoryConversationRepository

func NewMemoryConversationRepository() ConversationRepository

NewMemoryConversationRepository 创建会话的内存实现。

type ConversationService

type ConversationService struct {
	// contains filtered or unexported fields
}

ConversationService 编排多轮对话:负责历史拼接 + 复用 AgentService 执行每一轮。

func NewConversationService

func NewConversationService(agent *AgentService, repo ConversationRepository) *ConversationService

NewConversationService 创建 ConversationService;repo 为空时使用内存实现。

func (*ConversationService) CreateTurn

func (s *ConversationService) CreateTurn(ctx context.Context, in TurnInput) (*Task, *Conversation, error)

CreateTurn 准备一轮执行(不启动):

  1. 取得会话级锁(保证同一会话轮次串行);
  2. 加载 / 创建会话,追加 user 消息并持久化;
  3. 用完整历史组装 Request(SessionID = 会话 ID),交给 AgentService.CreateTask;
  4. 登记本轮中间态,返回 task 供上层(handler)在启动前订阅 WS。

锁在本轮结束时由 finishTurn 释放。

func (*ConversationService) GetConversation

func (s *ConversationService) GetConversation(ctx context.Context, id string) (*Conversation, error)

GetConversation 查询会话(含完整历史消息)。

func (*ConversationService) PageConversations

func (s *ConversationService) PageConversations(ctx context.Context, userID string, offset, limit int) ([]*Conversation, int64, error)

PageConversations 分页查询会话;userID 为空表示全部用户。

func (*ConversationService) StartTurn

func (s *ConversationService) StartTurn(ctx context.Context, taskID string) error

StartTurn 启动本轮执行,并注册捕获回调:累积 assistant 文本,在本轮终态时 写回历史并释放会话锁。

type EventBus

type EventBus interface {
	// Publish 发布一个事件给订阅了该任务(或全部任务)的订阅者。
	Publish(ctx context.Context, event AgentEvent)
	// Subscribe 订阅某任务的事件;taskID 为空表示订阅全部任务。
	// 返回的 unsubscribe 用于取消订阅。
	Subscribe(taskID string, handler EventHandler) (unsubscribe func())
}

EventBus 是实时通知层接口:只负责“告诉 UI 状态发生了变化”,不承担状态存储。

数据库(Repository)才是状态源;EventBus 之上可以接 WS / SSE 做实时推送。

func NewEventBus

func NewEventBus() EventBus

NewEventBus 创建一个内存事件总线。

type EventHandler

type EventHandler func(ctx context.Context, event AgentEvent) error

EventHandler 是事件订阅回调。 返回 error 表示处理失败;EventBus 目前采用同步分发,回调应避免阻塞。

type EventRepository

type EventRepository interface {
	// Append 为事件分配 sequence 并追加到任务事件流。
	Append(ctx context.Context, event *AgentEvent) error
	// ListByTask 返回任务中 sequence 大于 after 的事件(升序)。
	ListByTask(ctx context.Context, taskID string, after int64) ([]*AgentEvent, error)
	// Page 分页查询事件(按 CreatedAt 升序);taskID 为空表示全部任务。
	Page(ctx context.Context, taskID string, offset, limit int) ([]*AgentEvent, int64, error)
}

EventRepository 持久化任务事件(带 per-task 单调递增 sequence)。

func NewGormEventRepository

func NewGormEventRepository(db *gorm.DB) EventRepository

NewGormEventRepository 创建基于数据库的事件流 Repository。

func NewMemoryEventRepository

func NewMemoryEventRepository() EventRepository

NewMemoryEventRepository 创建事件流的内存实现。

type Memory

type Memory struct {
	ID        string     `json:"id" gorm:"column:id;primaryKey;type:varchar(64)"`
	UserID    string     `json:"user_id" gorm:"column:user_id;type:varchar(64);index:idx_agent_memories_user_kind,priority:1"`
	SessionID string     `json:"session_id,omitempty" gorm:"column:session_id;type:varchar(64);index"`
	Kind      MemoryKind `json:"kind" gorm:"column:kind;type:varchar(32);index:idx_agent_memories_user_kind,priority:2"`
	Content   string     `json:"content" gorm:"column:content;type:text"`

	// Importance 表示记忆重要度(0-10),检索排序时权重更高。
	Importance int `json:"importance" gorm:"column:importance"`
	// Metadata 承载扩展信息(来源、标签等),由序列化为 JSON 持久化。
	Metadata map[string]any `json:"metadata,omitempty" gorm:"column:metadata;serializer:json"`

	CreatedAt      time.Time  `json:"created_at" gorm:"column:created_at"`
	UpdatedAt      time.Time  `json:"updated_at" gorm:"column:updated_at"`
	LastAccessedAt *time.Time `json:"last_accessed_at,omitempty" gorm:"column:last_accessed_at"`
}

Memory 是一条可跨轮次 / 跨会话检索的持久化记忆。

UserID 是记忆的主归属维度(长期记忆按用户隔离);SessionID 可选,用于把记忆 与某个具体会话关联(例如该会话的摘要)。

func NewMemory

func NewMemory(userID, sessionID string, kind MemoryKind, content string) *Memory

NewMemory 构建一条记忆;ID 为空时由 Save 分配。

func (Memory) TableName

func (Memory) TableName() string

TableName 返回记忆表的表名。

type MemoryConfig

type MemoryConfig struct {
	Repo      MemoryRepository
	Retriever MemoryRetriever
	Extractor MemoryExtractor
}

MemoryConfig 是 MemoryManager 的依赖配置。

type MemoryExtractor

type MemoryExtractor interface {
	Extract(ctx context.Context, turn MemoryTurn) ([]*Memory, error)
}

MemoryExtractor 从一轮完成的对话 / 任务结果中提取值得长期记住的记忆。

这是一个可选钩子:AgentService 在任务完成后调用,把提取出的记忆写入 Repository。 返回 nil 表示本轮无需写入任何记忆。默认不配置(不提取);可由上层注入基于规则 或基于 LLM 的实现。

func MockMemoryExtractor

func MockMemoryExtractor() MemoryExtractor

MockMemoryExtractor 返回一个模拟的记忆提取器:把本轮的用户提问与助手回复 组合成一条 summary 记忆(内容做截断防止过长)。

用于演示 / 测试「任务完成 → 提取 → 落库」的调用链,不接入真实 LLM 或规则引擎; 生产环境应替换为基于规则或基于 LLM 的 MemoryExtractor 实现。

type MemoryExtractorFunc

type MemoryExtractorFunc func(ctx context.Context, turn MemoryTurn) ([]*Memory, error)

MemoryExtractorFunc 是把普通函数适配为 MemoryExtractor 的辅助类型。

func (MemoryExtractorFunc) Extract

func (f MemoryExtractorFunc) Extract(ctx context.Context, turn MemoryTurn) ([]*Memory, error)

Extract 实现 MemoryExtractor 接口。

type MemoryKind

type MemoryKind string

MemoryKind 描述记忆的类别,用于检索排序与前端展示。

const (
	MemoryKindFact    MemoryKind = "fact"    // 用户偏好 / 事实(长期有效)
	MemoryKindSummary MemoryKind = "summary" // 会话 / 任务摘要
	MemoryKindNote    MemoryKind = "note"    // 通用备注
	MemoryKindEvent   MemoryKind = "event"   // 事件记录(带时间语义)
)

type MemoryManager

type MemoryManager struct {
	// contains filtered or unexported fields
}

MemoryManager 负责记忆的创建、查询、检索与提取编排。

它是 memory 域的「门面」:上层(AgentService / HTTP 层)只依赖 MemoryManager, 不直接感知 Repository / Retriever / Extractor 的具体实现。

func NewMemoryManager

func NewMemoryManager(cfg MemoryConfig) *MemoryManager

NewMemoryManager 创建记忆管理器;未提供的依赖使用安全默认值。

func (*MemoryManager) Delete

func (m *MemoryManager) Delete(ctx context.Context, id string) error

Delete 删除记忆。

func (*MemoryManager) Extract

func (m *MemoryManager) Extract(ctx context.Context, turn MemoryTurn) ([]*Memory, error)

Extract 调用已配置的提取器,从一轮执行中提取待写入的记忆。 未配置提取器时返回空(不提取)。

func (*MemoryManager) Get

func (m *MemoryManager) Get(ctx context.Context, id string) (*Memory, error)

Get 按 ID 查询记忆。

func (*MemoryManager) List

func (m *MemoryManager) List(ctx context.Context, userID string, offset, limit int, kinds ...MemoryKind) ([]*Memory, int64, error)

List 分页查询某用户的记忆;kinds 为空表示全部类别。

func (*MemoryManager) Retrieve

func (m *MemoryManager) Retrieve(ctx context.Context, userID, query string, limit int) ([]*Memory, error)

Retrieve 检索与 query 相关的记忆,并刷新这些记忆的访问时间(Touch)。

func (*MemoryManager) Save

func (m *MemoryManager) Save(ctx context.Context, memory *Memory) error

Save 创建或更新一条记忆:ID 为空时分配新 ID 并创建,否则更新。

func (*MemoryManager) Touch

func (m *MemoryManager) Touch(ctx context.Context, id string) error

Touch 更新记忆的最近访问时间(用于淘汰 / 排序策略)。

type MemoryRepository

type MemoryRepository interface {
	Create(ctx context.Context, memory *Memory) error
	Get(ctx context.Context, id string) (*Memory, error)
	Update(ctx context.Context, memory *Memory) error
	Delete(ctx context.Context, id string) error
	// ListByUser 分页查询某用户的记忆(按 UpdatedAt 降序);kinds 为空表示全部类别。
	ListByUser(ctx context.Context, userID string, offset, limit int, kinds ...MemoryKind) ([]*Memory, int64, error)
	// Search 按关键词检索某用户的记忆(返回按相关度 + 重要度排序)。
	// 基础实现为子串 / LIKE 匹配,可被更高级的检索器(向量 / 语义)替换。
	Search(ctx context.Context, userID, query string, limit int) ([]*Memory, error)
}

MemoryRepository 持久化记忆。

与 TaskRepository / PermissionRepository 一致:当前提供内存实现,后续可替换为 GORM 等基于 DB 的实现(见 repository_gorm.go)。

func NewGormMemoryRepository

func NewGormMemoryRepository(db *gorm.DB) MemoryRepository

NewGormMemoryRepository 创建基于数据库的记忆 Repository。

func NewMemoryRepository

func NewMemoryRepository() MemoryRepository

NewMemoryRepository 创建记忆的内存实现。

type MemoryRetriever

type MemoryRetriever interface {
	// Retrieve 返回与 query 相关的记忆,按相关度降序,最多 limit 条。
	Retrieve(ctx context.Context, userID, query string, limit int) ([]*Memory, error)
}

MemoryRetriever 从记忆中检索与查询相关的内容。

与 Repository.Search 的区别:Retriever 是可插拔的「检索策略」抽象, 默认实现退化为关键词匹配(委托 Repository.Search);后续可接入向量检索 / 语义检索, 而无须改动 AgentService 的注入逻辑。

type MemoryTurn

type MemoryTurn struct {
	UserID    string
	SessionID string
	Request   Request
	Result    *Result
}

MemoryTurn 描述一轮已完成执行的上下文,供 MemoryExtractor 提取记忆。

type Message

type Message struct {
	Role    string `json:"role"`    // system / user / assistant / tool
	Content string `json:"content"` // 文本内容
}

Message 是一条对话消息。

type MessageBlock

type MessageBlock struct {
	ID        string     `json:"id"`                // messageId
	TurnID    string     `json:"turn_id,omitempty"` // 所属 turn
	Content   string     `json:"content"`
	ToolCalls []ToolCall `json:"tool_calls,omitempty"`
}

MessageBlock 是一条完整的 assistant 消息(对应 AssistantMessageData), 包含它发起的工具调用列表。

type Operation

type Operation struct {
	ID   string        `json:"id,omitempty"`
	Type OperationType `json:"type"`

	// read / write / delete / move
	Path string `json:"path,omitempty"`
	// write
	Content string `json:"content,omitempty"`
	// execute
	Command string `json:"command,omitempty"`

	// Metadata 承载操作相关的扩展信息(如命令参数、网络地址等)。
	Metadata map[string]any `json:"metadata,omitempty"`
}

Operation 描述 Agent 想要执行的一个原子操作。

它刻意与 PermissionRequest 分离:Operation 只描述“要做什么”, PermissionRequest 记录“这个操作是否被允许、当前处于什么状态”。

type OperationType

type OperationType string

OperationType 描述 Agent 想要执行的操作类别。

未来可继续扩展(install_package / git_push / docker / kubernetes ...), 权限策略按类型决定 allow / deny / ask。

const (
	OperationRead    OperationType = "read"    // 读取文件
	OperationWrite   OperationType = "write"   // 写入 / 修改文件
	OperationDelete  OperationType = "delete"  // 删除文件
	OperationMove    OperationType = "move"    // 移动 / 重命名文件
	OperationExecute OperationType = "execute" // 执行命令 / 脚本
	OperationNetwork OperationType = "network" // 网络访问
)

type Options

type Options struct {
	Model       string            `json:"model"`
	BaseURL     string            `json:"base_url"`
	APIKey      string            `json:"api_key"`
	BearerToken string            `json:"bearer_token"`
	WorkingDir  string            `json:"working_dir"`
	Extra       map[string]string `json:"extra"`

	// Tools 是本次调用可用的工具注册表。
	//
	// Provider 据此向模型暴露工具定义(tool.List()),并通过 ToolRunner /
	// tool.Executor 执行模型发起的工具调用。为 nil 表示本次调用不启用工具。
	Tools *tool.Registry `json:"-"`

	// Skills 是本次调用可用的技能注册表。
	//
	// Provider 据此向模型暴露技能定义(skill.List())与指令正文(skill.Instructions()),
	// 并通过 SkillRunner / skill.Invoker 执行模型发起的技能调用。为 nil 表示本次
	// 调用不启用技能。
	Skills *skill.Registry `json:"-"`
}

Options 是构建 Agent 实例所需的通用配置;具体 Provider 按需读取。 Extra 用于承载 Provider 特有配置,避免为每个 Provider 单独定义结构。

type PermissionDecision

type PermissionDecision string

PermissionDecision 是权限策略 / 决策结果。

const (
	DecisionAllow PermissionDecision = "allow" // 允许执行
	DecisionDeny  PermissionDecision = "deny"  // 拒绝执行
	DecisionAsk   PermissionDecision = "ask"   // 需要人工确认
)

type PermissionManager

type PermissionManager struct {
	// contains filtered or unexported fields
}

PermissionManager 负责权限请求的创建、持久化与决策流转。

它是“数据库才是状态源”的核心实现:

  • Create:把权限请求写入 Repository(pending),等待 UI 确认;
  • Approve / Deny:更新 Repository 状态,并唤醒正在阻塞等待的 Agent;
  • Wait:Agent 侧阻塞等待决策(内存 channel 只是运行时同步机制,真正状态在 Repository)。

注意:事件广播由上层 AgentService 负责(单一事件出口),PermissionManager 只维护状态。 Approve / Deny 与 Wait 通过互斥锁 + waiter channel 协同,避免“决策先于等待注册”的竞态。

func NewPermissionManager

func NewPermissionManager(repo PermissionRepository) *PermissionManager

NewPermissionManager 创建权限管理器。

func (*PermissionManager) Approve

func (m *PermissionManager) Approve(ctx context.Context, id, by string) (*PermissionRequest, error)

Approve 批准权限请求,返回更新后的权限请求;并唤醒正在等待的 Agent。

func (*PermissionManager) Create

func (m *PermissionManager) Create(ctx context.Context, taskID, sessionID string, operation Operation) (*PermissionRequest, error)

Create 创建一个 pending 状态的权限请求并返回。

func (*PermissionManager) Deny

Deny 拒绝权限请求,返回更新后的权限请求;并唤醒正在等待的 Agent。

func (*PermissionManager) Get

Get 按 ID 查询权限请求。

func (*PermissionManager) GetPending

func (m *PermissionManager) GetPending(ctx context.Context, taskID string) ([]*PermissionRequest, error)

GetPending 返回某任务当前全部待确认的权限请求。

func (*PermissionManager) Page

func (m *PermissionManager) Page(ctx context.Context, offset, limit int, taskID string, statuses ...PermissionStatus) ([]*PermissionRequest, int64, error)

Page 分页查询权限请求;taskID 为空表示全部任务,statuses 为空表示全部状态。

func (*PermissionManager) Wait

Wait 阻塞等待权限请求的决策。

返回:

  • DecisionAllow:已批准(批准后立即把请求标记为 consumed);
  • DecisionDeny:已拒绝 / 过期 / 取消;
  • error:ctx 取消等。

type PermissionPolicy

type PermissionPolicy interface {
	Check(ctx context.Context, operation Operation) PermissionDecision
}

PermissionPolicy 判断一个 Operation 应被允许、拒绝,还是需要人工确认。

Agent 在执行前把 Operation 交给策略;策略返回 ask 时,由 PermissionManager 持久化一个 pending 的 PermissionRequest 并等待 UI 确认。

func AllowAllPermissionPolicy

func AllowAllPermissionPolicy() PermissionPolicy

AllowAllPermissionPolicy 返回一个“全部放行”的策略实例。

func DefaultPermissionPolicy

func DefaultPermissionPolicy() PermissionPolicy

DefaultPermissionPolicy 返回框架内置的默认策略实例。

type PermissionRepository

type PermissionRepository interface {
	Create(ctx context.Context, permission *PermissionRequest) error
	Get(ctx context.Context, id string) (*PermissionRequest, error)
	Update(ctx context.Context, permission *PermissionRequest) error
	ListPendingByTask(ctx context.Context, taskID string) ([]*PermissionRequest, error)
	// Page 分页查询权限请求(按 CreatedAt 升序);taskID 为空表示全部任务,statuses 为空表示全部状态。
	Page(ctx context.Context, offset, limit int, taskID string, statuses ...PermissionStatus) ([]*PermissionRequest, int64, error)
}

PermissionRepository 持久化权限请求。

func NewGormPermissionRepository

func NewGormPermissionRepository(db *gorm.DB) PermissionRepository

NewGormPermissionRepository 创建基于数据库的权限请求 Repository。

func NewMemoryPermissionRepository

func NewMemoryPermissionRepository() PermissionRepository

NewMemoryPermissionRepository 创建权限请求的内存实现。

type PermissionRequest

type PermissionRequest struct {
	ID        string           `json:"id" gorm:"column:id;primaryKey;type:varchar(64)"`
	TaskID    string           `json:"task_id" gorm:"column:task_id;type:varchar(64);index"`
	SessionID string           `json:"session_id,omitempty" gorm:"column:session_id;type:varchar(64)"`
	Operation Operation        `json:"operation" gorm:"serializer:json"`
	Status    PermissionStatus `json:"status" gorm:"column:status;type:varchar(32);index"`

	CreatedAt  time.Time  `json:"created_at" gorm:"column:created_at"`
	UpdatedAt  time.Time  `json:"updated_at" gorm:"column:updated_at"`
	ResolvedAt *time.Time `json:"resolved_at,omitempty" gorm:"column:resolved_at"`
	ResolvedBy *string    `json:"resolved_by,omitempty" gorm:"column:resolved_by;type:varchar(64)"`
}

PermissionRequest 记录一次权限请求及其决策结果,是权限域的持久化对象。

它是“数据库才是状态源”这一原则的载体:Agent 阻塞等待的只是内存中的 channel, 真正的状态始终保存在 Repository 中,因此浏览器刷新 / 后端重启后仍可恢复。

func NewPermissionRequest

func NewPermissionRequest(taskID, sessionID string, operation Operation) *PermissionRequest

NewPermissionRequest 构建一个 pending 状态的权限请求。

func (*PermissionRequest) Decision

func (p *PermissionRequest) Decision() PermissionDecision

Decision 把当前状态映射为 Agent 可消费的决策结果。

func (PermissionRequest) TableName

func (PermissionRequest) TableName() string

TableName 返回权限请求表的表名。

func (*PermissionRequest) TransitionTo

func (p *PermissionRequest) TransitionTo(next PermissionStatus) bool

TransitionTo 校验并执行权限状态迁移;非法迁移返回 false 且不改变状态。

type PermissionStatus

type PermissionStatus string

PermissionStatus 是权限请求的生命周期状态。

状态机(详见 design.md 第 8 节):

pending → approved → consumed
pending → denied / expired / canceled
const (
	PermissionPending  PermissionStatus = "pending"  // 等待人工确认
	PermissionApproved PermissionStatus = "approved" // 已批准
	PermissionDenied   PermissionStatus = "denied"   // 已拒绝
	PermissionExpired  PermissionStatus = "expired"  // 已过期
	PermissionCanceled PermissionStatus = "canceled" // 已取消(任务被取消等)
	PermissionConsumed PermissionStatus = "consumed" // 已消费:Agent 已恢复并继续执行
)

type Profile

type Profile struct {
	ID           string        `json:"id" gorm:"column:id;primaryKey;type:varchar(64)"`
	Name         string        `json:"name" gorm:"column:name;type:varchar(64);index:idx_agent_profiles_user_name,priority:2"`
	DisplayName  string        `json:"display_name" gorm:"column:display_name;type:varchar(128)"`
	Description  string        `json:"description" gorm:"column:description;type:text"`
	UserID       string        `json:"user_id" gorm:"column:user_id;type:varchar(64);index:idx_agent_profiles_user_name,priority:1"`
	IsDefault    bool          `json:"is_default" gorm:"column:is_default"`
	IsBuiltin    bool          `json:"is_builtin" gorm:"column:is_builtin"`
	SystemPrompt string        `json:"system_prompt" gorm:"column:system_prompt;type:text"`
	Skills       []string      `json:"skills" gorm:"column:skills;serializer:json"`
	Context      ContextConfig `json:"context" gorm:"column:context;serializer:json"`

	CreatedAt time.Time `json:"created_at" gorm:"column:created_at"`
	UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"`
}

Profile 描述一类任务的 Agent 配置(系统提示词 + 技能 + 上下文注入开关)。

与 Options / Request(每次调用的动态参数)不同,Profile 是「按任务类型选择」的静态 配置快照:HTTP 层或前端在发起调用时通过 Request.Profile 指定名称,AgentService 在 调用前解析并应用(合并系统提示词、过滤技能、按开关注入背景)。

UserID 为空表示系统级(内置)Profile;非空表示某用户的自定义 Profile。

func BuiltinProfiles

func BuiltinProfiles() []*Profile

BuiltinProfiles 返回框架内置的 Profile。新增内置 Profile 时在此追加。

内置 Profile 由代码定义(不落库、不可删除),与用户自定义 Profile(落库)合并后 共同构成可选的 Profile 列表。

func DefaultBuiltinProfile

func DefaultBuiltinProfile() *Profile

DefaultBuiltinProfile 返回内置默认 Profile(用于兜底:未配置 ProfileManager 或解析失败时)。

func (Profile) TableName

func (Profile) TableName() string

TableName 返回 Profile 表的表名。

type ProfileManager

type ProfileManager struct {
	// contains filtered or unexported fields
}

ProfileManager 负责 Profile 的解析、列表与增删改查编排。

它把「内置 Profile(代码定义)」与「用户自定义 Profile(持久化)」合并成一个统一的 视图:按名称解析时用户自定义优先,其次内置;未指定名称时回退到默认 Profile。

func NewProfileManager

func NewProfileManager(repo ProfileRepository) *ProfileManager

NewProfileManager 创建 Profile 管理器;repo 为空时使用内存实现。

func (*ProfileManager) Delete

func (m *ProfileManager) Delete(ctx context.Context, userID, id string) error

Delete 删除某用户的自定义 Profile;内置 Profile 不可删除。

func (*ProfileManager) Get

func (m *ProfileManager) Get(ctx context.Context, userID, id string) (*Profile, error)

Get 按 ID 返回某用户的自定义 Profile(内置 Profile 不按 ID 取,列表已含其完整信息)。

func (*ProfileManager) List

func (m *ProfileManager) List(ctx context.Context, userID string) ([]*Profile, error)

List 返回内置 Profile 与指定用户自定义 Profile 的合并列表(按名称升序)。

func (*ProfileManager) Resolve

func (m *ProfileManager) Resolve(ctx context.Context, userID, name string) (*Profile, error)

Resolve 解析 Profile:

  • name 为空:取默认(用户自定义默认优先,其次内置默认);
  • name 非空:用户自定义优先,其次内置;
  • 均未命中:返回 ErrProfileNotFound。

func (*ProfileManager) Save

func (m *ProfileManager) Save(ctx context.Context, p *Profile) error

Save 创建或更新用户自定义 Profile;IsDefault 为 true 时清除该用户的其他默认标记。

type ProfileRepository

type ProfileRepository interface {
	Create(ctx context.Context, profile *Profile) error
	Get(ctx context.Context, id string) (*Profile, error)
	Update(ctx context.Context, profile *Profile) error
	Delete(ctx context.Context, id string) error
	// ListByUser 返回某用户全部自定义 Profile(按名称升序)。
	ListByUser(ctx context.Context, userID string) ([]*Profile, error)
	// GetByName 按名称返回某用户的自定义 Profile。
	GetByName(ctx context.Context, userID, name string) (*Profile, error)
	// GetDefault 返回某用户的默认自定义 Profile;不存在时返回 (nil, nil)。
	GetDefault(ctx context.Context, userID string) (*Profile, error)
	// ClearDefault 清除某用户除 exceptID 外的默认标记。
	ClearDefault(ctx context.Context, userID, exceptID string) error
}

ProfileRepository 持久化用户自定义 AgentProfile。

与 TaskRepository / MemoryRepository 一致:内置 Profile 由代码定义(不落库), 仅用户自定义 Profile 通过该接口持久化。

func NewGormProfileRepository

func NewGormProfileRepository(db *gorm.DB) ProfileRepository

NewGormProfileRepository 创建基于数据库的用户自定义 Profile Repository。

func NewMemoryProfileRepository

func NewMemoryProfileRepository() ProfileRepository

NewMemoryProfileRepository 创建 Profile 的内存实现。

type ProjectContextProvider

type ProjectContextProvider interface {
	// ProjectContext 返回当前用户激活项目下的上下文文本块;无可用内容时返回空串。
	//
	// 返回的文本会作为独立段落追加到 SystemPrompt 末尾。
	ProjectContext(ctx context.Context, userID string) (string, error)
}

ProjectContextProvider 是可选的领域上下文提供者。

AgentService 在调用前通过它把当前项目相关的背景(例如已完成的分析节点)注入 SystemPrompt,让 Agent「知道」当前项目的进展与可用结果。它保持 agent 包与领域层 (project / analysis)的解耦:agent 只依赖这个窄接口,具体实现由上层(manager / container)注入。

type Provider

type Provider interface {
	// Name 返回 Provider 唯一标识(小写,如 claude_code / codex / copilot / custom)。
	Name() string
	// New 基于 Options 构建 Agent 实例。
	New(opts Options) (Agent, error)
}

Provider 是 Agent 的工厂接口:根据 Options 构建一个 Agent 实例。 这样同一 Provider 可以有不同的配置(不同模型 / 不同 endpoint)。

type ReasoningBlock

type ReasoningBlock struct {
	ID      string `json:"id"`      // reasoningId
	Content string `json:"content"` // 完整思考文本
}

ReasoningBlock 是一段完整的思考内容(对应 Provider 的完整 reasoning 事件)。

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry 负责注册与解析 Provider。 容器启动时把全部 Provider 注册进来,运行时按名称解析。

func NewRegistry

func NewRegistry(providers ...Provider) *Registry

NewRegistry 创建 Registry 并注册传入的 Provider。

func (*Registry) Has

func (r *Registry) Has(name string) bool

Has 报告指定名称的 Provider 是否已注册。

func (*Registry) Names

func (r *Registry) Names() []string

Names 返回已注册的 Provider 名称列表(升序,便于调试与校验)。

func (*Registry) Register

func (r *Registry) Register(p Provider)

Register 注册 Provider;同名覆盖。

func (*Registry) Resolve

func (r *Registry) Resolve(name string, opts Options) (Agent, error)

Resolve 按名称解析并构建 Agent 实例。

type Request

type Request struct {
	// Provider 可选:强制指定 Provider 名称;为空则使用 Client 的默认 Provider。
	Provider string `json:"provider"`
	// Model 可选:模型名称,为空时由 Provider 自行决定。
	Model string `json:"model"`
	// SessionID 可选:会话标识,用于把多次调用关联到同一会话(与权限 / 任务联动)。
	SessionID string `json:"session_id"`
	// UserID 可选:发起调用的用户,用于记忆(memory)的归属隔离与检索。
	UserID string `json:"user_id,omitempty"`
	// Profile 可选:AgentProfile 名称,AgentService 据此解析系统提示词、技能与上下文注入开关。
	Profile string `json:"profile,omitempty"`
	// Skills 可选:本次调用启用的技能名列表;为空表示使用默认全部技能。
	Skills []string `json:"skills,omitempty"`
	// SystemPrompt 系统提示词。
	SystemPrompt string `json:"system_prompt"`
	// Messages 对话上下文(不含 SystemPrompt)。
	Messages []Message `json:"messages"`
	// WorkingDir 可选:Agent 执行的工作目录。
	WorkingDir string `json:"working_dir"`
	// Env 可选:额外环境变量(也可携带 Provider 特有开关)。
	Env map[string]string `json:"env"`
	// MaxTokens 可选:最大输出 token 数,0 表示不限制。
	MaxTokens int `json:"max_tokens"`
	// Stream 可选:任务模式下是否使用流式调用;默认 false 使用 Invoke。
	Stream bool `json:"stream"`
	// Timeout 可选:单次调用超时,0 表示不限制。
	Timeout time.Duration `json:"-"`
}

Request 描述一次 Agent 调用请求,与具体 Provider 无关。

type Result

type Result struct {
	Content string          `json:"content"`
	Usage   Usage           `json:"usage"`
	Raw     json.RawMessage `json:"raw,omitempty"` // Provider 原始返回,便于调试与扩展
}

Result 是一次 Invoke / Stream 调用的最终聚合结果。

type Runtime

type Runtime interface {
	// Emit 输出一个流式事件。
	Emit(ctx context.Context, event StreamEvent) error
	// RequestPermission 创建权限请求并阻塞等待决策(allow / deny)。
	RequestPermission(ctx context.Context, operation Operation) (PermissionDecision, error)
	// WaitPermission 等待一个已存在权限请求(permissionID)的决策。
	WaitPermission(ctx context.Context, permissionID string) (PermissionDecision, error)
}

Runtime 是 Agent 执行期间的运行时环境,由上层(Client 或 AgentService)注入。

Agent 通过它完成三件事:

  • Emit:向外输出流式事件(文本 / 推理 / 工具调用 / 权限通知等);
  • RequestPermission:创建一个权限请求并阻塞等待用户 / 策略决策;
  • WaitPermission:等待一个已存在的权限请求的决策(用于恢复场景)。

该接口把 Agent 与“持久化、通知、权限决策”等业务关注点解耦: Agent 只描述“要做什么”,具体“能不能做”由 Runtime 背后的 PermissionManager / Policy 决定。

func NewStandaloneRuntime

func NewStandaloneRuntime(handler StreamHandler) Runtime

NewStandaloneRuntime 返回一个独立于任务上下文的 Runtime,用于 Client.Invoke / Client.Stream 这类“无任务、无 UI”的一次性调用。

行为约定:

  • Emit:直接把事件交给 handler(handler 为 nil 时丢弃);
  • RequestPermission:应用默认策略,ask 降级为 allow(宽松放行),保证链路可跑通;
  • WaitPermission:无解析器,直接返回 ErrNoPermissionResolver。

type ServiceConfig

type ServiceConfig struct {
	Client   *Client
	Tasks    TaskRepository
	Perms    *PermissionManager
	Events   EventRepository
	Bus      EventBus
	Policy   PermissionPolicy
	Memory   *MemoryManager
	Project  ProjectContextProvider
	Profiles *ProfileManager
}

ServiceConfig 是 AgentService 的依赖配置。

type SkillCall

type SkillCall struct {
	ID        string `json:"id"`   // skillCallId
	Name      string `json:"name"` // 技能名
	Arguments any    `json:"arguments,omitempty"`
}

SkillCall 是一次完整的技能调用(对应模型发起的 skill 调用)。

type SkillCallProvider

type SkillCallProvider func(ctx context.Context, results []skill.Result) ([]SkillCall, error)

SkillCallProvider 由 Provider 提供:根据上一轮结果决定下一批待执行的技能调用。 返回空切片表示不再有技能调用,循环结束。

type SkillLoop

type SkillLoop struct {
	// contains filtered or unexported fields
}

SkillLoop 驱动标准的 skill-call 循环:执行 → 回传结果 → 再执行,直至无更多技能调用。

用法与 ToolLoop 对称:

resp := model(messages, skills)
for resp.hasSkillCalls() {
    results := loop.Run(ctx, func(ctx, last) ([]agent.SkillCall, error) {
        messages = appendSkillResults(messages, last)
        resp = model(messages, skills)
        return resp.skillCalls(), nil
    })
}

func NewSkillLoop

func NewSkillLoop(runner *SkillRunner) *SkillLoop

NewSkillLoop 创建技能调用循环。

func (*SkillLoop) Run

func (l *SkillLoop) Run(ctx context.Context, next SkillCallProvider) ([]skill.Result, error)

Run 驱动循环并返回累积的全部技能结果。

type SkillPermissionResolver

type SkillPermissionResolver func(ctx context.Context, call SkillCall) (Operation, bool)

SkillPermissionResolver 把一次技能调用映射为需要授权的 Operation。

返回 (op, true) 表示该技能需要权限确认(执行前阻塞等待决策); 返回 (op, false) 表示直接放行。

type SkillResultEvent

type SkillResultEvent struct {
	CallID  string `json:"call_id"`
	Name    string `json:"name"`
	Content string `json:"content"`
	IsError bool   `json:"is_error"`
}

SkillResultEvent 是 skill_result 事件的结构化载荷。

type SkillRunner

type SkillRunner struct {
	// contains filtered or unexported fields
}

SkillRunner 把 skill.Invoker 与 Runtime 桥接:执行技能调用并输出事件, 同时承载可选的权限门禁(把技能调用映射为 Operation,执行前请求授权)。

func NewSkillRunner

func NewSkillRunner(inv *skill.Invoker, rt Runtime) *SkillRunner

NewSkillRunner 创建技能执行器;inv 为 nil 时使用空注册表的执行器。

func (*SkillRunner) Run

func (r *SkillRunner) Run(ctx context.Context, call SkillCall) skill.Result

Run 执行一次技能调用:

  1. 输出 skill_call 事件(完整块,落库);
  2. 若配置了权限映射,执行前通过 Runtime.RequestPermission 阻塞等待决策;
  3. 执行技能;
  4. 输出 skill_result 事件并返回结果。

func (*SkillRunner) RunAll

func (r *SkillRunner) RunAll(ctx context.Context, calls []SkillCall) []skill.Result

RunAll 顺序执行一批技能调用。

func (*SkillRunner) SetPermissionResolver

func (r *SkillRunner) SetPermissionResolver(resolver SkillPermissionResolver) *SkillRunner

SetPermissionResolver 设置权限映射(可选),返回自身便于链式调用。

type StreamEvent

type StreamEvent struct {
	Type    StreamEventType `json:"type"`
	Content string          `json:"content,omitempty"` // 仅增量事件使用
	Data    any             `json:"data,omitempty"`    // 完整块的结构化数据(reasoning/message/tool_call/turn)
	Err     error           `json:"-"`                 // 仅当 Type == StreamEventError 时有效
}

StreamEvent 是一次流式输出过程中的单个事件。

type StreamEventType

type StreamEventType string

StreamEventType 枚举流式事件类型。

事件分为两类:

  • 增量(delta):text / reasoning_delta,用于前端实时渲染,默认不落库(仅走 WS/SSE 广播);
  • 完整块(block):turn_start / turn_end / reasoning / message / tool_call / tool_result, 是时间线的 source of truth,会持久化到 EventRepository。
const (
	// —— 增量(delta)——
	StreamEventText           StreamEventType = "text"            // 文本增量
	StreamEventReasoningDelta StreamEventType = "reasoning_delta" // 思维链/推理增量

	// —— 完整块(block)——
	StreamEventTurnStart   StreamEventType = "turn_start"   // 一轮开始(Data 为 TurnBlock)
	StreamEventTurnEnd     StreamEventType = "turn_end"     // 一轮结束(Data 为 TurnBlock)
	StreamEventReasoning   StreamEventType = "reasoning"    // 完整思考块(Data 为 ReasoningBlock)
	StreamEventMessage     StreamEventType = "message"      // 完整 assistant 消息(Data 为 MessageBlock)
	StreamEventToolCall    StreamEventType = "tool_call"    // 完整工具调用(Data 为 ToolCall)
	StreamEventToolResult  StreamEventType = "tool_result"  // 工具调用结果
	StreamEventSkillCall   StreamEventType = "skill_call"   // 完整技能调用(Data 为 SkillCall)
	StreamEventSkillResult StreamEventType = "skill_result" // 技能调用结果

	StreamEventPermission       StreamEventType = "permission"        // 权限请求通知(真正状态见 PermissionRequest)
	StreamEventPermissionResult StreamEventType = "permission_result" // 权限决策结果通知
	StreamEventDone             StreamEventType = "done"              // 正常结束
	StreamEventError            StreamEventType = "error"             // 出错结束
)

type StreamHandler

type StreamHandler func(ctx context.Context, event StreamEvent) error

StreamHandler 消费流式事件;返回非 nil 错误时中断流式调用。

type Task

type Task struct {
	ID         string     `json:"id" gorm:"column:id;primaryKey;type:varchar(64)"`
	SessionID  string     `json:"session_id,omitempty" gorm:"column:session_id;type:varchar(64);index"`
	Provider   string     `json:"provider" gorm:"column:provider;type:varchar(64)"`
	Model      string     `json:"model,omitempty" gorm:"column:model;type:varchar(128)"`
	Status     TaskStatus `json:"status" gorm:"column:status;type:varchar(32);index"`
	WorkingDir string     `json:"working_dir,omitempty" gorm:"column:working_dir;type:text"`

	// Request 保存原始请求,用于恢复时重建上下文。
	Request Request `json:"request,omitempty" gorm:"serializer:json"`
	// Error 保存最近一次错误信息(Status == failed 时有效)。
	Error string `json:"error,omitempty" gorm:"column:error;type:text"`

	CreatedAt  time.Time  `json:"created_at" gorm:"column:created_at"`
	UpdatedAt  time.Time  `json:"updated_at" gorm:"column:updated_at"`
	StartedAt  *time.Time `json:"started_at,omitempty" gorm:"column:started_at"`
	FinishedAt *time.Time `json:"finished_at,omitempty" gorm:"column:finished_at"`
}

Task 是一次 Agent 调用的持久化对象。

它与 PermissionRequest 形成两级状态机:Task 记录“整体执行到哪一步”, PermissionRequest 记录“某个具体操作是否被允许”。后端重启后,可根据 Task.Status 与 pending 的 PermissionRequest 重建运行态(见 Recovery)。

func NewTask

func NewTask(req Request) *Task

NewTask 基于请求构建一个 created 状态的任务。

func (Task) TableName

func (Task) TableName() string

TableName 返回任务表的表名。

func (*Task) TransitionTo

func (t *Task) TransitionTo(next TaskStatus) bool

TransitionTo 校验并执行任务状态迁移;非法迁移返回 false 且不改变状态。

type TaskRepository

type TaskRepository interface {
	Create(ctx context.Context, task *Task) error
	Get(ctx context.Context, id string) (*Task, error)
	Update(ctx context.Context, task *Task) error
	ListByStatus(ctx context.Context, statuses ...TaskStatus) ([]*Task, error)
	// Page 分页查询任务(按 CreatedAt 升序);statuses 为空表示全部状态。
	Page(ctx context.Context, offset, limit int, statuses ...TaskStatus) ([]*Task, int64, error)
}

TaskRepository 持久化 Agent 任务。

func NewGormTaskRepository

func NewGormTaskRepository(db *gorm.DB) TaskRepository

NewGormTaskRepository 创建基于数据库的任务 Repository。

func NewMemoryTaskRepository

func NewMemoryTaskRepository() TaskRepository

NewMemoryTaskRepository 创建任务的内存实现。

type TaskStatus

type TaskStatus string

TaskStatus 是 Agent 任务的生命周期状态。

状态机(详见 design.md 第 7 节):

created → running → completed
               ↘ failed / canceled
running → waiting_permission → running
const (
	TaskCreated           TaskStatus = "created"            // 已创建,尚未开始
	TaskRunning           TaskStatus = "running"            // 正在执行
	TaskWaitingPermission TaskStatus = "waiting_permission" // 等待权限确认
	TaskCompleted         TaskStatus = "completed"          // 已完成
	TaskFailed            TaskStatus = "failed"             // 失败
	TaskCanceled          TaskStatus = "canceled"           // 已取消
)

type ToolCall

type ToolCall struct {
	ID        string `json:"id"`   // toolCallId
	Name      string `json:"name"` // 工具名
	Arguments any    `json:"arguments,omitempty"`
}

ToolCall 是一次完整的工具调用(对应 AssistantMessageToolRequest)。

type ToolCallProvider

type ToolCallProvider func(ctx context.Context, results []tool.Result) ([]ToolCall, error)

ToolCallProvider 由 Provider 提供:根据上一轮结果决定下一批待执行的工具调用。 返回空切片表示不再有工具调用,循环结束。

type ToolLoop

type ToolLoop struct {
	// contains filtered or unexported fields
}

ToolLoop 驱动标准的 tool-call 循环:执行 → 回传结果 → 再执行,直至无更多工具调用。

Provider 侧通常这样配合:

resp := model(messages, tools)
for resp.hasToolCalls() {
    results := loop.Run(ctx, func(ctx, last) ([]agent.ToolCall, error) {
        messages = appendToolResults(messages, last) // 把结果回填
        resp = model(messages, tools)
        return resp.toolCalls(), nil
    })
}

func NewToolLoop

func NewToolLoop(runner *ToolRunner) *ToolLoop

NewToolLoop 创建工具调用循环。

func (*ToolLoop) Run

func (l *ToolLoop) Run(ctx context.Context, next ToolCallProvider) ([]tool.Result, error)

Run 驱动循环并返回累积的全部工具结果。

type ToolPermissionResolver

type ToolPermissionResolver func(ctx context.Context, call ToolCall) (Operation, bool)

ToolPermissionResolver 把一次工具调用映射为需要授权的 Operation。

返回 (op, true) 表示该工具需要权限确认(执行前阻塞等待决策); 返回 (op, false) 表示直接放行。

type ToolResultEvent

type ToolResultEvent struct {
	CallID  string `json:"call_id"`
	Name    string `json:"name"`
	Content string `json:"content"`
	IsError bool   `json:"is_error"`
}

ToolResultEvent 是 tool_result 事件的结构化载荷。

type ToolRunner

type ToolRunner struct {
	// contains filtered or unexported fields
}

ToolRunner 把 tool.Executor 与 Runtime 桥接:执行工具调用并输出事件, 同时承载可选的权限门禁(把工具调用映射为 Operation,执行前请求授权)。

func NewToolRunner

func NewToolRunner(exec *tool.Executor, rt Runtime) *ToolRunner

NewToolRunner 创建工具执行器;exec 为 nil 时使用空注册表的执行器。

func (*ToolRunner) Run

func (r *ToolRunner) Run(ctx context.Context, call ToolCall) tool.Result

Run 执行一次工具调用:

  1. 输出 tool_call 事件(完整块,落库);
  2. 若配置了权限映射,执行前通过 Runtime.RequestPermission 阻塞等待决策;
  3. 执行工具;
  4. 输出 tool_result 事件并返回结果。

func (*ToolRunner) RunAll

func (r *ToolRunner) RunAll(ctx context.Context, calls []ToolCall) []tool.Result

RunAll 顺序执行一批工具调用。

func (*ToolRunner) SetPermissionResolver

func (r *ToolRunner) SetPermissionResolver(resolver ToolPermissionResolver) *ToolRunner

SetPermissionResolver 设置权限映射(可选),返回自身便于链式调用。

type TurnBlock

type TurnBlock struct {
	TurnID string `json:"turn_id"`
	Model  string `json:"model,omitempty"`
}

TurnBlock 描述一轮(turn)的边界(对应 turn_start / turn_end 事件)。

type TurnInput

type TurnInput struct {
	UserID         string
	ConversationID string // 为空则创建新会话
	Message        string // 本轮用户输入
	Provider       string
	Model          string
	SystemPrompt   string
	Profile        string // AgentProfile 名称(为空取默认)
	WorkingDir     string
}

TurnInput 是一次「轮次」的输入,由 HTTP 层构造。

type Usage

type Usage struct {
	InputTokens  int64 `json:"input_tokens"`
	OutputTokens int64 `json:"output_tokens"`
}

Usage 统计 token 用量。

Directories

Path Synopsis
Package providers 提供 agent.Provider 的内置实现。
Package providers 提供 agent.Provider 的内置实现。
Package skill 定义 Agent 技能(skill)调用框架的基础设施。
Package skill 定义 Agent 技能(skill)调用框架的基础设施。
builtin
Package builtin 提供框架内置的技能(如 echo)。
Package builtin 提供框架内置的技能(如 echo)。
Package tool 定义 Agent 工具调用(function calling)的基础设施。
Package tool 定义 Agent 工具调用(function calling)的基础设施。
builtin
Package builtin 提供框架内置的工具(如 get_weather)。
Package builtin 提供框架内置的工具(如 get_weather)。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL