refactor: replace welcome message with server_info status payload
Unify the initial connection handshake and capability update paths. The server now sends a server_info status message on connect and whenever capabilities change, enabling the onboarding flow where voice becomes available after models are configured.
This commit is contained in:
@@ -356,7 +356,6 @@ export const MessageInput = forwardRef<MessageInputRef, MessageInputProps>(funct
|
||||
serverInfo,
|
||||
mode: 'dictation',
|
||||
})
|
||||
const dictationReadiness = serverInfo?.capabilities?.voice?.dictation ?? null
|
||||
|
||||
const canStartDictation = useCallback(() => {
|
||||
const socketConnected = client?.isConnected ?? false
|
||||
@@ -416,28 +415,7 @@ export const MessageInput = forwardRef<MessageInputRef, MessageInputProps>(funct
|
||||
}, [dictationStatus, isDictating, isDictationProcessing])
|
||||
|
||||
const startDictationIfAvailable = useCallback(async () => {
|
||||
console.info(
|
||||
`[DictationGate] start requested ${JSON.stringify({
|
||||
serverId: voiceServerId ?? null,
|
||||
agentId: voiceAgentId ?? null,
|
||||
socketConnected: client?.isConnected ?? false,
|
||||
isReadyForDictation: isReadyForDictation ?? null,
|
||||
disabled,
|
||||
serverInfoPresent: Boolean(serverInfo),
|
||||
capabilitiesPresent: Boolean(serverInfo?.capabilities),
|
||||
dictationReadinessEnabled: dictationReadiness?.enabled ?? null,
|
||||
dictationReadinessReason: dictationReadiness?.reason ?? null,
|
||||
dictationUnavailableMessage,
|
||||
})}`
|
||||
)
|
||||
if (dictationUnavailableMessage) {
|
||||
console.info(
|
||||
`[DictationGate] blocked before start ${JSON.stringify({
|
||||
serverId: voiceServerId ?? null,
|
||||
agentId: voiceAgentId ?? null,
|
||||
dictationUnavailableMessage,
|
||||
})}`
|
||||
)
|
||||
isDictatingRef.current = false
|
||||
toast.error(dictationUnavailableMessage)
|
||||
return
|
||||
@@ -446,18 +424,7 @@ export const MessageInput = forwardRef<MessageInputRef, MessageInputProps>(funct
|
||||
// state-ref sync effect, so a rapid second toggle routes to confirm.
|
||||
isDictatingRef.current = true
|
||||
await startDictation()
|
||||
}, [
|
||||
client,
|
||||
dictationReadiness,
|
||||
dictationUnavailableMessage,
|
||||
disabled,
|
||||
isReadyForDictation,
|
||||
serverInfo,
|
||||
startDictation,
|
||||
toast,
|
||||
voiceAgentId,
|
||||
voiceServerId,
|
||||
])
|
||||
}, [dictationUnavailableMessage, startDictation, toast])
|
||||
|
||||
// Animate overlay
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1100,19 +1100,6 @@ function SessionProviderInternal({
|
||||
if (message.type !== "status") return;
|
||||
const serverInfo = parseServerInfoStatusPayload(message.payload);
|
||||
if (serverInfo) {
|
||||
console.info(
|
||||
`[Session] server_info received ${JSON.stringify({
|
||||
serverId,
|
||||
payloadServerId: serverInfo.serverId,
|
||||
hostname: serverInfo.hostname,
|
||||
version: serverInfo.version,
|
||||
capabilitiesPresent: Boolean(serverInfo.capabilities),
|
||||
dictationCapabilityEnabled:
|
||||
serverInfo.capabilities?.voice?.dictation?.enabled ?? null,
|
||||
dictationCapabilityReason:
|
||||
serverInfo.capabilities?.voice?.dictation?.reason ?? null,
|
||||
})}`
|
||||
);
|
||||
updateSessionServerInfo(serverId, {
|
||||
serverId: serverInfo.serverId,
|
||||
hostname: serverInfo.hostname,
|
||||
|
||||
@@ -5,12 +5,11 @@ const daemonClientMock = vi.hoisted(() => {
|
||||
|
||||
class MockDaemonClient {
|
||||
public lastError: string | null = null;
|
||||
private lastWelcome = {
|
||||
type: "welcome" as const,
|
||||
private lastServerInfo = {
|
||||
status: "server_info" as const,
|
||||
serverId: "srv_probe_test",
|
||||
hostname: "probe-host" as string | null,
|
||||
version: "0.0.0",
|
||||
resumed: false,
|
||||
};
|
||||
|
||||
constructor(config: { clientId?: string; url?: string }) {
|
||||
@@ -29,8 +28,8 @@ const daemonClientMock = vi.hoisted(() => {
|
||||
return;
|
||||
}
|
||||
|
||||
getLastWelcomeMessage() {
|
||||
return this.lastWelcome;
|
||||
getLastServerInfoMessage() {
|
||||
return this.lastServerInfo;
|
||||
}
|
||||
|
||||
async ping(): Promise<{ rttMs: number }> {
|
||||
|
||||
@@ -115,12 +115,12 @@ export function connectAndProbe(
|
||||
|
||||
void client.connect().then(() => {
|
||||
clearTimeout(timer);
|
||||
const welcome = client.getLastWelcomeMessage();
|
||||
if (!welcome) {
|
||||
const serverInfo = client.getLastServerInfoMessage();
|
||||
if (!serverInfo) {
|
||||
void client.close().catch(() => undefined);
|
||||
reject(
|
||||
new DaemonConnectionTestError("Missing welcome message", {
|
||||
reason: "Missing welcome message",
|
||||
new DaemonConnectionTestError("Missing server info message", {
|
||||
reason: "Missing server info message",
|
||||
lastError: client.lastError ?? null,
|
||||
})
|
||||
);
|
||||
@@ -128,8 +128,8 @@ export function connectAndProbe(
|
||||
}
|
||||
resolve({
|
||||
client,
|
||||
serverId: welcome.serverId,
|
||||
hostname: welcome.hostname,
|
||||
serverId: serverInfo.serverId,
|
||||
hostname: serverInfo.hostname,
|
||||
});
|
||||
}).catch((error) => {
|
||||
clearTimeout(timer);
|
||||
|
||||
Reference in New Issue
Block a user