thesys-generative-ui

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

TheSys Generative UI Integration

TheSys生成式UI集成

Complete skill for building AI-powered interfaces with TheSys C1 Generative UI API. Convert LLM responses into streaming, interactive React components.

通过TheSys C1生成式UI API构建AI驱动界面的完整指南。将LLM响应转换为流式交互式React组件。

What is TheSys C1?

什么是TheSys C1?

TheSys C1 is a Generative UI API that transforms Large Language Model (LLM) responses into live, interactive React components instead of plain text. Rather than displaying walls of text, your AI applications can stream forms, charts, tables, search results, and custom UI elements in real-time.
TheSys C1是一款生成式UI API,可将大语言模型(LLM)的响应转换为实时交互式React组件,而非纯文本。您的AI应用无需展示大量纯文本,而是可以实时流式传输表单、图表、表格、搜索结果和自定义UI元素。

Key Innovation

核心创新

Traditional LLM applications return text that developers must manually convert into UI:
LLM → Text Response → Developer Parses → Manual UI Code → Display
TheSys C1 eliminates this manual step:
LLM → C1 API → Interactive React Components → Display
传统LLM应用返回文本,开发者必须手动将其转换为UI:
LLM → 文本响应 → 开发者解析 → 手动编写UI代码 → 展示
TheSys C1省去了这一手动步骤:
LLM → C1 API → 交互式React组件 → 展示

Real-World Impact

实际应用效果

  • 83% more engaging - Users prefer interactive components over text walls
  • 10x faster development - No manual text-to-UI conversion
  • 80% cheaper - Reduced development time and maintenance
  • Production-ready - Used by teams building AI-native products

  • 互动性提升83% - 用户更倾向于使用交互式组件而非纯文本内容
  • 开发速度提升10倍 - 无需手动将文本转换为UI
  • 成本降低80% - 减少开发时间与维护成本
  • 可用于生产环境 - 已被开发AI原生产品的团队采用

When to Use This Skill

适用场景

Use this skill when building:
  1. Chat Interfaces with Rich UI
    • Conversational interfaces that need more than text
    • Customer support chatbots with forms and actions
    • AI assistants that show data visualizations
  2. Data Visualization Applications
    • Analytics dashboards with AI-generated charts
    • Business intelligence tools with dynamic tables
    • Search interfaces with structured results
  3. Dynamic Form Generation
    • E-commerce product configurators
    • Multi-step workflows driven by AI
    • Data collection with intelligent forms
  4. AI Copilots and Assistants
    • Developer tools with code snippets and docs
    • Educational platforms with interactive lessons
    • Research tools with citations and references
  5. Search and Discovery
    • Semantic search with structured results
    • Document analysis with highlighted findings
    • Knowledge bases with interactive answers
在以下场景中使用本指南:
  1. 具备丰富UI的聊天界面
    • 不满足于纯文本的对话式界面
    • 带有表单和操作的客户支持聊天机器人
    • 展示数据可视化的AI助手
  2. 数据可视化应用
    • 带有AI生成图表的分析仪表盘
    • 具备动态表格的商业智能工具
    • 带有结构化结果的搜索界面
  3. 动态表单生成
    • 电商产品配置器
    • AI驱动的多步骤工作流
    • 智能数据收集表单
  4. AI copilots与助手
    • 带有代码片段和文档的开发者工具
    • 具备交互式课程的教育平台
    • 带有引用和参考文献的研究工具
  5. 搜索与发现
    • 带有结构化结果的语义搜索
    • 带有高亮结果的文档分析
    • 带有交互式答案的知识库

This Skill Prevents These Errors

本指南可避免的错误

  • ❌ Empty agent responses from incorrect streaming setup
  • ❌ Models ignoring system prompts due to message array issues
  • ❌ Version compatibility errors between SDK and API
  • ❌ Themes not applying without ThemeProvider
  • ❌ Streaming failures from improper response transformation
  • ❌ Tool calling bugs from invalid Zod schemas
  • ❌ Thread state loss from missing persistence
  • ❌ CSS conflicts from import order issues
  • ❌ TypeScript errors from outdated type definitions
  • ❌ CORS failures from missing headers
  • ❌ Rate limit crashes without retry logic
  • ❌ Authentication token errors from environment issues

  • ❌ 流式传输设置错误导致的Agent空响应
  • ❌ 消息数组问题导致模型忽略系统提示
  • ❌ SDK与API版本不兼容错误
  • ❌ 未使用ThemeProvider导致主题不生效
  • ❌ 响应转换不当导致的流式传输失败
  • ❌ Zod schema无效导致的工具调用错误
  • ❌ 缺少持久化导致的线程状态丢失
  • ❌ 导入顺序问题导致的CSS冲突
  • ❌ 类型定义过时导致的TypeScript错误
  • ❌ 缺少请求头导致的CORS失败
  • ❌ 无重试逻辑导致的速率限制崩溃
  • ❌ 环境配置问题导致的认证令牌错误

Quick Start by Framework

按框架快速开始

Vite + React Setup

Vite + React 配置

Most flexible setup for custom backends (your preferred stack).
最灵活的配置,适用于自定义后端(您偏好的技术栈)。

1. Install Dependencies

1. 安装依赖

bash
npm install @thesysai/genui-sdk @crayonai/react-ui @crayonai/react-core @crayonai/stream
npm install openai zod
bash
npm install @thesysai/genui-sdk @crayonai/react-ui @crayonai/react-core @crayonai/stream
npm install openai zod

2. Create Chat Component

2. 创建聊天组件

File:
src/App.tsx
typescript
import "@crayonai/react-ui/styles/index.css";
import { ThemeProvider, C1Component } from "@thesysai/genui-sdk";
import { useState } from "react";

export default function App() {
  const [isLoading, setIsLoading] = useState(false);
  const [c1Response, setC1Response] = useState("");
  const [question, setQuestion] = useState("");

  const makeApiCall = async (query: string) => {
    setIsLoading(true);
    setC1Response("");

    try {
      const response = await fetch("/api/chat", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ prompt: query }),
      });

      const data = await response.json();
      setC1Response(data.response);
    } catch (error) {
      console.error("Error:", error);
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <div className="container">
      <h1>AI Assistant</h1>

      <form onSubmit={(e) => {
        e.preventDefault();
        makeApiCall(question);
      }}>
        <input
          type="text"
          value={question}
          onChange={(e) => setQuestion(e.target.value)}
          placeholder="Ask me anything..."
        />
        <button type="submit" disabled={isLoading}>
          {isLoading ? "Processing..." : "Send"}
        </button>
      </form>

      {c1Response && (
        <ThemeProvider>
          <C1Component
            c1Response={c1Response}
            isStreaming={isLoading}
            updateMessage={(message) => setC1Response(message)}
            onAction={({ llmFriendlyMessage }) => {
              if (!isLoading) {
                makeApiCall(llmFriendlyMessage);
              }
            }}
          />
        </ThemeProvider>
      )}
    </div>
  );
}
文件
src/App.tsx
typescript
import "@crayonai/react-ui/styles/index.css";
import { ThemeProvider, C1Component } from "@thesysai/genui-sdk";
import { useState } from "react";

export default function App() {
  const [isLoading, setIsLoading] = useState(false);
  const [c1Response, setC1Response] = useState("");
  const [question, setQuestion] = useState("");

  const makeApiCall = async (query: string) => {
    setIsLoading(true);
    setC1Response("");

    try {
      const response = await fetch("/api/chat", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ prompt: query }),
      });

      const data = await response.json();
      setC1Response(data.response);
    } catch (error) {
      console.error("Error:", error);
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <div className="container">
      <h1>AI Assistant</h1>

      <form onSubmit={(e) => {
        e.preventDefault();
        makeApiCall(question);
      }}>
        <input
          type="text"
          value={question}
          onChange={(e) => setQuestion(e.target.value)}
          placeholder="Ask me anything..."
        />
        <button type="submit" disabled={isLoading}>
          {isLoading ? "Processing..." : "Send"}
        </button>
      </form>

      {c1Response && (
        <ThemeProvider>
          <C1Component
            c1Response={c1Response}
            isStreaming={isLoading}
            updateMessage={(message) => setC1Response(message)}
            onAction={({ llmFriendlyMessage }) => {
              if (!isLoading) {
                makeApiCall(llmFriendlyMessage);
              }
            }}
          />
        </ThemeProvider>
      )}
    </div>
  );
}

3. Configure Backend API (Express Example)

3. 配置后端API(Express示例)

typescript
import express from "express";
import OpenAI from "openai";
import { transformStream } from "@crayonai/stream";

const app = express();
app.use(express.json());

const client = new OpenAI({
  baseURL: "https://api.thesys.dev/v1/embed",
  apiKey: process.env.THESYS_API_KEY,
});

app.post("/api/chat", async (req, res) => {
  const { prompt } = req.body;

  const stream = await client.chat.completions.create({
    model: "c1/openai/gpt-5/v-20250930", // or any C1-compatible model
    messages: [
      { role: "system", content: "You are a helpful assistant." },
      { role: "user", content: prompt },
    ],
    stream: true,
  });

  // Transform OpenAI stream to C1 response
  const c1Stream = transformStream(stream, (chunk) => {
    return chunk.choices[0]?.delta?.content || "";
  });

  res.json({ response: await streamToString(c1Stream) });
});

async function streamToString(stream: ReadableStream) {
  const reader = stream.getReader();
  let result = "";

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    result += value;
  }

  return result;
}

app.listen(3000);

typescript
import express from "express";
import OpenAI from "openai";
import { transformStream } from "@crayonai/stream";

const app = express();
app.use(express.json());

const client = new OpenAI({
  baseURL: "https://api.thesys.dev/v1/embed",
  apiKey: process.env.THESYS_API_KEY,
});

app.post("/api/chat", async (req, res) => {
  const { prompt } = req.body;

  const stream = await client.chat.completions.create({
    model: "c1/openai/gpt-5/v-20250930", // 或任何兼容C1的模型
    messages: [
      { role: "system", content: "You are a helpful assistant." },
      { role: "user", content: prompt },
    ],
    stream: true,
  });

  // 将OpenAI流转换为C1响应
  const c1Stream = transformStream(stream, (chunk) => {
    return chunk.choices[0]?.delta?.content || "";
  });

  res.json({ response: await streamToString(c1Stream) });
});

async function streamToString(stream: ReadableStream) {
  const reader = stream.getReader();
  let result = "";

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    result += value;
  }

  return result;
}

app.listen(3000);

Next.js App Router Setup

Next.js App Router 配置

Most popular framework, full-stack with API routes.
最受欢迎的框架,全栈式API路由支持。

