npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ai_wanjia/sdk

v1.0.3

Published

Charx SDK for creator iframe integration

Downloads

497

Readme

@ai_wanjia/sdk

玩家AI 平台的创作者 SDK。

它用于运行在平台 iframe 内的独立页面,通过 postMessage RPC 与平台通信,读取角色信息、读写变量、发送消息、控制界面,并在 React 项目中提供现成的 Hooks 和组件。


适用场景

| 场景 | 是否适合 | |------|----------| | 独立 HTML 页面、原生 JS 页面 | ✅ | | React 独立页面 | ✅ | | 角色卡里需要完整自定义 UI 的游戏界面 | ✅ | | 仅在 AI 消息里插一个小卡片 | 更推荐直接用平台注入的 window.$charx | | Node.js 服务端、后端任务 | ❌ |


官方 Starter

仓库内已经提供两套官方快速开发模板:

| 模板 | 目录 | 适用场景 | |------|------|----------| | charx-h5-starter | sdk/examples/charx-h5-starter | 原生 html + css + js,零构建起步 | | charx-react-starter | sdk/examples/charx-react-starter | Vite + React + TypeScript,适合组件化开发 |

这两套模板都支持:

  • 本地开发态自动切到 mock 运行时
  • 平台 iframe 内自动切到真实 SDK
  • 首页自带 character / variable / storage / chat / ui.toast 示例

安装

npm install @ai_wanjia/sdk

五分钟上手

原生 JavaScript / TypeScript

import { CharxSdk } from '@ai_wanjia/sdk'

const sdk = CharxSdk.getInstance()
await sdk.init()

const info = await sdk.character.getInfo()
console.log('角色名:', info.name)

const hp = await sdk.variable.get<number>('hp')
console.log('当前 HP:', hp)

sdk.chat.send('总结一下我当前的状态', {
  onData: (chunk) => {
    console.log('流式片段:', chunk)
  },
  onComplete: (message) => {
    console.log('完整回复:', message.content)
  },
  onError: (error) => {
    console.error(error)
  },
})

React

import { CharxProvider, useChat, useVariable, useCharacter } from '@ai_wanjia/sdk/react'

export default function App() {
  return (
    <CharxProvider fallback={<div>连接平台中...</div>}>
      <GamePage />
    </CharxProvider>
  )
}

function GamePage() {
  const character = useCharacter()
  const { messages, send, status, stop } = useChat()
  const [hp, setHp] = useVariable<number>('hp', 100)

  return (
    <div>
      <h1>{character?.name}</h1>
      <p>HP: {hp}</p>

      {messages.map((message) => (
        <div key={message.id}>{message.content}</div>
      ))}

      {status === 'streaming' ? (
        <button onClick={stop}>停止</button>
      ) : (
        <button onClick={() => send('继续推进剧情')}>继续</button>
      )}

      <button onClick={() => setHp(hp + 5)}>恢复 5 点 HP</button>
    </div>
  )
}

运行时规则

1. 必须在平台 iframe 内运行

sdk.init() 会向父窗口发起握手。

const sdk = CharxSdk.getInstance()
await sdk.init()

如果页面不是由玩家AI平台加载,而是直接在浏览器里打开,init() 会在超时后抛错。

2. init() 之前不要调用其他 API

推荐做法:

const sdk = CharxSdk.getInstance()
await sdk.init()

// 从这里开始再调用其他模块

3. variablestorage 不是一回事

| 能力 | 作用域 | 是否随当前对话变化 | 适合存什么 | |------|--------|--------------------|------------| | sdk.variable | 当前对话 | 是 | HP、MP、好感度、剧情阶段、当前位置 | | sdk.storage | user + character | 否 | 设置、成就、已解锁结局、长期背包 |

4. SDK 负责界面层,不负责替代平台 AI 运行时

SDK 能做的事情:

  • 发送消息到平台聊天链路
  • 读写变量和持久化存储
  • 读取角色信息
  • 控制当前独立页面 UI

SDK 不做的事情:

  • 不直接调用模型
  • 不绕开平台上下文组装
  • 不替代角色卡、世界书、正则、系统提示词

API 概览

