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:
Mohamed Boudra
2026-03-12 20:38:03 +07:00
parent 554017b0b8
commit b09a731d85
16 changed files with 177 additions and 162 deletions
+1 -34
View File
@@ -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);