1. Install Dependencies

1. 安装依赖

bash
npm install @thesysai/genui-sdk @crayonai/react-ui @crayonai/react-core
npm install openai
bash
npm install @thesysai/genui-sdk @crayonai/react-ui @crayonai/react-core
npm install openai

2. Create Chat Page Component

2. 创建聊天页面组件

File:
app/page.tsx
typescript
"use client";

import { C1Chat } from "@thesysai/genui-sdk";
import "@crayonai/react-ui/styles/index.css";

export default function Home() {
  return (
    <div className="min-h-screen">
      <C1Chat apiUrl="/api/chat" />
    </div>
  );
}
文件
app/page.tsx
typescript
"use client";

import { C1Chat } from "@thesysai/genui-sdk";
import "@crayonai/react-ui/styles/index.css";

export default function Home() {
  return (
    <div className="min-h-screen">
      <C1Chat apiUrl="/api/chat" />
    </div>
  );
}

3. Create API Route Handler

3. 创建API路由处理程序

File:
app/api/chat/route.ts
typescript
import { NextRequest, NextResponse } from "next/server";
import OpenAI from "openai";
import { transformStream } from "@crayonai/stream";

const client = new OpenAI({
  baseURL: "https://api.thesys.dev/v1/embed",
  apiKey: process.env.THESYS_API_KEY,
});

export async function POST(req: NextRequest) {
  const { prompt } = await req.json();

  const stream = await client.chat.completions.create({
    model: "c1/openai/gpt-5/v-20250930",
    messages: [
      { role: "system", content: "You are a helpful AI assistant." },
      { role: "user", content: prompt },
    ],
    stream: true,
  });

  // Transform to C1-compatible stream
  const responseStream = transformStream(stream, (chunk) => {
    return chunk.choices[0]?.delta?.content || "";
  }) as ReadableStream<string>;

  return new NextResponse(responseStream, {
    headers: {
      "Content-Type": "text/event-stream",
      "Cache-Control": "no-cache, no-transform",
      "Connection": "keep-alive",
    },
  });
}
That's it! You now have a working Generative UI chat interface.

文件
app/api/chat/route.ts
typescript
import { NextRequest, NextResponse } from "next/server";
import OpenAI from "openai";
import { transformStream } from "@crayonai/stream";

const client = new OpenAI({
  baseURL: "https://api.thesys.dev/v1/embed",
  apiKey: process.env.THESYS_API_KEY,
});

export async function POST(req: NextRequest) {
  const { prompt } = await req.json();

  const stream = await client.chat.completions.create({
    model: "c1/openai/gpt-5/v-20250930",
    messages: [
      { role: "system", content: "You are a helpful AI assistant." },
      { role: "user", content: prompt },
    ],
    stream: true,
  });

  // 转换为兼容C1的流
  const responseStream = transformStream(stream, (chunk) => {
    return chunk.choices[0]?.delta?.content || "";
  }) as ReadableStream<string>;

  return new NextResponse(responseStream, {
    headers: {
      "Content-Type": "text/event-stream",
      "Cache-Control": "no-cache, no-transform",
      "Connection": "keep-alive",
    },
  });
}
完成! 您现在拥有一个可运行的生成式UI聊天界面。

Cloudflare Workers + Static Assets Setup

Cloudflare Workers + 静态资源 配置

Your stack: Workers backend with Vite+React frontend.
技术栈:Workers后端 + Vite+React前端。

1. Create Worker Backend (Hono)

1. 创建Worker后端(Hono)

File:
backend/src/index.ts
typescript
import { Hono } from "hono";
import { cors } from "hono/cors";

const app = new Hono();

app.use("/*", cors());

app.post("/api/chat", async (c) => {
  const { prompt } = await c.req.json();

  // Use Cloudflare Workers AI or proxy to OpenAI
  const response = await fetch("https://api.thesys.dev/v1/embed/chat/completions", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${c.env.THESYS_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      model: "c1/openai/gpt-5/v-20250930",
      messages: [
        { role: "system", content: "You are a helpful assistant." },
        { role: "user", content: prompt },
      ],
      stream: false, // or handle streaming
    }),
  });

  const data = await response.json();
  return c.json(data);
});

export default app;
文件
backend/src/index.ts
typescript
import { Hono } from "hono";
import { cors } from "hono/cors";

const app = new Hono();

app.use("/*", cors());

app.post("/api/chat", async (c) => {
  const { prompt } = await c.req.json();

  // 使用Cloudflare Workers AI或代理到OpenAI
  const response = await fetch("https://api.thesys.dev/v1/embed/chat/completions", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${c.env.THESYS_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      model: "c1/openai/gpt-5/v-20250930",
      messages: [
        { role: "system", content: "You are a helpful assistant." },
        { role: "user", content: prompt },
      ],
      stream: false, // 或处理流式传输
    }),
  });

  const data = await response.json();
  return c.json(data);
});

export default app;

2. Frontend Setup (Same as Vite+React)

2. 前端配置(与Vite+React相同)

Use the Vite+React example above, but configure API calls to your Worker endpoint.
使用上述Vite+React示例,但将API调用配置为指向您的Worker端点。

3. Wrangler Configuration

3. Wrangler配置

File:
wrangler.jsonc
jsonc
{
  "name": "thesys-chat-worker",
  "compatibility_date": "2025-10-26",
  "main": "backend/src/index.ts",
  "vars": {
    "ENVIRONMENT": "production"
  },
  "assets": {
    "directory": "dist",
    "binding": "ASSETS"
  }
}
Add
THESYS_API_KEY
as a secret:
bash
npx wrangler secret put THESYS_API_KEY

文件
wrangler.jsonc
jsonc
{
  "name": "thesys-chat-worker",
  "compatibility_date": "2025-10-26",
  "main": "backend/src/index.ts",
  "vars": {
    "ENVIRONMENT": "production"
  },
  "assets": {
    "directory": "dist",
    "binding": "ASSETS"
  }
}
添加
THESYS_API_KEY
作为密钥:
bash
npx wrangler secret put THESYS_API_KEY

Core Components

核心组件

<C1Chat>
- Pre-built Chat Component

<C1Chat>
- 预构建聊天组件

When to use: Building conversational interfaces with minimal setup.
The
C1Chat
component is a fully-featured chat UI with built-in:
  • Message history
  • Streaming responses
  • Thread management
  • Loading states
  • Error handling
  • Responsive design
适用场景:以最少的配置构建对话式界面。
C1Chat
组件是功能完整的聊天UI,内置:
  • 消息历史
  • 流式响应
  • 线程管理
  • 加载状态
  • 错误处理
  • 响应式设计

Basic Usage

基础用法

typescript
import { C1Chat } from "@thesysai/genui-sdk";
import "@crayonai/react-ui/styles/index.css";

export default function App() {
  return (
    <C1Chat
      apiUrl="/api/chat"
      agentName="My AI Assistant"
      logoUrl="https://example.com/logo.png"
    />
  );
}
typescript
import { C1Chat } from "@thesysai/genui-sdk";
import "@crayonai/react-ui/styles/index.css";

export default function App() {
  return (
    <C1Chat
      apiUrl="/api/chat"
      agentName="My AI Assistant"
      logoUrl="https://example.com/logo.png"
    />
  );
}

Key Props

关键属性

  • apiUrl
    (required) - Backend endpoint for chat completions
  • agentName
    - Display name for the AI agent
  • logoUrl
    - Logo/avatar for the agent
  • theme
    - Custom theme object (see Theming section)
  • threadManager
    - For multi-thread support (advanced)
  • threadListManager
    - For thread list UI (advanced)
  • customizeC1
    - Custom components (footer, thinking states)
  • apiUrl
    (必填)- 聊天补全的后端端点
  • agentName
    - AI助手的显示名称
  • logoUrl
    - 助手的Logo/头像
  • theme
    - 自定义主题对象(见主题部分)
  • threadManager
    - 用于多线程支持(进阶)
  • threadListManager
    - 用于线程列表UI(进阶)
  • customizeC1
    - 自定义组件(页脚、思考状态)

With Theme

带主题的用法

typescript
import { C1Chat } from "@thesysai/genui-sdk";
import { themePresets } from "@crayonai/react-ui";

<C1Chat
  apiUrl="/api/chat"
  theme={themePresets.candy} // or 'default', or custom object
/>

typescript
import { C1Chat } from "@thesysai/genui-sdk";
import { themePresets } from "@crayonai/react-ui";

<C1Chat
  apiUrl="/api/chat"
  theme={themePresets.candy} // 或'default',或自定义对象
/>

<C1Component>
- Custom Integration Component

<C1Component>
- 自定义集成组件

When to use: Need full control over state management and UI layout.
The
C1Component
is the low-level renderer. You handle:
  • Fetching data
  • Managing state
  • Layout structure
  • Error boundaries
适用场景:需要完全控制状态管理和UI布局。
C1Component
是底层渲染器,您需要处理:
  • 数据获取
  • 状态管理
  • 布局结构
  • 错误边界

Basic Usage

基础用法

typescript
import { C1Component, ThemeProvider } from "@thesysai/genui-sdk";
import "@crayonai/react-ui/styles/index.css";

const [c1Response, setC1Response] = useState("");
const [isStreaming, setIsStreaming] = useState(false);

// ... fetch logic

return (
  <ThemeProvider>
    <C1Component
      c1Response={c1Response}
      isStreaming={isStreaming}
      updateMessage={(message) => setC1Response(message)}
      onAction={({ llmFriendlyMessage }) => {
        // Handle interactive actions (button clicks, form submissions)
        console.log("User action:", llmFriendlyMessage);
        // Make new API call with llmFriendlyMessage
      }}
    />
  </ThemeProvider>
);
typescript
import { C1Component, ThemeProvider } from "@thesysai/genui-sdk";
import "@crayonai/react-ui/styles/index.css";

const [c1Response, setC1Response] = useState("");
const [isStreaming, setIsStreaming] = useState(false);

// ... 获取逻辑

return (
  <ThemeProvider>
    <C1Component
      c1Response={c1Response}
      isStreaming={isStreaming}
      updateMessage={(message) => setC1Response(message)}
      onAction={({ llmFriendlyMessage }) => {
        // 处理与生成UI的用户交互(按钮点击、表单提交)
        console.log("User action:", llmFriendlyMessage);
        // 发送llmFriendlyMessage进行新的API调用
      }}
    />
  </ThemeProvider>
);

Key Props