CharxSdk 是单例对象,所有能力都挂在它的模块上:

CharxSdk
├── chat
├── character
├── variable
├── storage
├── ui
├── media
├── game
├── worldbook
└── utils

sdk.character

读取当前角色、人设和对话配置。

const info = await sdk.character.getInfo()
const persona = await sdk.character.getPersona()
const settings = await sdk.character.getSettings()

sdk.chat

负责发消息、停止生成、切开场白、读取历史消息。

sdk.chat.send('你好', {
  onData: (chunk) => console.log(chunk),
  onComplete: (message) => console.log(message.content),
})

await sdk.chat.stop()
await sdk.chat.regenerate()
await sdk.chat.continue()

sdk.chat.setInput('帮我润色这句话')
const input = await sdk.chat.getInput()

await sdk.chat.setGreetingIndex(1)
const greetingIndex = await sdk.chat.getGreetingIndex()

const allMessages = await sdk.chat.messages.getAll()
const page = await sdk.chat.messages.list({ limit: 20, offset: 0 })

sdk.variable

负责当前对话变量。

const hp = await sdk.variable.get<number>('hp')
const vars = await sdk.variable.getAll()

await sdk.variable.set('hp', 80)
await sdk.variable.setMany({ hp: 80, mp: 50 })

await sdk.variable.increment('hp', 5)
await sdk.variable.decrement('mp', 2)

const unwatch = sdk.variable.watch<number>('hp', (value) => {
  console.log('新的 HP:', value)
})

sdk.storage

负责跨对话持久化数据。

await sdk.storage.set('preferredTheme', 'deep-sea')

const theme = await sdk.storage.get<string>('preferredTheme')
const settings = await sdk.storage.getOrDefault('settings', { bgm: true })
const keys = await sdk.storage.keys()

sdk.ui

负责 Toast、弹窗、主题、滚动和面板控制。

sdk.ui.toast({ text: '获得道具', type: 'success' })

await sdk.ui.alert('任务失败')
const confirmed = await sdk.ui.confirm('确认继续?')
const input = await sdk.ui.prompt('请输入角色名', '默认值')

sdk.ui.scrollToBottom()
sdk.ui.setTheme('dark')

await sdk.ui.openPanel({
  url: 'https://your-panel-url',
  title: '角色状态',
  mode: 'sidebar',
  width: 320,
})
await sdk.ui.closePanel()

sdk.media

负责 TTS、背景音乐和音效。

await sdk.media.speak('欢迎来到这里', { voice: 'character' })
sdk.media.stopSpeak()

await sdk.media.bgm.play('/assets/bgm.mp3', { loop: true, volume: 0.7 })
await sdk.media.bgm.stop({ fadeOut: 500 })
sdk.media.bgm.pause()
sdk.media.bgm.resume()
sdk.media.bgm.setVolume(0.5)

await sdk.media.sfx.play('/assets/hit.mp3', { volume: 0.8 })
sdk.media.sfx.preload(['/assets/hit.mp3'])

sdk.game

负责存档、成就和排行榜。

await sdk.game.save({ slot: 1, description: '第三章开头' })
const saveData = await sdk.game.load({ slot: 1 })
const saves = await sdk.game.listSaves()
await sdk.game.deleteSave(1)

await sdk.game.unlockAchievement('first_victory')
const achievements = await sdk.game.listAchievements()

await sdk.game.submitScore(9800, { category: 'story_mode' })
const top10 = await sdk.game.getTop({ limit: 10, category: 'story_mode' })
const myRank = await sdk.game.getSelfRank({ category: 'story_mode' })

sdk.worldbook

负责当前对话内的世界书动态控制。

所有操作只影响当前对话,不会改角色卡模板。

const worldbook = await sdk.worldbook.getAll()

await sdk.worldbook.enable('combat-mode')
await sdk.worldbook.disable('peace-mode')

await sdk.worldbook.batchToggle([
  { entryKey: 'combat-mode', enabled: true },
  { entryKey: 'peace-mode', enabled: false },
])

await sdk.worldbook.setContent('combat-mode', '新的世界书内容')
await sdk.worldbook.clearContent('combat-mode')
await sdk.worldbook.reset()

sdk.utils

