From d8df571cce11f718ea53f0bff3bad5b3b189b962 Mon Sep 17 00:00:00 2001 From: fuzhongyun <15339891972@163.com> Date: Mon, 22 Dec 2025 11:14:15 +0800 Subject: [PATCH] =?UTF-8?q?feat:=201.=E5=A2=9E=E5=8A=A0=20eino=20tool=20?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E9=85=8D=E7=BD=AE=EF=BC=8C=E8=B4=A7=E6=98=93?= =?UTF-8?q?=E9=80=9A=E5=95=86=E5=93=81=E4=B8=8A=E4=BC=A0=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=8C=96=202.=20eino=20tool=20=E6=B3=A8?= =?UTF-8?q?=E5=86=8C=E6=96=B9=E6=B3=95=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/config_env.yaml | 16 +- internal/config/config.go | 13 +- internal/data/constants/capability.go | 136 +---------------- .../domain/tools/hyt/product_upload/client.go | 16 +- .../tools/hyt/product_upload/client_test.go | 3 +- .../tools/hyt/supplier_search/client.go | 19 ++- .../tools/hyt/warehouse_search/client.go | 15 +- internal/domain/tools/registry.go | 31 ++-- .../domain/workflow/hyt/product_upload.go | 138 +++++++----------- internal/domain/workflow/provider_set.go | 4 +- internal/domain/workflow/registry.go | 6 +- internal/domain/workflow/runtime/registry.go | 6 +- 12 files changed, 155 insertions(+), 248 deletions(-) diff --git a/config/config_env.yaml b/config/config_env.yaml index aa8b07b..a10a7d4 100644 --- a/config/config_env.yaml +++ b/config/config_env.yaml @@ -74,11 +74,19 @@ tools: zltxOrderAfterSaleResellerBatch: enabled: true base_url: "https://gateway.dev.cdlsxd.cn/zltx_api/admin/afterSales/reseller_pre_ai" + +# eino tool 配置 +eino_tools: + # 货易通商品上传 hytProductUpload: - enabled: true - base_url: "https://gateway.dev.cdlsxd.cn/zltx_api/admin/oursProduct" - - + base_url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/goods/supplier/batch/add/complete" + add_url: "https://gateway.dev.cdlsxd.cn/sw//#/goods/goodsManage" + # 货易通供应商查询 + hytSupplierSearch: + base_url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/supplier/list" + # 货易通仓库查询 + hytWarehouseSearch: + base_url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/warehouse/list" default_prompt: img_recognize: diff --git a/internal/config/config.go b/internal/config/config.go index 0c3f4dd..5cbb506 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -15,6 +15,7 @@ type Config struct { Coze CozeConfig `mapstructure:"coze"` Sys SysConfig `mapstructure:"sys"` Tools ToolsConfig `mapstructure:"tools"` + EinoTools EinoToolsConfig `mapstructure:"eino_tools"` Logging LoggingConfig `mapstructure:"logging"` Redis Redis `mapstructure:"redis"` DB DB `mapstructure:"db"` @@ -141,8 +142,6 @@ type ToolsConfig struct { CozeExpress ToolConfig `mapstructure:"cozeExpress"` // Coze 公司查询工具 CozeCompany ToolConfig `mapstructure:"cozeCompany"` - // 货易通商品上传 - HytProductUpload ToolConfig `mapstructure:"hytProductUpload"` } // ToolConfig 单个工具配置 @@ -155,6 +154,16 @@ type ToolConfig struct { AddURL string `mapstructure:"add_url"` } +// EinoToolsConfig eino tool 配置 +type EinoToolsConfig struct { + // 货易通商品上传 + HytProductUpload ToolConfig `mapstructure:"hytProductUpload"` + // 货易通供应商查询 + HytSupplierSearch ToolConfig `mapstructure:"hytSupplierSearch"` + // 货易通仓库查询 + HytWarehouseSearch ToolConfig `mapstructure:"hytWarehouseSearch"` +} + // LoggingConfig 日志配置 type LoggingConfig struct { Level string `mapstructure:"level"` diff --git a/internal/data/constants/capability.go b/internal/data/constants/capability.go index 9956336..fab9db7 100644 --- a/internal/data/constants/capability.go +++ b/internal/data/constants/capability.go @@ -32,11 +32,6 @@ const ( "货品图片": ["string"], // 商品多图,取1-2个即可 "电商销售价格": "string", // 商品电商销售价格 decimal(10,2) "销售价": "string", // 商品销售价格 decimal(10,2) - "供应商报价": "string", // 商品供应商报价 decimal(10,2) - "税率": "string", // 商品税率 x% - "默认供应商": "string", // 供应商名称 - "默认存放仓库": "string", // 仓库名称 - "利润": "string", // 商品利润 decimal(10,2) "备注": "string", // 备注 "长": "string", // 商品长度,decimal(10,2)+单位 "宽": "string", // 商品宽度,decimal(10,2)+单位 @@ -44,135 +39,14 @@ const ( "重量": "string", // 商品重量(kg) "SPU名称": "string", // 商品SPU名称 "SPU编码": "string" // 编码串,jd_{timestamp}_rand(1000-999) + "供应商报价": "string", // 商品供应商报价 decimal(10,2) + "税率": "string", // 商品税率 x% + "利润": "string", // 商品利润 decimal(10,2) + "默认供应商": "string", // 供应商名称 + "默认存放仓库": "string", // 仓库名称 }` ) -// 商品属性模板 -const ( - HYTProductPropertyTemplate = `{ - "important_data": { - "type": "object", - "properties": { - "supplier_name": { - "type": "string", - "description": "供应商名称" - }, - "warehouse_name": { - "type": "string", - "description": "仓库名称" - }, - "profit": { - "type": "float64", - "description": "利润 decimal(10,2)" - }, - "tax_rate": { - "type": "integer", - "description": "税率 (x)%" - } - } - }, - "goods_info": { - "type": "object", - "properties": { - "title": { - "type": "string", - "description": "商品名称" - }, - "brand": { - "type": "string", - "description": "品牌" - }, - "category": { - "type": "string", - "description": "分类" - }, - "price": { - "type": "float64", - "description": "市场价 decimal(10,2)" - }, - "sales_price": { - "type": "float64", - "description": "建议销售价 decimal(10,2)" - }, - "discount": { - "type": "integer", - "description": "折扣百分比 公式:(市场价-建议销售价)/市场价*100" - }, - "goods_attributes": { - "type": "string", - "description": "商品属性" - }, - "goods_bar_code": { - "type": "string", - "description": "商品条码" - }, - "goods_illustration": { - "type": "string", - "description": "商品插图" - }, - "goods_num": { - "type": "string", - "description": "商品编号" - }, - "introduction": { - "type": "string", - "description": "商品介绍" - }, - "spu_name": { - "type": "string", - "description": "SPU名称" - }, - "spu_num": { - "type": "string", - "description": "SPU编号" - }, - "stock": { - "type": "integer", - "description": "库存" - }, - "tax_rate": { - "type": "integer", - "description": "税率" - }, - "unit": { - "type": "string", - "description": "单位" - }, - "weight": { - "type": "string", - "description": "重量" - } - } - }, - "goods_media_list": { - "type": "array", - "description": "商品媒体文件列表", - "items": { - "type": "object", - "properties": { - "url": { - "type": "string", - "description": "媒体文件URL" - }, - "type": { - "type": "integer", - "description": "媒体类型(1:图片, 2:视频)" - }, - "sort": { - "type": "integer", - "description": "排序序号" - } - } - } - } - }` -) - -// 外部平台地址 -const ( - HYTProductListPageURL = "https://gateway.dev.cdlsxd.cn/sw//#/goods/goodsManage" -) - // 缓存key const ( CapabilityProductIngestCacheKey = "ai_scheduler:capability:product_ingest:%s" diff --git a/internal/domain/tools/hyt/product_upload/client.go b/internal/domain/tools/hyt/product_upload/client.go index 1cacbd9..6ebcc62 100644 --- a/internal/domain/tools/hyt/product_upload/client.go +++ b/internal/domain/tools/hyt/product_upload/client.go @@ -9,7 +9,17 @@ import ( "errors" ) -func Call(ctx context.Context, cfg config.ToolConfig, toolReq *ProductUploadRequest) (toolResp *ProductUploadResponse, err error) { +type Client struct { + cfg config.ToolConfig +} + +func New(cfg config.ToolConfig) *Client { + return &Client{ + cfg: cfg, + } +} + +func (c *Client) Call(ctx context.Context, toolReq *ProductUploadRequest) (toolResp *ProductUploadResponse, err error) { // 商品有且只能有一个 if len(toolReq.GoodsList) != 1 { err = errors.New("商品只能有一个") @@ -20,7 +30,7 @@ func Call(ctx context.Context, cfg config.ToolConfig, toolReq *ProductUploadRequ req := l_request.Request{ Method: "Post", - Url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/goods/supplier/batch/add/complete", + Url: c.cfg.BaseURL, Json: apiReq, } res, err := req.Send() @@ -51,7 +61,7 @@ func Call(ctx context.Context, cfg config.ToolConfig, toolReq *ProductUploadRequ } toolResp = &ProductUploadResponse{ - PreviewUrl: "https://gateway.dev.cdlsxd.cn/sw//#/goods/goodsManage", + PreviewUrl: c.cfg.AddURL, SpuNum: toolReq.GoodsList[0].GoodsInfo.SpuNum, Id: resMap.Data.Ids[0], } diff --git a/internal/domain/tools/hyt/product_upload/client_test.go b/internal/domain/tools/hyt/product_upload/client_test.go index 5e8b111..fdd99f0 100644 --- a/internal/domain/tools/hyt/product_upload/client_test.go +++ b/internal/domain/tools/hyt/product_upload/client_test.go @@ -50,7 +50,8 @@ func Test_Call(t *testing.T) { }, }, } - toolResp, err := Call(context.Background(), config.ToolConfig{}, req) + client := New(config.ToolConfig{}) + toolResp, err := client.Call(context.Background(), req) if err != nil { t.Errorf("Call() error = %v", err) diff --git a/internal/domain/tools/hyt/supplier_search/client.go b/internal/domain/tools/hyt/supplier_search/client.go index ebffe0b..bd53aa9 100644 --- a/internal/domain/tools/hyt/supplier_search/client.go +++ b/internal/domain/tools/hyt/supplier_search/client.go @@ -1,16 +1,27 @@ package supplier_search import ( + "ai_scheduler/internal/config" "ai_scheduler/internal/pkg/l_request" "context" "encoding/json" - "errors" "fmt" ) -func Call(ctx context.Context, name string) (int, error) { +type Client struct { + cfg config.ToolConfig +} + +func New(cfg config.ToolConfig) *Client { + return &Client{ + cfg: cfg, + } +} + +func (c *Client) Call(ctx context.Context, name string) (int, error) { if name == "" { - return 0, errors.New("supplier name is empty") + // 如果没有供应商名,返回0,不报错,由上层业务决定是否允许 + return 0, nil } reqBody := SearchRequest{ @@ -27,7 +38,7 @@ func Call(ctx context.Context, name string) (int, error) { req := l_request.Request{ Method: "Post", - Url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/supplier/list", + Url: c.cfg.BaseURL, Json: apiReq, Headers: map[string]string{ "User-Agent": "Apifox/1.0.0 (https://apifox.com)", diff --git a/internal/domain/tools/hyt/warehouse_search/client.go b/internal/domain/tools/hyt/warehouse_search/client.go index 7b0190b..32d7fa4 100644 --- a/internal/domain/tools/hyt/warehouse_search/client.go +++ b/internal/domain/tools/hyt/warehouse_search/client.go @@ -1,13 +1,24 @@ package warehouse_search import ( + "ai_scheduler/internal/config" "ai_scheduler/internal/pkg/l_request" "context" "encoding/json" "fmt" ) -func Call(ctx context.Context, name string) (int, error) { +type Client struct { + cfg config.ToolConfig +} + +func New(cfg config.ToolConfig) *Client { + return &Client{ + cfg: cfg, + } +} + +func (c *Client) Call(ctx context.Context, name string) (int, error) { if name == "" { // 如果没有仓库名,返回0,不报错,由上层业务决定是否允许 return 0, nil @@ -22,7 +33,7 @@ func Call(ctx context.Context, name string) (int, error) { req := l_request.Request{ Method: "Get", - Url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/warehouse/list", + Url: c.cfg.BaseURL, Params: params, Headers: map[string]string{ "User-Agent": "Apifox/1.0.0 (https://apifox.com)", diff --git a/internal/domain/tools/registry.go b/internal/domain/tools/registry.go index dc6a67e..31a8636 100644 --- a/internal/domain/tools/registry.go +++ b/internal/domain/tools/registry.go @@ -1,16 +1,29 @@ package tools -type Tool interface{ - Name() string +import ( + "ai_scheduler/internal/config" + "ai_scheduler/internal/domain/tools/hyt/product_upload" + "ai_scheduler/internal/domain/tools/hyt/supplier_search" + "ai_scheduler/internal/domain/tools/hyt/warehouse_search" +) + +type Manager struct { + Hyt *HytTools + // Zltx *ZltxTools } -var registry = map[string]Tool{} - -func Register(t Tool){ - registry[t.Name()] = t +type HytTools struct { + ProductUpload *product_upload.Client + SupplierSearch *supplier_search.Client + WarehouseSearch *warehouse_search.Client } -func Get(name string) Tool{ - return registry[name] +func NewManager(cfg *config.Config) *Manager { + return &Manager{ + Hyt: &HytTools{ + ProductUpload: product_upload.New(cfg.EinoTools.HytProductUpload), + SupplierSearch: supplier_search.New(cfg.EinoTools.HytSupplierSearch), + WarehouseSearch: warehouse_search.New(cfg.EinoTools.HytWarehouseSearch), + }, + } } - diff --git a/internal/domain/workflow/hyt/product_upload.go b/internal/domain/workflow/hyt/product_upload.go index 4b85f37..0a93ce1 100644 --- a/internal/domain/workflow/hyt/product_upload.go +++ b/internal/domain/workflow/hyt/product_upload.go @@ -2,36 +2,33 @@ package hyt import ( "ai_scheduler/internal/config" - "ai_scheduler/internal/data/constants" + toolManager "ai_scheduler/internal/domain/tools" toolPu "ai_scheduler/internal/domain/tools/hyt/product_upload" - toolSs "ai_scheduler/internal/domain/tools/hyt/supplier_search" - toolWs "ai_scheduler/internal/domain/tools/hyt/warehouse_search" "ai_scheduler/internal/domain/workflow/runtime" "ai_scheduler/internal/entitys" "context" "encoding/json" + "errors" "fmt" "strconv" "strings" "sync" - eino_ollama "github.com/cloudwego/eino-ext/components/model/ollama" - "github.com/cloudwego/eino/components/prompt" "github.com/cloudwego/eino/compose" - "github.com/cloudwego/eino/schema" ) const WorkflowID = "hyt.productUpload" func init() { runtime.Register(WorkflowID, func(d *runtime.Deps) (runtime.Workflow, error) { - return &productUpload{cfg: d.Conf}, nil + return &productUpload{cfg: d.Conf, toolManager: d.ToolManager}, nil }) } type productUpload struct { - cfg *config.Config - data *ProductUploadWorkflowInput + cfg *config.Config + toolManager *toolManager.Manager + data *ProductUploadWorkflowInput } type ProductUploadWorkflowInput struct { @@ -41,8 +38,8 @@ type ProductUploadWorkflowInput struct { func (o *productUpload) ID() string { return WorkflowID } func (o *productUpload) Invoke(ctx context.Context, rec *entitys.Recognize) (map[string]any, error) { - // 构建工作流 (使用 V2 Graph 版本) - runnable, err := o.buildWorkflowV2(ctx) + // 构建工作流 + runnable, err := o.buildWorkflow(ctx) if err != nil { return nil, err } @@ -103,65 +100,11 @@ type ProductUploadContext struct { UploadResp *toolPu.ProductUploadResponse } +// buildWorkflow 构建基于 Graph 的并行工作流 func (o *productUpload) buildWorkflow(ctx context.Context) (compose.Runnable[*ProductUploadWorkflowInput, map[string]any], error) { - // 定义工作流 - c := compose.NewChain[*ProductUploadWorkflowInput, map[string]any]() - - // AI映射工具所需参数' - paramMappingModel, err := eino_ollama.NewChatModel(ctx, &eino_ollama.ChatModelConfig{ - BaseURL: o.cfg.Ollama.BaseURL, - Timeout: o.cfg.Ollama.Timeout, - Model: o.cfg.Ollama.Model, - Thinking: &eino_ollama.ThinkValue{Value: true}, - Options: &eino_ollama.Options{Temperature: 0.5}, - }) - if err != nil { - return nil, err - } - - // 1. 构建参数LLM数映射提示词 - c.AppendChatTemplate(prompt.FromMessages( - schema.FString, - schema.SystemMessage("你是一个专业的商品参数解析器,你需要根据用户输入的商品描述,解析出商品的目标参数。"), - schema.SystemMessage("目标参数:"+constants.HYTProductPropertyTemplate), - schema.UserMessage("用户输入:{{.Text}}"), - )) - // 2. 调用LLM - c.AppendChatModel(paramMappingModel) - - // 3.工具参数整理 - c.AppendLambda(compose.InvokableLambda(func(_ context.Context, in *schema.Message) (*toolPu.ProductUploadRequest, error) { - toolReq := &toolPu.ProductUploadRequest{} - if err := json.Unmarshal([]byte(in.Content), toolReq); err != nil { - return nil, err - } - return toolReq, nil - })) - - // 4.工具调用 - c.AppendLambda(compose.InvokableLambda(func(_ context.Context, in *toolPu.ProductUploadRequest) (*toolPu.ProductUploadResponse, error) { - toolRes, err := toolPu.Call(ctx, o.cfg.Tools.HytProductUpload, in) - return toolRes, err - })) - - // 5.结果数据映射 - c.AppendLambda(compose.InvokableLambda(func(_ context.Context, in *toolPu.ProductUploadResponse) (map[string]any, error) { - return map[string]any{ - "预览URL(货易通商品列表)": in.PreviewUrl, - "SPU编码": in.SpuNum, - "商品ID": in.Id, - }, nil - })) - - // 6.编译工作流 - return c.Compile(ctx) -} - -// buildWorkflowV2 构建基于 Graph 的并行工作流 -func (o *productUpload) buildWorkflowV2(ctx context.Context) (compose.Runnable[*ProductUploadWorkflowInput, map[string]any], error) { g := compose.NewGraph[*ProductUploadWorkflowInput, map[string]any]() - // 1. DataMapping 节点: 解析 JSON -> 填充基础 Request -> 提取供应商/仓库名 + // 1. DataMapping 节点: 解析 JSON -> 填充基础 Request g.AddLambdaNode("data_mapping", compose.InvokableLambda(func(ctx context.Context, in *ProductUploadWorkflowInput) (*ProductUploadContext, error) { state := &ProductUploadContext{ mu: &sync.Mutex{}, // 初始化锁 @@ -176,6 +119,21 @@ func (o *productUpload) buildWorkflowV2(ctx context.Context) (compose.Runnable[* if err := json.Unmarshal([]byte(in.Text), &ingestData); err != nil { return nil, fmt.Errorf("解析商品数据失败: %w", err) } + + // 必填校验 + if ingestData.SupplierName == "" { + return nil, errors.New("供应商名称不能为空") + } + if ingestData.WarehouseName == "" { + return nil, errors.New("仓库名称不能为空") + } + if ingestData.Profit == "" { + return nil, errors.New("利润不能为空") + } + if ingestData.TaxRate == "" { + return nil, errors.New("税率不能为空") + } + state.IngestData = &ingestData state.SupplierName = ingestData.SupplierName state.WarehouseName = ingestData.WarehouseName @@ -240,32 +198,38 @@ func (o *productUpload) buildWorkflowV2(ctx context.Context) (compose.Runnable[* // 2. 获取供应商ID 节点 g.AddLambdaNode("get_supplier_id", compose.InvokableLambda(func(ctx context.Context, state *ProductUploadContext) (*ProductUploadContext, error) { - if state.SupplierName != "" { - supplierId, err := toolSs.Call(ctx, state.SupplierName) - if err != nil { - // 记录日志,但不阻断流程,可能允许 ID 为 0 - fmt.Printf("warning: failed to get supplier id for %s: %v\n", state.SupplierName, err) - } else { - state.mu.Lock() - defer state.mu.Unlock() - state.UploadReq.SupplierId = supplierId - } + if state.SupplierName == "" { + return state, errors.New("供应商名称不能为空") } + + supplierId, err := o.toolManager.Hyt.SupplierSearch.Call(ctx, state.SupplierName) + if err != nil { + // 记录日志,但不阻断流程,可能允许 ID 为 0 + fmt.Printf("warning: failed to get supplier id for %s: %v\n", state.SupplierName, err) + } else { + state.mu.Lock() + defer state.mu.Unlock() + state.UploadReq.SupplierId = supplierId + } + return state, nil })) // 3. 获取仓库ID 节点 g.AddLambdaNode("get_warehouse_id", compose.InvokableLambda(func(ctx context.Context, state *ProductUploadContext) (*ProductUploadContext, error) { - if state.WarehouseName != "" { - warehouseId, err := toolWs.Call(ctx, state.WarehouseName) - if err != nil { - fmt.Printf("warning: failed to get warehouse id for %s: %v\n", state.WarehouseName, err) - } else { - state.mu.Lock() - defer state.mu.Unlock() - state.UploadReq.WarehouseId = warehouseId - } + if state.WarehouseName == "" { + return state, errors.New("仓库名称不能为空") } + + warehouseId, err := o.toolManager.Hyt.WarehouseSearch.Call(ctx, state.WarehouseName) + if err != nil { + fmt.Printf("warning: failed to get warehouse id for %s: %v\n", state.WarehouseName, err) + } else { + state.mu.Lock() + defer state.mu.Unlock() + state.UploadReq.WarehouseId = warehouseId + } + return state, nil })) @@ -280,7 +244,7 @@ func (o *productUpload) buildWorkflowV2(ctx context.Context) (compose.Runnable[* // 5. 上传节点 g.AddLambdaNode("upload_product", compose.InvokableLambda(func(ctx context.Context, state *ProductUploadContext) (*ProductUploadContext, error) { - toolRes, err := toolPu.Call(ctx, o.cfg.Tools.HytProductUpload, state.UploadReq) + toolRes, err := o.toolManager.Hyt.ProductUpload.Call(ctx, state.UploadReq) if err != nil { return nil, err } diff --git a/internal/domain/workflow/provider_set.go b/internal/domain/workflow/provider_set.go index c728b44..97e1b5d 100644 --- a/internal/domain/workflow/provider_set.go +++ b/internal/domain/workflow/provider_set.go @@ -5,6 +5,8 @@ import ( "ai_scheduler/internal/domain/workflow/runtime" "ai_scheduler/internal/pkg/utils_ollama" + toolManager "ai_scheduler/internal/domain/tools" + "github.com/google/wire" ) @@ -13,7 +15,7 @@ var ProviderSetWorkflow = wire.NewSet(NewRegistry) // NewRegistry 注入共享依赖并注册默认 Registry,确保自注册工作流可被发现 func NewRegistry(conf *config.Config, llm *utils_ollama.Client) *runtime.Registry { // 步骤1:设置运行时依赖(配置与LLM客户端),供工作流工厂在首次实例化时使用;必须在任何调用 Invoke 之前完成,否则会触发 "deps not set" - runtime.SetDeps(&runtime.Deps{Conf: conf, LLM: llm}) + runtime.SetDeps(&runtime.Deps{Conf: conf, LLM: llm, ToolManager: toolManager.NewManager(conf)}) // 步骤2:创建新的工作流注册表;注册表负责按工作流ID惰性实例化并缓存单例实例,保障并发访问下的安全 r := runtime.NewRegistry() // 步骤3:将该注册表设置为全局默认,便于通过 runtime.Default() 获取;自注册的工作流可通过默认注册表被发现并调用 diff --git a/internal/domain/workflow/registry.go b/internal/domain/workflow/registry.go index cbde3b6..af69a03 100644 --- a/internal/domain/workflow/registry.go +++ b/internal/domain/workflow/registry.go @@ -2,11 +2,13 @@ package workflow import ( "ai_scheduler/internal/config" + toolManager "ai_scheduler/internal/domain/tools" "ai_scheduler/internal/pkg/utils_ollama" ) // 仅声明依赖结构,避免在 workflow 包内实现注册中心逻辑导致循环依赖 type Deps struct { - Conf *config.Config - LLM *utils_ollama.Client + Conf *config.Config + LLM *utils_ollama.Client + ToolManager *toolManager.Manager } diff --git a/internal/domain/workflow/runtime/registry.go b/internal/domain/workflow/runtime/registry.go index bf840e6..2b4049b 100644 --- a/internal/domain/workflow/runtime/registry.go +++ b/internal/domain/workflow/runtime/registry.go @@ -2,6 +2,7 @@ package runtime import ( "ai_scheduler/internal/config" + toolManager "ai_scheduler/internal/domain/tools" "ai_scheduler/internal/entitys" "ai_scheduler/internal/pkg/utils_ollama" "context" @@ -16,8 +17,9 @@ type Workflow interface { } type Deps struct { - Conf *config.Config - LLM *utils_ollama.Client + Conf *config.Config + LLM *utils_ollama.Client + ToolManager *toolManager.Manager } type Factory func(deps *Deps) (Workflow, error)