Files
Cyrene/backend/gateway/internal/ws/protocol.go
T
AskaEth 6ef9e082a6 feat: 语音流式输入管线 + VAD前端集成 + 插件-工具合并清理
- 前端: VAD语音检测(@ricky0123/vad-web) + useVoiceInput双模式(流式WS/REST)
- Gateway: VoiceStreamManager代理WS流式STT到voice-service
- Voice-service: DashScope REST → Realtime WS → Whisper三级引擎 + ffmpeg转码
- 共享模块: pkg/audio(音频转换) + pkg/dashscope(ASR REST客户端)
- 清理: 移除旧plugin-manager和pkg/plugins,完成插件→工具合并
- 文档: 完善gateway-api.md和voice-service.md语音API文档
- 工具: scripts/voice/ 语音转换脚本集

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 11:50:40 +08:00

144 lines
7.5 KiB
Go

package ws
// MessageAttachment 消息附件 (图片等)
type MessageAttachment struct {
Type string `json:"type"` // image
URL string `json:"url,omitempty"` // 图片 URL 或 data URL(旧格式,向后兼容)
FileID string `json:"file_id,omitempty"` // 文件 ID(新格式,轻量引用)
ThumbnailURL string `json:"thumbnail_url,omitempty"` // 缩略图 URL
Filename string `json:"filename,omitempty"`
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
Size int64 `json:"size,omitempty"` // 文件大小 bytes
Description string `json:"description,omitempty"` // AI 对图片的描述
}
// 客户端 → 服务端消息
type ClientMessage struct {
Type string `json:"type"` // message | voice_input | voice_stream_start | voice_stream_chunk | voice_stream_end | ping | history
SessionID string `json:"session_id"`
Mode string `json:"mode"` // text | voice_msg | voice_assistant
Content string `json:"content"`
AudioData string `json:"audio_data,omitempty"` // base64
Format string `json:"format,omitempty"` // 音频格式: webm, wav, pcm, opus
Language string `json:"language,omitempty"` // 识别语言: zh, en, ja, ko, auto
Sequence int `json:"sequence,omitempty"` // 音频块序列号 (voice_stream_chunk)
Attachments []MessageAttachment `json:"attachments,omitempty"` // 图片等附件
Timestamp int64 `json:"timestamp"`
ClientID string `json:"client_id,omitempty"` // 客户端唯一标识 (多端区分)
DeviceName string `json:"device_name,omitempty"` // 设备备注名称
UserAgent string `json:"user_agent,omitempty"` // 浏览器 UA
ClientMsgID string `json:"client_msg_id,omitempty"` // 客户端消息ID (跨端去重)
}
// ReviewMessage 审查后的结构化消息(动作/聊天/Markdown/代码块/搜索结果)
type ReviewMessage struct {
Type string `json:"type"` // action | chat | markdown | code | search_result
Content string `json:"content"`
DelayMs int `json:"delay_ms,omitempty"` // ms to wait before sending (0 = immediate)
Metadata map[string]any `json:"metadata,omitempty"` // 类型特定元数据 (code 语言、搜索结果 URL 等)
}
// ClientInfo carries the originating client's device metadata.
type ClientInfo struct {
ClientID string `json:"client_id,omitempty"`
DeviceName string `json:"device_name,omitempty"`
UserAgent string `json:"user_agent,omitempty"`
}
// 服务端 → 客户端消息
type ServerMessage struct {
Type string `json:"type"` // response | segment | audio | error | device_update | pong | history_response | stream_chunk | stream_end | background_thinking | notification | multi_message | stream_segments | review | thinking | tool_progress | system_info | voice_interim | voice_final
MessageID string `json:"message_id"`
Text string `json:"text,omitempty"`
Content string `json:"content,omitempty"` // stream_chunk 的增量文本
Role string `json:"role,omitempty"` // stream 消息的角色
SessionID string `json:"session_id,omitempty"` // 会话 ID
Segments []VoiceSegment `json:"segments,omitempty"` // 断句数组
FullAudioURL string `json:"full_audio_url,omitempty"`
ResponseMode string `json:"response_mode"`
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
Error string `json:"error,omitempty"`
Timestamp int64 `json:"timestamp"`
Messages []Message `json:"messages,omitempty"` // 历史消息列表
Devices []IotDeviceInfo `json:"devices,omitempty"` // IoT 设备状态
ThinkingStatus string `json:"thinking_status,omitempty"` // 后台思考状态
ThinkingContent string `json:"thinking_content,omitempty"` // 思考内容 (thinking 类型)
Notification *NotificationInfo `json:"notification,omitempty"` // 通知推送
MultiMessage *MultiMessagePayload `json:"multi_message,omitempty"` // 多条消息批量发送
ReviewMessages []ReviewMessage `json:"review_messages,omitempty"` // 审查后的结构化消息列表
MsgType string `json:"msg_type,omitempty"` // 消息展示类型: action | chat | thinking | tool_progress | system_info | markdown | code | search_result
Metadata map[string]any `json:"metadata,omitempty"` // 消息元数据 (code 语言等)
ToolProgress *ToolProgressInfo `json:"tool_progress,omitempty"` // 工具执行进度
SystemInfo *SystemInfoPayload `json:"system_info,omitempty"` // 系统通知信息
ProtocolVersion int `json:"protocol_version,omitempty"` // 协议版本
ClientInfo *ClientInfo `json:"client_info,omitempty"` // 消息来源客户端信息
}
// ToolProgressInfo 工具执行进度
type ToolProgressInfo struct {
ToolName string `json:"tool_name"`
Status string `json:"status"` // started, running, completed, failed
Progress float64 `json:"progress"`
Message string `json:"message"`
}
// SystemInfoPayload 系统信息负载
type SystemInfoPayload struct {
Level string `json:"level"` // info, warning, error
Message string `json:"message"`
Action string `json:"action,omitempty"`
}
// MultiMessagePayload 多条消息的容器 (对应昔涟的多消息回复风格)
type MultiMessagePayload struct {
Messages []MultiMessageItem `json:"messages"`
}
// MultiMessageItem 多消息中的单条
type MultiMessageItem struct {
Index int `json:"index"`
Content string `json:"content"`
MsgType string `json:"msg_type,omitempty"` // chat | action | system_info
}
// NotificationInfo 通知推送信息
type NotificationInfo struct {
ID string `json:"id"`
Type string `json:"type"` // info | warning | success | thinking | reminder
Title string `json:"title"`
Body string `json:"body"`
Timestamp string `json:"timestamp"`
Data map[string]interface{} `json:"data,omitempty"`
}
// IotDeviceInfo IoT 设备信息(用于 WebSocket 推送)
type IotDeviceInfo struct {
ID string `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
Status string `json:"status"`
Brightness int `json:"brightness,omitempty"`
Color string `json:"color,omitempty"`
Temperature float64 `json:"temperature,omitempty"`
Mode string `json:"mode,omitempty"`
Position int `json:"position,omitempty"`
Value float64 `json:"value,omitempty"`
Unit string `json:"unit,omitempty"`
Battery int `json:"battery,omitempty"`
LastUpdated string `json:"last_updated"`
}
type VoiceSegment struct {
Index int `json:"index"`
Text string `json:"text"`
AudioURL string `json:"audio_url"`
DurationMs int `json:"duration_ms"`
}
type ToolCall struct {
Name string `json:"name"`
Arguments map[string]interface{} `json:"arguments"`
Result interface{} `json:"result,omitempty"`
}