Tworzenie i dostosowywanie katalogów komponentów

W architekturze A2UI każda powierzchnia jest obsługiwana przez katalog komponentów. Katalog to formalna umowa, która określa komponenty interfejsu, schematy właściwości i lokalne funkcje klienta dostępne dla agenta AI. Zamiast generować dowolny kod lub wymyślać nieznane elementy, agent musi tworzyć interfejsy użytkownika, korzystając wyłącznie z komponentów zadeklarowanych w katalogu.

Innymi słowy: katalog deklaruje komponenty, a agent używa ich do tworzenia interfejsu aplikacji.

Podczas tworzenia aplikacji na Androida za pomocą renderera A2UI Jetpack Compose masz do wyboru elastyczne opcje dostarczania katalogów:

  • Katalog podstawowy: projekt A2UI definiuje standardową specyfikację do zwykłych obciążeń o nazwie Katalog podstawowy, która zawiera typowe elementy, takie jak przyciski, tekst, pola tekstowe, karty i listy. Biblioteka AndroidXandroidx.compose.material3:material3-a2ui zapewnia gotową implementację tej specyfikacji katalogu podstawowego przy użyciu natywnych komponentów Material Design 3. androidx.a2ui.compose:compose-uiBiblioteka zawiera też ogólną definicję schematu dla katalogu podstawowego, która pomaga wdrożyć katalog podstawowy w własnym systemie projektowania.
  • Katalogi niestandardowe: w przypadku aplikacji produkcyjnych z własnymi systemami projektowania możesz utworzyć katalog niestandardowy od zera. Ogranicza to agenta do dokładnych komponentów, tokenów stylów i języka wizualnego aplikacji.
  • Podzbiór lub hybryda: możesz połączyć konkretne implementacje komponentów z podstawowego katalogu z własnymi komponentami niestandardowymi lub zastąpić poszczególne implementacje komponentów w pakiecie podstawowego katalogu.

Korzystanie z podstawowego katalogu

Aby szybko rozpocząć pracę bez tworzenia schematu komponentu od zera, możesz użyć podanej implementacji specyfikacji A2UI Basic Catalog. Biblioteka androidx.compose.material3:material3-a2ui implementuje katalog podstawowy za pomocą komponentów Material Design 3.

Podczas tworzenia instancji materialA2uiBasicCatalogV1 podaj renderery i procedury obsługi tych elementów:

  • komponenty multimedialne, takie jak obrazy, odtwarzacze wideo i audio;
  • Otwieranie adresu URL
  • Formatowanie przetłumaczonych wiadomości

Biblioteki A2UI celowo nie zawierają zależności od mediów zewnętrznych i sieci, takich jak Coil, Glide czy Media3. Zamiast tego udostępniasz własne moduły renderujące. Zapobiega to konfliktom zależności, ponieważ udostępnia unikalne biblioteki. Jeśli na przykład Twoja aplikacja korzysta już z biblioteki Coil do wczytywania obrazów lub z biblioteki Media3 do odtwarzania, możesz podłączyć te biblioteki bezpośrednio do katalogu.

Poniższy przykład pokazuje, jak utworzyć instancję podstawowego katalogu i połączyć preferowane biblioteki multimediów, otwieracz adresów URL i formater wiadomości:

// Instantiate the provided Basic Catalog (implemented with Material 3)
val basicCatalog = materialA2uiBasicCatalogV1(
    // Example: Wire up Coil for image loading (via AsyncImage)
    image = MaterialA2uiBasicCatalogV1Defaults.image {
            url, description, scale, modifier, onError ->
        AsyncImage(
            model = url,
            contentDescription = description,
            contentScale = scale,
            modifier = modifier,
            onError = { state -> onError(state.result.throwable) },
        )
    },

    // Example: Use ExoPlayer/Media3 for video
    video = MaterialA2uiBasicCatalogV1Defaults.video { url, modifier, onError ->
        // Custom ExoPlayer video integration here
    },

    // Example: Use an audio player
    audioPlayer = MaterialA2uiBasicCatalogV1Defaults.audioPlayer {
            url, description, modifier, onError ->
        // Custom audio integration here
    },

    // Handle outbound URLs, such as using an app navigator or context intents.
    urlOpener = { url ->
        appNavigator.openUrl(url)
    },

    // Handle localized message formatting
    messageFormatter = { pattern, locale, args ->
        MessageFormat.format(context, locale, pattern, args)
    },
    localeProvider = A2uiLocaleProvider.Default,
)

Tworzenie katalogu komponentów niestandardowych od podstaw

Jeśli Twoja aplikacja korzysta z niestandardowego systemu projektowania, możesz zdefiniować własny katalog zawierający własne niestandardowe implementacje A2uiComponent. Dzięki temu będziesz mieć pełną kontrolę nad schematami komponentów udostępnianymi agentowi i generowanym natywnym interfejsem Compose:

// Define a custom catalog that mirrors your app's design system
val CustomDesignSystemCatalog = A2uiCatalog(
    catalogId = "https://example.com/catalogs/my-design-system/v1/catalog.json",
    components = listOf(
        CustomButtonComponent,
        CustomCardComponent,
        CustomTextFieldComponent,
    ),
    functions = listOf(MyCustomLocalFunction()),
)

