0717928496
## 调试日志
### 1. 插件管理器启动失败
- **症状**: DevTools 显示插件管理器一直"已停止",手动启动正常
- **排查**: 对比 process-manager.js 传入的环境变量 vs plugin-manager config.go 读取的变量
- **根因**: config.js 传入 PLUGIN_MANAGER_PORT=8094,但 config.go 读取 os.Getenv("PORT"),env 名不匹配。且 process.env 中 PORT 泄露时被误读为 9090,与 DevTools 端口冲突
- **修复**: config.js 将 PLUGIN_MANAGER_PORT → PORT,使 env 名与代码一致 (c3055f4)
### 2. 历史消息刷新后消失
- **症状**: 浏览器刷新后聊天历史清空
- **排查**: WebSocket history_response handler 中 if (msg.messages) 对空数组 [] 为 truthy
- **根因**: 后端返回空的 history_response (缓存为空) 时,空数组覆盖了 HTTP 已加载的消息
- **修复**: useWebSocket.ts 改为 if (msg.messages && msg.messages.length > 0),空数组走 else-if 分支仅打日志,不覆盖已有消息
### 3. Phase 6 多模型配置系统
- Gateway: ModelsConfigStore (JSON文件持久化) + Admin CRUD API (providers/models/routing)
- ai-core: ModelSelector 支持按 purpose 选择 + fallback_chain,无配置时回退 .env
- DevTools: 模型配置管理面板 (Providers/Models/Routing 三Tab)、在线模型查询代理、路由表单 checkbox 多选、关键词搜索过滤
- .gitignore: models.json + platform_configs.json
### 4. 多端客户端追踪
- Hub 新增 knownClients 映射 (clientID → KnownClient),在线/离线状态追踪
- 客户端备注持久化到 PostgreSQL
- DevTools 客户端管理面板
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
136 lines
6.4 KiB
Go
136 lines
6.4 KiB
Go
package ws
|
|
|
|
// MessageAttachment 消息附件 (图片等)
|
|
type MessageAttachment struct {
|
|
Type string `json:"type"` // image
|
|
URL string `json:"url"` // 图片 URL 或 data URL
|
|
ThumbnailURL string `json:"thumbnail_url,omitempty"`
|
|
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 | 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
|
|
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
|
|
}
|
|
|
|
// ReviewMessage 审查后的结构化消息(动作/聊天分离)
|
|
type ReviewMessage struct {
|
|
Type string `json:"type"` // "action" | "chat"
|
|
Content string `json:"content"`
|
|
DelayMs int `json:"delay_ms,omitempty"` // ms to wait before sending (0 = immediate)
|
|
}
|
|
|
|
// 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
|
|
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
|
|
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"`
|
|
}
|
|
|
|
// 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"`
|
|
}
|