feat: add graph visualizer by mermaid

Change-Id: I97c20a4a3cccdb4fb95dfb12c9c0dbfc9e313f6e
drew/english
shentong.martin 5 months ago committed by shentongmartin
parent 89b2d21a9f
commit 589b192304

@ -31,6 +31,7 @@ import (
"github.com/cloudwego/eino/schema"
"github.com/coze-dev/cozeloop-go"
"github.com/cloudwego/eino-examples/devops/visualize"
"github.com/cloudwego/eino-examples/internal/gptr"
"github.com/cloudwego/eino-examples/internal/logs"
)
@ -142,7 +143,7 @@ func main() {
}))
// compile
r, err := chain.Compile(ctx)
r, err := chain.Compile(ctx, compose.WithGraphCompileCallbacks(visualize.NewMermaidGenerator("compose/chain")), compose.WithGraphName("chain"))
if err != nil {
log.Panic(err)
return

@ -29,6 +29,8 @@ import (
"github.com/cloudwego/eino/compose"
"github.com/cloudwego/eino/schema"
"github.com/coze-dev/cozeloop-go"
"github.com/cloudwego/eino-examples/devops/visualize"
)
const (
@ -68,11 +70,18 @@ func main() {
_ = g.AddEdge(nodeOfPrompt, nodeOfModel)
_ = g.AddEdge(nodeOfModel, compose.END)
r, err := g.Compile(ctx, compose.WithMaxRunSteps(10))
gen := visualize.NewMermaidGenerator("compose/graph/simple")
r, err := g.Compile(ctx,
compose.WithMaxRunSteps(10),
compose.WithGraphCompileCallbacks(gen),
compose.WithGraphName("SimpleGraph"),
)
if err != nil {
panic(err)
}
// Mermaid markdown and images are auto-generated in compose/graph/simple
in := map[string]any{"location": "beijing"}
ret, err := r.Invoke(ctx, in)
if err != nil {

@ -25,6 +25,7 @@ import (
"github.com/cloudwego/eino/compose"
"github.com/coze-dev/cozeloop-go"
"github.com/cloudwego/eino-examples/devops/visualize"
"github.com/cloudwego/eino-examples/internal/logs"
)
@ -90,12 +91,15 @@ func main() {
wf.End().AddInput("b1", compose.ToField("bidder1")).
AddInput("b2", compose.ToField("bidder2"))
runner, err := wf.Compile(context.Background())
gen := visualize.NewMermaidGenerator("compose/workflow/4_control_only_branch")
runner, err := wf.Compile(context.Background(), compose.WithGraphCompileCallbacks(gen), compose.WithGraphName("Workflow-Control-Only-Branch"))
if err != nil {
logs.Errorf("workflow compile error: %v", err)
return
}
// Mermaid markdown and images are auto-generated in compose/workflow/4_control_only_branch
result, err := runner.Invoke(context.Background(), 3.0)
if err != nil {
logs.Errorf("workflow run err: %v", err)

@ -0,0 +1,456 @@
/*
* Copyright 2025 CloudWeGo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package visualize
import (
"context"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"sort"
"strings"
"github.com/chromedp/chromedp"
"github.com/cloudwego/eino/compose"
)
// MermaidGenerator renders a Mermaid diagram from a compiled Eino graph (Graph/Chain/Workflow).
//
// Core concepts and mapping:
// - Nodes: labeled with their key and component type. Lambda nodes use rounded shapes.
// - Special nodes: START/END are rendered with safe IDs (start_node/end_node) to avoid Mermaid keyword conflicts.
// - SubGraphs: nested Graph/Chain/Workflow are rendered as Mermaid sub-graphs with their component type in the title.
// - Edges:
// - In general graphs/chains: a single solid arrow (-->), representing standard control+data execution.
// - In workflows (workflowStyle=true): edges are distinguished by semantics:
// - control+data: normal arrow with label "control+data" ("-- control+data -->")
// - control-only: bold arrow with label "control-only" ("== control-only ==>")
// - data-only: dotted arrow with label "data-only" ("-. data-only .->")
// Branch decision diamonds and their incoming/outgoing edges are treated as control-only in workflows.
//
// Usage:
//
// buf := &bytes.Buffer{}
// gen := visualize.NewMermaidGenerator(buf) // for Graph/Chain
// // or
// gen := visualize.NewMermaidGeneratorWorkflow(buf) // for Workflow with labeled edges
// _, _ = g.Compile(ctx, compose.WithGraphCompileCallbacks(gen), compose.WithGraphName("MyGraph"))
// // Write to a Markdown file:
// md := "```mermaid\n" + buf.String() + "\n```\n"
// _ = os.WriteFile("my_graph.md", []byte(md), 0644)
type MermaidGenerator struct {
w io.Writer
workflowStyle bool
autoWrite bool
outDir string
baseName string
makeImages bool
}
// NewMermaidGenerator creates a generator that auto-writes Markdown and attempts PNG/SVG generation.
// If dir is empty, current working directory is used. File name is derived from graph name or defaults to "topology".
func NewMermaidGenerator(dir string) *MermaidGenerator {
return &MermaidGenerator{autoWrite: true, outDir: dir, makeImages: true}
}
// OnFinish is the compile callback entrypoint invoked by Eino after graph compilation.
// It reads the compile-time GraphInfo and writes a complete Mermaid diagram to the writer.
func (m *MermaidGenerator) OnFinish(_ context.Context, info *compose.GraphInfo) {
m.generate(info)
}
// generate orchestrates diagram construction by delegating to renderGraph.
// The top-level direction is TD (top-down) for readability and consistency.
func (m *MermaidGenerator) generate(info *compose.GraphInfo) {
var isWorkflow bool
if len(info.Edges) > len(info.DataEdges) {
isWorkflow = true
}
if !isWorkflow {
for from, edges := range info.Edges {
dataEdges, ok := info.DataEdges[from]
if !ok {
isWorkflow = true
break
}
if len(edges) != len(dataEdges) {
isWorkflow = true
break
}
for i := range edges {
edge := edges[i]
found := false
for _, dEdge := range dataEdges {
if dEdge == edge {
found = true
break
}
}
if !found {
isWorkflow = true
break
}
}
}
}
sb := &strings.Builder{}
sb.WriteString("graph TD\n")
m.renderGraph(sb, info, "", 1, isWorkflow)
if m.w != nil && !m.autoWrite {
_, _ = fmt.Fprint(m.w, sb.String())
return
}
dir := m.outDir
if dir == "" {
if wd, err := os.Getwd(); err == nil {
dir = wd
} else {
dir = "."
}
}
name := m.baseName
if name == "" {
if len(info.Name) > 0 {
name = sanitize(info.Name)
} else {
name = "topology"
}
}
mdPath := filepath.Join(dir, name+".md")
content := sb.String()
_ = os.WriteFile(mdPath, []byte("```mermaid\n"+content+"\n```"), 0644)
if m.makeImages {
mmdPath := filepath.Join(dir, name+".mmd")
_ = os.WriteFile(mmdPath, []byte(content), 0644)
m.renderImage(mmdPath, filepath.Join(dir, name+".png"))
_ = os.Remove(mmdPath)
}
}
// renderGraph builds a Mermaid diagram section for the given GraphInfo.
// It:
// 1) Collects and sorts node keys for deterministic output
// 2) Renders nodes (including nested sub-graphs)
// 3) Renders control/data edges with workflow-aware styles
// 4) Renders branches with decision diamonds and proper edge types
func (m *MermaidGenerator) renderGraph(sb *strings.Builder, info *compose.GraphInfo, prefix string, indentLevel int, style bool) {
indent := strings.Repeat(" ", indentLevel)
// Collect all nodes from info.Nodes, Edges, and Branches
allNodes := make(map[string]bool)
for k := range info.Nodes {
allNodes[k] = true
}
for start, ends := range info.Edges {
allNodes[start] = true
for _, end := range ends {
allNodes[end] = true
}
}
for start, branches := range info.Branches {
allNodes[start] = true
for _, branch := range branches {
endNodes := branch.GetEndNode()
for end := range endNodes {
allNodes[end] = true
}
}
}
// Sort nodes for deterministic output
nodes := make([]string, 0, len(allNodes))
for k := range allNodes {
nodes = append(nodes, k)
}
sort.Strings(nodes)
// Render Nodes
for _, nodeKey := range nodes {
nodeID := m.nodeID(prefix, nodeKey)
if nodeInfo, ok := info.Nodes[nodeKey]; ok {
if nodeInfo.GraphInfo != nil {
// Subgraph
subgraphLabel := nodeKey
if nodeInfo.Component == compose.ComponentOfChain {
subgraphLabel = fmt.Sprintf("%s (Chain)", nodeKey)
} else if nodeInfo.Component == compose.ComponentOfWorkflow {
subgraphLabel = fmt.Sprintf("%s (Workflow)", nodeKey)
} else if nodeInfo.Component == compose.ComponentOfGraph {
subgraphLabel = fmt.Sprintf("%s (Graph)", nodeKey)
}
sb.WriteString(fmt.Sprintf("%ssubgraph %s [\"%s\"]\n", indent, nodeID, subgraphLabel))
childStyle := style
if nodeInfo.Component == compose.ComponentOfWorkflow {
childStyle = true
} else if nodeInfo.Component == compose.ComponentOfGraph || nodeInfo.Component == compose.ComponentOfChain {
// for explicit Graph/Chain sub-graphs, do not apply workflow styling
childStyle = false
}
m.renderGraph(sb, nodeInfo.GraphInfo, nodeID+"_", indentLevel+1, childStyle)
sb.WriteString(fmt.Sprintf("%send\n", indent))
} else {
// Regular Node
shapeStart, shapeEnd := "[", "]"
if nodeInfo.Component == compose.ComponentOfLambda {
shapeStart, shapeEnd = "(", ")"
}
label := fmt.Sprintf("%s<br/>(%s)", nodeKey, nodeInfo.Component)
sb.WriteString(fmt.Sprintf("%s%s%s\"%s\"%s\n", indent, nodeID, shapeStart, label, shapeEnd))
}
} else if nodeKey == compose.START || nodeKey == compose.END {
// Special nodes: avoid reserved keyword conflict with 'end'
safeID := nodeID
if nodeKey == compose.START {
safeID = m.nodeID(prefix, "start_node")
} else {
safeID = m.nodeID(prefix, "end_node")
}
sb.WriteString(fmt.Sprintf("%s%s([%s])\n", indent, safeID, nodeKey))
}
}
// Render Control Edges
// Sort edges for deterministic output
startNodes := make([]string, 0, len(info.Edges))
for k := range info.Edges {
startNodes = append(startNodes, k)
}
sort.Strings(startNodes)
for _, start := range startNodes {
ends := info.Edges[start]
for _, end := range ends {
startID := m.nodeID(prefix, start)
endID := m.nodeID(prefix, end)
if start == compose.START {
startID = m.nodeID(prefix, "start_node")
}
if end == compose.END {
endID = m.nodeID(prefix, "end_node")
}
// Determine edge semantics by checking if a matching data edge exists.
hasData := false
if des, ok := info.DataEdges[start]; ok {
for _, de := range des {
if de == end {
hasData = true
break
}
}
}
if style {
if hasData {
sb.WriteString(fmt.Sprintf("%s%s -- control+data --> %s\n", indent, startID, endID))
} else {
sb.WriteString(fmt.Sprintf("%s%s == control-only ==> %s\n", indent, startID, endID))
}
} else {
sb.WriteString(fmt.Sprintf("%s%s --> %s\n", indent, startID, endID))
}
}
}
// Render Data Edges
// Only render if they differ from control edges; otherwise already represented as control+data.
dataStartNodes := make([]string, 0, len(info.DataEdges))
for k := range info.DataEdges {
dataStartNodes = append(dataStartNodes, k)
}
sort.Strings(dataStartNodes)
for _, start := range dataStartNodes {
ends := info.DataEdges[start]
for _, end := range ends {
// Check if this edge already exists as a control edge
alreadyExists := false
for _, controlEnd := range info.Edges[start] {
if controlEnd == end {
alreadyExists = true
break
}
}
if !alreadyExists {
startID := m.nodeID(prefix, start)
endID := m.nodeID(prefix, end)
if start == compose.START {
startID = m.nodeID(prefix, "start_node")
}
if end == compose.END {
endID = m.nodeID(prefix, "end_node")
}
if style {
sb.WriteString(fmt.Sprintf("%s%s -. data-only .-> %s\n", indent, startID, endID))
} else {
sb.WriteString(fmt.Sprintf("%s%s -.-> %s\n", indent, startID, endID))
}
}
}
}
// Render Branches
branchStarts := make([]string, 0, len(info.Branches))
for k := range info.Branches {
branchStarts = append(branchStarts, k)
}
sort.Strings(branchStarts)
for _, start := range branchStarts {
branches := info.Branches[start]
for i, branch := range branches {
// Branch decision node (diamond)
// We need a unique ID for the decision point if there are multiple branches from the same node?
// Actually, `info.Branches` maps startNode -> []GraphBranch.
// Usually a node has one set of branches.
// Let's represent the branch condition as a diamond.
// If there are multiple branches, they might be parallel or sequential conditions.
// Eino `AddBranch` adds a branch.
// For visualization, maybe we just draw arrows from startNode to endNodes with a label?
// Or introduce a "decision" node?
// Decision node visualization: startNode -> decision{branch} -> endNodes
decisionID := fmt.Sprintf("%s_branch_%d", m.nodeID(prefix, start), i)
sb.WriteString(fmt.Sprintf("%s%s{\"%s\"}\n", indent, decisionID, "branch"))
startID := m.nodeID(prefix, start)
if start == compose.START {
startID = m.nodeID(prefix, "start_node")
}
if style {
sb.WriteString(fmt.Sprintf("%s%s ==> %s\n", indent, startID, decisionID))
} else {
sb.WriteString(fmt.Sprintf("%s%s --> %s\n", indent, startID, decisionID))
}
// Sort end nodes
endNodesMap := branch.GetEndNode()
endNodes := make([]string, 0, len(endNodesMap))
for k := range endNodesMap {
endNodes = append(endNodes, k)
}
sort.Strings(endNodes)
for _, end := range endNodes {
endID := m.nodeID(prefix, end)
if end == compose.END {
endID = m.nodeID(prefix, "end_node")
}
if style {
sb.WriteString(fmt.Sprintf("%s%s ==> %s\n", indent, decisionID, endID))
} else {
sb.WriteString(fmt.Sprintf("%s%s --> %s\n", indent, decisionID, endID))
}
}
}
}
}
// nodeID sanitizes a node key to be a valid Mermaid identifier, and adds a caller-provided prefix
// to ensure uniqueness when rendering nested graphs.
func (m *MermaidGenerator) nodeID(prefix, key string) string {
// Sanitize key for Mermaid ID
safeKey := strings.ReplaceAll(key, " ", "_")
safeKey = strings.ReplaceAll(safeKey, "-", "_")
return prefix + safeKey
}
func (m *MermaidGenerator) renderImage(input, output string) {
if _, err := exec.LookPath("mmdc"); err != nil {
// fallback to chromedp rendering
data, rErr := os.ReadFile(input)
if rErr != nil {
return
}
_ = renderWithChromedp(string(data), output)
return
}
cmd := exec.Command("mmdc", "-i", input, "-o", output)
_ = cmd.Run()
}
func sanitize(s string) string {
s = strings.TrimSpace(s)
s = strings.ReplaceAll(s, " ", "_")
s = strings.ReplaceAll(s, "/", "_")
s = strings.ReplaceAll(s, "\\", "_")
return s
}
func renderWithChromedp(mermaidCode, output string) error {
html := buildMermaidHTML(mermaidCode)
ctx, cancel := chromedp.NewContext(context.Background())
defer cancel()
var err error
ext := strings.ToLower(filepath.Ext(output))
switch ext {
case ".png":
var buf []byte
err = chromedp.Run(ctx,
chromedp.Navigate("data:text/html,"+urlEncode(html)),
chromedp.WaitVisible(`#container svg`, chromedp.ByQuery),
chromedp.Screenshot(`#container svg`, &buf, chromedp.NodeVisible, chromedp.ByQuery),
)
if err == nil {
err = os.WriteFile(output, buf, 0644)
}
case ".svg":
var svg string
err = chromedp.Run(ctx,
chromedp.Navigate("data:text/html,"+urlEncode(html)),
chromedp.WaitVisible(`#container svg`, chromedp.ByQuery),
chromedp.OuterHTML(`#container svg`, &svg, chromedp.ByQuery),
)
if err == nil {
err = os.WriteFile(output, []byte(svg), 0644)
}
default:
// unsupported extension
return nil
}
return err
}
func buildMermaidHTML(code string) string {
return `<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="https://unpkg.com/mermaid@10/dist/mermaid.min.js"></script>
<style>body{margin:0;padding:20px;background:#fff}</style>
<script>mermaid.initialize({startOnLoad:true});</script>
</head>
<body>
<div id="container" class="mermaid">` + code + `</div>
</body>
</html>`
}
func urlEncode(s string) string { // minimal percent-encoding for data URL
r := strings.NewReplacer("%", "%25", "#", "%23", "\n", "%0A", "\r", "%0D")
return r.Replace(s)
}

@ -22,8 +22,11 @@ import (
"io"
"os"
"github.com/cloudwego/eino/compose"
"github.com/cloudwego/eino/flow/agent/multiagent/host"
"github.com/cloudwego/eino/schema"
"github.com/cloudwego/eino-examples/devops/visualize"
)
func main() {
@ -68,6 +71,17 @@ func main() {
panic(err)
}
// export the graph via API and render mermaid (non-critical path)
{
anyG, opts := hostMA.ExportGraph()
gen := visualize.NewMermaidGenerator("flow/agent/multiagent/host/journal")
g := compose.NewGraph[[]*schema.Message, *schema.Message]()
_ = g.AddGraphNode("host_multiagent", anyG, opts...)
_ = g.AddEdge(compose.START, "host_multiagent")
_ = g.AddEdge("host_multiagent", compose.END)
_, _ = g.Compile(context.Background(), compose.WithGraphCompileCallbacks(gen))
}
cb := &logCallback{}
for { // 多轮对话,除非用户输入了 "exit",否则一直循环

@ -27,6 +27,7 @@ import (
"github.com/cloudwego/eino/flow/agent"
"github.com/cloudwego/eino/schema"
"github.com/cloudwego/eino-examples/devops/visualize"
"github.com/cloudwego/eino-examples/flow/agent/multiagent/plan_execute/prompt"
)
@ -196,12 +197,20 @@ func NewMultiAgent(ctx context.Context, config *Config) (*PlanExecuteMultiAgent,
}))
_ = graph.AddEdge(nodeKeyReviserToList, nodeKeyExecutor)
// 编译 graph将节点、边、分支转化为面向运行时的结构。由于 graph 中存在环,使用 AnyPredecessor 模式,同时设置运行时最大步数。
runnable, err := graph.Compile(ctx, compose.WithNodeTriggerMode(compose.AnyPredecessor), compose.WithMaxRunSteps(maxStep))
// 编译 graph并生成 Mermaid 拓扑图。由于 graph 中存在环,使用 AnyPredecessor 模式,同时设置运行时最大步数。
gen := visualize.NewMermaidGenerator("flow/agent/multiagent/plan_execute")
runnable, err := graph.Compile(ctx,
compose.WithNodeTriggerMode(compose.AnyPredecessor),
compose.WithMaxRunSteps(maxStep),
compose.WithGraphCompileCallbacks(gen),
compose.WithGraphName("PlanExecuteMultiAgent"),
)
if err != nil {
return nil, err
}
// Mermaid markdown and images are auto-generated in flow/agent/multiagent/plan_execute
return &PlanExecuteMultiAgent{
runnable: runnable,
}, nil

@ -27,8 +27,6 @@ import (
"time"
"github.com/bytedance/sonic"
"github.com/cloudwego/eino-examples/flow/agent/multiagent/plan_execute/debug"
"github.com/cloudwego/eino-examples/flow/agent/multiagent/plan_execute/tools"
clc "github.com/cloudwego/eino-ext/callbacks/cozeloop"
"github.com/cloudwego/eino-ext/components/model/ark"
"github.com/cloudwego/eino-ext/components/model/deepseek"
@ -40,6 +38,9 @@ import (
"github.com/cloudwego/eino/schema"
"github.com/cloudwego/eino/utils/callbacks"
"github.com/coze-dev/cozeloop-go"
"github.com/cloudwego/eino-examples/flow/agent/multiagent/plan_execute/debug"
"github.com/cloudwego/eino-examples/flow/agent/multiagent/plan_execute/tools"
)
func main() {

@ -35,6 +35,7 @@ import (
"github.com/cloudwego/eino/schema"
"github.com/coze-dev/cozeloop-go"
"github.com/cloudwego/eino-examples/devops/visualize"
"github.com/cloudwego/eino-examples/flow/agent/react/tools"
"github.com/cloudwego/eino-examples/internal/logs"
)
@ -60,14 +61,15 @@ func main() {
}
callbacks.AppendGlobalHandlers(handlers...)
config := &ark.ChatModelConfig{
APIKey: arkApiKey,
Model: arkModelName,
}
// minimal: we will export graph via API when available and compile a mermaid diagram
// Create a new cached ark chat model.
//arkModel, err = NewCachedARKChatModel(ctx, config)
config := &ark.ChatModelConfig{
APIKey: arkApiKey,
Model: arkModelName,
}
arkModel, err := ark.NewChatModel(ctx, config)
if err != nil {
logs.Errorf("failed to create chat model: %v", err)
@ -75,8 +77,8 @@ func main() {
}
// prepare tools
restaurantTool := tools.GetRestaurantTool() // 查询餐厅信息的工具
dishTool := tools.GetDishTool() // 查询餐厅菜品信息的工具
restaurantTool := tools.GetRestaurantTool()
dishTool := tools.GetDishTool()
// prepare persona (system prompt) (optional)
persona := `# Character:
@ -106,7 +108,7 @@ func main() {
return false, nil
}*/
ragent, err := react.NewAgent(ctx, &react.AgentConfig{
rAgent, err := react.NewAgent(ctx, &react.AgentConfig{
ToolCallingModel: arkModel,
ToolsConfig: compose.ToolsNodeConfig{
Tools: []tool.BaseTool{restaurantTool, dishTool},
@ -145,7 +147,18 @@ func main() {
//react.WithChatModelOptions(ark.WithCache(cacheOption)),
}
sr, err := ragent.Stream(ctx, []*schema.Message{
// Export graph and compile with mermaid (non-critical path)
{
anyG, opts := rAgent.ExportGraph()
gen := visualize.NewMermaidGenerator("flow/agent/react")
g := compose.NewGraph[[]*schema.Message, *schema.Message]()
_ = g.AddGraphNode("react_agent", anyG, opts...)
_ = g.AddEdge(compose.START, "react_agent")
_ = g.AddEdge("react_agent", compose.END)
_, _ = g.Compile(context.Background(), compose.WithGraphCompileCallbacks(gen))
}
sr, err := rAgent.Stream(ctx, []*schema.Message{
{
Role: schema.System,
Content: persona,

@ -6,6 +6,7 @@ toolchain go1.24.9
require (
github.com/bytedance/sonic v1.14.2
github.com/chromedp/chromedp v0.9.5
github.com/cloudwego/eino v0.7.0
github.com/cloudwego/eino-ext/callbacks/cozeloop v0.1.6
github.com/cloudwego/eino-ext/components/document/parser/html v0.0.0-20251117090452-bd6375a0b3cf
@ -24,7 +25,7 @@ require (
github.com/google/uuid v1.6.0
github.com/json-iterator/go v1.1.12
github.com/kaptinlin/jsonrepair v0.2.4
github.com/ollama/ollama v0.11.4
github.com/pkoukk/tiktoken-go v0.1.8
github.com/stretchr/testify v1.11.1
github.com/volcengine/volcengine-go-sdk v1.1.44
github.com/wk8/go-ordered-map/v2 v2.1.8
@ -42,6 +43,8 @@ require (
github.com/bytedance/gopkg v0.1.3 // indirect
github.com/bytedance/sonic/loader v0.4.0 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/chromedp/cdproto v0.0.0-20240202021202-6d0b6a386732 // indirect
github.com/chromedp/sysutil v1.0.0 // indirect
github.com/cloudwego/base64x v0.1.6 // indirect
github.com/cloudwego/eino-ext/libs/acl/openai v0.1.2 // indirect
github.com/cohesion-org/deepseek-go v1.3.2 // indirect
@ -52,14 +55,13 @@ require (
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/eino-contrib/ollama v0.1.0 // indirect
github.com/evanphx/json-patch v0.5.2 // indirect
github.com/getkin/kin-openapi v0.118.0 // indirect
github.com/go-openapi/jsonpointer v0.21.1 // indirect
github.com/go-openapi/swag v0.23.1 // indirect
github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect
github.com/gobwas/ws v1.3.2 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/goph/emperror v0.17.2 // indirect
github.com/gorilla/css v1.0.1 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/invopop/yaml v0.3.1 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/joho/godotenv v1.5.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
@ -71,14 +73,12 @@ require (
github.com/microcosm-cc/bluemonday v1.0.27 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/nikolalohinski/gonja v1.5.3 // indirect
github.com/nikolalohinski/gonja/v2 v2.3.1 // indirect
github.com/ollama/ollama v0.11.4 // indirect
github.com/openai/openai-go v1.10.1 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pkoukk/tiktoken-go v0.1.8 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/richardlehane/mscfb v1.0.4 // indirect
github.com/richardlehane/msoleps v1.0.4 // indirect
@ -90,7 +90,6 @@ require (
github.com/tidwall/sjson v1.2.5 // indirect
github.com/tiendc/go-deepcopy v1.7.1 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.3.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/volcengine/volc-sdk-golang v1.0.199 // indirect

@ -104,6 +104,12 @@ github.com/certifi/gocertifi v0.0.0-20190105021004-abcd57078448/go.mod h1:GJKEex
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chromedp/cdproto v0.0.0-20240202021202-6d0b6a386732 h1:XYUCaZrW8ckGWlCRJKCSoh/iFwlpX316a8yY9IFEzv8=
github.com/chromedp/cdproto v0.0.0-20240202021202-6d0b6a386732/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
github.com/chromedp/chromedp v0.9.5 h1:viASzruPJOiThk7c5bueOUY91jGLJVximoEMGoH93rg=
github.com/chromedp/chromedp v0.9.5/go.mod h1:D4I2qONslauw/C7INoCir1BJkSwBYMyZgx8X276z3+Y=
github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic=
github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
@ -113,64 +119,30 @@ github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5P
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
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.5.14 h1:cthGepU40W75YXYGjpbfakVHrsBOXJhqXVLLcpY+UqM=
github.com/cloudwego/eino v0.5.14/go.mod h1:N6E+toMzWw/3ql0IVM5n5lbYFCeblCYx7ebH16kt1JQ=
github.com/cloudwego/eino v0.6.2-0.20251119064845-207bfdd551a5 h1:wMWSasWJf7/VSe+AA4ZBgnP9Si6zEqZfAB86wtZwszg=
github.com/cloudwego/eino v0.6.2-0.20251119064845-207bfdd551a5/go.mod h1:JNapfU+QUrFFpboNDrNOFvmz0m9wjBFHHCr77RH6a50=
github.com/cloudwego/eino v0.6.2-0.20251120035928-4a4f0c16bdd3 h1:dUQXYicmUNZO/xM8wMKdICGJervM2JGwL37E92wVuW4=
github.com/cloudwego/eino v0.6.2-0.20251120035928-4a4f0c16bdd3/go.mod h1:JNapfU+QUrFFpboNDrNOFvmz0m9wjBFHHCr77RH6a50=
github.com/cloudwego/eino v0.6.2-0.20251120060359-fd8688de61e0 h1:UG+RnyF4kkD3G7W86JuuCcUUM2wE1VhxCVykqd3yo4c=
github.com/cloudwego/eino v0.6.2-0.20251120060359-fd8688de61e0/go.mod h1:JNapfU+QUrFFpboNDrNOFvmz0m9wjBFHHCr77RH6a50=
github.com/cloudwego/eino v0.6.2-0.20251120060852-4c29682b927c h1:XupuM1TJ8qEzADtqAnNkmZxbejg8kKvEzTlADOCcpfE=
github.com/cloudwego/eino v0.6.2-0.20251120060852-4c29682b927c/go.mod h1:JNapfU+QUrFFpboNDrNOFvmz0m9wjBFHHCr77RH6a50=
github.com/cloudwego/eino v0.7.0 h1:XDGdGMZCAVx+OC0IxiLlyNFELoLN+56THUhYYqEujuM=
github.com/cloudwego/eino v0.7.0/go.mod h1:JNapfU+QUrFFpboNDrNOFvmz0m9wjBFHHCr77RH6a50=
github.com/cloudwego/eino-ext/callbacks/cozeloop v0.1.4 h1:Cwm80+fMEAoY7uI9XUukDEV5J3Adb9HiXKmcXpXcDiM=
github.com/cloudwego/eino-ext/callbacks/cozeloop v0.1.4/go.mod h1:xxjNsJeZwdIooEYTt6tjw/YJzkA6xPcxn1u/HvA5xc0=
github.com/cloudwego/eino-ext/callbacks/cozeloop v0.1.6 h1:gS4nAOpQQC5WItt1k32yjZt9O2UWMpnbgF6vkMQAWhg=
github.com/cloudwego/eino-ext/callbacks/cozeloop v0.1.6/go.mod h1:ZniRkgN+9FUFxtN60X7yzD6UOruqrKQusjrOiGcH4I8=
github.com/cloudwego/eino-ext/components/document/parser/html v0.0.0-20250117061805-cd80d1780d76 h1:kK4f2kunb5xlc0XTkg6wkjy8Z/BDfJjWAVm9EOdRErg=
github.com/cloudwego/eino-ext/components/document/parser/html v0.0.0-20250117061805-cd80d1780d76/go.mod h1:LWR+h0EfIELl/I1tDSVH0Tgx8j2gymxa174U1C8BNps=
github.com/cloudwego/eino-ext/components/document/parser/html v0.0.0-20251117090452-bd6375a0b3cf h1:Uwh3VT+xPrfDjM677dj1pSidCzBFoTrYlC274kEci5w=
github.com/cloudwego/eino-ext/components/document/parser/html v0.0.0-20251117090452-bd6375a0b3cf/go.mod h1:DBwsPrdNxPeE3HNr5XyjjFreG4ypqCUjN0T2C2JSy6k=
github.com/cloudwego/eino-ext/components/document/parser/pdf v0.0.0-20250117061805-cd80d1780d76 h1:GJ4OqxyBH8la8Gu4PhTHXZNZFmrtEIrrymkCEpJ7XZU=
github.com/cloudwego/eino-ext/components/document/parser/pdf v0.0.0-20250117061805-cd80d1780d76/go.mod h1:swAgO0nNekTSKGgFqiy4zShKaCDhiIZoKEFwpi7NBFE=
github.com/cloudwego/eino-ext/components/document/parser/pdf v0.0.0-20251117090452-bd6375a0b3cf h1:0KFSxuvFqs9dJ3Pu9Lk+4+Stt43I2u9eu3L4gDNcZ4A=
github.com/cloudwego/eino-ext/components/document/parser/pdf v0.0.0-20251117090452-bd6375a0b3cf/go.mod h1:kHC3xkGM/gv3IHpOk33p75BfBaEIYATOs2XmYFKffcs=
github.com/cloudwego/eino-ext/components/model/ark v0.1.41 h1:l+WDY/nR1A5CzNkOJ+394EY+TxaW+NC5if1gnwcsvtE=
github.com/cloudwego/eino-ext/components/model/ark v0.1.41/go.mod h1:RIJTJsjS1Z1Xrldk6oeIkM0IHFasmYVfPh4b6ceExpY=
github.com/cloudwego/eino-ext/components/model/ark v0.1.45 h1:LWvSHJVlvS1S/IxN9XUKNw/MI0I7YPePt3LMNxyCrZ0=
github.com/cloudwego/eino-ext/components/model/ark v0.1.45/go.mod h1:e8P5dGVI/JMQ1FYNgmu5EFRWA8fivBc6NwNJ9g8FBK8=
github.com/cloudwego/eino-ext/components/model/deepseek v0.0.0-20250826125654-37d4a5029810 h1:zichoSWCoGqhUUwWscRNiTSH9j3KA8hReeEBMvr4i5w=
github.com/cloudwego/eino-ext/components/model/deepseek v0.0.0-20250826125654-37d4a5029810/go.mod h1:O6leaZBwE5s1wSsf5idW52Yaj1zWzhtjinSnfPXASNU=
github.com/cloudwego/eino-ext/components/model/deepseek v0.0.0-20251117090452-bd6375a0b3cf h1:JA2W09VU+9zG9qRXheARRbi31cH+xHVzSJ/kFMxZvlo=
github.com/cloudwego/eino-ext/components/model/deepseek v0.0.0-20251117090452-bd6375a0b3cf/go.mod h1:3AlAYkxwlOAP0SnFj7Yu1Lsgp8XHpbSMaE3l0+vDHKQ=
github.com/cloudwego/eino-ext/components/model/ollama v0.1.2 h1:WxJ+7oXnr3AhM6u4VbFF3L2ionxCrPfmLetx7V+zthw=
github.com/cloudwego/eino-ext/components/model/ollama v0.1.2/go.mod h1:OgGMCiR/G/RnOWaJvdK8pVSxAzoz2SlCqim43oFTuwo=
github.com/cloudwego/eino-ext/components/model/ollama v0.1.6 h1:ZbrhV91uE0hGIOYXhb2i3G6tQJ/rK2SLYtoYrmocZXM=
github.com/cloudwego/eino-ext/components/model/ollama v0.1.6/go.mod h1:GDXrvorGdRNV6g2mK5jdla2D8Xc/hh7XDrTeGDteLLo=
github.com/cloudwego/eino-ext/components/model/openai v0.0.0-20250826125654-37d4a5029810 h1:M8A7666rddupncJ4p3p1lH5jkNKtjzD7ULPE/I02o64=
github.com/cloudwego/eino-ext/components/model/openai v0.0.0-20250826125654-37d4a5029810/go.mod h1:QQhCuQxuBAVWvu/YAZBhs/RsR76mUigw59Tl0kh04C8=
github.com/cloudwego/eino-ext/components/model/openai v0.1.5 h1:+yvGbTPw93li9GSmdm6Rix88Yy8AXg5NNBcRbWx3CQU=
github.com/cloudwego/eino-ext/components/model/openai v0.1.5/go.mod h1:IPVYMFoZcuHeVEsDTGN6SZjvue0xr1iZFhdpq1SBWdQ=
github.com/cloudwego/eino-ext/components/retriever/volc_vikingdb v0.0.0-20250319082935-6219ec437e56 h1:yL7nTthGoz35dh7RK9lazxDedGmSmlss8HrtXmd0O3Q=
github.com/cloudwego/eino-ext/components/retriever/volc_vikingdb v0.0.0-20250319082935-6219ec437e56/go.mod h1:OPQYefu4EWAUcP0HhtzJK+UjLtQc8T9YzmxcAwFf29o=
github.com/cloudwego/eino-ext/components/retriever/volc_vikingdb v0.0.0-20251120060928-25485ef519b5 h1:HoXqcYm3x4eXk6i2HLBklvx8WeFW7/MxijpCsEBQLSE=
github.com/cloudwego/eino-ext/components/retriever/volc_vikingdb v0.0.0-20251120060928-25485ef519b5/go.mod h1:He7AHJpLTs0MXKPx5JpI8MdYtLUcKhUAZwCsgNtaq6k=
github.com/cloudwego/eino-ext/components/tool/commandline v0.0.0-20251111090228-91a10bbc864f h1:JkELXl5NquNnDgi81T3uiPfgpfcXzH81e3B/NDO4cwM=
github.com/cloudwego/eino-ext/components/tool/commandline v0.0.0-20251111090228-91a10bbc864f/go.mod h1:WfhOxJY7J2ZqY9muahNOMtypoe4ovcAG1E97y4bQPfU=
github.com/cloudwego/eino-ext/components/tool/commandline v0.0.0-20251117090452-bd6375a0b3cf h1:LLyVGanJpHpSSiqsbRXkuSpdpc1UmuaUIEs/BiOQkH4=
github.com/cloudwego/eino-ext/components/tool/commandline v0.0.0-20251117090452-bd6375a0b3cf/go.mod h1:cMZb1KM71kM+2hTJwxLwXT+HC66HimZirDDA5Oo64Hw=
github.com/cloudwego/eino-ext/components/tool/duckduckgo/v2 v2.0.0-20250826125654-37d4a5029810 h1:VtmhPdOY6wFR34Hdm4HNzWF9bwGz11x1TqBr8VpJDoc=
github.com/cloudwego/eino-ext/components/tool/duckduckgo/v2 v2.0.0-20250826125654-37d4a5029810/go.mod h1:QB9TkAu6OVDvQm5hEoK+VFVIbfDHO+ZQyUR2cPSo6jk=
github.com/cloudwego/eino-ext/components/tool/duckduckgo/v2 v2.0.0-20251117090452-bd6375a0b3cf h1:54xcNETtXP1gYieDuNyOIvzE4Mk/jOxjlqCERr4cxTk=
github.com/cloudwego/eino-ext/components/tool/duckduckgo/v2 v2.0.0-20251117090452-bd6375a0b3cf/go.mod h1:Np0BXy/9hPRu3wCgn+ij6L7YsjFcybVzg1k7uYOXh0M=
github.com/cloudwego/eino-ext/devops v0.1.7 h1:w8q4SGDtrZk+8WUrLyVidX7GNsyWFsYPPz5HoJKgRcA=
github.com/cloudwego/eino-ext/devops v0.1.7/go.mod h1:W53NPBmkmM7ClyQqwOcFUC2kV4bsvCfh2FtHUcyMzMY=
github.com/cloudwego/eino-ext/devops v0.1.8 h1:qBg5vjZSDnd9tHzCHG8YsjnGB5vKG2EoZuuQCI8qrGs=
github.com/cloudwego/eino-ext/devops v0.1.8/go.mod h1:8yjvPNTaB5Ve4aJmJ0ysFgB10y3YbIuqMh0/Uwt5Fnw=
github.com/cloudwego/eino-ext/libs/acl/openai v0.0.0-20250826113018-8c6f6358d4bb h1:RMslzyijc3bi9EkqCulpS0hZupTl1y/wayR3+fVRN/c=
github.com/cloudwego/eino-ext/libs/acl/openai v0.0.0-20250826113018-8c6f6358d4bb/go.mod h1:fHn/6OqPPY1iLLx9wzz+MEVT5Dl9gwuZte1oLEnCoYw=
github.com/cloudwego/eino-ext/libs/acl/openai v0.1.2 h1:r9Id2wzJ05PoHl+Km7jQgNMgciaZI93TVnUYso89esM=
github.com/cloudwego/eino-ext/libs/acl/openai v0.1.2/go.mod h1:S4OkvglPY9hsm9tXeShODrf/WN1Cgu4bqu4nn/CnIic=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
@ -184,8 +156,6 @@ github.com/corpix/uarand v0.2.0 h1:U98xXwud/AVuCpkpgfPF7J5TQgr7R5tqT8VZP5KWbzE=
github.com/corpix/uarand v0.2.0/go.mod h1:/3Z1QIqWkDIhf6XWn/08/uMHoQ8JUoTIKc2iPchBOmM=
github.com/coze-dev/cozeloop-go v0.1.11 h1:NzdBKK3klhRgnPEH/PCjtP21+cRuz6qZlKPmJC7bkiM=
github.com/coze-dev/cozeloop-go v0.1.11/go.mod h1:GDF+MpqsUsq4oKy+L1FTd6Giy2cAmr/xXl9rOnub39A=
github.com/coze-dev/cozeloop-go/spec v0.1.4 h1:6yhjFQ39yn9VkZ68QG2W5WjzICl6GgwVsXmDmn75ySg=
github.com/coze-dev/cozeloop-go/spec v0.1.4/go.mod h1:/f3BrWehffwXIpd4b5rYIqktLd/v5dlLBw0h9F/LQIU=
github.com/coze-dev/cozeloop-go/spec v0.1.5 h1:tEQ82qlz9/HZv8MqyZq+043SaHs5C44MWslyGm5UcNI=
github.com/coze-dev/cozeloop-go/spec v0.1.5/go.mod h1:/f3BrWehffwXIpd4b5rYIqktLd/v5dlLBw0h9F/LQIU=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
@ -229,8 +199,6 @@ github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/getkin/kin-openapi v0.118.0 h1:z43njxPmJ7TaPpMSCQb7PN0dEYno4tyBPQcrFdHoLuM=
github.com/getkin/kin-openapi v0.118.0/go.mod h1:l5e9PaFUo9fyLJCPGQeXI2ML8c3P8BHOEV2VaAVf/pc=
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-check/check v0.0.0-20180628173108-788fd7840127 h1:0gkP6mzaMqkmpcJYCFOLkIBwI7xFExG03bbkOkCvUPI=
@ -249,19 +217,17 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic=
github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=
github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.3.2 h1:zlnbNHxumkRvfPWgfXu8RBwyNR1x8wh9cf5PTOCqs9Q=
github.com/gobwas/ws v1.3.2/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
@ -385,9 +351,6 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/invopop/yaml v0.1.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
github.com/invopop/yaml v0.3.1 h1:f0+ZpmhfBSS4MhG+4HYseMdJhoeeopbSKbq5Rpeelso=
github.com/invopop/yaml v0.3.1/go.mod h1:PMOp3nn4/12yEZUFfmOuNHJsZToEEOwoWsT+D81KkeA=
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
@ -439,8 +402,8 @@ 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/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kULo2bwGEkFvCePZ3qHDDTC3/J9Swo=
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
@ -461,8 +424,6 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k
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/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/meguminnnnnnnnn/go-openai v0.0.0-20250821095446-07791bea23a0 h1:nIohpHs1ViKR0SVgW/cbBstHjmnqFZDM9RqgX9m9Xu8=
github.com/meguminnnnnnnnn/go-openai v0.0.0-20250821095446-07791bea23a0/go.mod h1:qs96ysDmxhE4BZoU45I43zcyfnaYxU3X+aRzLko/htY=
github.com/meguminnnnnnnnn/go-openai v0.1.0 h1:BGzB1PlS2Epq0mBB2TGLwzMihbR7BANrlMH3w4ZnY88=
github.com/meguminnnnnnnnn/go-openai v0.1.0/go.mod h1:qs96ysDmxhE4BZoU45I43zcyfnaYxU3X+aRzLko/htY=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
@ -487,8 +448,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
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/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nats-io/jwt v1.2.2/go.mod h1:/xX356yQA6LuXI9xWW7mZNpxgF2mBmGecH+Fj34sP5Q=
@ -527,14 +486,13 @@ github.com/openai/openai-go v1.10.1 h1:7VR8z1foqJDjlaFZsNH5zZIYTWKYz97tdsVSzXDHQ
github.com/openai/openai-go v1.10.1/go.mod h1:g461MYGXEXBVdV5SaR/5tNzNbSfwTBBefwc+LlDCK0Y=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE=
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde h1:x0TT0RDC7UhAVbbWWBzr41ElhJx5tXPWkIHA2HWPRuw=
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
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/performancecopilot/speed/v4 v4.0.0/go.mod h1:qxrSyuDGrTOWfV+uKRFhfxw6h/4HXRGUiZiufxo49BM=
github.com/perimeterx/marshmallow v1.1.4/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -618,7 +576,6 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
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.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
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=
@ -638,18 +595,12 @@ github.com/tiendc/go-deepcopy v1.7.1/go.mod h1:4bKjNC2r7boYOkD2IOuZpYjmlDdzjbpTR
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
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 v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/volcengine/volc-sdk-golang v1.0.23/go.mod h1:AfG/PZRUkHJ9inETvbjNifTDgut25Wbkm2QoYBTbvyU=
github.com/volcengine/volc-sdk-golang v1.0.196 h1:KYbX76ibTlNhgm6Kq3sDTjrujDBd0za8ULg0v7+sCag=
github.com/volcengine/volc-sdk-golang v1.0.196/go.mod h1:stZX+EPgv1vF4nZwOlEe8iGcriUPRBKX8zA19gXycOQ=
github.com/volcengine/volc-sdk-golang v1.0.199 h1:zv9QOqTl/IsLwtfC37GlJtcz6vMAHi+pjq8ILWjLYUc=
github.com/volcengine/volc-sdk-golang v1.0.199/go.mod h1:stZX+EPgv1vF4nZwOlEe8iGcriUPRBKX8zA19gXycOQ=
github.com/volcengine/volcengine-go-sdk v1.1.44 h1:WLoLlzt67ZlJeow55PPx65/Mh52DewVXqkHcFSodM9w=
@ -901,9 +852,11 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
@ -1118,7 +1071,6 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0/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=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

Loading…
Cancel
Save