关键属性

  • c1Response
    (required) - The C1 API response string
  • isStreaming
    - Whether response is still streaming (shows loading indicator)
  • updateMessage
    - Callback for response updates during streaming
  • onAction
    - Callback for user interactions with generated UI
    • llmFriendlyMessage
      : Pre-formatted message to send back to LLM
    • rawAction
      : Raw action data from the component
  • c1Response
    (必填)- C1 API响应字符串
  • isStreaming
    - 响应是否仍在流式传输(显示加载指示器)
  • updateMessage
    - 流式传输期间响应更新的回调
  • onAction
    - 用户与生成UI交互的回调
    • llmFriendlyMessage
      :预格式化的消息,可发送回LLM
    • rawAction
      :来自组件的原始操作数据

Important: Must Wrap with ThemeProvider

重要提示:必须用ThemeProvider包裹

typescript
// ❌ Wrong - theme won't apply
<C1Component c1Response={response} />

// ✅ Correct
<ThemeProvider>
  <C1Component c1Response={response} />
</ThemeProvider>

typescript
// ❌ 错误 - 主题不会生效
<C1Component c1Response={response} />

// ✅ 正确
<ThemeProvider>
  <C1Component c1Response={response} />
</ThemeProvider>

<ThemeProvider>
- Theming and Customization

<ThemeProvider>
- 主题与自定义

When to use: Always wrap
<C1Component>
or customize
<C1Chat>
appearance.
适用场景:始终包裹
<C1Component>
或自定义
<C1Chat>
外观。

Theme Presets

主题预设

TheSys includes pre-built themes:
typescript
import { themePresets } from "@crayonai/react-ui";

// Available presets:
// - themePresets.default
// - themePresets.candy
// ... (check docs for full list)

<C1Chat theme={themePresets.candy} />
TheSys包含预构建主题:
typescript
import { themePresets } from "@crayonai/react-ui";

// 可用预设:
// - themePresets.default
// - themePresets.candy
// ...(查看文档获取完整列表)

<C1Chat theme={themePresets.candy} />

Dark Mode Support

深色模式支持

typescript
import { useSystemTheme } from "./hooks/useSystemTheme"; // custom hook

export default function App() {
  const systemTheme = useSystemTheme(); // 'light' | 'dark'

  return (
    <C1Chat
      apiUrl="/api/chat"
      theme={{ ...themePresets.default, mode: systemTheme }}
    />
  );
}
typescript
import { useSystemTheme } from "./hooks/useSystemTheme"; // 自定义钩子

export default function App() {
  const systemTheme = useSystemTheme(); // 'light' | 'dark'

  return (
    <C1Chat
      apiUrl="/api/chat"
      theme={{ ...themePresets.default, mode: systemTheme }}
    />
  );
}

Custom Theme Object

自定义主题对象

typescript
const customTheme = {
  mode: "dark", // 'light' | 'dark' | 'system'
  colors: {
    primary: "#3b82f6",
    secondary: "#8b5cf6",
    background: "#1f2937",
    foreground: "#f9fafb",
    // ... more colors
  },
  fonts: {
    body: "Inter, sans-serif",
    heading: "Poppins, sans-serif",
  },
  borderRadius: "12px",
  spacing: {
    base: "16px",
  },
};

<C1Chat theme={customTheme} />
typescript
const customTheme = {
  mode: "dark", // 'light' | 'dark' | 'system'
  colors: {
    primary: "#3b82f6",
    secondary: "#8b5cf6",
    background: "#1f2937",
    foreground: "#f9fafb",
    // ... 更多颜色
  },
  fonts: {
    body: "Inter, sans-serif",
    heading: "Poppins, sans-serif",
  },
  borderRadius: "12px",
  spacing: {
    base: "16px",
  },
};

<C1Chat theme={customTheme} />

CSS Overrides

CSS覆盖

Create a
custom.css
file:
css
/* Override specific component styles */
.c1-chat-container {
  max-width: 900px;
  margin: 0 auto;
}

.c1-message-user {
  background-color: #3b82f6 !important;
}

.c1-message-assistant {
  background-color: #6b7280 !important;
}
Then import:
typescript
import "@crayonai/react-ui/styles/index.css";
import "./custom.css"; // AFTER the default styles

创建
custom.css
文件:
css
/* 覆盖特定组件样式 */
.c1-chat-container {
  max-width: 900px;
  margin: 0 auto;
}

.c1-message-user {
  background-color: #3b82f6 !important;
}

.c1-message-assistant {
  background-color: #6b7280 !important;
}
然后导入:
typescript
import "@crayonai/react-ui/styles/index.css";
import "./custom.css"; // 在默认样式之后导入

AI Provider Integration

AI提供商集成

TheSys C1 API is OpenAI-compatible, meaning it works with any LLM provider that uses OpenAI's API format.
TheSys C1 API兼容OpenAI,意味着它可与任何采用OpenAI API格式的LLM提供商配合使用。

OpenAI Integration

OpenAI集成

Setup

配置

bash
npm install openai
typescript
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.thesys.dev/v1/embed",
  apiKey: process.env.THESYS_API_KEY, // TheSys API key
});
bash
npm install openai
typescript
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.thesys.dev/v1/embed",
  apiKey: process.env.THESYS_API_KEY, // TheSys API密钥
});

Model Selection

模型选择

TheSys supports OpenAI models through C1:
typescript
// GPT 5 (Stable - Recommended for Production)
model: "c1/openai/gpt-5/v-20250930"

// GPT 4.1 (Experimental)
model: "c1-exp/openai/gpt-4.1/v-20250617"
TheSys通过C1支持OpenAI模型:
typescript
// GPT 5(稳定版 - 生产环境推荐)
model: "c1/openai/gpt-5/v-20250930"

// GPT 4.1(实验版)
model: "c1-exp/openai/gpt-4.1/v-20250617"

Complete Example

完整示例

typescript
const response = await client.chat.completions.create({
  model: "c1/openai/gpt-5/v-20250930",
  messages: [
    {
      role: "system",
      content: "You are a helpful assistant that generates interactive UI components.",
    },
    {
      role: "user",
      content: "Show me a comparison table of the top 3 project management tools.",
    },
  ],
  stream: true, // Enable streaming
  temperature: 0.7,
  max_tokens: 2000,
});

typescript
const response = await client.chat.completions.create({
  model: "c1/openai/gpt-5/v-20250930",
  messages: [
    {
      role: "system",
      content: "You are a helpful assistant that generates interactive UI components.",
    },
    {
      role: "user",
      content: "Show me a comparison table of the top 3 project management tools.",
    },
  ],
  stream: true, // 启用流式传输
  temperature: 0.7,
  max_tokens: 2000,
});

Anthropic (Claude) Integration

Anthropic(Claude)集成

Setup

配置

TheSys C1 supports Anthropic's Claude models via OpenAI-compatible endpoint:
typescript
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.thesys.dev/v1/embed",
  apiKey: process.env.THESYS_API_KEY,
});
TheSys C1通过兼容OpenAI的端点支持Anthropic的Claude模型:
typescript
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.thesys.dev/v1/embed",
  apiKey: process.env.THESYS_API_KEY,
});

Model Selection

模型选择

typescript
// Claude Sonnet 4 (Stable - Recommended for Production)
model: "c1/anthropic/claude-sonnet-4/v-20250930"

// Claude 3.5 Haiku (Experimental)
model: "c1-exp/anthropic/claude-3.5-haiku/v-20250709"
⚠️ Deprecated Models: Claude 3.5 Sonnet and Claude 3.7 Sonnet are no longer recommended. Use the stable Claude Sonnet 4 version above.
typescript
// Claude Sonnet 4(稳定版 - 生产环境推荐)
model: "c1/anthropic/claude-sonnet-4/v-20250930"

// Claude 3.5 Haiku(实验版)
model: "c1-exp/anthropic/claude-3.5-haiku/v-20250709"
⚠️ 已弃用模型:Claude 3.5 Sonnet和Claude 3.7 Sonnet不再推荐使用。请使用上述稳定版Claude Sonnet 4。

Example with Claude

Claude示例

typescript
const response = await client.chat.completions.create({
  model: "c1/anthropic/claude-sonnet-4/v-20250930",
  messages: [
    {
      role: "system",
      content: "You are Claude, an AI assistant that creates interactive interfaces.",
    },
    {
      role: "user",
      content: "Create a product comparison chart for electric vehicles.",
    },
  ],
  stream: true,
  temperature: 0.8,
  max_tokens: 4096,
});

typescript
const response = await client.chat.completions.create({
  model: "c1/anthropic/claude-sonnet-4/v-20250930",
  messages: [
    {
      role: "system",
      content: "You are Claude, an AI assistant that creates interactive interfaces.",
    },
    {
      role: "user",
      content: "Create a product comparison chart for electric vehicles.",
    },
  ],
  stream: true,
  temperature: 0.8,
  max_tokens: 4096,
});

Model Specifications & Pricing

模型规格与定价

The table below shows the current stable and experimental models available via TheSys C1 API:
ModelModel IDInput PriceOutput PriceContextMax Output
Claude Sonnet 4
c1/anthropic/claude-sonnet-4/v-20250930
$6.00/M$18.00/M180K64K
GPT 5
c1/openai/gpt-5/v-20250930
$2.50/M$12.50/M380K128K
GPT 4.1 (exp)
c1-exp/openai/gpt-4.1/v-20250617
$4.00/M$10.00/M1M32K
Claude 3.5 Haiku (exp)
c1-exp/anthropic/claude-3.5-haiku/v-20250709
$1.60/M$5.00/M180K8K
Pricing Notes:
  • Costs are per million tokens (M)
  • Pricing is based on model name, regardless of endpoint type (embed or visualize)
  • Stable models (prefixed with
    c1/
    ) are recommended for production
  • Experimental models (prefixed with
    c1-exp/
    ) are for testing and may have different behavior
Model Versions: Model identifiers include version dates (e.g.,
v-20250930
). Always check the TheSys Playground for the latest stable versions.

下表显示了TheSys C1 API当前可用的稳定版和实验版模型:
模型模型ID输入价格输出价格上下文长度最大输出长度
Claude Sonnet 4
c1/anthropic/claude-sonnet-4/v-20250930
$6.00/M$18.00/M180K64K
GPT 5
c1/openai/gpt-5/v-20250930
$2.50/M$12.50/M380K128K
GPT 4.1(实验版)
c1-exp/openai/gpt-4.1/v-20250617
$4.00/M$10.00/M1M32K
Claude 3.5 Haiku(实验版)
c1-exp/anthropic/claude-3.5-haiku/v-20250709
$1.60/M$5.00/M180K8K
定价说明:
  • 成本基于每百万令牌(M)计算
  • 定价基于模型名称,与端点类型(embed或visualize)无关
  • 稳定版模型(前缀为
    c1/
    )推荐用于生产环境
  • 实验版模型(前缀为
    c1-exp/
    )用于测试,行为可能不同
