Token导航 LogoToken导航

Agent Skill · 研究检索

thesys-generative-ui(论文生成用户界面)

用于辅助界面设计、视觉规范、排版、配色、布局和交互体验优化。它适合让 Agent 根据产品场景整理页面结构、生成 UI 方案、检查视觉一致性或改进组件层级。使用时需要结合现有品牌、设计系统和用户任务,不应只堆装饰元素;涉及真实页面改动时,应通过截图或浏览器预览检查文本溢出、对齐和响应式表现。

thesys-generative-ui 是研究检索类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为接触敏感数据;许可证为 MIT,暂无第三方扫描结果,按安装量在研究检索类的 73,675 个 Skill 里排第 50,488。

总安装 612周安装 26GitHub Stars 公开资料未说明下载 214核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
MIT

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:thesys-generative-ui(论文生成用户界面)
来源仓库:https://github.com/jackspace/claudeskillz
仓库路径:skills/thesys-generative-ui
安装命令:
npx skills add jackspace/claudeskillz --skill "thesys-generative-ui"
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

AgentSkills.tonpx skills
npx skills add jackspace/claudeskillz --skill "thesys-generative-ui"

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

thesys-generative-ui 用于辅助界面设计、视觉规范、排版、配色、布局和交互体验优化。适合整理页面结构、生成 UI 方案、检查视觉一致性或改进组件层级。使用时需结合现有品牌、设计系统和用户任务,不应只堆装饰元素。涉及真实页面改动时,应通过截图或浏览器预览检查文本溢出、对齐和响应式表现。

确保设计符合业务需求和技术约束。

来源仓库内路径:skills/thesys-generative-ui

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add jackspace/claudeskillz --skill "thesys-generative-ui";命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要接触敏感数据,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

thesys-generative-ui 怎么安装?

在终端执行 npx skills add jackspace/claudeskillz --skill "thesys-generative-ui"。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

thesys-generative-ui 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

thesys-generative-ui 需要什么权限?

权限级别是接触敏感数据。该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

thesys-generative-ui 是免费的吗?

来源标注的许可证是 MIT。本站不代收任何费用,也不托管安装包;能否商用、要不要署名,以许可证原文为准。

thesys-generative-ui 用的人多吗?

公开数据是累计安装 612 次,近一周安装 26 次,下载 214 次。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

thesys-generative-ui 安全吗?

没有查到第三方扫描结果,安全性无法从公开资料判断,安装前请自行审查源码、依赖和命令行为。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 许可证明确为 MIT,商用和分发边界好判断。

先想清楚的地方

  • 需要接触敏感数据,装到常用环境前要先评估影响面。
  • 没有第三方扫描结果,安全性只能靠自己读源码判断。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理研究检索类任务、又不想每次都手写提示词的人。

不太适合

  • 环境里有大量密钥、凭证,不方便给第三方 Skill 读取的人。
  • 要求有安全扫描结论才肯安装的团队。
  • 需要厂商级技术支持和 SLA 的生产系统。

研究检索类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
find-skills

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
thesys-generative-ui

论文生成用户界面 · 本页

612—接触敏感数据MIT未收录

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

name
thesys-generative-ui
description
|
Keywords
TheSys C1, TheSys Generative UI, @thesysai/genui-sdk, generative UI, AI UI, streaming UI components, interactive components, AI forms, AI charts, AI tables, conversational UI, AI assistants UI, React generative UI, Vite generative UI, Next.js generative UI, Cloudflare Workers generative UI, OpenAI generative UI, Claude generative UI, Anthropic UI, Cloudflare Workers AI UI, tool calling UI, Zod schemas UI, thread management, theming UI, chat interface, data visualization, dynamic forms, streaming LLM UI
license
MIT
metadata
version
1.0.0
package
@thesysai/genui-sdk
package_version
0.6.40
last_verified
2025-10-26
production_tested
true
token_savings
~65-70%
errors_prevented
12

TheSys Generative UI Integration

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


What is 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.

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

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

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

  1. Data Visualization Applications

- Analytics dashboards with AI-generated charts - Business intelligence tools with dynamic tables - Search interfaces with structured results

  1. Dynamic Form Generation

