Skip to content
Fonctionnalité du Langage

UI Générative

Des agents qui affichent des composants riches et interactifs en ligne — tableaux, graphiques, formulaires, diffs — pas seulement du texte. Aucun code frontend requis.

Intégré
11 Composants
Extensible

Au-delà du Texte

Les interfaces de chatbot traditionnelles affichent tout sous forme de bulles de texte. Mais les agents produisent des données structurées — résultats de requêtes, rapports de validation, statuts de déploiement, diffs de comparaison. Afficher tout cela en markdown est une mauvaise expérience.

L'UI Générative de Haira permet aux outils de contrôler déclarativement la façon dont leur sortie s'affiche. Une requête de base de données s'affiche en tableau. Un résultat de validation s'affiche en carte de statut. Un pipeline de déploiement s'affiche en suivi de progression. Tout cela en ligne dans le chat, sans écrire de code frontend.

Comment Ça Fonctionne

Les outils retournent des composants UI en utilisant le module ui. Le runtime fait deux choses avec chaque résultat :

Pour l'Utilisateur
Composant Riche
Diffusé vers le frontend via le protocole ARP et affiché sous forme de tableau, carte, graphique ou formulaire interactif.
Pour l'Agent
Résumé Textuel
Une représentation textuelle compacte est envoyée au LLM pour qu'il puisse raisonner sur les données et décider des prochaines étapes.

Aucun chemin n'est sacrifié. L'utilisateur voit un beau tableau, l'agent voit des données structurées.

Exemple — Outil avec Sortie UI
haira
import "ui"

tool query_database(query: string) -> any {
    """Executes a SQL query and displays results."""
    rows, err = postgres.query(db, query)
    if err != nil {
        return ui.status_card("error", "Query Failed", conv.to_string(err))
    }
    return ui.table("Query Results", headers, rows)
}

Activez l'UI sur un agent avec une seule ligne :

haira
agent DataExplorer {
    provider: OpenAI
    tools: [query_database, search_data]
    ui: ui
    memory: conversation(max_turns: 30)
}

11 Composants Intégrés

status-card
Cartes de résultat succès, erreur, avertissement avec sections réductibles
table
Tableaux de données consultables et défilables avec onglets et en-têtes fixes
code-block
Code avec coloration syntaxique, bouton de copie et onglets multiples
diff
Comparaison avant/après côte à côte avec coloration syntaxique
key-value
Listes de propriétés avec valeurs stylisées pour l'affichage de métadonnées
progress
Suivi de pipeline multi-étapes avec statut par étape
chart
Visualisations de données en courbes, barres, camembert, aires et nuages de points
form
Formulaires interactifs avec champs texte, sélection, case à cocher et zone de texte
confirm
Dialogues de confirmation oui/non pour les actions destructives
choices
Sélecteurs d'options par bouton ou liste pour le choix de l'utilisateur
product-cards
Grilles de cartes image pour le e-commerce et les affichages de catalogue
Utilisation
haira
import "ui"

ui.status_card("success", "Deploy Complete", "All 3 services updated")
ui.table("Results", ["Name", "Email"], [["Alice", "a@co"], ["Bob", "b@co"]])
ui.key_value("Server Info", {"Region": "us-east-1", "Status": "healthy"})
ui.chart("bar", "Revenue", ["Q1", "Q2", "Q3", "Q4"], [dataset])
ui.confirm("Delete this record?", "Yes, delete", "Cancel")
ui.group(
    ui.status_card("success", "Query Complete", "42 rows"),
    ui.table("Results", headers, rows)
)

Interface Web Auto-générée

Chaque workflow Haira obtient automatiquement une interface web. Définissez un workflow, Haira génère le formulaire :

haira
@webui(title: "File Summarizer", description: "Upload a file and get an AI summary")
@post("/summarize")
workflow Summarize(document: file, context: string) -> { summary: string } {
    content, err = io.read_file(document)
    if err != nil { return { summary: "Failed to read file." } }
    reply, err = Summarizer.ask("Summarize: ${content}")
    if err != nil { return { summary: "AI error." } }
    return { summary: reply }
}

Le décorateur @webui définit le titre et la description. Les paramètres file s'affichent en champs d'envoi. Les workflows en streaming (-> stream) obtiennent une interface de chat complète.

Interface Chat en Streaming

Les workflows en streaming bénéficient de l'expérience la plus riche — streaming de tokens en temps réel, cartes d'exécution d'outils et composants UI en ligne :

haira
@webhook("/chat")
workflow Chat(message: string, session_id: string) -> stream {
    return Assistant.stream(message, session: session_id)
}

fn main() {
    http.Server([Chat]).listen(8080)
}

L'interface de chat communique via le protocole ARP — gérant les deltas de texte, les événements du cycle de vie des outils et le rendu de composants riches via WebSocket ou SSE.

Composants Personnalisés

Pour des besoins spécifiques à un domaine, déposez des Web Components TypeScript dans un répertoire components/ :

components/gantt-chart.ts
typescript
export class HairaGanttChart extends HTMLElement {
  connectedCallback() {
    this.attachShadow({ mode: "open" });
  }
  setProps(props) {
    // Render your custom UI
  }
}

export default {
  tag: "haira-gantt-chart",
  component: HairaGanttChart,
};

Les composants personnalisés héritent du thème Haira via des propriétés CSS personnalisées et peuvent dispatcher des événements haira-action qui deviennent des messages de chat. Le compilateur les découvre, les regroupe et les intègre au moment de la compilation.

Le Pipeline

1
Outils
Retournent des données typées via les fonctions ui.*
2
Runtime
Émet des messages ARP via WebSocket ou SSE
3
Frontend
Affiche le composant correspondant en ligne dans le chat

Pas de dépôt frontend séparé. Pas de client API à maintenir. Pas de bibliothèque de composants à installer. Un seul fichier .haira, un seul binaire, une interface complète.

Released under the Apache-2.0 License.