模型版本:模型标识符包含版本日期(例如
v-20250930
)。请始终查看TheSys Playground获取最新稳定版本。

Cloudflare Workers AI Integration

Cloudflare Workers AI集成

Setup with Workers AI Binding

与Workers AI绑定配置

typescript
// In your Cloudflare Worker
export default {
  async fetch(request: Request, env: Env) {
    // Use Workers AI directly (cheaper for some use cases)
    const aiResponse = await env.AI.run('@cf/meta/llama-3-8b-instruct', {
      messages: [
        { role: "system", content: "You are a helpful assistant." },
        { role: "user", content: "Hello!" },
      ],
    });

    // Then transform to C1 format and send to frontend
    // ...
  }
};
typescript
// 在您的Cloudflare Worker中
export default {
  async fetch(request: Request, env: Env) {
    // 直接使用Workers AI(某些场景下成本更低)
    const aiResponse = await env.AI.run('@cf/meta/llama-3-8b-instruct', {
      messages: [
        { role: "system", content: "You are a helpful assistant." },
        { role: "user", content: "Hello!" },
      ],
    });

    // 然后转换为C1格式并发送到前端
    // ...
  }
};

Hybrid Approach: Workers AI + C1

混合方式:Workers AI + C1

typescript
// Option 1: Use Workers AI for processing, C1 for UI generation
const thinkingResponse = await env.AI.run('@cf/meta/llama-3-8b-instruct', {
  messages: [{ role: "user", content: "Analyze this data..." }],
});

// Then use C1 to generate UI from the analysis
const c1Response = await fetch("https://api.thesys.dev/v1/embed/chat/completions", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${env.THESYS_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "c1/openai/gpt-5/v-20250930",
    messages: [
      {
        role: "system",
        content: "Generate a chart visualization for this data.",
      },
      {
        role: "user",
        content: thinkingResponse.response,
      },
    ],
  }),
});

typescript
// 选项1:使用Workers AI处理,C1生成UI
const thinkingResponse = await env.AI.run('@cf/meta/llama-3-8b-instruct', {
  messages: [{ role: "user", content: "Analyze this data..." }],
});

// 然后使用C1根据分析结果生成UI
const c1Response = await fetch("https://api.thesys.dev/v1/embed/chat/completions", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${env.THESYS_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "c1/openai/gpt-5/v-20250930",
    messages: [
      {
        role: "system",
        content: "Generate a chart visualization for this data.",
      },
      {
        role: "user",
        content: thinkingResponse.response,
      },
    ],
  }),
});

Python Backend Integration

Python后端集成

TheSys provides a Python SDK for backend implementations with FastAPI, Flask, or Django.
TheSys为FastAPI、Flask或Django的后端实现提供Python SDK。

Setup

配置

bash
pip install thesys-genui-sdk openai
bash
pip install thesys-genui-sdk openai

FastAPI Example

FastAPI示例

python
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
from thesys_genui_sdk import with_c1_response, write_content
import openai
import os

app = FastAPI()

client = openai.OpenAI(
    base_url="https://api.thesys.dev/v1/embed",
    api_key=os.getenv("THESYS_API_KEY")
)

@app.post("/api/chat")
@with_c1_response  # Automatically handles streaming headers
async def chat_endpoint(request: dict):
    prompt = request.get("prompt")

    stream = client.chat.completions.create(
        model="c1/anthropic/claude-sonnet-4/v-20250930",
        messages=[
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": prompt}
        ],
        stream=True
    )

    # Stream chunks to frontend
    async def generate():
        for chunk in stream:
            content = chunk.choices[0].delta.content
            if content:
                yield write_content(content)

    return StreamingResponse(generate(), media_type="text/event-stream")
python
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
from thesys_genui_sdk import with_c1_response, write_content
import openai
import os

app = FastAPI()

client = openai.OpenAI(
    base_url="https://api.thesys.dev/v1/embed",
    api_key=os.getenv("THESYS_API_KEY")
)

@app.post("/api/chat")
@with_c1_response  # 自动处理流式传输请求头
async def chat_endpoint(request: dict):
    prompt = request.get("prompt")

    stream = client.chat.completions.create(
        model="c1/anthropic/claude-sonnet-4/v-20250930",
        messages=[
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": prompt}
        ],
        stream=True
    )

    // 向前端流式传输数据块
    async def generate():
        for chunk in stream:
            content = chunk.choices[0].delta.content
            if content:
                yield write_content(content)

    return StreamingResponse(generate(), media_type="text/event-stream")

Key Features

核心特性

  • @with_c1_response
    decorator
    : Automatically sets proper response headers for streaming
  • write_content
    helper
    : Formats chunks for C1Component rendering
  • Framework agnostic: Works with FastAPI, Flask, Django, or any Python web framework
  • @with_c1_response
    装饰器
    :自动设置流式传输所需的响应头
  • write_content
    辅助函数
    :格式化数据块以适配C1Component渲染
  • 框架无关:适用于FastAPI、Flask、Django或任何Python Web框架

Flask Example

Flask示例

python
from flask import Flask, request, Response
from thesys_genui_sdk import with_c1_response, write_content
import openai
import os

app = Flask(__name__)

client = openai.OpenAI(
    base_url="https://api.thesys.dev/v1/embed",
    api_key=os.getenv("THESYS_API_KEY")
)

@app.route("/api/chat", methods=["POST"])
@with_c1_response
def chat():
    data = request.get_json()
    prompt = data.get("prompt")

    stream = client.chat.completions.create(
        model="c1/openai/gpt-5/v-20250930",
        messages=[
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": prompt}
        ],
        stream=True
    )

    def generate():
        for chunk in stream:
            content = chunk.choices[0].delta.content
            if content:
                yield write_content(content)

    return Response(generate(), mimetype="text/event-stream")

python
from flask import Flask, request, Response
from thesys_genui_sdk import with_c1_response, write_content
import openai
import os

app = Flask(__name__)

client = openai.OpenAI(
    base_url="https://api.thesys.dev/v1/embed",
    api_key=os.getenv("THESYS_API_KEY")
)

@app.route("/api/chat", methods=["POST"])
@with_c1_response
def chat():
    data = request.get_json()
    prompt = data.get("prompt")

    stream = client.chat.completions.create(
        model="c1/openai/gpt-5/v-20250930",
        messages=[
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": prompt}
        ],
        stream=True
    )

    def generate():
        for chunk in stream:
            content = chunk.choices[0].delta.content
            if content:
                yield write_content(content)

    return Response(generate(), mimetype="text/event-stream")

Universal Patterns (Any Provider)

通用模式(任何提供商)

Error Handling

错误处理

typescript
try {
  const response = await client.chat.completions.create({
    model: "c1/openai/gpt-5/v-20250930",
    messages: [...],
    stream: true,
  });

  // Process stream...
} catch (error) {
  if (error.status === 429) {
    // Rate limit - implement exponential backoff
    await new Promise(resolve => setTimeout(resolve, 1000));
    // Retry...
  } else if (error.status === 401) {
    // Invalid API key
    console.error("Authentication failed. Check THESYS_API_KEY");
  } else {
    // Other errors
    console.error("API Error:", error);
  }
}
typescript
try {
  const response = await client.chat.completions.create({
    model: "c1/openai/gpt-5/v-20250930",
    messages: [...],
    stream: true,
  });

  // 处理流...
} catch (error) {
  if (error.status === 429) {
    // 速率限制 - 实现指数退避
    await new Promise(resolve => setTimeout(resolve, 1000));
    // 重试...
  } else if (error.status === 401) {
    // 无效API密钥
    console.error("Authentication failed. Check THESYS_API_KEY");
  } else {
    // 其他错误
    console.error("API Error:", error);
  }
}

Streaming with transformStream

使用transformStream进行流式传输

typescript
import { transformStream } from "@crayonai/stream";

const llmStream = await client.chat.completions.create({
  model: "c1/openai/gpt-5/v-20250930",
  messages: [...],
  stream: true,
});

// Transform OpenAI stream to C1 stream
const c1Stream = transformStream(llmStream, (chunk) => {
  return chunk.choices[0]?.delta?.content || "";
}) as ReadableStream<string>;

return new Response(c1Stream, {
  headers: {
    "Content-Type": "text/event-stream",
    "Cache-Control": "no-cache, no-transform",
    "Connection": "keep-alive",
  },
});

typescript
import { transformStream } from "@crayonai/stream";

const llmStream = await client.chat.completions.create({
  model: "c1/openai/gpt-5/v-20250930",
  messages: [...],
  stream: true,
});

// 将OpenAI流转换为C1流
const c1Stream = transformStream(llmStream, (chunk) => {
  return chunk.choices[0]?.delta?.content || "";
}) as ReadableStream<string>;

return new Response(c1Stream, {
  headers: {
    "Content-Type": "text/event-stream",
    "Cache-Control": "no-cache, no-transform",
    "Connection": "keep-alive",
  },
});

Tool Calling with Zod Schemas

使用Zod Schema进行工具调用

Tool calling allows your AI to invoke functions and display interactive UI for data collection, external API calls, and complex workflows.
工具调用允许您的AI调用函数,并展示用于数据收集、外部API调用和复杂工作流的交互式UI。

1. Define Tools with Zod

1. 使用Zod定义工具

typescript
import { z } from "zod";
import zodToJsonSchema from "zod-to-json-schema";

// Define the tool schema
const webSearchSchema = z.object({
  query: z.string().describe("The search query"),
  max_results: z.number().int().min(1).max(10).default(5)
    .describe("Maximum number of results to return"),
});

// Convert to OpenAI tool format
export const webSearchTool = {
  type: "function" as const,
  function: {
    name: "web_search",
    description: "Search the web for current information",
    parameters: zodToJsonSchema(webSearchSchema),
  },
};
typescript
import { z } from "zod";
import zodToJsonSchema from "zod-to-json-schema";

// 定义工具schema
const webSearchSchema = z.object({
  query: z.string().describe("The search query"),
  max_results: z.number().int().min(1).max(10).default(5)
    .describe("Maximum number of results to return"),
});

// 转换为OpenAI工具格式
export const webSearchTool = {
  type: "function" as const,
  function: {
    name: "web_search",
    description: "Search the web for current information",
    parameters: zodToJsonSchema(webSearchSchema),
  },
};

2. More Complex Example: Order Management

2. 更复杂的示例:订单管理

typescript
import { z } from "zod";

