feat(robot): add guided hotspot binding flow

This commit is contained in:
2026-08-16 14:27:43 +08:00
parent 54443232dd
commit b7a1590ca1
7 changed files with 855 additions and 18 deletions

View File

@@ -33,6 +33,8 @@ const SAFE_ERROR_MESSAGES: Record<string, string> = {
AI_HARDWARE_RATE_LIMITED: 'AI hardware service is busy; retry later',
AI_HARDWARE_INVALID_REQUEST: 'Invalid AI hardware request',
AI_HARDWARE_INVALID_RESPONSE: 'AI hardware service returned an invalid response',
AI_HARDWARE_PROVISIONING_DISABLED: 'AI hardware guided provisioning is not enabled',
AI_HARDWARE_PORTAL_OPEN_FAILED: 'AI hardware provisioning portal could not be opened',
};
const OPERATION_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
@@ -61,6 +63,10 @@ export type AiHardwareOverview = {
devices: AiHardwareDevice[];
};
export type AiHardwareProvisioningCapabilities = {
guidedHotspotBinding: boolean;
};
export type AiHardwareAgentConfiguration = AiHardwareAgent & {
system_prompt: string | null;
lang_code: string | null;
@@ -343,6 +349,17 @@ function readEnvelope(value: unknown): MainEnvelope {
return value;
}
function readProvisioningCapabilities(value: unknown): AiHardwareProvisioningCapabilities {
if (!isRecord(value) || !hasOnlyKeys(value, ['guided_hotspot_binding'])
|| typeof value.guided_hotspot_binding !== 'boolean') invalidPayload();
return { guidedHotspotBinding: value.guided_hotspot_binding };
}
function readPortalOpened(value: unknown): { opened: true } {
if (!isRecord(value) || !hasOnlyKeys(value, ['opened']) || value.opened !== true) invalidPayload();
return { opened: true };
}
function throwEnvelopeError(envelope: MainEnvelope): never {
const status = isInteger(envelope.status, 400, 599) ? envelope.status : 502;
const code = typeof envelope.code === 'string' && /^[A-Za-z0-9._-]{1,128}$/.test(envelope.code)
@@ -503,6 +520,22 @@ export async function getAiHardwareOverview(): Promise<AiHardwareOverview> {
return request('', undefined, readOverview) as Promise<AiHardwareOverview>;
}
export async function getAiHardwareProvisioningCapabilities(): Promise<AiHardwareProvisioningCapabilities> {
return request(
'/provisioning-capabilities',
undefined,
readProvisioningCapabilities,
) as Promise<AiHardwareProvisioningCapabilities>;
}
export async function openAiHardwareProvisioningPortal(): Promise<{ opened: true }> {
return request(
'/provisioning-portal/open',
jsonInit('POST', {}),
readPortalOpened,
) as Promise<{ opened: true }>;
}
export async function getAiHardwareConfigurationCatalog(
ttsModelId?: string,
): Promise<AiHardwareConfigurationCatalog> {