feat(voice): 提升桌面端语音交互与本地任务执行支持
This commit is contained in:
@@ -285,6 +285,33 @@ func (b *Bus) SubscribeExec(taskID string, onEvent func([]byte), onDone func())
|
||||
return sub.Unsubscribe, nil
|
||||
}
|
||||
|
||||
// ---- 语音事件(JARVIS 动作/主动播报,core NATS pub-sub)----
|
||||
|
||||
// PublishVoiceEvent 给某用户的语音会话发一条事件(navigate/announce)。
|
||||
// 无人订阅(用户没开语音)就静默丢弃——即时性消息,不补投。
|
||||
func (b *Bus) PublishVoiceEvent(uid string, ev *contract.VoiceEvent) error {
|
||||
data, err := json.Marshal(ev)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return b.nc.Publish(contract.VoiceEventSubject(uid), data)
|
||||
}
|
||||
|
||||
// SubscribeVoiceEvent 订阅某用户的语音事件(语音 WS 会话建立时挂上,会话结束退订)。
|
||||
func (b *Bus) SubscribeVoiceEvent(uid string, onEvent func(*contract.VoiceEvent)) (unsub func() error, err error) {
|
||||
sub, err := b.nc.Subscribe(contract.VoiceEventSubject(uid), func(m *nats.Msg) {
|
||||
var ev contract.VoiceEvent
|
||||
if json.Unmarshal(m.Data, &ev) != nil {
|
||||
return
|
||||
}
|
||||
onEvent(&ev)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("subscribe voice event: %w", err)
|
||||
}
|
||||
return sub.Unsubscribe, nil
|
||||
}
|
||||
|
||||
// ---- MCP 工具调用(core NATS request-reply)----
|
||||
|
||||
// CallTool 同步调用一个 MCP 工具:发到 subject,阻塞等待应答。
|
||||
|
||||
@@ -25,6 +25,21 @@ const (
|
||||
QueueToolsGo = "mcp-go-workers" // mcp-go 队列组(多副本负载均衡)
|
||||
QueueToolsPy = "mcp-py-workers" // mcp-py 队列组
|
||||
|
||||
// 平台工具(JARVIS 大脑中枢,见 JARVIS_BRAIN_DESIGN.md):由 gateway 自己提供——
|
||||
// 平台操作的权威(提交关卡/归属校验/计费)都在 gateway,工具就长在权威所在地。
|
||||
SubjectToolsPlatform = "sundynix.tools.platform" // 前缀;实际 sundynix.tools.platform.<tool>
|
||||
SubjectToolsPlatformAll = "sundynix.tools.platform.>" // gateway 通配订阅
|
||||
QueueToolsPlatform = "platform-tools-workers" // gateway 多副本队列组
|
||||
|
||||
// 语音事件通道(JARVIS P2 动作/P3 主动播报):服务端任意副本 → 某用户的语音 WS 会话。
|
||||
// core NATS pub-sub(即时性消息:navigate/播报,丢一条无伤;会话在哪个副本谁订阅谁收)。
|
||||
SubjectVoiceEvent = "sundynix.voice.event" // 前缀;实际 sundynix.voice.event.<user_id>
|
||||
|
||||
// 本地执行路由(JARVIS P4「本地的手」,LOCAL_AGENT_DESIGN 档 A):local_* 工具调用
|
||||
// 经此主题路由到「持有该用户桌面 runner WS 连接」的 gateway 副本(request-reply,
|
||||
// 载荷复用 ToolCall/ToolResult)。无人订阅 = 用户桌面端不在线 → 调用方明确报不可用。
|
||||
SubjectLocalExec = "sundynix.local.exec" // 前缀;实际 sundynix.local.exec.<user_id>
|
||||
|
||||
// QueueGateway 是网关侧事件订阅/配置应答的队列组:多网关副本下,每条
|
||||
// eval/usage/status 事件与每个 config 请求只由组内一个副本处理,避免重复落库/重复应答(HA)。
|
||||
QueueGateway = "gateway-workers"
|
||||
@@ -247,6 +262,25 @@ func StreamSubject(id string) string { return SubjectStream + "." + id }
|
||||
func ToolSubjectGo(tool string) string { return SubjectToolsGo + "." + tool }
|
||||
func ToolSubjectPy(tool string) string { return SubjectToolsPy + "." + tool }
|
||||
|
||||
// ToolSubjectPlatform 平台工具主题(gateway 提供,JARVIS 中枢用)。
|
||||
func ToolSubjectPlatform(tool string) string { return SubjectToolsPlatform + "." + tool }
|
||||
|
||||
// VoiceEventSubject 某用户的语音事件主题(JARVIS 动作/主动播报)。
|
||||
func VoiceEventSubject(uid string) string { return SubjectVoiceEvent + "." + uid }
|
||||
|
||||
// LocalExecSubject 某用户的本地执行路由主题(local_* 工具 → 桌面 runner)。
|
||||
func LocalExecSubject(uid string) string { return SubjectLocalExec + "." + uid }
|
||||
|
||||
// VoiceEvent 是发往用户语音会话的一条事件:
|
||||
// - action=navigate:让客户端界面跳转(view + 可选 task_id)
|
||||
// - action=announce:主动播报(text 会被 TTS 念出来 + 对话流显示)
|
||||
type VoiceEvent struct {
|
||||
Action string `json:"action"`
|
||||
View string `json:"view,omitempty"`
|
||||
TaskID string `json:"task_id,omitempty"`
|
||||
Text string `json:"text,omitempty"`
|
||||
}
|
||||
|
||||
// ToolCall 是 Dispatcher 对一个 MCP 工具的调用请求(NATS request 体)。
|
||||
type ToolCall struct {
|
||||
Tool string `json:"tool"` // 工具名,如 wiki_search
|
||||
|
||||
Reference in New Issue
Block a user