// Discriminated union for different product types
const productOrderSchema = z.discriminatedUnion("type", [
  z.object({
    type: z.literal("gloves"),
    size: z.enum(["S", "M", "L", "XL"]),
    color: z.string(),
    quantity: z.number().int().min(1),
  }),
  z.object({
    type: z.literal("hat"),
    style: z.enum(["beanie", "baseball", "fedora"]),
    color: z.string(),
    quantity: z.number().int().min(1),
  }),
  z.object({
    type: z.literal("scarf"),
    length: z.enum(["short", "medium", "long"]),
    material: z.enum(["wool", "cotton", "silk"]),
    quantity: z.number().int().min(1),
  }),
]);

const createOrderSchema = z.object({
  customer_email: z.string().email(),
  items: z.array(productOrderSchema).min(1),
  shipping_address: z.object({
    street: z.string(),
    city: z.string(),
    state: z.string(),
    zip: z.string(),
  }),
});

export const createOrderTool = {
  type: "function" as const,
  function: {
    name: "create_order",
    description: "Create a new order for products",
    parameters: zodToJsonSchema(createOrderSchema),
  },
};
typescript
import { z } from "zod";

// 不同产品类型的判别联合
const productOrderSchema = z.discriminatedUnion("type", [
  z.object({
    type: z.literal("gloves"),
    size: z.enum(["S", "M", "L", "XL"]),
    color: z.string(),
    quantity: z.number().int().min(1),
  }),
  z.object({
    type: z.literal("hat"),
    style: z.enum(["beanie", "baseball", "fedora"]),
    color: z.string(),
    quantity: z.number().int().min(1),
  }),
  z.object({
    type: z.literal("scarf"),
    length: z.enum(["short", "medium", "long"]),
    material: z.enum(["wool", "cotton", "silk"]),
    quantity: z.number().int().min(1),
  }),
]);

const createOrderSchema = z.object({
  customer_email: z.string().email(),
  items: z.array(productOrderSchema).min(1),
  shipping_address: z.object({
    street: z.string(),
    city: z.string(),
    state: z.string(),
    zip: z.string(),
  }),
});

export const createOrderTool = {
  type: "function" as const,
  function: {
    name: "create_order",
    description: "Create a new order for products",
    parameters: zodToJsonSchema(createOrderSchema),
  },
};

3. Implement Tool Execution

3. 实现工具执行

typescript
// tools.ts
import { TavilySearchAPIClient } from "@tavily/core";

const tavily = new TavilySearchAPIClient({
  apiKey: process.env.TAVILY_API_KEY,
});

export async function executeWebSearch(query: string, max_results: number) {
  const results = await tavily.search(query, {
    maxResults: max_results,
    includeAnswer: true,
  });

  return {
    query,
    results: results.results.map((r) => ({
      title: r.title,
      url: r.url,
      snippet: r.content,
    })),
    answer: results.answer,
  };
}

export async function executeCreateOrder(orderData: z.infer<typeof createOrderSchema>) {
  // Validate with Zod
  const validated = createOrderSchema.parse(orderData);

  // Save to database
  const orderId = await saveOrderToDatabase(validated);

  return {
    success: true,
    orderId,
    message: `Order ${orderId} created successfully`,
  };
}
typescript
// tools.ts
import { TavilySearchAPIClient } from "@tavily/core";

const tavily = new TavilySearchAPIClient({
  apiKey: process.env.TAVILY_API_KEY,
});

export async function executeWebSearch(query: string, max_results: number) {
  const results = await tavily.search(query, {
    maxResults: max_results,
    includeAnswer: true,
  });

  return {
    query,
    results: results.results.map((r) => ({
      title: r.title,
      url: r.url,
      snippet: r.content,
    })),
    answer: results.answer,
  };
}

export async function executeCreateOrder(orderData: z.infer<typeof createOrderSchema>) {
  // 使用Zod验证
  const validated = createOrderSchema.parse(orderData);

  // 保存到数据库
  const orderId = await saveOrderToDatabase(validated);

  return {
    success: true,
    orderId,
    message: `Order ${orderId} created successfully`,
  };
}

4. Integrate Tools in API Route

4. 在API路由中集成工具

typescript
import { NextRequest, NextResponse } from "next/server";
import OpenAI from "openai";
import { transformStream } from "@crayonai/stream";
import { webSearchTool, createOrderTool } from "./tools";

const client = new OpenAI({
  baseURL: "https://api.thesys.dev/v1/embed",
  apiKey: process.env.THESYS_API_KEY,
});

export async function POST(req: NextRequest) {
  const { prompt } = await req.json();

  const llmStream = await client.beta.chat.completions.runTools({
    model: "c1/anthropic/claude-sonnet-4/v-20250930",
    messages: [
      {
        role: "system",
        content: "You are a helpful shopping assistant. Use tools to search for products and create orders.",
      },
      {
        role: "user",
        content: prompt,
      },
    ],
    stream: true,
    tools: [webSearchTool, createOrderTool],
    toolChoice: "auto", // Let AI decide when to use tools
  });

  // Handle tool execution
  llmStream.on("message", async (event) => {
    if (event.tool_calls) {
      for (const toolCall of event.tool_calls) {
        if (toolCall.function.name === "web_search") {
          const args = JSON.parse(toolCall.function.arguments);
          const result = await executeWebSearch(args.query, args.max_results);
          // Send result back to LLM...
        } else if (toolCall.function.name === "create_order") {
          const args = JSON.parse(toolCall.function.arguments);
          const result = await executeCreateOrder(args);
          // Send result back to LLM...
        }
      }
    }
  });

  const responseStream = transformStream(llmStream, (chunk) => {
    return chunk.choices[0]?.delta?.content || "";
  }) as ReadableStream<string>;

  return new NextResponse(responseStream, {
    headers: {
      "Content-Type": "text/event-stream",
      "Cache-Control": "no-cache, no-transform",
      "Connection": "keep-alive",
    },
  });
}
typescript
import { NextRequest, NextResponse } from "next/server";
import OpenAI from "openai";
import { transformStream } from "@crayonai/stream";
import { webSearchTool, createOrderTool } from "./tools";

const client = new OpenAI({
  baseURL: "https://api.thesys.dev/v1/embed",
  apiKey: process.env.THESYS_API_KEY,
});

export async function POST(req: NextRequest) {
  const { prompt } = await req.json();

  const llmStream = await client.beta.chat.completions.runTools({
    model: "c1/anthropic/claude-sonnet-4/v-20250930",
    messages: [
      {
        role: "system",
        content: "You are a helpful shopping assistant. Use tools to search for products and create orders.",
      },
      {
        role: "user",
        content: prompt,
      },
    ],
    stream: true,
    tools: [webSearchTool, createOrderTool],
    toolChoice: "auto", // 让AI决定何时使用工具
  });

  // 处理工具执行
  llmStream.on("message", async (event) => {
    if (event.tool_calls) {
      for (const toolCall of event.tool_calls) {
        if (toolCall.function.name === "web_search") {
          const args = JSON.parse(toolCall.function.arguments);
          const result = await executeWebSearch(args.query, args.max_results);
          // 将结果发送回LLM...
        } else if (toolCall.function.name === "create_order") {
          const args = JSON.parse(toolCall.function.arguments);
          const result = await executeCreateOrder(args);
          // 将结果发送回LLM...
        }
      }
    }
  });

  const responseStream = transformStream(llmStream, (chunk) => {
    return chunk.choices[0]?.delta?.content || "";
  }) as ReadableStream<string>;

  return new NextResponse(responseStream, {
    headers: {
      "Content-Type": "text/event-stream",
      "Cache-Control": "no-cache, no-transform",
      "Connection": "keep-alive",
    },
  });
}

5. Display Tool Results in UI

5. 在UI中展示工具结果

The C1Component automatically renders tool interactions as forms and displays results. You just need to handle the
onAction
callback:
typescript
<C1Component
  c1Response={c1Response}
  onAction={async ({ llmFriendlyMessage, rawAction }) => {
    console.log("Tool action triggered:", rawAction);
    // Make API call with llmFriendlyMessage to continue conversation
    await makeApiCall(llmFriendlyMessage);
  }}
/>

C1Component会自动将工具交互渲染为表单并展示结果。您只需处理
onAction
回调:
typescript
<C1Component
  c1Response={c1Response}
  onAction={async ({ llmFriendlyMessage, rawAction }) => {
    console.log("Tool action triggered:", rawAction);
    // 发送llmFriendlyMessage进行API调用以继续对话
    await makeApiCall(llmFriendlyMessage);
  }}
/>

Advanced Features

进阶特性

Thread Management (Multi-Conversation Support)

线程管理(多对话支持)

Enable users to have multiple conversation threads with thread switching, history, and persistence.
允许用户进行多对话线程,支持线程切换、历史记录和持久化。

1. Define Thread API

1. 定义线程API

Create backend endpoints:
  • GET /api/threads
    - List all threads
  • POST /api/threads
    - Create new thread
  • PUT /api/threads/:id
    - Update thread title
  • DELETE /api/threads/:id
    - Delete thread
  • GET /api/threads/:id/messages
    - Load thread messages
创建后端端点:
  • GET /api/threads
    - 列出所有线程
  • POST /api/threads
    - 创建新线程
  • PUT /api/threads/:id
    - 更新线程标题
  • DELETE /api/threads/:id
    - 删除线程
  • GET /api/threads/:id/messages
    - 加载线程消息

2. Implement Thread Managers

2. 实现线程管理器

typescript
import {
  useThreadListManager,
  useThreadManager,
} from "@thesysai/genui-sdk";
import { Thread, Message, UserMessage } from "@crayonai/react-core";

export default function App() {
  const threadListManager = useThreadListManager({
    // Fetch all threads
    fetchThreadList: async (): Promise<Thread[]> => {
      const response = await fetch("/api/threads");
      return response.json();
    },

    // Delete thread
    deleteThread: async (threadId: string): Promise<void> => {
      await fetch(`/api/threads/${threadId}`, { method: "DELETE" });
    },

    // Update thread title
    updateThread: async (thread: Thread): Promise<Thread> => {
      const response = await fetch(`/api/threads/${thread.threadId}`, {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ title: thread.title }),
      });
      return response.json();
    },

    // Create new thread
    createThread: async (firstMessage: UserMessage): Promise<Thread> => {
      const response = await fetch("/api/threads", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          title: firstMessage.message || "New Chat",
        }),
      });
      return response.json();
    },

    // URL synchronization
    onSwitchToNew: () => {
      window.history.replaceState(null, "", window.location.pathname);
    },
    onSelectThread: (threadId: string) => {
      const url = new URL(window.location.href);
      url.searchParams.set("threadId", threadId);
      window.history.replaceState(null, "", url.toString());
    },
  });

  const threadManager = useThreadManager({
    threadListManager,

    // Load messages for selected thread
    loadThread: async (threadId: string): Promise<Message[]> => {
      const response = await fetch(`/api/threads/${threadId}/messages`);
      return response.json();
    },

    // Handle message updates (e.g., feedback)
    onUpdateMessage: async ({ message }: { message: Message }) => {
      if (threadListManager.selectedThreadId) {
        await fetch(
          `/api/threads/${threadListManager.selectedThreadId}/message`,
          {
            method: "PUT",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify(message),
          }
        );
      }
    },
  });

  return (
    <C1Chat
      threadManager={threadManager}
      threadListManager={threadListManager}
    />
  );
}

