refactor: 统一实时协议类型并扩展会话状态字段
This commit is contained in:
@@ -8,15 +8,22 @@ import "encoding/json"
|
||||
type MsgType string
|
||||
|
||||
const (
|
||||
MsgStart MsgType = "start" // Begin recording session
|
||||
MsgStop MsgType = "stop" // End recording session
|
||||
MsgPaste MsgType = "paste" // Re-paste a history item
|
||||
MsgHello MsgType = "hello"
|
||||
MsgStart MsgType = "start"
|
||||
MsgStop MsgType = "stop"
|
||||
MsgPaste MsgType = "paste"
|
||||
MsgPing MsgType = "ping"
|
||||
MsgPong MsgType = "pong"
|
||||
)
|
||||
|
||||
// ClientMsg is a JSON control message from the phone.
|
||||
type ClientMsg struct {
|
||||
Type MsgType `json:"type"`
|
||||
SessionID string `json:"sessionId,omitempty"`
|
||||
Seq int64 `json:"seq,omitempty"`
|
||||
Text string `json:"text,omitempty"` // Only for "paste"
|
||||
Version int `json:"version,omitempty"`
|
||||
TS int64 `json:"ts,omitempty"`
|
||||
// Future extension: dynamic hotwords (Phase 2)
|
||||
// Hotwords []string `json:"hotwords,omitempty"`
|
||||
}
|
||||
@@ -24,17 +31,33 @@ type ClientMsg struct {
|
||||
// ── Server → Client messages ──
|
||||
|
||||
const (
|
||||
MsgPartial MsgType = "partial" // Interim ASR result
|
||||
MsgFinal MsgType = "final" // Final ASR result
|
||||
MsgPasted MsgType = "pasted" // Paste confirmed
|
||||
MsgError MsgType = "error" // Error notification
|
||||
MsgReady MsgType = "ready"
|
||||
MsgState MsgType = "state"
|
||||
MsgStartAck MsgType = "start_ack"
|
||||
MsgStopAck MsgType = "stop_ack"
|
||||
MsgPartial MsgType = "partial"
|
||||
MsgFinal MsgType = "final"
|
||||
MsgPasted MsgType = "pasted"
|
||||
MsgError MsgType = "error"
|
||||
)
|
||||
|
||||
const (
|
||||
StateIdle = "idle"
|
||||
StateRecording = "recording"
|
||||
StateStopping = "stopping"
|
||||
)
|
||||
|
||||
// ServerMsg is a JSON message sent to the phone.
|
||||
type ServerMsg struct {
|
||||
Type MsgType `json:"type"`
|
||||
State string `json:"state,omitempty"`
|
||||
SessionID string `json:"sessionId,omitempty"`
|
||||
Seq int64 `json:"seq,omitempty"`
|
||||
Text string `json:"text,omitempty"`
|
||||
Message string `json:"message,omitempty"` // For errors
|
||||
Code string `json:"code,omitempty"`
|
||||
Retryable bool `json:"retryable,omitempty"`
|
||||
TS int64 `json:"ts,omitempty"`
|
||||
}
|
||||
|
||||
func (m ServerMsg) Bytes() []byte {
|
||||
|
||||
35
web/src/protocol.ts
Normal file
35
web/src/protocol.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
export type ClientMsgType = "hello" | "start" | "stop" | "paste" | "ping";
|
||||
|
||||
export type ServerMsgType =
|
||||
| "ready"
|
||||
| "state"
|
||||
| "start_ack"
|
||||
| "stop_ack"
|
||||
| "partial"
|
||||
| "final"
|
||||
| "pasted"
|
||||
| "error"
|
||||
| "pong";
|
||||
|
||||
export type SessionState = "idle" | "recording" | "stopping";
|
||||
|
||||
export interface ClientMsg {
|
||||
type: ClientMsgType;
|
||||
sessionId?: string;
|
||||
seq?: number;
|
||||
text?: string;
|
||||
version?: number;
|
||||
ts?: number;
|
||||
}
|
||||
|
||||
export interface ServerMsg {
|
||||
type: ServerMsgType;
|
||||
state?: SessionState;
|
||||
sessionId?: string;
|
||||
seq?: number;
|
||||
text?: string;
|
||||
message?: string;
|
||||
code?: string;
|
||||
retryable?: boolean;
|
||||
ts?: number;
|
||||
}
|
||||
@@ -13,9 +13,13 @@ type ConnectionStatus = "connected" | "disconnected" | "connecting";
|
||||
interface AppState {
|
||||
// Connection
|
||||
connectionStatus: ConnectionStatus;
|
||||
weakNetwork: boolean;
|
||||
// Recording
|
||||
recording: boolean;
|
||||
pendingStart: boolean;
|
||||
stopping: boolean;
|
||||
micReady: boolean;
|
||||
activeSessionId: string | null;
|
||||
// Preview
|
||||
previewText: string;
|
||||
previewActive: boolean;
|
||||
@@ -24,8 +28,12 @@ interface AppState {
|
||||
|
||||
// Actions
|
||||
setConnectionStatus: (status: ConnectionStatus) => void;
|
||||
setWeakNetwork: (weak: boolean) => void;
|
||||
setRecording: (recording: boolean) => void;
|
||||
setPendingStart: (pending: boolean) => void;
|
||||
setStopping: (stopping: boolean) => void;
|
||||
setMicReady: (ready: boolean) => void;
|
||||
setActiveSessionId: (sessionId: string | null) => void;
|
||||
setPreview: (text: string, isFinal: boolean) => void;
|
||||
clearPreview: () => void;
|
||||
addHistory: (text: string) => void;
|
||||
@@ -36,15 +44,23 @@ export const useAppStore = create<AppState>()(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
connectionStatus: "connecting",
|
||||
weakNetwork: false,
|
||||
recording: false,
|
||||
pendingStart: false,
|
||||
stopping: false,
|
||||
micReady: false,
|
||||
activeSessionId: null,
|
||||
previewText: "",
|
||||
previewActive: false,
|
||||
history: [],
|
||||
|
||||
setConnectionStatus: (connectionStatus) => set({ connectionStatus }),
|
||||
setWeakNetwork: (weakNetwork) => set({ weakNetwork }),
|
||||
setRecording: (recording) => set({ recording }),
|
||||
setPendingStart: (pendingStart) => set({ pendingStart }),
|
||||
setStopping: (stopping) => set({ stopping }),
|
||||
setMicReady: (micReady) => set({ micReady }),
|
||||
setActiveSessionId: (activeSessionId) => set({ activeSessionId }),
|
||||
|
||||
setPreview: (text, isFinal) =>
|
||||
set({
|
||||
|
||||
Reference in New Issue
Block a user