Files
sundynix-agentix/sundynix-dispatcher/internal/eino/orchestrator.go
T
Blizzard c7a02c3905 feat: 初始化 sundynix-agentix 分层式 AI Agent 平台脚手架
5 层 + 1 条 NATS 零拷贝消息总线的 monorepo(Monolith First → Microservices Morph B)。
纵向主干(任务流 + Token 流回流)已真实跑通,横向各层能力为带注释的桩。

已贯通(real code):
- sundynix-shared: 共享契约 + JetStream/core NATS 真实收发(bus) + 内嵌 NATS(devnats) + e2e 测试
- sundynix-gateway: Gin 接入 + DSL 解析组装 + NATS Publish + SSE 流式输出
- sundynix-dispatcher: NATS 消费 + Eino Orchestrator 流式回流 + 熔断器 + LLM Pool 占位流式
- 链路: HTTP POST → DSL → sundynix.tasks.* → Dispatcher → Token 经 sundynix.streams.<id> 回流 → SSE
- 基础设施: docker-compose(nats/postgres/redis/neo4j/milvus) + Makefile(make demo/e2e)

待填(桩):
- Eino 图编排 compose.NewGraph、LLM Pool 接 vLLM/Ollama
- Gateway store 换真实 pgx/redis
- sundynix-mcp-go: Bleve+Milvus+Neo4j 混合检索 / UniOffice / 外部 API
- sundynix-mcp-py: gVisor 沙箱 / MinerU(PaddleOCR) / Docker 解释器
- sundynix-desktop: React Flow 画布 → DSL 导出 → SSE 展示
2026-06-10 11:00:29 +08:00

61 lines
1.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Package eino 封装基于 CloudWeGo Eino 的 Agent 图编排引擎。
package eino
import (
"context"
"log"
"github.com/sundynix/sundynix-dispatcher/internal/harness"
"github.com/sundynix/sundynix-dispatcher/internal/llm"
"github.com/sundynix/sundynix-shared/contract"
)
// TokenSink 是 Token 流回流出口(由 NATS bus 实现)。
type TokenSink interface {
PublishToken(taskID string, token []byte) error
CompleteStream(taskID string) error
}
// Orchestrator 将 DSL 图编译为 Eino Graph 并驱动执行。
type Orchestrator struct {
pool *llm.Pool
breaker *harness.CircuitBreaker
sink TokenSink
}
func NewOrchestrator(pool *llm.Pool, breaker *harness.CircuitBreaker, sink TokenSink) *Orchestrator {
return &Orchestrator{pool: pool, breaker: breaker, sink: sink}
}
// Handle 消费一个任务:编译图 → 流式推理 → 经 sink 把 Token 回流到 sundynix.streams.<id>。
func (o *Orchestrator) Handle(ctx context.Context, t *contract.Task) error {
if !o.breaker.Allow() {
log.Printf("[eino] circuit open, drop task %s", t.ID)
return nil
}
log.Printf("[eino] task %s received (graph=%d bytes), streaming tokens...", t.ID, len(t.Graph))
// TODO: compose.NewGraph(...) 编译 DSL;此处 prompt 占位为图原文。
// 工具节点经 NATS 调用第 5 层 MCPsundynix.tools.go.* / sundynix.tools.py.*)。
prompt := string(t.Graph)
n := 0
err := o.pool.Stream(ctx, prompt, func(tok []byte) {
if perr := o.sink.PublishToken(t.ID, tok); perr != nil {
log.Printf("[eino] publish token failed: %v", perr)
return
}
n++
})
if err != nil {
log.Printf("[eino] task %s stream error: %v", t.ID, err)
}
if cerr := o.sink.CompleteStream(t.ID); cerr != nil {
log.Printf("[eino] complete stream failed: %v", cerr)
}
log.Printf("[eino] task %s done, %d tokens streamed", t.ID, n)
o.breaker.Report(err == nil)
return err
}