typescript
import {
  useThreadListManager,
  useThreadManager,
} from "@thesysai/genui-sdk";
import { Thread, Message, UserMessage } from "@crayonai/react-core";

export default function App() {
  const threadListManager = useThreadListManager({
    // 获取所有线程
    fetchThreadList: async (): Promise<Thread[]> => {
      const response = await fetch("/api/threads");
      return response.json();
    },

    // 删除线程
    deleteThread: async (threadId: string): Promise<void> => {
      await fetch(`/api/threads/${threadId}`, { method: "DELETE" });
    },

    // 更新线程标题
    updateThread: async (thread: Thread): Promise<Thread> => {
      const response = await fetch(`/api/threads/${thread.threadId}`, {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ title: thread.title }),
      });
      return response.json();
    },

    // 创建新线程
    createThread: async (firstMessage: UserMessage): Promise<Thread> => {
      const response = await fetch("/api/threads", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          title: firstMessage.message || "New Chat",
        }),
      });
      return response.json();
    },

    // URL同步
    onSwitchToNew: () => {
      window.history.replaceState(null, "", window.location.pathname);
    },
    onSelectThread: (threadId: string) => {
      const url = new URL(window.location.href);
      url.searchParams.set("threadId", threadId);
      window.history.replaceState(null, "", url.toString());
    },
  });

  const threadManager = useThreadManager({
    threadListManager,

    // 加载选中线程的消息
    loadThread: async (threadId: string): Promise<Message[]> => {
      const response = await fetch(`/api/threads/${threadId}/messages`);
      return response.json();
    },

    // 处理消息更新(例如反馈)
    onUpdateMessage: async ({ message }: { message: Message }) => {
      if (threadListManager.selectedThreadId) {
        await fetch(
          `/api/threads/${threadListManager.selectedThreadId}/message`,
          {
            method: "PUT",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify(message),
          }
        );
      }
    },
  });

  return (
    <C1Chat
      threadManager={threadManager}
      threadListManager={threadListManager}
    />
  );
}

Thinking States (Progress Indicators)

思考状态(进度指示器)

Show users what the AI is doing during processing (searching web, analyzing data, etc.).
在处理过程中向用户展示AI正在执行的操作(搜索网页、分析数据等)。

1. Server-Side: Write Think Items

1. 服务端:写入思考项

typescript
import { makeC1Response } from "@thesysai/genui-sdk/server";

export async function POST(req: NextRequest) {
  const c1Response = makeC1Response();

  // Initial thinking state
  c1Response.writeThinkItem({
    title: "Thinking…",
    description: "Analyzing your question and planning the response.",
  });

  const { prompt } = await req.json();

  // Update thinking state when calling tools
  const llmStream = await client.beta.chat.completions.runTools({
    model: "c1/anthropic/claude-sonnet-4/v-20250930",
    messages: [...],
    tools: [
      getWebSearchTool(() => {
        c1Response.writeThinkItem({
          title: "Searching the web…",
          description: "Finding the most relevant and up-to-date information.",
        });
      }),
    ],
  });

  transformStream(
    llmStream,
    (chunk) => {
      const content = chunk.choices[0]?.delta?.content;
      if (content) {
        c1Response.writeContent(content);
      }
      return content;
    },
    {
      onEnd: () => {
        c1Response.end();
      },
    }
  );

  return new NextResponse(c1Response.responseStream, {
    headers: {
      "Content-Type": "text/event-stream",
      "Cache-Control": "no-cache, no-transform",
      "Connection": "keep-alive",
    },
  });
}
typescript
import { makeC1Response } from "@thesysai/genui-sdk/server";

export async function POST(req: NextRequest) {
  const c1Response = makeC1Response();

  // 初始思考状态
  c1Response.writeThinkItem({
    title: "Thinking…",
    description: "Analyzing your question and planning the response.",
  });

  const { prompt } = await req.json();

  // 调用工具时更新思考状态
  const llmStream = await client.beta.chat.completions.runTools({
    model: "c1/anthropic/claude-sonnet-4/v-20250930",
    messages: [...],
    tools: [
      getWebSearchTool(() => {
        c1Response.writeThinkItem({
          title: "Searching the web…",
          description: "Finding the most relevant and up-to-date information.",
        });
      }),
    ],
  });

  transformStream(
    llmStream,
    (chunk) => {
      const content = chunk.choices[0]?.delta?.content;
      if (content) {
        c1Response.writeContent(content);
      }
      return content;
    },
    {
      onEnd: () => {
        c1Response.end();
      },
    }
  );

  return new NextResponse(c1Response.responseStream, {
    headers: {
      "Content-Type": "text/event-stream",
      "Cache-Control": "no-cache, no-transform",
      "Connection": "keep-alive",
    },
  });
}

2. Custom Think Component

2. 自定义思考组件

typescript
// CustomThink.tsx
import { ThinkItem } from "@crayonai/react-core";

export function CustomThink({ item }: { item: ThinkItem }) {
  return (
    <div className="custom-think">
      <div className="spinner" />
      <div>
        <h4>{item.title}</h4>
        <p>{item.description}</p>
      </div>
    </div>
  );
}

// In your app
<C1Chat
  apiUrl="/api/chat"
  customizeC1={{ thinkComponent: CustomThink }}
/>

typescript
// CustomThink.tsx
import { ThinkItem } from "@crayonai/react-core";

export function CustomThink({ item }: { item: ThinkItem }) {
  return (
    <div className="custom-think">
      <div className="spinner" />
      <div>
        <h4>{item.title}</h4>
        <p>{item.description}</p>
      </div>
    </div>
  );
}

// 在您的应用中
<C1Chat
  apiUrl="/api/chat"
  customizeC1={{ thinkComponent: CustomThink }}
/>

Message and Thread Sharing

消息与线程分享

Enable users to share conversations via public URLs.
允许用户通过公共URL分享对话。

1. Generate Share Links

1. 生成分享链接

typescript
import { C1ShareThread } from "@thesysai/genui-sdk";

const selectedThreadId = threadListManager.selectedThreadId;

<C1ShareThread
  generateShareLink={
    !selectedThreadId
      ? undefined
      : async () => {
          const baseUrl = window.location.origin;
          return `${baseUrl}/shared/${selectedThreadId}`;
        }
  }
/>
typescript
import { C1ShareThread } from "@thesysai/genui-sdk";

const selectedThreadId = threadListManager.selectedThreadId;

<C1ShareThread
  generateShareLink={
    !selectedThreadId
      ? undefined
      : async () => {
          const baseUrl = window.location.origin;
          return `${baseUrl}/shared/${selectedThreadId}`;
        }
  }
/>

2. Create Shared View Page

2. 创建共享视图页面

typescript
// app/shared/[threadId]/page.tsx
"use client";

import { C1ChatViewer } from "@thesysai/genui-sdk";
import { Message } from "@crayonai/react-core";
import { use, useEffect, useState } from "react";
import "@crayonai/react-ui/styles/index.css";

export default function ViewSharedThread({
  params,
}: {
  params: Promise<{ threadId: string }>;
}) {
  const { threadId } = use(params);
  const [messages, setMessages] = useState<Message[]>([]);

  useEffect(() => {
    const fetchMessages = async () => {
      const response = await fetch(`/api/share/${threadId}`);
      const data = await response.json();
      setMessages(data);
    };
    fetchMessages();
  }, [threadId]);

  if (!messages.length) return <div>Loading...</div>;

  return <C1ChatViewer messages={messages} />;
}

typescript
// app/shared/[threadId]/page.tsx
"use client";

import { C1ChatViewer } from "@thesysai/genui-sdk";
import { Message } from "@crayonai/react-core";
import { use, useEffect, useState } from "react";
import "@crayonai/react-ui/styles/index.css";

export default function ViewSharedThread({
  params,
}: {
  params: Promise<{ threadId: string }>;
}) {
  const { threadId } = use(params);
  const [messages, setMessages] = useState<Message[]>([]);

  useEffect(() => {
    const fetchMessages = async () => {
      const response = await fetch(`/api/share/${threadId}`);
      const data = await response.json();
      setMessages(data);
    };
    fetchMessages();
  }, [threadId]);

  if (!messages.length) return <div>Loading...</div>;

  return <C1ChatViewer messages={messages} />;
}

Production Patterns

生产环境模式

Message Persistence

消息持久化

Don't use in-memory storage in production!
typescript
// ❌ Bad - loses data on restart
const messageStore = new Map<string, Message[]>();

// ✅ Good - use a database
import { db } from "./database"; // D1, PostgreSQL, etc.

export async function saveMessage(threadId: string, message: Message) {
  await db.insert(messages).values({
    threadId,
    role: message.role,
    content: message.content,
    createdAt: new Date(),
  });
}

export async function getThreadMessages(threadId: string): Promise<Message[]> {
  return db.select().from(messages).where(eq(messages.threadId, threadId));
}
生产环境请勿使用内存存储!
typescript
// ❌ 错误 - 重启后数据丢失
const messageStore = new Map<string, Message[]>();

// ✅ 正确 - 使用数据库
import { db } from "./database"; // D1、PostgreSQL等

export async function saveMessage(threadId: string, message: Message) {
  await db.insert(messages).values({
    threadId,
    role: message.role,
    content: message.content,
    createdAt: new Date(),
  });
}

export async function getThreadMessages(threadId: string): Promise<Message[]> {
  return db.select().from(messages).where(eq(messages.threadId, threadId));
}

Authentication Integration (Clerk Example)

认证集成(Clerk示例)

typescript
import { auth } from "@clerk/nextjs";