Instrukcje dotyczące definiowania poszczególnych schematów komponentów i logiki renderowania interfejsu Compose UI znajdziesz w artykule Implementowanie niestandardowych komponentów A2UI.

Używanie podzbioru podstawowych komponentów katalogu z komponentami niestandardowymi

Nie musisz wybierać między budowaniem wszystkiego od zera a wdrażaniem całego katalogu podstawowego. Możesz utworzyć katalog, który łączy wybrane komponenty z dostarczonej implementacji katalogu podstawowego z własnymi komponentami niestandardowymi:

// Assemble a catalog using select Basic Catalog components alongside custom components
val hybridCatalog = A2uiCatalog(
    catalogId = "https://example.com/catalogs/my-app/v1/catalog.json",
    components = listOf(
        // Use provided Basic Catalog components (built with Material 3)
        MaterialA2uiBasicCatalogV1Defaults.text,
        MaterialA2uiBasicCatalogV1Defaults.card,

        // Add proprietary components from your app's design system
        CustomChartComponent,
        CustomProductCardComponent,
    ),
    functions = createBasicCatalogFunctions(...),
)

Możesz też dostosować udostępniony pakiet Podstawowy katalog, zastępując konkretne miejsca na komponenty:

// Override specific components within the Basic Catalog suite
val customizedBasicCatalog = materialA2uiBasicCatalogV1(
    // Supply required renderers (such as Coil or ExoPlayer) as shown earlier
    image = MaterialA2uiBasicCatalogV1Defaults.image(myImageRenderer),
    video = MaterialA2uiBasicCatalogV1Defaults.video(myVideoRenderer),
    audioPlayer = MaterialA2uiBasicCatalogV1Defaults
        .audioPlayer(myAudioRenderer),
    urlOpener = { url -> /* Open URL */ },
    messageFormatter = { pattern, _, _ -> pattern },
    localeProvider = A2uiLocaleProvider.Default,
    // Replaces the default button. If you use this, implement the
    // A2uiBasicCatalogV1.Button interface.
    button = MyCustomBrandButtonComponent,
    
)

Zarządzanie wersjami katalogu i ewolucją schematu

Katalogi A2UI są jawnie wersjonowane na podstawie umowy schematu JSON. Wprowadzając zmiany w schemacie, które powodują niezgodność wsteczną, musisz zwiększyć numer wersji:

// Original component (v1 catalog)
object CustomButtonComponent : A2uiComponent { ... }

// Unchanged component across versions
object CustomTextComponent : A2uiComponent { ... }

// Future breaking schema change (v2 catalog)
object CustomButtonComponentV2 : A2uiComponent { ... }

// Assembles the v1 catalog
fun customCatalogV1(
    button: A2uiComponent = CustomButtonComponent,
    text: A2uiComponent = CustomTextComponent,
): A2uiCatalog = A2uiCatalog(
    catalogId = "https://example.com/catalogs/my-app/v1/catalog.json",
    components = listOf(button, text),
)

// Assembles the v2 catalog
fun customCatalogV2(
    button: A2uiComponent = CustomButtonComponentV2,
    text: A2uiComponent = CustomTextComponent,
): A2uiCatalog = A2uiCatalog(
    catalogId = "https://example.com/catalogs/my-app/v2/catalog.json",
    components = listOf(button, text),
)

Aby umożliwić płynne migracje bez przestojów, klient może zarejestrować w procesorze wiadomości jednocześnie kilka obsługiwanych wersji katalogu:

private val processor = A2uiMessageProcessor(
    catalogs = listOf(
        customCatalogV1(),
        customCatalogV2(),
    ),
)

Podczas negocjacji katalogu agent wykrywa wszystkie obsługiwane identyfikatory katalogów i kieruje reklamy na odpowiednią wersję na każdej platformie.

Szczegóły implementacji

W kolejnych sekcjach znajdziesz wyjaśnienie weryfikacji katalogu wewnętrznego i negocjacji schematu.

Ścieżki użytkownika zarządzania katalogiem przedstawiają te kluczowe interfejsy API:

  • A2uiCatalog: Interfejs i funkcja fabryczna najwyższego poziomu do definiowania katalogów komponentów.
  • materialA2uiBasicCatalogVX: funkcje fabryczne z określonymi wersjami (np. materialA2uiBasicCatalogV1), które zapewniają implementację Material 3 standardowej specyfikacji A2UI Basic Catalog.
  • A2uiReadinessEvaluatorasReadinessEvaluator(): A2uiReadinessEvaluator to interfejs do oceny gotowości komponentu. Funkcja rozszerzenia asReadinessEvaluator() określa stany gotowości za pomocą komponentów zarejestrowanych w katalogu.

Katalog wersji A2UI i schematy komponentów

Definicja schematu katalogu jest powiązana z konkretną wersją protokołu. Wraz z rozwojem protokołu definicja katalogu jest aktualizowana do nowszej wersji. Implementacje komponentów w tej nowej wersji mogą korzystać ze zaktualizowanych interfejsów API renderowania, a starsze wersje będą nadal działać równolegle.