diff --git a/README.md b/README.md index 5423dc6..b8c6757 100644 --- a/README.md +++ b/README.md @@ -2,41 +2,45 @@ [![Go](https://img.shields.io/badge/Go-1.25.6+-00ADD8?style=flat-square&logo=go)](https://go.dev/) [![Gin](https://img.shields.io/badge/Gin-HTTP-00ACD7?style=flat-square)](https://gin-gonic.com/) +[![Google ADK Go](https://img.shields.io/badge/Google%20ADK-Go-4285F4?style=flat-square)](https://google.github.io/adk-docs/) [![Eino](https://img.shields.io/badge/Eino-Agent-111827?style=flat-square)](https://github.com/cloudwego/eino) -[![ADK Go](https://img.shields.io/badge/Google%20ADK-Go-4285F4?style=flat-square)](https://github.com/google/adk-go) [![GORM](https://img.shields.io/badge/GORM-MySQL-2D3748?style=flat-square)](https://gorm.io/) -[![Redis](https://img.shields.io/badge/Redis-Session-DC382D?style=flat-square&logo=redis)](https://redis.io/) -[![Next.js](https://img.shields.io/badge/Next.js-Frontend-000000?style=flat-square&logo=nextdotjs)](https://nextjs.org/) +[![Redis](https://img.shields.io/badge/Redis-Optional-DC382D?style=flat-square&logo=redis)](https://redis.io/) +[![Next.js](https://img.shields.io/badge/Next.js-Demo%20UI-000000?style=flat-square&logo=nextdotjs)](https://nextjs.org/) AI Agent Scaffold Go 是一个面向 Agent 应用开发的 Go 脚手架,围绕 Gin、Eino、Google ADK Go、GORM、MySQL、Redis 构建,重点提供清晰的 DDD 分层、配置驱动的 Agent 装配、多 Agent 工作流编排和 HTTP 运行时接口。仓库同时附带一个基于 Next.js 的 `frontend/` 子项目,作为对接后端 API 的示例前端,这个场景是通过drawio组件搭建的,旨在通过多轮对话来画出理想中的流程图。 -这个项目适合作为 Agent 平台、智能助手后端、工作流 Agent 服务的起点。它把模型、工具、技能、Agent、Workflow、Runner 的装配逻辑收敛在领域层,通过端口隔离基础设施实现,让核心业务代码不直接依赖具体 SDK 或框架。 - ## 目录 -- [核心特性](#核心特性) +- [核心能力](#核心能力) - [技术栈](#技术栈) - [项目结构](#项目结构) -- [架构设计](#架构设计) +- [后端架构](#后端架构) +- [启动流程](#启动流程) - [Armory 装配流程](#armory-装配流程) +- [运行时对话流程](#运行时对话流程) - [快速开始](#快速开始) - [配置说明](#配置说明) - [HTTP API](#http-api) -- [开发命令](#开发命令) -- [当前实现状态](#当前实现状态) -- [路线图](#路线图) -- [Star 趋势](#star-趋势) -- [许可证](#许可证) +- [前端启动](#前端启动) +- [开发与验证](#开发与验证) +- [联系作者](#联系作者) -## 核心特性 +## 项目讲解文档 -- **配置驱动 Agent**:通过 YAML 定义模型 API、ChatModel、工具、技能、单 Agent、Workflow 和 Runner。 -- **多 Agent 工作流**:支持 `loop`、`parallel`、`sequential` 三类工作流 Agent 组装。 -- **Armory 规则树装配**:使用 `Root -> AiApi -> ChatModel -> Agent -> AgentWorkflow -> Runner` 的显式节点链路构建运行时 Agent。 -- **DDD 六层结构**:将 API 契约、应用启动、领域模型、触发器、基础设施和通用类型分离。 -- **端口隔离基础设施**:领域层依赖本地 ports,不直接耦合 Gin、GORM、Redis、Eino、ADK Go 等实现细节。 -- **HTTP 运行时接口**:提供查询 Agent、创建会话(POST/GET)、同步对话、流式对话四类接口。 -- **本地开发资产**:包含示例配置、MySQL/Redis Docker Compose、环境变量模板和可一键启动的 Next.js 示例前端。 +- 地址:[项目文档](https://my.feishu.cn/wiki/FbISwBnZPiGx0vkxyHFc8a1enig?fromScene=spaceOverview) +- 内容:简历写法、项目亮点与难点解析等 + +## 核心能力 + +- **配置驱动 Agent**:通过 `configs/agent/*.yaml` 声明模型 API、ChatModel、MCP 工具、skills、LLM Agent、workflow Agent 和 Runner。 +- **Armory 装配链**:按 `Root -> AiAPI -> ChatModel -> Agent -> AgentWorkflow -> Runner` 的顺序装配运行时对象。 +- **多 Agent 工作流**:支持 `loop`、`parallel`、`sequential` 三类 workflow Agent,串行工作流可通过 `output-key` 把上一步结果注入下一步指令。 +- **HTTP 运行时接口**:提供 Agent 列表、创建会话、同步聊天、SSE 流式聊天接口。 +- **OpenAI-compatible 模型调用**:基础设施层直接构造 Chat Completions 请求,支持普通响应和 `stream: true`。 +- **MCP SSE 工具调用**:装配阶段注册 SSE MCP 工具,运行时在模型触发 tool call 后执行 JSON-RPC `tools/call`,再把工具结果回灌给模型。 +- **Skill 资源扫描**:支持扫描 `SKILL.md`,把 skill 元数据转换为模型可见工具。 +- **分层边界清晰**:领域层依赖本地 `ports`,避免直接耦合 Gin、GORM、Redis、模型 provider 和 ADK 实现。 ## 技术栈 @@ -44,194 +48,262 @@ AI Agent Scaffold Go 是一个面向 Agent 应用开发的 Go 脚手架,围绕 | --- | --- | | 后端语言 | Go 1.25.6+ | | HTTP 框架 | Gin | -| Agent / 模型封装 | Eino | -| Agent 编排 | Google ADK Go | -| 持久化 | GORM + MySQL | -| 缓存 / 会话 | Redis | -| 配置 | YAML + 环境变量 | -| 日志 | zap | -| 前端 | Next.js + React + TailwindCSS | +| Agent 运行与插件 | Google ADK Go | +| 模型/工具抽象依赖 | Eino 相关依赖已纳入模块;当前模型调用由本地 OpenAI-compatible adapter 完成 | +| 配置 | YAML + dotenv + 环境变量占位符 | +| 模型协议 | OpenAI-compatible Chat Completions | +| 工具协议 | MCP SSE;stdio/local 配置结构已存在 | +| 持久化适配器 | GORM + MySQL,当前默认启动路径未强制启用 | +| 缓存适配器 | go-redis,当前默认启动路径未强制启用 | +| 日志 | zap + Gin logger | +| 前端 | Next.js 16 + React 19 + Tailwind CSS + react-drawio | ## 项目结构 ```text ai-agent-scaffold-go -├── cmd/server # 服务入口,当前负责启动日志初始化 +├── cmd/server +│ └── main.go # 后端入口:加载 .env、读取配置、构建应用、启动 HTTP 服务 ├── configs -│ ├── application.yaml # 应用、服务端口、MySQL、Redis、Agent 配置入口 +│ ├── application.yaml # 应用、端口、LLM 超时、Agent 配置路径、可选 DB/Redis 设置 │ └── agent -│ ├── only-one-agent.yaml # 单 Agent 示例配置(含 MCP 与 skills) -│ ├── agent-draw-io.yaml # draw.io Agent 示例配置 -│ └── skills/ # 内置 skill 资源(battle-plan、pdf 等) +│ ├── only-one-agent.yaml # 单 Agent 示例 +│ ├── agent-draw-io.yaml # draw.io 多 Agent 工作流示例 +│ └── skills/ # skill 资源,按 SKILL.md 扫描 ├── deployments -│ └── docker-compose.yml # 本地 MySQL / Redis -├── frontend # Next.js 示例前端,调用后端 /api/v1 +│ ├── docker-compose.yml # 本地 MySQL/Redis 参考服务 +│ ├── mysql/my.cnf +│ └── redis/redis.conf +├── frontend # Next.js draw.io 示例前端 ├── internal -│ ├── api # DTO 与统一响应封装 -│ ├── app # 应用装配与配置加载边界 +│ ├── api +│ │ ├── dto # HTTP 请求/响应 DTO +│ │ └── response # code/info/data 统一响应封装 +│ ├── app +│ │ ├── bootstrap # 应用装配:配置表加载、Armory、ChatService、Gin 路由 +│ │ └── config # application.yaml 与 Agent YAML 加载/校验 │ ├── domain │ │ ├── agent -│ │ │ ├── model # Agent 配置、聊天命令、Runner 等领域模型 -│ │ │ ├── ports # 模型、工具、Agent、Runner、Registry 等领域端口 +│ │ │ ├── model # Agent 配置模型、聊天命令、Runner 接口 +│ │ │ ├── ports # 模型、工具、Agent、Runner、Registry、SessionStore 端口 │ │ │ └── service -│ │ │ ├── armory # Agent 装配领域服务与核心节点 -│ │ │ │ ├── factory # 默认装配工厂 -│ │ │ │ └── workflow # loop / parallel / sequential 工作流节点 -│ │ │ └── chat # 会话与聊天运行时服务 +│ │ │ ├── armory # Agent 装配领域服务与节点链 +│ │ │ └── chat # 会话解析与聊天运行时服务 │ │ └── shared/tree # 泛型策略树路由框架 -│ ├── infrastructure # Eino、ADK、MySQL、Redis、日志等适配器 -│ └── trigger/http # Gin HTTP 入站适配器 -├── pkg/types # 响应码与应用错误 -├── .env.example # 环境变量示例 +│ ├── infrastructure +│ │ ├── adk # Agent/Runner/插件适配 +│ │ ├── ai # OpenAI-compatible client、MCP SSE client、tool/skill 工厂 +│ │ ├── cache # Redis client adapter +│ │ ├── logging # zap logger +│ │ └── persistence # MySQL/GORM adapter +│ └── trigger/http # Gin HTTP 入站路由 +├── pkg/types # 应用错误码与 AppError +├── .env.example ├── go.mod └── README.md ``` -## 架构设计 +## 后端架构 ```mermaid flowchart LR - Client["客户端 / frontend"] --> Trigger["trigger/http
Gin 路由"] - Trigger --> ChatService["domain/service/chat
聊天服务"] - ChatService --> Registry["AgentRegistry"] - Registry --> Runner["Runner"] + Client["Client / frontend"] --> Gin["trigger/http
Gin routes"] + Gin --> ChatService["domain/agent/service/chat"] + ChatService --> Registry["AgentRegistry
in-memory by default"] + ChatService --> SessionStore["SessionStore
in-memory by default"] + Registry --> Runner["model.Runner"] + Runner --> Agent["ADK adapter Agent"] + Agent --> Model["ports.ChatModel"] + Model --> OpenAI["OpenAI-compatible
chat/completions"] + Agent --> ToolRouter["MCPToolRouter"] + ToolRouter --> MCP["MCP SSE tools"] - Config["configs/*.yaml"] --> App["internal/app
配置加载与应用装配"] - App --> Armory["domain/service/armory
Agent 装配"] + Config["configs/application.yaml
configs/agent/*.yaml"] --> Bootstrap["internal/app/bootstrap"] + Bootstrap --> Armory["domain/agent/service/armory"] Armory --> Registry - - Armory --> Ports["domain/agent/ports"] - ChatService --> Ports - Ports --> Infra["internal/infrastructure"] - Infra --> Eino["Eino"] - Infra --> ADK["Google ADK Go"] - Infra --> MySQL["MySQL / GORM"] - Infra --> Redis["Redis"] ``` -### 分层边界 +后端按端口与适配器组织: -- `internal/api`:请求/响应 DTO 与统一响应结构。 -- `internal/app`:应用启动、配置加载、服务装配边界。 -- `internal/domain`:领域模型、端口、Armory 装配、聊天运行时、策略树框架。 -- `internal/trigger`:HTTP 等入站触发器。 -- `internal/infrastructure`:数据库、缓存、AI SDK、日志等外部依赖适配。 -- `pkg/types`:跨层可复用的错误码和应用错误。 +- `internal/domain` 定义核心模型、端口、Armory 装配和聊天服务。 +- `internal/app/bootstrap` 负责把配置、领域服务、基础设施 adapter 和 Gin 路由连起来。 +- `internal/infrastructure` 实现外部依赖适配,包括模型 client、MCP client、ADK Runner、Redis、MySQL 和日志。 +- `internal/trigger/http` 只处理 HTTP 入参、出参和路由注册。 +- `pkg/types` 提供跨层使用的错误码:`0000` 成功、`0001` 未知错误、`0002` 参数错误、`0003` Agent 不存在。 -领域层保持稳定,不直接导入 Gin、GORM、Redis、Eino、ADK Go 或 provider-specific 的基础设施包。 +## 启动流程 + +```mermaid +sequenceDiagram + participant Main as cmd/server + participant Config as app/config + participant Bootstrap as app/bootstrap + participant Armory as domain/armory + participant HTTP as Gin + + Main->>Main: parse -env and -config flags + Main->>Main: load dotenv file if present + Main->>Config: LoadApplication(configs/application.yaml) + Main->>Bootstrap: Build(context, appCfg, logger) + Bootstrap->>Config: LoadAgentTablesFile(configured paths) + Bootstrap->>Armory: AcceptArmoryAgents(tables) + Armory->>Bootstrap: registered runnable Agents + Bootstrap->>HTTP: create router and register /healthz + /api/v1 + Main->>HTTP: engine.Run() +``` + +入口文件是 `cmd/server/main.go`。默认行为: + +- `-env` 默认读取 `.env`,也可通过 `APP_ENV_FILE` 指定;传空字符串可跳过 dotenv。 +- `-config` 默认读取 `configs/application.yaml`,也可通过 `APP_CONFIG` 指定。 +- dotenv 中的变量会进入进程环境,Agent YAML 里的 `${VAR}` 和 `${VAR:-default}` 会在加载时展开。 +- `configs/application.yaml` 负责声明服务地址、LLM 请求超时、Agent 配置文件路径,以及当前可选的 MySQL/Redis 设置。 +- `bootstrap.Build` 会装配 Agent、创建 `ChatService`、注册 Gin 路由并返回可运行的 `Engine`。 ## Armory 装配流程 -Armory 是项目里的 Agent 装配链路。它接收 Agent 配置表,按节点顺序构建模型、工具、Agent、Workflow 和 Runner。 +Armory 是 Agent 配置到运行时对象的装配链。每个 Agent table 都会使用新的 `DynamicContext`,按节点顺序构建和传递装配状态。 ```mermaid flowchart TD - Root["RootNode
装配入口"] --> AiApi["AiAPINode
创建模型 API"] - AiApi --> ChatModel["ChatModelNode
创建 ChatModel 并挂载工具"] - ChatModel --> Agent["AgentNode
创建单 Agent"] - Agent --> Workflow["workflow.AgentWorkflowNode
创建工作流 Agent"] - Workflow --> Runner["RunnerNode
创建并注册 Runner"] + Root["RootNode"] --> Api["AiAPINode
build ModelAPI"] + Api --> ChatModel["ChatModelNode
build MCP/skill tools
build ChatModel"] + ChatModel --> Agent["AgentNode
build LLM Agents"] + Agent --> Workflow["AgentWorkflowNode
build loop/parallel/sequential Agents"] + Workflow --> Runner["RunnerNode
build Runner and register Agent"] ``` -最新代码已经按职责拆分: +关键文件: -```text -internal/domain/agent/service/armory -├── root_node.go -├── ai_api_node.go -├── chat_model_node.go -├── agent_node.go -├── runner_node.go -├── factory/factory.go -└── workflow - ├── agent_workflow_node.go - ├── loop_node.go - ├── parallel_node.go - └── sequential_node.go +- `internal/domain/agent/service/armory/factory/factory.go`:组合完整节点链。 +- `internal/domain/agent/service/armory/context.go`:保存 ModelAPI、ChatModel、已构建 Agent、当前 workflow 进度和临时值。 +- `internal/domain/agent/service/armory/chat_model_node.go`:构建 MCP 工具、skill 工具和 ChatModel。 +- `internal/domain/agent/service/armory/workflow/*.go`:按 `loop`、`parallel`、`sequential` 构建 workflow Agent。 +- `internal/domain/agent/service/armory/runner_node.go`:根据 `runner.agent-name` 找到入口 Agent,创建 Runner 并注册到 `AgentRegistry`。 + +Workflow 行为: + +- `sequential`:按配置顺序执行子 Agent,并用子 Agent 的 `output-key` 保存中间结果,后续 Agent 指令可用 `{output_key}` 引用。 +- `loop`:当前 adapter 中按 fan-out 方式执行配置的子 Agent;配置里保留 `max-iterations` 字段。 +- `parallel`:当前 adapter 中按 fan-out 方式聚合子 Agent 输出。 + +## 运行时对话流程 + +```mermaid +sequenceDiagram + participant Client + participant Handler as trigger/http + participant Chat as chat.Service + participant Registry as AgentRegistry + participant Runner + participant Agent + participant Model as OpenAI-compatible model + participant Tool as MCPToolRouter + + Client->>Handler: POST /api/v1/chat + Handler->>Chat: HandleMessage(agentId,userId,sessionId,message) + Chat->>Registry: Get(agentId) + Chat->>Runner: Run(userId,sessionId,content) + Runner->>Agent: run(content) + Agent->>Model: chat/completions + alt model requests tool calls + Agent->>Tool: CallTool(name,args) + Tool-->>Agent: tool result + Agent->>Model: next chat/completions with tool result + end + Model-->>Agent: final content + Agent-->>Runner: output + Runner-->>Handler: []string + Handler-->>Client: {code,info,data} ``` -Workflow 支持三种编排方式: - -- `loop`:循环执行子 Agent,支持最大迭代次数配置。 -- `parallel`:并行组合多个子 Agent。 -- `sequential`:按顺序串联单 Agent 或已装配的 Workflow Agent。 +同步聊天走 `Runner.Run`,流式聊天走 `Runner.Stream`。LLM Agent 最多允许 4 轮 tool-call 循环,避免工具调用无限递归。 ## 快速开始 ### 环境要求 - Go 1.25.6+ -- Node.js 18+ 与 npm(仅在启动 `frontend/` 时需要) -- Docker,可选,用于本地 MySQL / Redis +- Node.js 18+ 和 npm,仅启动 `frontend/` 时需要 +- Docker,可选,仅在本地启动 MySQL/Redis 参考服务时需要 +- 一个 OpenAI-compatible Chat Completions 服务 +- 如果启用示例里的百度搜索 MCP,还需要可访问的 MCP SSE endpoint -### 获取代码并编译 +### 1. 安装依赖并编译 ```bash -git clone cd ai-agent-scaffold-go go mod tidy go build ./... ``` -### 启动后端服务入口 +### 2. 准备环境变量 + +复制示例文件: ```bash -go run ./cmd/server +cp .env.example .env ``` -当前 `cmd/server` 会完成日志初始化并输出启动日志。完整运行时装配、Armory 初始化、Gin 路由挂载等能力已经按包结构准备好,后续可以继续在入口层串接。 +至少替换以下变量为自己的真实值: -### 启动本地基础设施 +```dotenv +OPENAI_BASE_URL=https://api.example.com/ +OPENAI_API_KEY=replace-with-your-key +BAIDU_SEARCH_MCP_BASE_URI=http://example.com/mcp/ +BAIDU_SEARCH_MCP_SSE_ENDPOINT=sse?api_key=replace-with-your-key +``` + +`configs/agent/*.yaml` 会读取这些变量来构建模型和 MCP 工具。 + +### 3. 可选:启动本地 MySQL/Redis + +当前默认后端启动路径使用内存态 Agent registry 和 session store;MySQL/Redis 适配器已经存在,但不是默认启动的硬依赖。需要本地服务时可以使用: ```bash docker compose -f deployments/docker-compose.yml up -d ``` -默认端口: +参考端口: - MySQL:`127.0.0.1:13306` - Redis:`127.0.0.1:16379` -### 启动前端 - -仓库内置一个 Next.js 示例前端,默认调用后端 `http://localhost:8091/api/v1`。最小启动方式: +### 4. 启动后端 ```bash -cd frontend -npm install -npm run dev +go run ./cmd/server ``` -访问: +也可以显式指定文件: + +```bash +go run ./cmd/server -env .env -config configs/application.yaml +``` + +默认监听地址来自 `configs/application.yaml`: ```text -http://localhost:3000 +:8091 ``` -更多前端使用细节见 `frontend/README.md`。 +健康检查: + +```bash +curl http://localhost:8091/healthz +``` + +预期响应: + +```json +{"status":"ok"} +``` ## 配置说明 -应用主配置: +### 应用配置 -```text -configs/application.yaml -``` - -Agent 示例配置: - -```text -configs/agent/only-one-agent.yaml -configs/agent/agent-draw-io.yaml -``` - -环境变量示例: - -```text -.env.example -``` - -`configs/application.yaml` 会声明服务端口、本地数据库、Redis 和 Agent 配置路径: +`configs/application.yaml` 控制应用启动参数: ```yaml app: @@ -241,16 +313,30 @@ server: addr: ":8091" database: required: false - dsn: "root:123456@tcp(127.0.0.1:13306)/ai_agent_scaffold_go?charset=utf8mb4&parseTime=True&loc=Local" + dsn: "root:@tcp(127.0.0.1:13306)/ai-agent-scaffold-go?charset=utf8mb4&parseTime=True&loc=Local" redis: required: false addr: "127.0.0.1:16379" + password: "" + db: 0 +llm: + request-timeout: 5m agent: config-paths: - configs/agent/only-one-agent.yaml + - configs/agent/agent-draw-io.yaml ``` -Agent 配置示例(节选自 `configs/agent/only-one-agent.yaml`): +说明: + +- `server.addr` 是 Gin 监听地址。 +- `llm.request-timeout` 使用 Go `time.ParseDuration` 格式,例如 `30s`、`5m`、`1h`。 +- `agent.config-paths` 可配置多个 Agent YAML,启动时会合并所有 tables。 +- `database` 和 `redis` 设置目前主要对应基础设施 adapter;默认 bootstrap 没有强制打开它们。 + +### Agent 配置 + +Agent 配置文件结构位于 `configs/agent/*.yaml`: ```yaml ai: @@ -265,17 +351,17 @@ ai: agent-desc: "single agent demo" module: ai-api: - base-url: "https://apis.itedus.cn" - api-key: "${OPENAI_API_KEY}" + base-url: ${OPENAI_BASE_URL} + api-key: ${OPENAI_API_KEY} completions-path: "v1/chat/completions" embeddings-path: "v1/embeddings" chat-model: - model: "gpt-4.1" + model: "gpt-5.5" tool-mcp-list: - sse: name: baidu-search - base-uri: http://appbuilder.baidu.com - sse-endpoint: /v2/ai_search/mcp/sse?api_key=${BAIDU_SEARCH_MCP_API_KEY} + base-uri: ${BAIDU_SEARCH_MCP_BASE_URI} + sse-endpoint: ${BAIDU_SEARCH_MCP_SSE_ENDPOINT} request-timeout: 500000 tool-skills-list: - type: "resource" @@ -292,25 +378,77 @@ ai: - "myLogPlugin" ``` -连接真实模型服务前,需要复制 `.env.example` 并设置真实的模型 API Key。 +启动时会校验: + +- `app-name` +- `agent.agent-id` +- `module.ai-api.base-url` +- `module.ai-api.api-key` +- `module.chat-model.model` +- `module.agents[].name` +- `module.agents[].instruction` +- `module.runner.agent-name` +- 每个 MCP tool 必须且只能声明 `local`、`sse`、`stdio` 之一 +- workflow type 必须是 `loop`、`parallel` 或 `sequential` + +默认值: + +- `ai-api.completions-path` 默认 `v1/chat/completions` +- `ai-api.embeddings-path` 默认 `v1/embeddings` +- `tool-skills-list[].type` 默认 `directory` +- `agent-workflows[].max-iterations` 默认 `3` ## HTTP API -基础路径: +非流式接口统一返回: -```text -/api/v1 +```json +{ + "code": "0000", + "info": "success", + "data": {} +} ``` -这些路由由 `internal/trigger/http/agent_handler.go` 中的 `RegisterAgentRoutes` 注册。当前服务入口还没有把 Gin 路由完整挂到 `cmd/server`,接入时可复用 `RegisterAgentRoutes(router, chatService)`。 +### GET /healthz -### 查询 Agent 配置 +健康检查。 + +```bash +curl http://localhost:8091/healthz +``` + +```json +{"status":"ok"} +``` + +### GET /api/v1/query_ai_agent_config_list + +查询已经注册的 Agent。 ```bash curl http://localhost:8091/api/v1/query_ai_agent_config_list ``` -### 创建会话 +响应示例: + +```json +{ + "code": "0000", + "info": "success", + "data": [ + { + "agentId": "100003", + "agentName": "single agent", + "agentDesc": "single agent demo" + } + ] +} +``` + +### POST /api/v1/create_session + +创建或复用某个 `userId + agentId` 的会话。 ```bash curl -X POST http://localhost:8091/api/v1/create_session \ @@ -318,31 +456,107 @@ curl -X POST http://localhost:8091/api/v1/create_session \ -d '{"agentId":"100003","userId":"u1001"}' ``` -也支持 GET: +响应示例: + +```json +{ + "code": "0000", + "info": "success", + "data": { + "sessionId": "testAgent03:u1001:1" + } +} +``` + +同等 GET 形式: ```bash curl 'http://localhost:8091/api/v1/create_session?agentId=100003&userId=u1001' ``` -### 同步对话 +### POST /api/v1/chat + +同步聊天。`sessionId` 可为空;为空时服务会自动创建或复用会话。 ```bash curl -X POST http://localhost:8091/api/v1/chat \ -H 'Content-Type: application/json' \ - -d '{"agentId":"100003","userId":"u1001","message":"帮我制定一个学习计划"}' + -d '{ + "agentId": "100003", + "userId": "u1001", + "sessionId": "", + "message": "帮我制定一个 Go Agent 学习计划" + }' ``` -### 流式对话 +响应示例: -`/chat_stream` 通过 SSE(`text/event-stream`)推送结果,每个分片以 `event: message` 形式发送,错误以 `event: error` 结束。 +```json +{ + "code": "0000", + "info": "success", + "data": { + "content": "..." + } +} +``` + +### POST /api/v1/chat_stream + +流式聊天,响应类型为 `text/event-stream`。 ```bash curl -N -X POST http://localhost:8091/api/v1/chat_stream \ -H 'Content-Type: application/json' \ - -d '{"agentId":"100003","userId":"u1001","sessionId":"session-u1001","message":"继续"}' + -d '{ + "agentId": "100003", + "userId": "u1001", + "sessionId": "", + "message": "继续细化第一周计划" + }' ``` -## 开发命令 +流式片段示例: + +```text +event: message +data: 第一周可以从... + +event: message +data: 接下来... +``` + +如果执行出错,服务会发送: + +```text +event: error +data: +``` + +## 前端启动 + +`frontend/` 是一个 Next.js draw.io 示例前端,默认调用 `http://localhost:8091/api/v1`;启动方式是 `cd frontend && npm install && npm run dev`,然后访问 `http://localhost:3000`。 + +如需改后端地址,设置: + +```bash +NEXT_PUBLIC_API_BASE_URL=http://localhost:8091/api/v1 +``` + +## 开发与验证 + +后端常用命令: + +```bash +go test ./... +go build ./... +``` + +检查 Go 文件是否需要格式化: + +```bash +test -z "$(gofmt -l .)" +``` 格式化: @@ -350,45 +564,14 @@ curl -N -X POST http://localhost:8091/api/v1/chat_stream \ gofmt -w . ``` -编译: +前端常用命令: ```bash -go build ./... +cd frontend +npm run lint +npm run build ``` -启动前端开发服务器: +## 联系作者 -```bash -cd frontend && npm run dev -``` - -## 当前实现状态 - -- DDD 包结构、领域模型、端口、策略树和 Armory 装配链路已经建立。 -- Armory 核心节点、工厂、Workflow 节点已按职责拆分。 -- ChatService、AgentRegistry、SessionStore 和 HTTP 路由边界已在代码结构中分离。 -- Eino、ADK Go、GORM、Redis、zap 等依赖已经纳入模块,并通过本地端口和基础设施包隔离。 -- `cmd/server` 已串接配置加载、Armory 装配、Gin 路由和插件链路,启动后即对外提供 `/api/v1` 接口。 -- Runner 已接入真实 OpenAI 兼容 ChatModel:`/api/v1/chat` 调 `chat/completions` 同步接口,`/api/v1/chat_stream` 走 `stream: true` SSE 推送 delta。 -- SSE MCP 客户端可用:装配阶段连接 `tool-mcp-list[].sse`,运行时模型选中工具后真正发起 JSON-RPC `tools/call` 并把结果回灌给下一轮模型请求,工具调用循环上限为 4 轮。 -- Local MCP、stdio MCP 仍返回 unsupported 错误;Skill 工具当前只向模型暴露名字,不参与执行。 -- `frontend/` 提供基于 Next.js 的 draw.io 示例前端,默认对接后端 `/api/v1`。 - -## 路线图 - -- 接入更稳定的模型 backoff / 重试与请求级超时控制。 -- 补齐 stdio MCP 客户端实现,扩展 local MCP 真实执行入口。 -- 让 Skill 工具具备运行时调用能力,并把 skill 元数据注入模型 tool schema。 -- 增加基于 MySQL 的 Agent 配置仓储。 -- 增加基于 Redis 的分布式会话存储。 -- 增加请求追踪、Token 用量、Agent Workflow 事件等可观测能力。 - -## Star 趋势 - -[![Star History Chart](https://api.star-history.com/svg?repos=peakxy/ai-agent-scaffold-go&type=Date)](https://star-history.com/#peakxy/ai-agent-scaffold-go&Date) - -## 许可证 - -## 联系方式 - -- 邮箱: 2465549609@qq.com +- 邮箱:2465549609@qq.com diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..993e4b7 --- /dev/null +++ b/go.sum @@ -0,0 +1,284 @@ +cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= +cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= +cloud.google.com/go/auth v0.20.0 h1:kXTssoVb4azsVDoUiF8KvxAqrsQcQtB53DcSgta74CA= +cloud.google.com/go/auth v0.20.0/go.mod h1:942/yi/itH1SsmpyrbnTMDgGfdy2BUqIKyd0cyYLc5Q= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/airbrake/gobrake v3.6.1+incompatible/go.mod h1:wM4gu3Cn0W0K7GUuVWnlXZU11AGBXMILnrdOU8Kn00o= +github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= +github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= +github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= +github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/bugsnag/bugsnag-go v1.4.0/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= +github.com/bugsnag/panicwrap v1.2.0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= +github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M= +github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM= +github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE= +github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k= +github.com/bytedance/sonic/loader v0.5.0 h1:gXH3KVnatgY7loH5/TkeVyXPfESoqSBSBEiDd5VjlgE= +github.com/bytedance/sonic/loader v0.5.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= +github.com/certifi/gocertifi v0.0.0-20190105021004-abcd57078448/go.mod h1:GJKEexRPVJrBSOjoqN5VNOIKJ5Q3RViH6eu3puDRwx4= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= +github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= +github.com/cloudwego/eino v0.9.2 h1:q9nsOy79UAs2yiCpVLzEzIOyv1BWbiP1rrdmNcv1wf0= +github.com/cloudwego/eino v0.9.2/go.mod h1:OBD1mrkfkt/pJa4rkg1P0VnaMeOVl7l8IAdEqY//3IQ= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/eino-contrib/jsonschema v1.0.3 h1:2Kfsm1xlMV0ssY2nuxshS4AwbLFuqmPmzIjLVJ1Fsp0= +github.com/eino-contrib/jsonschema v1.0.3/go.mod h1:cpnX4SyKjWjGC7iN2EbhxaTdLqGjCi0e9DxpLYxddD4= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw= +github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= +github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= +github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w= +github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= +github.com/gin-gonic/gin v1.12.0 h1:b3YAbrZtnf8N//yjKeU2+MQsh2mY5htkZidOM7O0wG8= +github.com/gin-gonic/gin v1.12.0/go.mod h1:VxccKfsSllpKshkBWgVgRniFFAzFb9csfngsqANjnLc= +github.com/go-check/check v0.0.0-20180628173108-788fd7840127 h1:0gkP6mzaMqkmpcJYCFOLkIBwI7xFExG03bbkOkCvUPI= +github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.30.1 h1:f3zDSN/zOma+w6+1Wswgd9fLkdwy06ntQJp0BBvFG0w= +github.com/go-playground/validator/v10 v10.30.1/go.mod h1:oSuBIQzuJxL//3MelwSLD5hc2Tu889bF0Idm9Dg26cM= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= +github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= +github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= +github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/jsonschema-go v0.4.2 h1:tmrUohrwoLZZS/P3x7ex0WAVknEkBZM46iALbcqoRA8= +github.com/google/jsonschema-go v0.4.2/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE= +github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= +github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= +github.com/google/safehtml v0.1.0 h1:EwLKo8qawTKfsi0orxcQAZzu07cICaBeFMegAU9eaT8= +github.com/google/safehtml v0.1.0/go.mod h1:L4KWwDsUJdECRAEpZoBn3O64bQaywRscowZjJAzjHnU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.15 h1:xolVQTEXusUcAA5UgtyRLjelpFFHWlPQ4XfWGc7MBas= +github.com/googleapis/enterprise-certificate-proxy v0.3.15/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= +github.com/googleapis/gax-go/v2 v2.22.0 h1:PjIWBpgGIVKGoCXuiCoP64altEJCj3/Ei+kSU5vlZD4= +github.com/googleapis/gax-go/v2 v2.22.0/go.mod h1:irWBbALSr0Sk3qlqb9SyJ1h68WjgeFuiOzI4Rqw5+aY= +github.com/goph/emperror v0.17.2 h1:yLapQcmEsO0ipe9p5TaN22djm3OFV/TfM/fcYP0/J18= +github.com/goph/emperror v0.17.2/go.mod h1:+ZbQ+fUNO/6FNiUo0ujtMjhgad9Xa6fQL9KhH4LNHic= +github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= +github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= +github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= +github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/nikolalohinski/gonja v1.5.3 h1:GsA+EEaZDZPGJ8JtpeGN78jidhOlxeJROpqMT9fTj9c= +github.com/nikolalohinski/gonja v1.5.3/go.mod h1:RmjwxNiXAEqcq1HeK5SSMmqFJvKOfTfXhkJv6YBtPa4= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= +github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= +github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw= +github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU= +github.com/redis/go-redis/v9 v9.20.0 h1:WnQYxLkgO2xiXTCJY0ldIiI8dNqCDlQAG+AtaH7a2a0= +github.com/redis/go-redis/v9 v9.20.0/go.mod h1:v/M13XI1PVCDcm01VtPFOADfZtHf8YW3baQf57KlIkA= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/rollbar/rollbar-go v1.0.2/go.mod h1:AcFs5f0I+c71bpHlXNNDbOWJiKwjFDtISeXco0L5PKQ= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/slongfield/pyfmt v0.0.0-20220222012616-ea85ff4c361f h1:Z2cODYsUxQPofhpYRMQVwWz4yUVpHF+vPi+eUdruUYI= +github.com/slongfield/pyfmt v0.0.0-20220222012616-ea85ff4c361f/go.mod h1:JqzWyvTuI2X4+9wOHmKSQCYxybB/8j6Ko43qVmXDuZg= +github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY= +github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= +github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY= +github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY= +github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4= +github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= +github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= +github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg= +github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= +github.com/yargevad/filepathx v1.0.0 h1:SYcT+N3tYGi+NvazubCNlvgIPbzAk7i7y2dwg3I5FYc= +github.com/yargevad/filepathx v1.0.0/go.mod h1:BprfX/gpYNJHJfc35GjRRpVcwWXS89gGulUIU5tK3tA= +github.com/zeebo/xxh3 v1.1.0 h1:s7DLGDK45Dyfg7++yxI0khrfwq9661w9EN78eP/UZVs= +github.com/zeebo/xxh3 v1.1.0/go.mod h1:IisAie1LELR4xhVinxWS5+zf1lA4p0MW4T+w+W07F5s= +go.mongodb.org/mongo-driver/v2 v2.5.0 h1:yXUhImUjjAInNcpTcAlPHiT7bIXhshCTL3jVBkF3xaE= +go.mongodb.org/mongo-driver/v2 v2.5.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo= +go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= +go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= +go.opentelemetry.io/otel/log v0.16.0 h1:DeuBPqCi6pQwtCK0pO4fvMB5eBq6sNxEnuTs88pjsN4= +go.opentelemetry.io/otel/log v0.16.0/go.mod h1:rWsmqNVTLIA8UnwYVOItjyEZDbKIkMxdQunsIhpUMes= +go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= +go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= +go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= +go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= +go.opentelemetry.io/otel/sdk/log v0.16.0 h1:e/b4bdlQwC5fnGtG3dlXUrNOnP7c8YLVSpSfEBIkTnI= +go.opentelemetry.io/otel/sdk/log v0.16.0/go.mod h1:JKfP3T6ycy7QEuv3Hj8oKDy7KItrEkus8XJE6EoSzw4= +go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= +go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= +go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= +go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= +go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= +go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.28.0 h1:IZzaP1Fv73/T/pBMLk4VutPl36uNC+OSUh3JLG3FIjo= +go.uber.org/zap v1.28.0/go.mod h1:rDLpOi171uODNm/mxFcuYWxDsqWSAVkFdX4XojSKg/Q= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/arch v0.22.0 h1:c/Zle32i5ttqRXjdLyyHZESLD/bB90DCU1g9l/0YBDI= +golang.org/x/arch v0.22.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= +golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= +golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= +golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w= +golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= +golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= +golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= +golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= +google.golang.org/adk v1.4.0 h1:Qi4KB9YKD00/I5K9v3QsZ9ng5YiZQ7MfMgM8BZjNcsM= +google.golang.org/adk v1.4.0/go.mod h1:R8tNFnI/eiBXHn7zJPJtqdiK/WXC+tVkyuZsXyNZXN4= +google.golang.org/api v0.279.0 h1:hsx2M2OaRcaKtVYK6vXEUnQvdjnend7ZYES+lYaot74= +google.golang.org/api v0.279.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ= +google.golang.org/genai v1.57.0 h1:qTyG2ynz5dQy2jF4CvZdLHHVslhR0heMue+zM1a4GNM= +google.golang.org/genai v1.57.0/go.mod h1:A3kkl0nyBjyFlNjgxIwKq70julKbIxpSxqKO5gw/gmk= +google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7 h1:XzmzkmB14QhVhgnawEVsOn6OFsnpyxNPRY9QV01dNB0= +google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7/go.mod h1:L43LFes82YgSonw6iTXTxXUX1OlULt4AQtkik4ULL/I= +google.golang.org/genproto/googleapis/api v0.0.0-20260427160629-7cedc36a6bc4 h1:yOzSCGPx+cp5VO7IxvZ9SBFF7j1tZVcNtlHR2iYKtVo= +google.golang.org/genproto/googleapis/api v0.0.0-20260427160629-7cedc36a6bc4/go.mod h1:Q9HWtNeE7tM9npdIsEvqXj1QJIvVoeAV3rtXtS715Cw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260511170946-3700d4141b60 h1:seT2EwLWM78plQ7wcDfuWBc/4FAEAXDDiaSol4ku4qo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260511170946-3700d4141b60/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.81.0 h1:W3G9N3KQf3BU+YuCtGKJk0CmxQNbAISICD/9AORxLIw= +google.golang.org/grpc v1.81.0/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/mysql v1.6.0 h1:eNbLmNTpPpTOVZi8MMxCi2aaIm0ZpInbORNXDwyLGvg= +gorm.io/driver/mysql v1.6.0/go.mod h1:D/oCC2GWK3M/dqoLxnOlaNKmXz8WNTfcS9y5ovaSqKo= +gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg= +gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs= +rsc.io/omap v1.2.0 h1:c1M8jchnHbzmJALzGLclfH3xDWXrPxSUHXzH5C+8Kdw= +rsc.io/omap v1.2.0/go.mod h1:C8pkI0AWexHopQtZX+qiUeJGzvc8HkdgnsWK4/mAa00= +rsc.io/ordered v1.1.1 h1:1kZM6RkTmceJgsFH/8DLQvkCVEYomVDJfBRLT595Uak= +rsc.io/ordered v1.1.1/go.mod h1:evAi8739bWVBRG9aaufsjVc202+6okf8u2QeVL84BCM=