- E-commerce product configurators - Multi-step workflows driven by AI - Data collection with intelligent forms

  1. AI Copilots and Assistants

- Developer tools with code snippets and docs - Educational platforms with interactive lessons - Research tools with citations and references

  1. Search and Discovery

- Semantic search with structured results - Document analysis with highlighted findings - Knowledge bases with interactive answers

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

Quick Start by Framework

Vite + React Setup

Most flexible setup for custom backends (your preferred stack).

1. Install Dependencies
npm install @thesysai/genui-sdk @crayonai/react-ui @crayonai/react-core @crayonai/stream
npm install openai zod
2. Create Chat Component

File: src/App.tsx

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)
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);

Next.js App Router Setup

Most popular framework, full-stack with API routes.

1. Install Dependencies
npm install @thesysai/genui-sdk @crayonai/react-ui @crayonai/react-core
npm install openai
2. Create Chat Page Component

File: app/page.tsx

"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

File: app/api/chat/route.ts

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.


Cloudflare Workers + Static Assets Setup

Your stack: Workers backend with Vite+React frontend.

1. Create Worker Backend (Hono)

File: backend/src/index.ts

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;
2. Frontend Setup (Same as Vite+React)

Use the Vite+React example above, but configure API calls to your Worker endpoint.

3. Wrangler Configuration

File: wrangler.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:

npx wrangler secret put THESYS_API_KEY

Core Components

<C1Chat> - Pre-built Chat Component

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
Basic Usage
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)
With Theme
import { C1Chat } from "@thesysai/genui-sdk";
import { themePresets } from "@crayonai/react-ui";

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

<C1Component> - Custom Integration Component

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
Basic Usage
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>
);
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

Important: Must Wrap with ThemeProvider
// ❌ Wrong - theme won't apply
<C1Component c1Response={response} />

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

<ThemeProvider> - Theming and Customization

When to use: Always wrap <C1Component> or customize <C1Chat> appearance.

Theme Presets

TheSys includes pre-built themes:

import { themePresets } from "@crayonai/react-ui";

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

<C1Chat theme={themePresets.candy} />
Dark Mode Support
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 }}
    />
  );
}
Custom Theme Object
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} />
CSS Overrides

Create a custom.css file:

/* 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:

import "@crayonai/react-ui/styles/index.css";
import "./custom.css"; // AFTER the default styles

AI Provider Integration

TheSys C1 API is OpenAI-compatible, meaning it works with any LLM provider that uses OpenAI's API format.

OpenAI Integration

Setup
npm install openai
import OpenAI from "openai";

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

TheSys supports OpenAI models through C1:

// 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"
Complete Example
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,
});

Anthropic (Claude) Integration

Setup

TheSys C1 supports Anthropic's Claude models via OpenAI-compatible endpoint:

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.thesys.dev/v1/embed",
  apiKey: process.env.THESYS_API_KEY,
});
Model Selection
// 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.
Example with Claude
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 4c1/anthropic/claude-sonnet-4/v-20250930$6.00/M$18.00/M180K64K
GPT 5c1/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.

Cloudflare Workers AI Integration

Setup with Workers AI Binding
// 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
    // ...
  }
};
Hybrid Approach: Workers AI + C1
// 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,
      },
    ],
  }),
});

Python Backend Integration

TheSys provides a Python SDK for backend implementations with FastAPI, Flask, or Django.

Setup
pip install thesys-genui-sdk openai
FastAPI Example
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")
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
Flask Example
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
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);
  }
}
Streaming with transformStream
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",
  },
});

Tool Calling with Zod Schemas

Tool calling allows your AI to invoke functions and display interactive UI for data collection, external API calls, and complex workflows.

1. Define Tools with Zod

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),
  },
};

2. More Complex Example: Order Management

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),
  },
};

3. Implement Tool Execution

// 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`,
  };
}

4. Integrate Tools in API Route

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",
    },
  });
}

5. Display Tool Results in UI

The C1Component automatically renders tool interactions as forms and displays results. You just need to handle the onAction callback:

<C1Component
  c1Response={c1Response}
  onAction={async ({ llmFriendlyMessage, rawAction }) => {
    console.log("Tool action triggered:", rawAction);
    // Make API call with llmFriendlyMessage to continue conversation
    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

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
2. Implement Thread Managers
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}
    />
  );
}

Thinking States (Progress Indicators)

Show users what the AI is doing during processing (searching web, analyzing data, etc.).

1. Server-Side: Write Think Items
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",
    },
  });
}
2. Custom Think Component
// 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 }}
/>

Message and Thread Sharing

Enable users to share conversations via public URLs.

1. Generate Share Links
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
// 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!

// ❌ 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));
}

Authentication Integration (Clerk Example)

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));

  // ...
}

Rate Limiting

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...
}

Error Boundaries

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

// 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
);

Common Errors & Solutions

1. Empty Agent Responses

Problem: AI returns empty responses, UI shows nothing.

Cause: Incorrect streaming transformation or response format.

Solution:

// ✅ 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>;

2. Model Not Following System Prompt

Problem: AI ignores instructions in system prompt.

Cause: System prompt is not first in messages array or improperly formatted.

Solution:

// ✅ 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
];

3. Version Compatibility Errors

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
# Update to compatible versions
npm install @thesysai/ [email protected]  @crayonai/ [email protected]  @crayonai/ [email protected] 

4. Theme Not Applying

Problem: UI components don't match custom theme.

Cause: Missing ThemeProvider wrapper.

Solution:

// ❌ Wrong
<C1Component c1Response={response} />

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

5. Streaming Not Working

Problem: UI doesn't update in real-time, waits for full response.

Cause: Not using streaming or improper response headers.

Solution:

// 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
/>

6. Tool Calling Failures

Problem: Tools not executing or validation errors.

Cause: Invalid Zod schema or incorrect tool format.

Solution:

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

Problem: Threads disappear on page refresh.

Cause: No backend persistence, using in-memory storage.

Solution: Implement database storage (see Production Patterns section).


8. CSS Conflicts

Problem: Styles from C1 components clash with app styles.

Cause: CSS import order or global styles overriding.

Solution:

// ✅ 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 */
}