export async function POST(req: NextRequest) {
  const { userId } = auth();

  if (!userId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  // Proceed with chat logic, scoping to user
  const userThreads = await db
    .select()
    .from(threads)
    .where(eq(threads.userId, userId));

  // ...
}
typescript
import { auth } from "@clerk/nextjs";

export async function POST(req: NextRequest) {
  const { userId } = auth();

  if (!userId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  // 继续聊天逻辑,限定用户范围
  const userThreads = await db
    .select()
    .from(threads)
    .where(eq(threads.userId, userId));

  // ...
}

Rate Limiting

速率限制

typescript
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";

const ratelimit = new Ratelimit({
  redis: Redis.fromEnv(),
  limiter: Ratelimit.slidingWindow(10, "1 m"), // 10 requests per minute
});

export async function POST(req: NextRequest) {
  const { userId } = auth();
  const { success } = await ratelimit.limit(userId);

  if (!success) {
    return NextResponse.json(
      { error: "Rate limit exceeded. Please try again later." },
      { status: 429 }
    );
  }

  // Proceed...
}
typescript
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";

const ratelimit = new Ratelimit({
  redis: Redis.fromEnv(),
  limiter: Ratelimit.slidingWindow(10, "1 m"), // 每分钟10次请求
});

export async function POST(req: NextRequest) {
  const { userId } = auth();
  const { success } = await ratelimit.limit(userId);

  if (!success) {
    return NextResponse.json(
      { error: "Rate limit exceeded. Please try again later." },
      { status: 429 }
    );
  }

  // 继续...
}

Error Boundaries

错误边界

typescript
import { ErrorBoundary } from "react-error-boundary";

function ErrorFallback({ error, resetErrorBoundary }) {
  return (
    <div role="alert">
      <h2>Something went wrong</h2>
      <pre>{error.message}</pre>
      <button onClick={resetErrorBoundary}>Try again</button>
    </div>
  );
}

export default function App() {
  return (
    <ErrorBoundary FallbackComponent={ErrorFallback}>
      <C1Chat apiUrl="/api/chat" />
    </ErrorBoundary>
  );
}
typescript
import { ErrorBoundary } from "react-error-boundary";

function ErrorFallback({ error, resetErrorBoundary }) {
  return (
    <div role="alert">
      <h2>Something went wrong</h2>
      <pre>{error.message}</pre>
      <button onClick={resetErrorBoundary}>Try again</button>
    </div>
  );
}

export default function App() {
  return (
    <ErrorBoundary FallbackComponent={ErrorFallback}>
      <C1Chat apiUrl="/api/chat" />
    </ErrorBoundary>
  );
}

Performance Optimization

性能优化

typescript
// 1. Lazy load C1Chat
import { lazy, Suspense } from "react";

const C1Chat = lazy(() =>
  import("@thesysai/genui-sdk").then((mod) => ({ default: mod.C1Chat }))
);

export default function App() {
  return (
    <Suspense fallback={<div>Loading chat...</div>}>
      <C1Chat apiUrl="/api/chat" />
    </Suspense>
  );
}

// 2. Memoize expensive computations
import { useMemo } from "react";

const threadListManager = useMemo(
  () =>
    useThreadListManager({
      // ... config
    }),
  [] // Empty deps - only create once
);

typescript
// 1. 懒加载C1Chat
import { lazy, Suspense } from "react";

const C1Chat = lazy(() =>
  import("@thesysai/genui-sdk").then((mod) => ({ default: mod.C1Chat }))
);

export default function App() {
  return (
    <Suspense fallback={<div>Loading chat...</div>}>
      <C1Chat apiUrl="/api/chat" />
    </Suspense>
  );
}

// 2. 记忆化昂贵计算
import { useMemo } from "react";

const threadListManager = useMemo(
  () =>
    useThreadListManager({
      // ... 配置
    }),
  [] // 空依赖 - 仅创建一次
);

Common Errors & Solutions

常见错误与解决方案

1. Empty Agent Responses

1. Agent空响应

Problem: AI returns empty responses, UI shows nothing.
Cause: Incorrect streaming transformation or response format.
Solution:
typescript
// ✅ Use transformStream helper
import { transformStream } from "@crayonai/stream";

const c1Stream = transformStream(llmStream, (chunk) => {
  return chunk.choices[0]?.delta?.content || ""; // Fallback to empty string
}) as ReadableStream<string>;

问题:AI返回空响应,UI无内容展示。
原因:流式传输转换错误或响应格式不正确。
解决方案
typescript
// ✅ 使用transformStream辅助函数
import { transformStream } from "@crayonai/stream";

const c1Stream = transformStream(llmStream, (chunk) => {
  return chunk.choices[0]?.delta?.content || ""; // 回退到空字符串
}) as ReadableStream<string>;

2. Model Not Following System Prompt

2. 模型不遵循系统提示

Problem: AI ignores instructions in system prompt.
Cause: System prompt is not first in messages array or improperly formatted.
Solution:
typescript
// ✅ System prompt MUST be first
const messages = [
  { role: "system", content: "You are a helpful assistant." }, // FIRST!
  ...conversationHistory,
  { role: "user", content: userPrompt },
];

// ❌ Wrong - system prompt after user messages
const messages = [
  { role: "user", content: "Hello" },
  { role: "system", content: "..." }, // TOO LATE
];

问题:AI忽略系统提示中的指令。
原因:系统提示未放在消息数组首位或格式不正确。
解决方案
typescript
// ✅ 系统提示必须是第一个
const messages = [
  { role: "system", content: "You are a helpful assistant." }, // 首位!
  ...conversationHistory,
  { role: "user", content: userPrompt },
];

// ❌ 错误 - 系统提示在用户消息之后
const messages = [
  { role: "user", content: "Hello" },
  { role: "system", content: "..." }, // 太晚了
];

3. Version Compatibility Errors

3. 版本兼容性错误

Problem:
TypeError: Cannot read property 'X' of undefined
or component rendering errors.
Cause: Mismatched SDK versions.
Solution: Check compatibility matrix:
C1 Version@thesysai/genui-sdk@crayonai/react-ui@crayonai/react-core
v-20250930~0.6.40~0.8.42~0.7.6
bash
undefined
问题
TypeError: Cannot read property 'X' of undefined
或组件渲染错误。
原因:SDK版本不匹配。
解决方案:查看兼容性矩阵:
C1版本@thesysai/genui-sdk@crayonai/react-ui@crayonai/react-core
v-20250930~0.6.40~0.8.42~0.7.6
bash
// 更新到兼容版本
npm install @thesysai/genui-sdk@0.6.40 @crayonai/react-ui@0.8.42 @crayonai/react-core@0.7.6

Update to compatible versions

4. 主题不生效

npm install @thesysai/genui-sdk@0.6.40 @crayonai/react-ui@0.8.42 @crayonai/react-core@0.7.6

---
问题:UI组件与自定义主题不匹配。
原因:缺少
ThemeProvider
包裹。
解决方案
typescript
// ❌ 错误
<C1Component c1Response={response} />

// ✅ 正确
<ThemeProvider theme={customTheme}>
  <C1Component c1Response={response} />
</ThemeProvider>

4. Theme Not Applying

5. 流式传输不工作

Problem: UI components don't match custom theme.
Cause: Missing
ThemeProvider
wrapper.
Solution:
typescript
// ❌ Wrong
<C1Component c1Response={response} />

// ✅ Correct
<ThemeProvider theme={customTheme}>
  <C1Component c1Response={response} />
</ThemeProvider>

问题:UI不实时更新,等待完整响应后才展示。
原因:未启用流式传输或响应头设置不正确。
解决方案
typescript
// 1. 在API调用中启用流式传输
const stream = await client.chat.completions.create({
  model: "c1/openai/gpt-5/v-20250930",
  messages: [...],
  stream: true, // ✅ 重要
});

// 2. 设置正确的响应头
return new NextResponse(responseStream, {
  headers: {
    "Content-Type": "text/event-stream",
    "Cache-Control": "no-cache, no-transform",
    "Connection": "keep-alive",
  },
});

// 3. 传递isStreaming属性
<C1Component
  c1Response={response}
  isStreaming={true} // ✅ 显示加载指示器
/>

5. Streaming Not Working

6. 工具调用失败

Problem: UI doesn't update in real-time, waits for full response.
Cause: Not using streaming or improper response headers.
Solution:
typescript
// 1. Enable streaming in API call
const stream = await client.chat.completions.create({
  model: "c1/openai/gpt-5/v-20250930",
  messages: [...],
  stream: true, // ✅ IMPORTANT
});

// 2. Set proper response headers
return new NextResponse(responseStream, {
  headers: {
    "Content-Type": "text/event-stream",
    "Cache-Control": "no-cache, no-transform",
    "Connection": "keep-alive",
  },
});

// 3. Pass isStreaming prop
<C1Component
  c1Response={response}
  isStreaming={true} // ✅ Shows loading indicator
/>

问题:工具未执行或验证错误。
原因:Zod schema无效或工具格式不正确。
解决方案
typescript
import { z } from "zod";
import zodToJsonSchema from "zod-to-json-schema";

// ✅ 带描述的正确Zod schema
const toolSchema = z.object({
  query: z.string().describe("Search query"), // 描述所有字段
  limit: z.number().int().min(1).max(100).describe("Max results"),
});

// ✅ 转换为OpenAI格式
const tool = {
  type: "function" as const,
  function: {
    name: "search_web",
    description: "Search the web for information", // 清晰描述
    parameters: zodToJsonSchema(toolSchema), // 转换schema
  },
};

// ✅ 验证传入的工具调用
const args = toolSchema.parse(JSON.parse(toolCall.function.arguments));

6. Tool Calling Failures

7. 线程状态不持久

Problem: Tools not executing or validation errors.
Cause: Invalid Zod schema or incorrect tool format.
Solution:
typescript
import { z } from "zod";
import zodToJsonSchema from "zod-to-json-schema";

// ✅ Proper Zod schema with descriptions
const toolSchema = z.object({
  query: z.string().describe("Search query"), // DESCRIBE all fields
  limit: z.number().int().min(1).max(100).describe("Max results"),
});

// ✅ Convert to OpenAI format
const tool = {
  type: "function" as const,
  function: {
    name: "search_web",
    description: "Search the web for information", // Clear description
    parameters: zodToJsonSchema(toolSchema), // Convert schema
  },
};

// ✅ Validate incoming tool calls
const args = toolSchema.parse(JSON.parse(toolCall.function.arguments));

问题:页面刷新后线程消失。
原因:无后端持久化,使用内存存储。
解决方案:实现数据库存储(见生产环境模式部分)。

7. Thread State Not Persisting

8. CSS冲突

Problem: Threads disappear on page refresh.
Cause: No backend persistence, using in-memory storage.
Solution: Implement database storage (see Production Patterns section).

问题:C1组件样式与应用样式冲突。
原因:CSS导入顺序或全局样式覆盖。
解决方案
typescript
// ✅ 正确导入顺序
import "@crayonai/react-ui/styles/index.css"; // 先导入C1样式
import "./your-app.css"; // 再导入您的样式

// 在您的CSS中,必要时使用特异性
.your-custom-class .c1-message {
  /* 覆盖特定样式 */
}

8. CSS Conflicts

9. TypeScript类型错误

Problem: Styles from C1 components clash with app styles.
Cause: CSS import order or global styles overriding.
Solution:
typescript
// ✅ Correct import order
import "@crayonai/react-ui/styles/index.css"; // C1 styles FIRST
import "./your-app.css"; // Your styles SECOND

// In your CSS, use specificity if needed
.your-custom-class .c1-message {
  /* Override specific styles */
}

问题:TypeScript提示缺少类型或类型不兼容。
原因:包版本过时或缺少类型定义。
解决方案
bash
// 更新包
npm install @thesysai/genui-sdk@latest @crayonai/react-ui@latest @crayonai/react-core@latest

// 如果仍有错误,检查tsconfig.json
{
  "compilerOptions": {
    "moduleResolution": "bundler", // 或"node16"
    "skipLibCheck": true // 跳过node_modules的类型检查
  }
}

9. TypeScript Type Errors

10. API的CORS错误

Problem: TypeScript complains about missing types or incompatible types.
Cause: Outdated package versions or missing type definitions.
Solution:
bash
undefined
问题:调用后端时出现
Access-Control-Allow-Origin
错误。
原因:API响应缺少CORS头。
解决方案
typescript
// Next.js API路由
export async function POST(req: NextRequest) {
  const response = new NextResponse(stream, {
    headers: {
      "Content-Type": "text/event-stream",
      "Access-Control-Allow-Origin": "*", // 或特定域名
      "Access-Control-Allow-Methods": "POST, OPTIONS",
      "Access-Control-Allow-Headers": "Content-Type",
    },
  });

  return response;
}

// Express
app.use(cors({
  origin: "http://localhost:5173", // 您的前端URL
  methods: ["POST", "OPTIONS"],
}));

Update packages

11. 速率限制问题

npm install @thesysai/genui-sdk@latest @crayonai/react-ui@latest @crayonai/react-core@latest
问题:API调用因429错误失败,无重试机制。
原因:无速率限制退避逻辑。
解决方案
typescript
async function callApiWithRetry(apiCall, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await apiCall();
    } catch (error) {
      if (error.status === 429 && i < maxRetries - 1) {
        const waitTime = Math.pow(2, i) * 1000; // 指数退避
        await new Promise((resolve) => setTimeout(resolve, waitTime));
        continue;
      }
      throw error;
    }
  }
}

