Files
sundynix-agentix/sundynix-gateway/internal/nats/publisher.go
T
Blizzard 3c65189f30 feat: 配置控制面 + LLM Pool 接第三方在线 API (OpenAI 兼容)
后端从占位回显变为真实生成:管理员经控制面登记/激活模型,Gateway 经 NATS
下发,Dispatcher 热更新 LLM Pool,Eino 图用 OpenAI 兼容流式真实推理。

- shared: contract.ModelConfig(provider/base_url/api_key/model) + 配置 subjects;
  bus.RequestModelConfig/ServeModelConfig/Publish/Subscribe ModelConfigUpdated
- gateway: store.LLMModel→sundynix_model(AutoMigrate,唯一激活) + admin REST
  (GET/POST/active/delete/test models, api_key 脱敏) + main ServeModelConfig +
  变更广播; 路由 /api/v1/admin/models*
- dispatcher: llm.Pool OpenAI 兼容 SSE 流式客户端(ChatStream) + 热更新配置 +
  未配置则降级桩; poolModel.Ready()?真实流式:注入记忆的桩; main 取配置+订阅
- 开发期接在线 API 不拉本地模型(见 llm-provider-strategy memory)
- 验证: 4 模块 build✓ + e2e PASS; mock OpenAI 服务 live 跑通——登记/测试连接✓/
  激活→NATS 热更新→提交→真实 SSE 流出 mock 回复, mock 日志证明端点被调用且
  注入画像(老王)进了模型上下文

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 15:41:39 +08:00

62 lines
2.0 KiB
Go

// Package nats 是网关对共享 bus 的薄封装(发布任务 / 订阅 Token 回流)。
package nats
import (
"context"
"log"
sharedbus "github.com/sundynix/sundynix-shared/bus"
"github.com/sundynix/sundynix-shared/contract"
)
// Bus 包装共享 bus,向网关其余代码暴露发布能力。
type Bus struct {
inner *sharedbus.Bus
}
// MustConnect 接入 NATS 并确保任务流存在。
func MustConnect(url string) *Bus {
inner, err := sharedbus.Connect(url)
if err != nil {
log.Fatalf("[nats] connect: %v", err)
}
if err := inner.EnsureTaskStream(context.Background()); err != nil {
log.Fatalf("[nats] ensure stream: %v", err)
}
log.Printf("[nats] connected %s, task stream ready", url)
return &Bus{inner: inner}
}
// PublishTask 把组装后的 Task 发布到 sundynix.tasks.<id>。
func (b *Bus) PublishTask(ctx context.Context, t *contract.Task) error {
seq, err := b.inner.PublishTask(ctx, t)
if err != nil {
return err
}
log.Printf("[nats] published task %s (seq=%d)", t.ID, seq)
return nil
}
// SubscribeTokens 订阅 sundynix.streams.<taskID> 的 Token 回流,
// 每个 Token 触发 onToken,流结束触发 onDone,返回 unsub。
func (b *Bus) SubscribeTokens(taskID string, onToken func([]byte), onDone func()) (func() error, error) {
return b.inner.SubscribeTokens(taskID, onToken, onDone)
}
// CallTool 经 NATS 同步调用一个 MCP 工具(用于网关侧写偏好记忆等)。
func (b *Bus) CallTool(ctx context.Context, subject string, call *contract.ToolCall) (*contract.ToolResult, error) {
return b.inner.CallTool(ctx, subject, call)
}
// ServeModelConfig 让网关作为配置控制面,响应 Dispatcher 的模型配置请求。
func (b *Bus) ServeModelConfig(provide func() *contract.ModelConfig) (func() error, error) {
return b.inner.ServeModelConfig(provide)
}
// PublishModelConfigUpdated 广播模型配置变更。
func (b *Bus) PublishModelConfigUpdated(cfg *contract.ModelConfig) error {
return b.inner.PublishModelConfigUpdated(cfg)
}
func (b *Bus) Close() { b.inner.Close() }