负责剪贴板和轻量格式处理。

await sdk.utils.clipboard.writeText('复制这段文本')
const text = await sdk.utils.clipboard.readText()

const html = sdk.utils.format.markdown('**加粗** _斜体_ `代码`')
const safeHtml = sdk.utils.format.sanitize('<script>alert(1)</script>')

React 集成

导出入口

import { CharxSdk } from '@ai_wanjia/sdk'
import { CharxProvider, useChat, useVariable, useCharacter, usePersona, useStorage } from '@ai_wanjia/sdk/react'

CharxProvider

CharxProvider 负责初始化 SDK 并通过 React Context 向下提供实例。

import { CharxProvider } from '@ai_wanjia/sdk/react'

export default function App() {
  return (
    <CharxProvider
      fallback={<div>连接中...</div>}
      errorFallback={(error) => <div>初始化失败:{error.message}</div>}
    >
      <YourApp />
    </CharxProvider>
  )
}

Hooks

| Hook | 作用 | |------|------| | useChat() | 管理消息列表、发送、停止、继续、重试 | | useVariable(key, defaultValue) | 订阅单个变量 | | useVariables() | 订阅全部变量 | | useCharacter() | 读取当前角色信息 | | usePersona() | 读取当前用户人设 | | useStorage(key, defaultValue) | 读取并同步一个持久化存储值 |

示例:

import { useChat, useVariable, useCharacter, useStorage } from '@ai_wanjia/sdk/react'

function GamePanel() {
  const character = useCharacter()
  const { messages, send, status } = useChat()
  const [hp, setHp] = useVariable<number>('hp', 100)
  const [theme, setTheme] = useStorage('preferredTheme', 'deep-sea')

  return (
    <div>
      <h2>{character?.name}</h2>
      <p>HP: {hp}</p>
      <p>Theme: {theme}</p>

      <button onClick={() => setHp(hp + 5)}>恢复 5 点 HP</button>
      <button onClick={() => setTheme('mist')}>切换主题</button>
      <button disabled={status !== 'idle'} onClick={() => send('继续')}>
        继续
      </button>

      {messages.map((message) => (
        <div key={message.id}>{message.content}</div>
      ))}
    </div>
  )
}

组件

Thread.MessageList

Thread 是一个命名空间对象,当前导出的是 Thread.MessageListThread.MessageItem

import { Thread, useChat } from '@ai_wanjia/sdk/react'

function ChatView() {
  const { messages, status, loadMore } = useChat()

  return (
    <Thread.MessageList
      messages={messages}
      isStreaming={status === 'streaming'}
      onLoadMore={loadMore}
    />
  )
}

MdRenderer

import { MdRenderer } from '@ai_wanjia/sdk/react'

function MessageBody({ content }: { content: string }) {
  return <MdRenderer content={content} />
}

包导出

| 导出路径 | 内容 | |----------|------| | @ai_wanjia/sdk | 核心 SDK、事件常量、类型 | | @ai_wanjia/sdk/react | React Provider、Hooks、组件 | | @ai_wanjia/sdk/types | 独立类型导出 |


通信协议

SDK 通过 postMessage 与平台通信。

| 方向 | 消息类型 | 说明 | |------|----------|------| | iframe → 平台 | __charx_rpc__ | 方法调用 | | 平台 → iframe | __charx_ready__ | 初始化握手成功 | | 平台 → iframe | __charx_rpc_response__ | RPC 响应 | | 平台 → iframe | __charx_push__ | 平台主动推送事件 |

如果要直接订阅底层推送事件,可以使用:

import { CharxSdk, PUSH } from '@ai_wanjia/sdk'

const sdk = CharxSdk.getInstance()
await sdk.init()

const unwatch = sdk.getRpc().push(PUSH.CHAT_STREAM_CHUNK, (data) => {
  console.log(data)
})

构建与开发

npm run build
npm run dev
npm run typecheck

输出目录为 dist/


相关文档

  • 仓库内创作者教程:docs/sdk-creator-guide.md
  • 原生模板:sdk/examples/charx-h5-starter
  • React 模板:sdk/examples/charx-react-starter

许可

内部使用,版权归玩家AI平台所有。