# @copilotkit/react-native 中文文档

规范地址：https://npmcn.com/package/%40copilotkit/react-native/

版本：1\.86\.0
npm 元数据更新时间：2026-11-11T06:10:38.923Z
中文译文更新时间：2026-11-11T06:15:18.744Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40copilotkit/react-native
原文对照：https://npmcn.com/package/%40copilotkit/react-native/?lang=original
项目主页：https://github.com/CopilotKit/CopilotKit
源码仓库：https://github.com/CopilotKit/CopilotKit

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：1.3 MB，160 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- 运行依赖：6 个
- peer 依赖：zod \>=3\.0\.0，react ^18 \|\| ^19，react-native \>=0\.70，expo-file-system \>=17\.0\.0，@gorhom/bottom-sheet ^5\.0\.0，expo-document-picker \>=12\.0\.0，react-native-reanimated \>=3\.0\.0，react-native-streamdown \>=0\.1\.0，react-native-gesture-handler \>=2\.0\.0
- 首次发布：2026-05-07T01:19:08.131Z
- 最新版本发布：2026-11-11T06:10:38.571Z
- 近 30 天下载量：150581（2026-10-11 至 2026-11-09，npm 官方下载统计）
- 已发布版本数：160（近 12 个月 160 个）

## 中文简介

副驾驶Kit的无头回放原生装订. 提供轻量级提供商并再出口平台-不可知钩-没有DOM,CSS,或网络框架依赖性. 您用标准 React 本地组件构建聊天 UI .

## 安装

```sh
npm install @copilotkit/react-native
```

也可以使用：`pnpm add @copilotkit/react-native`、`yarn add @copilotkit/react-native`、`bun add @copilotkit/react-native`

## README

# @ copilotkit/ 反应本地化

副驾驶Kit的无头回放原生装订. 提供轻量级提供商并再出口平台-不可知钩-没有DOM,CSS,或网络框架依赖性. 您用标准 React 本地组件构建聊天 UI .

## 安装

```bash
npm install @copilotkit/react-native "zod@^3.25"
```

每一个条目都需要 `zod` 3.25 或以后,同龄人依赖 `@copilotkit/react-core`。命令安装了 zod 3, 这是一种基因化的 UI 使用目录 `child()` 或者说 `childList()` 需要帮助.

## 圆柱体

React Industrial's JS runtime (Hermes) 缺少几个由CopilotKit所依赖的Web API. 导入多填充器 **在任何其他代码之前** 输入点 :

```js
// index.js
import "@copilotkit/react-native/polyfills";

import { AppRegistry } from "react-native";
import App from "./App";
import { name as appName } from "./app.json";

AppRegistry.registerComponent(appName, () => App);
```

如果您已经填充了其中的一些 API, 您只能导入您需要的 :

```js
import "@copilotkit/react-native/polyfills/streams";
import "@copilotkit/react-native/polyfills/encoding";
import "@copilotkit/react-native/polyfills/crypto";
import "@copilotkit/react-native/polyfills/dom";
import "@copilotkit/react-native/polyfills/location";
```

## 快开始

```tsx
import {
  CopilotKitProvider,
  useAgent,
  useCopilotKit,
} from "@copilotkit/react-native/headless";

export default function App() {
  return (
    <CopilotKitProvider runtimeUrl="https://your-server/api/copilotkit">
      <ChatScreen />
    </CopilotKitProvider>
  );
}
```

再出口钩子从 `@copilotkit/react-core`数字 : `useAgent`, (中文(简体) ), `useFrontendTool`, (中文(简体) ), `useComponent`, (中文(简体) ), `useHumanInTheLoop`, (中文(简体) ), `useInterrupt`, (中文(简体) ), `useSuggestions`, (中文(简体) ), `useConfigureSuggestions`, (中文(简体) ), `useAgentContext`, (中文(简体) ), `useThreads`,以及 `useCopilotKit`。 。 。 .

## 基因UI(实验性)

`@copilotkit/react-native/generative-ui` 让代理制作您的目录 拥有本地组件 `render_ui` 工具。 安装 `zod` 3.25或以后: 包的每个条目都需要它 因为 `@copilotkit/react-core` 需求 作为同伴的依赖关系(`@copilotkit/react-native` 声明 `zod` 选项 端点 `>=3.0.0` 只因为缩小这个范围是一次突破 页:1 安装 zod 3 (`npm install "zod@^3.25"`用于目录 `child()` 或者说 `childList()`:它们返回了zod 3个计划,这个zod 4个计划 无法维持。 运行时间默认不需要更改 : `CopilotRuntime` 添加 当应用程序发送至少包含一个组件的目录时的工具,除非 服务器集 `generativeUI: false` 或者限制它与 `generativeUI: { agents: [...] }`。此示例需要 `home` 代理在 运行时间: 一旦运行时间连接, `useAgent` 抛出没有它. `/generative-ui` 1.8.5.0或任何较早的版本 1.8.5.0之后释放的船舶.

```tsx
import { useCallback, useEffect, useRef, useState } from "react";
import {
  ActivityIndicator,
  Pressable,
  ScrollView,
  Text,
  View,
} from "react-native";
import { z } from "zod";
import {
  CopilotKitCoreErrorCode,
  CopilotKitCoreRuntimeConnectionStatus,
  CopilotKitProvider,
  useAgent,
  useAgentContext,
  useCopilotKit,
} from "@copilotkit/react-native/headless";
import {
  GenerativeUIActivity,
  GenerativeUIProvider,
  createGenerativeUI,
  isGenerativeUIActivity,
  useGenerativeUIRuntime,
  type GenerativeUIActivityMessage,
} from "@copilotkit/react-native/generative-ui";

const ui = createGenerativeUI({
  id: "acme/bank@1",
  components: {
    BalanceCard: {
      component: ({ account, amount }: { account: string; amount: number }) => (
        <View>
          <Text>{account}</Text>
          <Text>{amount}</Text>
        </View>
      ),
      description:
        "The balance of one account. Copy the values from the context.",
      props: z.object({ account: z.string(), amount: z.number() }),
    },
  },
});

type CopilotKit = ReturnType<typeof useCopilotKit>["copilotkit"];
type Agent = ReturnType<typeof useAgent>["agent"];

/**
 * The errors that end a run. A failed tool call is not one of them
 * (TOOL_HANDLER_FAILED, TOOL_ARGUMENT_PARSE_FAILED): its error goes back to
 * the model as the result of the call, and the run goes on.
 */
const RUN_FAILURES: ReadonlySet<CopilotKitCoreErrorCode> = new Set([
  CopilotKitCoreErrorCode.AGENT_RUN_FAILED,
  CopilotKitCoreErrorCode.AGENT_RUN_FAILED_EVENT,
  CopilotKitCoreErrorCode.AGENT_RUN_ERROR_EVENT,
  CopilotKitCoreErrorCode.AGENT_THREAD_LOCKED,
]);

// Date.now() alone repeats within a millisecond; with a counter, ids do not.
let sent = 0;

/**
 * Sends one user message and runs the agent. Resolves with the run's error,
 * or undefined; it never rejects. It counts every run failure of this agent
 * while it waits, so start one run of an agent at a time.
 */
async function runTurn(copilotkit: CopilotKit, agent: Agent, content: string) {
  const before = agent.messages.map((message) => message.id);
  const { threadId } = agent;
  let failure: Error | undefined;
  const subscription = copilotkit.subscribe({
    onError: ({ error, code, context }) => {
      if (context.agentId === agent.agentId && RUN_FAILURES.has(code)) {
        failure ??= error;
      }
    },
  });
  try {
    sent += 1;
    agent.addMessage({
      id: `user-${Date.now()}-${sent}`,
      role: "user",
      content,
    });
    await copilotkit.runAgent({ agent });
  } catch (error) {
    failure ??= error instanceof Error ? error : new Error(String(error));
  } finally {
    subscription.unsubscribe();
  }
  try {
    if (failure) takeBack(agent, before, threadId);
  } catch (error) {
    console.error("Could not take the failed turn back:", error);
  }
  return failure;
}

/**
 * Removes the messages added since `before` (their ids), such as the user
 * message and a partial reply. It keeps the surfaces: the provider keeps
 * every surface that a run rendered, and the model still sees it, so the
 * screen shows it too.
 */
function takeBack(
  agent: Agent,
  before: readonly string[],
  threadId: string | undefined,
) {
  // The agent moved to another thread: those messages are not this turn's.
  if (agent.threadId !== threadId) return;
  const kept = new Set(before);
  agent.setMessages(
    agent.messages.filter(
      (message) => kept.has(message.id) || isGenerativeUIActivity(message),
    ),
  );
}

/**
 * An activity message that GenerativeUIActivity draws: its surface is aimed at
 * the chat (the target it shows) and the agent has not deleted it.
 */
function isChatSurface(message: GenerativeUIActivityMessage) {
  if (!isGenerativeUIActivity(message)) return false;
  const content = message.content as {
    target?: unknown;
    operations?: unknown;
  } | null;
  const operations = Array.isArray(content?.operations)
    ? content.operations
    : [];
  return (
    content?.target === "chat" &&
    !operations.some(
      (op) => typeof op === "object" && op !== null && "deleteSurface" in op,
    )
  );
}

/**
 * The chat surfaces that this device built, each message id with its operations,
 * to tell whether a run rendered or updated one here. The operations alone: each
 * call of the agent also refills the list of rejected operations, so a call whose
 * updates were all rejected changes the content but not the surface. A surface
 * whose createSurface the app rejected (`failed`) does not count: the app checks
 * the operations again, prop values included, and GenerativeUIActivity then shows
 * only an error line.
 */
function chatSurfaces(
  messages: readonly GenerativeUIActivityMessage[],
  failed: (surfaceId: string) => boolean,
) {
  const built = new Map<string | undefined, string>();
  for (const message of messages.filter(isChatSurface)) {
    const { surfaceId, operations } = message.content as {
      surfaceId?: unknown;
      operations?: unknown;
    };
    if (typeof surfaceId === "string" && failed(surfaceId)) continue;
    built.set(message.id, JSON.stringify(operations));
  }
  return built;
}

// Your app's data. The agent sees only what you give it with useAgentContext.
const accounts = [
  { account: "Chequing", amount: 3482.1 },
  { account: "Savings", amount: 6150 },
];

function Home() {
  const { copilotkit } = useCopilotKit();
  // Until the runtime connects, `agent` is a stand-in (`isReady` is false). The
  // registered agent replaces it, so a run started on the stand-in is lost.
  // Once the runtime has connected, useAgent throws if it has no `home` agent.
  const { agent, isReady } = useAgent({ agentId: "home" });
  const runtime = useGenerativeUIRuntime();
  // The thread it last checked: a ref, so StrictMode's second effect run sees it.
  const checkedThread = useRef<string | undefined>(undefined);
  const composing = useRef(false); // a ref, so a second tap is ignored at once
  const [checked, setChecked] = useState(false);
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState<string>();

  useAgentContext({
    description:
      "The user's accounts. Show only these, with these exact balances.",
    value: accounts,
  });

  const failed = useCallback(
    (surfaceId: string) =>
      !!runtime?.manager.getFailedSurface(agent.threadId, surfaceId),
    [runtime, agent],
  );

  const compose = useCallback(async () => {
    // A stand-in agent (not ready) would lose the run.
    if (composing.current || !isReady) return;
    composing.current = true;
    setBusy(true);
    setError(undefined);
    try {
      const before = agent.messages.map((message) => message.id);
      const { threadId } = agent;
      const shownBefore = chatSurfaces(agent.messages, failed);
      const failure = await runTurn(copilotkit, agent, "Show my balances.");
      const shownAfter = chatSurfaces(agent.messages, failed);
      if (failure) {
        // runTurn took the prompt back, so a retry sends it once.
        setError(failure.message);
      } else if (
        ![...shownAfter].some(
          ([id, content]) => shownBefore.get(id) !== content,
        )
      ) {
        // This run rendered or updated nothing here. Take its prompt back too.
        takeBack(agent, before, threadId);
        setError("The agent rendered nothing for this screen.");
      }
    } catch (reason) {
      setError(reason instanceof Error ? reason.message : String(reason));
    } finally {
      composing.current = false;
      setBusy(false);
    }
  }, [agent, copilotkit, failed, isReady]);

  // The agent and its messages live in the core and outlive this screen. Run only
  // when the registered agent has no surface here yet and is not running, so a
  // screen that mounts again shows what it has instead of composing it again.
  // Check again when the agent moves to another thread, once it is not running
  // and no compose is under way (`busy` reruns this when one ends).
  useEffect(() => {
    if (
      !isReady ||
      busy ||
      composing.current ||
      agent.isRunning ||
      checkedThread.current === agent.threadId
    ) {
      return;
    }
    checkedThread.current = agent.threadId;
    setChecked(true);
    setError(undefined);
    if (chatSurfaces(agent.messages, failed).size === 0) {
      void compose();
    }
  }, [isReady, busy, agent, agent.threadId, agent.isRunning, compose, failed]);

  const surfaces = agent.messages.filter(isChatSurface);
  const built = chatSurfaces(agent.messages, failed);
  const unreachable =
    copilotkit.runtimeConnectionStatus ===
    CopilotKitCoreRuntimeConnectionStatus.Error;
  const waiting = !isReady || !checked || busy || agent.isRunning;

  return (
    <ScrollView contentContainerStyle={{ padding: 16 }}>
      {surfaces.map((message) => (
        <GenerativeUIActivity
          key={message.id}
          message={message}
          agent={agent}
        />
      ))}
      {unreachable ? (
        <Text accessibilityRole="alert">
          Can't reach the agent. Check the runtime URL.
        </Text>
      ) : waiting ? (
        <ActivityIndicator />
      ) : error || built.size === 0 ? (
        <Pressable accessibilityRole="button" onPress={() => void compose()}>
          <Text>
            Couldn't load your balances{error ? ` (${error})` : ""}. Tap to try
            again.
          </Text>
        </Pressable>
      ) : null}
    </ScrollView>
  );
}

export default function App() {
  return (
    <CopilotKitProvider runtimeUrl="https://your-server/api/copilotkit">
      <GenerativeUIProvider ui={ui}>
        <Home />
      </GenerativeUIProvider>
    </CopilotKitProvider>
  );
}
```

`GenerativeUIActivity` 使一个活动消息的表面在您自己的 信件列表或屏幕上没有聊天。 就像网络聊天,它只显示 面向聊天的表面; 通过 `target` 以显示另一个目标。 它让 无所事事(并在发展中发出警告) `GenerativeUIProvider`下,a 没有提供者 `ui`,或当代理人没有 `threadId`。示例显示 一个旋转器,一个无法到达的跑步时间 和与原因的重试。 运行失败 迅速被带回,但表面 它使停留: 提供者和 模特儿留着 文档添加聊天列表 . `GenerativeUISurface` 在应用程序中标出一个命名的地方; `style` 应用时 倒计时秀也。 只传送工具; 没有标准目录, 没有 `theme` 道具(a) `theme` 由 JavaScript 传递, 并随开发而放弃 (警告)和无 `openUrl` ( 它失败 ) “ 打开Url 无法在此访问 平台”和预建 `CopilotChat` 尚未绘制表面。 见 [反应原生文件](https://docs.copilotkit.ai/react-native#generative-ui-with-your-own-components)。 。 。 .

## API 表面

根导入( E)`@copilotkit/react-native`这是v2 API. 和SDK的网络不同 `/v2` 子路径, 反应本地导出 直接取自包根的 v2 API.

根还再导出聊天组件和 `useAttachments`,哪个 进口 `expo-document-picker` 财务报告和审定财务报表 `expo-file-system`; Metro解决了它们 捆绑时间,所以从根部导入的应用程序必须同时安装两种. `@copilotkit/react-native/headless` 将提供者和钩子导出 这就是上面的"快起步"使用的原因.

## 文档

完整的设置指令、使用示例和故障排除,见 [反应原生文件](https://docs.copilotkit.ai/react-native)。 。 。 .

## 常见问题

### @copilotkit/react-native 是什么？

副驾驶Kit的无头回放原生装订\. 提供轻量级提供商并再出口平台-不可知钩-没有DOM,CSS,或网络框架依赖性\. 您用标准 React 本地组件构建聊天 UI \.

### 如何安装 @copilotkit/react-native？

在项目目录运行 npm install @copilotkit/react-native，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：react（^18 \|\| ^19）、react-native（\>=0\.70）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @copilotkit/react-native 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @copilotkit/react-native 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @copilotkit/react-native 可以商用吗？

@copilotkit/react-native 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @copilotkit/react-native 的下载量有多少？

根据 npm 官方下载统计，@copilotkit/react-native 在 2026/10/11 – 2026/11/09 这 30 天内被下载 150,581 次，日均约 5,019 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @copilotkit/react-native 还在维护吗？

最新版本 1\.86\.0 发布于 2026/11/11（今天）；至今共发布 160 个版本，其中过去 12 个月发布了 160 个；首次发布于 2026/05/07。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

