yao/sui/docs/agent-sui.md
Max ebf3dcc870 Refactor Documentation for Backend API Method Naming and Iframe Communication
- Updated iframe documentation to remove token handling from the setup message, clarifying the focus on theme and locale.
- Added a new section in MCP documentation detailing HTTP transport configuration for API access, enhancing clarity on authorization.
- Revised frontend API documentation to standardize method naming by removing the 'Api' prefix in examples, improving consistency across backend calls.
- Enhanced event handling documentation by updating method names in examples, ensuring alignment with the new naming conventions.
2026-01-03 11:42:23 +08:00

8.4 KiB

Agent SUI

Agent SUI is a special SUI configuration designed for AI Agent applications. It automatically loads pages from the /agent/template/ directory and individual assistant pages from /assistants/<name>/pages/.

Directory Structure

<app>/
├── agent/
│   ├── agent.yao              # Agent configuration
│   └── template/              # Agent SUI template directory
│       ├── template.json      # Optional template configuration
│       ├── __document.html    # Global document template
│       ├── __data.json        # Global data
│       ├── __assets/          # Global assets (CSS, JS, images)
│       │   ├── css/
│       │   ├── js/
│       │   └── images/
│       ├── pages/             # Global agent pages (login, error, etc.)
│       │   └── login/
│       │       └── login.html
│       └── __locales/         # Internationalization
│
└── assistants/                # Assistants directory
    ├── demo/                  # Assistant: demo
    │   ├── package.yao        # Assistant configuration
    │   └── pages/             # Assistant-specific pages
    │       ├── index/
    │       │   ├── index.html
    │       │   ├── index.css
    │       │   └── index.ts
    │       └── __assets/      # Optional assistant-specific assets
    │
    └── another/               # Assistant: another
        ├── package.yao
        └── pages/
            └── settings/
                └── settings.html

Route Mapping

File Path Public URL
/agent/template/pages/login/login.html /agents/login
/assistants/demo/pages/index/index.html /agents/demo/index
/assistants/another/pages/settings/settings.html /agents/another/settings

Asset Paths

  • Global assets: /agents/assets/.../agent/template/__assets/...
  • Assistant assets: /agents/<assistant-id>/assets/.../assistants/<assistant-id>/pages/__assets/...

Build Commands

# Build Agent SUI
yao sui build agent

# Watch Agent SUI for changes
yao sui watch agent

Build Output

After running yao sui build agent, the following structure is generated:

<app>/public/
└── agents/                        # Public root for Agent SUI
    ├── assets/                    # Static assets
    │   ├── libsui.min.js          # SUI frontend SDK
    │   ├── libsui.min.js.map      # Source map
    │   ├── css/                   # From /agent/template/__assets/css/
    │   ├── js/                    # From /agent/template/__assets/js/
    │   └── images/                # From /agent/template/__assets/images/
    │
    ├── login.sui                  # Compiled page
    ├── login.cfg                  # Page configuration
    │
    ├── demo/                      # Assistant: demo
    │   ├── index.sui              # Compiled page
    │   └── index.cfg              # Page configuration
    │
    └── another/                   # Assistant: another
        ├── settings.sui           # Compiled page
        └── settings.cfg           # Page configuration

File Types:

Extension Description
.sui Compiled HTML page (includes template, styles, scripts)
.cfg Page configuration (JSON format)
.jit JIT component (for dynamic loading)

Auto-Loading

Agent SUI is automatically loaded when:

  1. The /agent/template/ directory exists
  2. At least one assistant has a pages/ directory

No additional configuration is required.

Document Template

Create /agent/template/__document.html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>{{ $global.title }}</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="icon" href="/agents/assets/images/favicon.png" />
  </head>
  <body>
    <div class="container">{{ __page }}</div>
  </body>
</html>

Global Data

Create /agent/template/__data.json:

{
  "title": "AI Agent",
  "version": "1.0.0",
  "theme": "light"
}

Example Assistant Page

/assistants/demo/pages/index/index.html:

<div id="demo-index" class="page">
  <h1>{{ title }}</h1>
  <div class="content">
    <p>{{ description }}</p>
  </div>
</div>

/assistants/demo/pages/index/index.json:

{
  "title": "Welcome",
  "description": "This is a demo page"
}

/assistants/demo/pages/index/index.css:

.page {
  max-width: 800px;
  margin: 0 auto;
  padding: 24px;
}

Page Configuration

Create <page>.config for page settings:

{
  "title": "Page Title",
  "guard": "bearer-jwt",
  "cache": 3600
}

Backend Scripts

Each page can have a backend script:

/assistants/demo/pages/index/index.backend.ts:

function BeforeRender(request: Request): Record<string, any> {
  return {
    user: Process("session.Get", "user"),
    data: Process("models.data.Get", {}),
  };
}

function ApiGetData(request: Request): any {
  return Process("models.data.Get", {});
}

Using Components

Pages can use other pages as components:

<import s:as="Header" s:from="/shared/header" />
<import s:as="Footer" s:from="/shared/footer" />

<div class="page">
  <header title="Demo" />
  <main>
    <p>Content here</p>
  </main>
  <footer />
</div>

Accessing in Templates

Use standard SUI template syntax:

<!-- Data binding -->
<h1>{{ title }}</h1>

<!-- Conditionals -->
<div s:if="{{ isLoggedIn }}">Welcome!</div>

<!-- Loops -->
<ul>
  <li s:for="{{ items }}" s:for-item="item">{{ item.name }}</li>
</ul>

<!-- Events -->
<button s:on-click="handleClick">Click Me</button>

Frontend Script

Frontend scripts can be written in two styles:

Direct Style (Simple Pages)

// Runs immediately when script loads
document.addEventListener("DOMContentLoaded", () => {
  const form = document.querySelector("#myForm") as HTMLFormElement;

  form.addEventListener("submit", async (e) => {
    e.preventDefault();
    // Handle submission
  });
});

// Smooth scrolling
document.querySelectorAll('a[href^="#"]').forEach((anchor) => {
  anchor.addEventListener("click", function (e) {
    e.preventDefault();
    const target = document.querySelector(this.getAttribute("href"));
    target?.scrollIntoView({ behavior: "smooth" });
  });
});

Component Style (Interactive Pages)

/assistants/demo/pages/index/index.ts:

import { $Backend, Component, EventData } from "@yao/sui";

const self = this as Component;

// Event handler bound to s:on-click="HandleClick"
self.HandleClick = async (event: Event, data: EventData) => {
  const result = await $Backend().Call("GetData", data.id);
  console.log(result);
};

// Form submission
self.HandleSubmit = async (event: Event) => {
  event.preventDefault();
  const form = event.target as HTMLFormElement;
  const formData = new FormData(form);
  await $Backend().Call("Submit", Object.fromEntries(formData));
};

CUI Integration

When Agent SUI pages are embedded in CUI via /web/ routes, they can communicate with the CUI host.

Receiving Context

window.addEventListener("message", (e) => {
  if (e.origin !== window.location.origin) return;

  if (e.data.type === "setup") {
    const { theme, locale } = e.data.message;
    document.documentElement.setAttribute("data-theme", theme);
  }
});

Sending Actions

// Helper function
const sendAction = (name: string, payload?: any) => {
  window.parent.postMessage(
    { type: "action", message: { name, payload } },
    window.location.origin
  );
};

// Show notification
sendAction("notify.success", { message: "Done!" });

// Navigate
sendAction("navigate", {
  route: "/agents/demo/detail",
  title: "Details",
});

// Close sidebar
sendAction("event.emit", { key: "app/closeSidebar", value: {} });

See Frontend API - CUI Integration for complete documentation.