// 使用
const response = await callApiWithRetry(() =>
  client.chat.completions.create({...})
);

If still errors, check tsconfig.json

12. 认证令牌错误

{ "compilerOptions": { "moduleResolution": "bundler", // or "node16" "skipLibCheck": true // Skip type checking for node_modules } }

---
问题:已设置API密钥但仍出现
401 Unauthorized
原因:环境变量未加载或变量名称错误。
解决方案
bash
undefined

10. CORS Errors with API

.env文件(Next.js)

Problem:
Access-Control-Allow-Origin
errors when calling backend.
Cause: Missing CORS headers in API responses.
Solution:
typescript
// Next.js API Route
export async function POST(req: NextRequest) {
  const response = new NextResponse(stream, {
    headers: {
      "Content-Type": "text/event-stream",
      "Access-Control-Allow-Origin": "*", // Or specific domain
      "Access-Control-Allow-Methods": "POST, OPTIONS",
      "Access-Control-Allow-Headers": "Content-Type",
    },
  });

  return response;
}

// Express
app.use(cors({
  origin: "http://localhost:5173", // Your frontend URL
  methods: ["POST", "OPTIONS"],
}));

THESYS_API_KEY=your_api_key_here
// 验证是否加载 // 在代码中: if (!process.env.THESYS_API_KEY) { throw new Error("THESYS_API_KEY is not set"); }
// 对于Vite,客户端使用VITE_前缀 VITE_THESYS_API_KEY=your_key # 客户端 THESYS_API_KEY=your_key # 服务端
// 在Vite中访问 const apiKey = import.meta.env.VITE_THESYS_API_KEY;
// 对于Cloudflare Workers,使用wrangler secrets npx wrangler secret put THESYS_API_KEY

---

11. Rate Limiting Issues

模板与示例

Problem: API calls fail with 429 errors, no retry mechanism.
Cause: No backoff logic for rate limits.
Solution:
typescript
async function callApiWithRetry(apiCall, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await apiCall();
    } catch (error) {
      if (error.status === 429 && i < maxRetries - 1) {
        const waitTime = Math.pow(2, i) * 1000; // Exponential backoff
        await new Promise((resolve) => setTimeout(resolve, waitTime));
        continue;
      }
      throw error;
    }
  }
}

// Usage
const response = await callApiWithRetry(() =>
  client.chat.completions.create({...})
);

本指南在
templates/
目录中包含15+可运行模板:

12. Authentication Token Errors

Vite + React(5个模板)

Problem:
401 Unauthorized
even with API key set.
Cause: Environment variable not loaded or incorrect variable name.
Solution:
bash
undefined
  1. basic-chat.tsx
    - 带自定义后端的极简C1Chat配置
  2. custom-component.tsx
    - 使用C1Component并手动管理状态
  3. tool-calling.tsx
    - 网页搜索+数据库查询工具
  4. theme-dark-mode.tsx
    - 带深色模式切换的自定义主题
  5. package.json
    - 精确的依赖版本

.env file (Next.js)

Next.js(4个模板)

THESYS_API_KEY=your_api_key_here
  1. app/page.tsx
    - C1Chat页面组件
  2. app/api/chat/route.ts
    - 流式API路由处理程序
  3. tool-calling-route.ts
    - 集成工具的API路由
  4. package.json
    - Next.js依赖配置

Verify it's loaded

Cloudflare Workers(3个模板)

In your code:

if (!process.env.THESYS_API_KEY) { throw new Error("THESYS_API_KEY is not set"); }
  1. worker-backend.ts
    - 带TheSys代理的Hono API
  2. frontend-setup.tsx
    - React前端配置
  3. wrangler.jsonc
    - Worker部署配置

For Vite, use VITE_ prefix for client-side

共享工具(3个模板)

VITE_THESYS_API_KEY=your_key # Client-side THESYS_API_KEY=your_key # Server-side
  1. theme-config.ts
    - 可复用主题配置
  2. tool-schemas.ts
    - 工具通用Zod schema
  3. streaming-utils.ts
    - 流式传输辅助函数

Access in Vite

额外资源

参考指南

const apiKey = import.meta.env.VITE_THESYS_API_KEY;
查看
references/
目录获取详细指南:
  • component-api.md
    - 所有组件的完整属性参考
  • ai-provider-setup.md
    - 各AI提供商的分步配置
  • tool-calling-guide.md
    - 全面的工具调用模式
  • theme-customization.md
    - 主题系统深度解析
  • common-errors.md
    - 扩展错误目录与解决方案

For Cloudflare Workers, use wrangler secrets

脚本

npx wrangler secret put THESYS_API_KEY

---
  • scripts/install-dependencies.sh
    - 安装所有所需包
  • scripts/check-versions.sh
    - 验证包版本

Templates & Examples

官方文档

This skill includes 15+ working templates in the
templates/
directory:

Vite + React (5 templates)

成功指标

  1. basic-chat.tsx
    - Minimal C1Chat setup with custom backend
  2. custom-component.tsx
    - Using C1Component with manual state
  3. tool-calling.tsx
    - Web search + database query tools
  4. theme-dark-mode.tsx
    - Custom theming with dark mode toggle
  5. package.json
    - Exact dependency versions
  • 令牌节省:比手动实现节省约65-70%
  • 避免的错误:12+已记录问题
  • 开发速度:提升10倍(来自TheSys数据)
  • 用户参与度:83%用户偏好交互式UI
  • 包版本:最新稳定版(2025年10月)

Next.js (4 templates)

下一步

  1. app/page.tsx
    - C1Chat page component
  2. app/api/chat/route.ts
    - Streaming API route handler
  3. tool-calling-route.ts
    - API route with tool integration
  4. package.json
    - Next.js dependency setup
  1. 选择您的框架(Vite+React、Next.js或Cloudflare Workers)
  2. templates/
    复制相关模板
  3. 设置
    THESYS_API_KEY
    环境变量
  4. 运行
    npm install
    安装依赖
  5. 启动开发服务器
  6. 自定义主题与UI组件
  7. 添加工具调用实现进阶功能
  8. 部署到生产环境并配置持久化
如有疑问或问题,请参考
references/common-errors.md
指南或查看TheSys官方文档。

最后更新:2025-10-26 包版本:@thesysai/genui-sdk@0.6.40 生产环境测试:✅ 是 符合官方标准:✅ 是

Cloudflare Workers (3 templates)

  1. worker-backend.ts
    - Hono API with TheSys proxy
  2. frontend-setup.tsx
    - React frontend configuration
  3. wrangler.jsonc
    - Worker deployment config

Shared Utilities (3 templates)

  1. theme-config.ts
    - Reusable theme configurations
  2. tool-schemas.ts
    - Common Zod schemas for tools
  3. streaming-utils.ts
    - Helper functions for streaming

Additional Resources

Reference Guides

See the
references/
directory for detailed guides:
  • component-api.md
    - Complete prop reference for all components
  • ai-provider-setup.md
    - Step-by-step setup for each AI provider
  • tool-calling-guide.md
    - Comprehensive tool calling patterns
  • theme-customization.md
    - Theme system deep dive
  • common-errors.md
    - Expanded error catalog with solutions

Scripts

  • scripts/install-dependencies.sh
    - Install all required packages
  • scripts/check-versions.sh
    - Verify package versions

Official Documentation


Success Metrics

  • Token savings: ~65-70% vs manual implementation
  • Errors prevented: 12+ documented issues
  • Development speed: 10x faster (per TheSys)
  • User engagement: 83% prefer interactive UI
  • Package versions: Latest stable (Oct 2025)

Next Steps

  1. Choose your framework (Vite+React, Next.js, or Cloudflare Workers)
  2. Copy the relevant template from
    templates/
  3. Set up
    THESYS_API_KEY
    environment variable
  4. Install dependencies with
    npm install
  5. Run the development server
  6. Customize theming and UI components
  7. Add tool calling for advanced features
  8. Deploy to production with proper persistence
For questions or issues, refer to the
references/common-errors.md
guide or check official TheSys documentation.

Last Updated: 2025-10-26 Package Version: @thesysai/genui-sdk@0.6.40 Production Tested: ✅ Yes Official Standards Compliant: ✅ Yes