9. TypeScript Type Errors

Problem: TypeScript complains about missing types or incompatible types.

Cause: Outdated package versions or missing type definitions.

Solution:

# Update packages
npm install @thesysai/genui-sdk@latest @crayonai/react-ui@latest @crayonai/react-core@latest

# If still errors, check tsconfig.json
{
  "compilerOptions": {
    "moduleResolution": "bundler", // or "node16"
    "skipLibCheck": true // Skip type checking for node_modules
  }
}

10. CORS Errors with API

Problem: Access-Control-Allow-Origin errors when calling backend.

Cause: Missing CORS headers in API responses.

Solution:

// 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"],
}));

11. Rate Limiting Issues

Problem: API calls fail with 429 errors, no retry mechanism.

Cause: No backoff logic for rate limits.

Solution:

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({...})
);

12. Authentication Token Errors

Problem: 401 Unauthorized even with API key set.

Cause: Environment variable not loaded or incorrect variable name.

Solution:

# .env file (Next.js)
THESYS_API_KEY=your_api_key_here

# Verify it's loaded
# In your code:
if (!process.env.THESYS_API_KEY) {
  throw new Error("THESYS_API_KEY is not set");
}

# For Vite, use VITE_ prefix for client-side
VITE_THESYS_API_KEY=your_key # Client-side
THESYS_API_KEY=your_key      # Server-side

# Access in Vite
const apiKey = import.meta.env.VITE_THESYS_API_KEY;

# For Cloudflare Workers, use wrangler secrets
npx wrangler secret put THESYS_API_KEY

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

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

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

  • TheSys Docs: https://docs.thesys.dev
  • C1 Playground: https://console.thesys.dev/playground
  • GitHub Examples: Search for "thesysai" on GitHub
  • Context7: /websites/thesys_dev

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/ [email protected] Production Tested: ✅ Yes Official Standards Compliant: ✅ Yes

平台分布

Claude Code

27.72%
按下载量换算59

windsurf

25.02%
按下载量换算54

OpenCode

18.59%
按下载量换算40

Codex

12.46%
按下载量换算27

Antigravity

7.69%
按下载量换算16

Gemini CLI

3.44%
按下载量换算7

安全审计

暂无安全审计结果可展示。

权限和风险

接触敏感数据

该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills