@forwardpath/react

中文文档
0.3.0发布于 2026/11/03UNLICENSEDTypeScriptES Module近 30 天下载 4068

反应提供者、 钩子、 聊天和反馈部件用于ForwardPath录入 .

中文使用文档
文档目录14 节
  1. 安装
  2. 快开始
  3. 可公开的密钥
  4. 记者是谁
  5. 验证用户为 userHash
  6. 电子邮件表
  7. 从服务器验证的用户
  8. <ForwardPathProvider>
  9. useFeedback()
  10. <FeedbackWidget />
  11. <FeedbackChat />
  12. 附录
  13. 屏幕抓取
  14. 他们

@ forwardpath/反应

反应组件用于ForwardPath摄入. 将您的应用程序包入 <ForwardPathProvider>输入 <FeedbackWidget /> 对于浮点 "退后"按钮, <FeedbackChat /> 用于内置聊天,或构建自己的用户界面 与 useFeedback()。在 @forwardpath/js。 。 。 .

安装

npm install @forwardpath/react @ai-sdk/react ai

react 财务报告和审定财务报表 react-dom 页:1, @ai-sdk/react (v4)和 ai (v7) 是对等的 依赖性。 不需要尾风 添加 @forwardpath/node 仅在您的服务器上 以 userHash 或从自己的路线上薄荷会议.

快开始

  1. 在 FrontPath 门户网站中,为您的项目创建可发布密钥 。 添加 每一个来源您的应用程序运行( 例如 ). https://app.acme.com, (中文(简体) ), http://localhost:3000)并选择如何收集电子邮件。 复制密钥 (单位:千美元)fppk_…) (中文(简体) ).

  2. 将您的应用程序包入提供者并导入样式一次 .

// app/providers.tsx
"use client";

import { ForwardPathProvider } from "@forwardpath/react";
import "@forwardpath/react/styles.css";

type User = { id: string; email?: string | null; name?: string | null };

export function Providers({
  user,
  children,
}: {
  user: User | null;
  children: React.ReactNode;
}) {
  return (
    <ForwardPathProvider
      baseUrl="https://app.forwardpath.ai"
      publishableKey={process.env.NEXT_PUBLIC_FORWARDPATH_KEY!}
      user={user}
      appName="Acme"
      appVersion={process.env.NEXT_PUBLIC_APP_VERSION}
      environment={process.env.NODE_ENV}
    >
      {children}
    </ForwardPathProvider>
  );
}
  1. 将部件添加到您的布局中, 在提供者内部 .
// app/layout.tsx
import { FeedbackWidget } from "@forwardpath/react";

import { getUser } from "@/auth"; // your own auth
import { Providers } from "./providers";

export default async function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  const user = await getUser(); // null when signed out
  return (
    <html lang="en">
      <body>
        <Providers user={user}>
          {children}
          <FeedbackWidget />
        </Providers>
      </body>
    </html>
  );
}

或让聊天在自己的一页内:

// app/support/page.tsx
"use client";

import { FeedbackChat } from "@forwardpath/react";

export default function SupportPage() {
  return (
    <FeedbackChat
      placeholder="What went wrong?"
      onSubmitted={(report) => console.log("Filed", report.customerReference)}
    />
  );
}

可公开的密钥

可公布的密钥按设计公开. 任何人都可以从你的页面上读到, 因此它只能为它的一个项目开始录入聊天,并且只能从 允许在密钥上输入源 。 前进率限制它。 千万别把秘密藏起来 API 密钥( E)fp_…或钥匙的身份秘密(fpiv_…)在浏览器代码中.

记者是谁

你通过记者含义
user 财务报告和审定财务报表 userHashverified您的服务器在用户签名 .
user 仅限claimed浏览器命名了用户. 任何人都可以发送任何ID或电子邮件,所以视之为未经核实.
也没有anonymous无名来客.

对于匿名的访客,提供者 保持一个随机的ID在 localStorage (单位:千美元)forwardpath:anonymous-id),所以重复访问地图给同一个记者. 在存储被屏蔽的地方,ID会持续到页面负载.

何时 publishableKey, (中文(简体) ), user.id, (中文(简体) ), user.email 或者说 userHash 变化 提供者放下缓存会话并薄荷新会话, 所以签入和 退出不需要加载页面。 一个新的 user 保留相同字段的天体 会议闭幕.

验证用户为 userHash

计算服务器上的散列 createUserHash 从 @forwardpath/node 和钥匙的身份秘密(fpiv_…,在 您创建了密钥 。 交给旁边的供应商 user。 。 。 .

// app/layout.tsx (a server component)
import { createUserHash } from "@forwardpath/node";

export default async function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  const user = await getUser();
  const userHash = user
    ? createUserHash({
        identitySecret: process.env.FORWARDPATH_IDENTITY_SECRET!,
        user,
      })
    : undefined;
  // Pass both on: <ForwardPathProvider user={user} userHash={userHash} …>
  return (
    <html lang="en">
      <body>
        <Providers user={user} userHash={userHash}>
          {children}
          <FeedbackWidget />
        </Providers>
      </body>
    </html>
  );
}

散列标志 user.id 财务报告和审定财务报表 user.email而不是这个名字。 显示相同值 你通过作为 user: 错配以 401 失败会话 。 无 userHash 用户是 claimed。 。 。 .

电子邮件表

当代理人没有给记者的邮件时,例如匿名访客或 user 无 email它在聊天中显示一个简短的形式: 电子邮件,一个可选的 名并发相. 一旦用户回答,聊天就自行进行. 虽然 窗体打开,作曲者被禁用.

设定 contactCollection 门户中的每个密钥 :

  • required:代理只有在用户发出电子邮件后才将报告归档 .
  • optional:表单也显示跳过.
  • off:经纪人从来不问.

服务器在外部报告前保存已提交的电子邮件 助理继续。 将报告人链接到请求中并包含 它们在请求元数据和线性描述中的联系方式。 键入 电子邮件被标记为自报;它不创建一个门户账户.

如果您的应用程序已经知道用户的电子邮件, 请通过 user={{ id: user.id, email: user.email, name: user.name }} 打开 ForwardPathProvider。聊天时不用再次询问.

从服务器验证的用户

要在您的服务器上使用您的 API 密钥进行薄荷会话, 请省略 publishableKey 并添加会话路由 @forwardpath/node编辑 提供者 POSTs { clientContext } 改为 /api/forwardpath/session 默认 和预期 { token, expiresAt } 回来 这些记者总是 verified。 。 。 .

// app/api/forwardpath/session/route.ts
import {
  createForwardPathClient,
  createIntakeSessionHandler,
} from "@forwardpath/node";

import { auth } from "@/auth";

const client = createForwardPathClient({
  apiKey: process.env.FORWARDPATH_API_KEY!,
  baseUrl: "https://app.forwardpath.ai",
});

export const POST = createIntakeSessionHandler({
  client,
  projectSlug: "acme-web",
  // Return the signed-in user, or null to answer 401.
  getUser: async () => {
    const session = await auth();
    if (!session?.user) return null;
    return {
      externalId: session.user.id,
      email: session.user.email,
      name: session.user.name ?? undefined,
    };
  },
});
<ForwardPathProvider baseUrl="https://app.forwardpath.ai" sessionKey={userId}>

您的 API 密钥可以为任何用户薄荷会话 。 放在服务器上. 提供者只向ForwardPath发送短暂的会话符号.

<ForwardPathProvider>

Prop说明
baseUrlFPOS起源,例如:. https://app.forwardpath.ai。 。 。 .
publishableKey可公布的密钥( E)fppk_…) (中文(简体) ). 浏览器薄荷会与之相会.
user{ id, email?, name? } 用于登录用户,或 null 给匿名访客 使用过的 publishableKey。 。 。 .
userHashcreateUserHash() 从您的服务器输出 。 制造 user verified。 。 。 .
sessionEndpoint你的路线,薄荷一个会话。 默认 /api/forwardpath/session。 。 。 .
getSessionToken薄荷会自己。 获取 { clientContext }; 返回 { token, expiresAt } 或符号字符串.
sessionKey会话是给谁用的,例如签名的用户代号. 更改它会减少缓存会话 .
appName, (中文(简体) ), appVersion, (中文(简体) ), environment, (中文(简体) ), custom发送每个信息,使团队看到反馈的来源.
fetch自定义 fetch 每个请求.

getSessionToken 胜过 publishableKey,获胜 sessionEndpoint。 。 。 .

提供商在首次使用时会将一个代币薄荷并保存在记忆中. 薄荷糖 薄荷糖 60秒前的新时间 expiresAt,如果API回答401. 空弦从 getSessionToken 保存到401号 过 sessionKey 这样 没有页面负载的用户切换不会再重复旧用户的会话.

useFeedback()

回返 { messages, sendMessage, status, error, stop, retry, reset, submitted, attachments, uploading, attachmentError, attach, removeAttachment, contactRequest, submitContact }。 。 。 .

  • sendMessage(text) 随任何待处理附件发送用户消息。 这个 此时不做 contactRequest 打开.
  • status 是 AI SDK 聊天状态 : ready, (中文(简体) ), submitted, (中文(简体) ), streaming 或者说 error。 。 。 .
  • retry() 在出错后再发送最后一个消息.
  • reset() 清除聊天内容.
  • submitted 是最近成功提交的 (单位:千美元){ customerReference, title, ... }),或 null。 。 。 .
  • attach(file) 上传一个 File 与下一个信息一起发送。 见 附录。 。 。 .
  • attachments 列出等待下一个消息的上传文件,以及 removeAttachment(id) 掉一个.
  • uploading 计算飞行中的上传; attachmentError 说为什么最后 一个失败.
  • contactRequest 是代理服务器打开的电子邮件请求 (单位:千美元){ toolCallId, canSkip }),或 null。见 电子邮件表。 。 。 .
  • submitContact(toolCallId, { email, name? }) 接电话,或者 submitContact(toolCallId, { skipped: true }) 何时 canSkip 这是真的。 这个 三进制值, 丢弃空名并拒绝无效的电子邮件 。 闲聊 然后自己继续. <FeedbackChat> 做这个表格给你.

每个 useFeedback() 呼叫自己负责谈话 来推动聊天 <FeedbackChat> 或者说 <FeedbackWidget> 显示结果,通过结果 feedback 道具 (英语).

import { useFeedback } from "@forwardpath/react";

function MyChat() {
  const { messages, sendMessage, submitted } = useFeedback();
  if (submitted) return <p>Thanks! Your reference is {submitted.customerReference}.</p>;
  // ...
}

<FeedbackWidget />

打开的固定发射器按钮 <FeedbackChat /> 在一个面板。 打开它 一次,在提供者内部.

Prop说明
positionbottom-right (违约)或 bottom-left。 。 。 .
label发射器文本和面板标题。 默认 Feedback。 。 。 .
title独立于发射装置而覆盖面板标题.
launcherIcon发射口标记的反应节点. 默认为 assistantIcon,然后是一个内置聊天标记。 过 null 藏起来.
defaultOpen打开挂载面板 .
className添加到部件的根元素中 .
style内置样式并输入 --fp-* 部件根上的主题变量.

还要花很多时间 <FeedbackChat /> 道具 (英语). className 财务报告和审定财务报表 style 应用 转到部件根后,主题由面板继承。 埃克还是 关闭按钮关闭面板并返回焦点到发射台。 闭幕 隐藏面板而不结束对话.

<FeedbackChat />

Prop说明
placeholder作曲占位符.
assistantName在助理信件和部件标题上显示名称。 默认 ForwardPath assistant。不改变模式或指示.
assistantIcon装饰性反相节点,例如带有SVG或图像 alt=""。用于欢迎状态、助理消息和部件标题。 过 null 藏起来.
welcomeTitle头一通消息前去. 默认 How can we help?。 。 。 .
welcomeMessage在第一个消息之前支持文本 。 不发送消息或启动会话 .
onSubmitted(report)每成功提交一次.
className被添加到根元素中.
style内置样式并输入 --fp-* 主题变量.
feedbackA 类 useFeedback() 而不是聊天时自己做的.

以换行符将信件变成纯文本 。 信件中的 HTML 显示为 文本并永远不运行。 当代理请求电子邮件时, 表格会显示在内 它的讯息.

附录

用户可以在纸张剪贴按钮中附加文件,或将其放入 闲聊。 每个文件一次上传,并显示为作曲家之上的芯片,直到 下一个信息发送它。 图像附件向代理显示, 所有 附件可以添加到已备案的请求中.

在上传前, 聊天检查每个文件 :

  • 低于 10 MB(上传请求,包含框架,必须符合 10 MB),
  • 是 PNG、 JPEG、 WebP 或 GIF 图像、 PDF、 纯文本、 CSV 或 JSON 文件( 或 没有类型, 上传为 application/octet-stream),以及
  • 不把谈话 超过10附件.

从自己的代码附加一个文件, 例如日志导出, 调用 attach数字 :

"use client";

import { FeedbackWidget, useFeedback } from "@forwardpath/react";

export function Feedback({ getLogs }: { getLogs: () => string }) {
  const feedback = useFeedback();
  async function attachLogs() {
    await feedback.attach(
      new File([getLogs()], "app-log.txt", { type: "text/plain" }),
    );
  }
  return (
    <>
      <button onClick={attachLogs}>Attach logs</button>
      <FeedbackWidget feedback={feedback} />
    </>
  );
}

attach 拒绝检查或上传失败,并设定 attachmentError。 。 。 .

屏幕抓取

“ Capture 屏幕” 按钮要求浏览器共享屏幕、 窗口或 选项卡 getDisplayMedia,将一个框架保存为 screenshot-<ISO time>.png, (中文(简体) ), 停止共享并附加图像。 没有其他记录.

  • 浏览器每次都会提示用户. 取消提示无效 .
  • 按钮只显示在哪里 navigator.mediaDevices.getDisplayMedia 存在: 安全上下文( HTTPS 或 localhost)在桌面浏览器中. 多数 移动浏览器不支持.
  • 在iframe中,母页必须允许: <iframe allow="display-capture">A级 Permissions-Policy 标题 块 display-capture 也禁用它 .

他们

标记每个执行而不替换聊天 UI :

<FeedbackWidget
  label="Help"
  title="Acme support"
  assistantName="Acme assistant"
  assistantIcon={<img src="/acme-mark.svg" alt="" />}
  welcomeTitle="How can we help?"
  welcomeMessage="Tell us what's happening or what you'd like to improve."
  style={{
    "--fp-accent": "#0f766e",
    "--fp-accent-foreground": "#ffffff",
    "--fp-radius": "16px",
    "--fp-panel-width": "420px",
  }}
/>

发射器使用相同的标记,除非你提供 launcherIcon全部数据 图标为装饰; label, (中文(简体) ), title 财务报告和审定财务报表 assistantName 提供 可读文本。 选择带有可读对比度的口音和前景对 在你的应用的光和暗的主题. FeedbackStyle 导出为共享 在部件和内置聊天实例之间键入样式.

每个课从头开始 fp-设置这些变量 :root,一个祖先 或者说 .fp-root数字 :

:root {
  --fp-accent: #0f766e;
  --fp-accent-foreground: #ffffff;
  --fp-bg: #ffffff;
  --fp-fg: #111827;
  --fp-radius: 8px;
  --fp-font: "Inter", sans-serif;
  --fp-z-index: 1000; /* widget stacking order */
  --fp-panel-width: 400px;
  --fp-panel-height: 620px;
}

添加 data-fp-theme="dark" 给祖先(如:. <html>) 对于黑暗 默认值。 如果你准备好了 --fp-bg 或者说 --fp-fg {\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}你也可以把它们放在下面 你的黑暗模式选择者.

版本与发布记录

@forwardpath/react 共发布 5 个版本,首次发布于 2026/10/22;过去 12 个月发布了 5 个版本。

版本发布日期距今
0.3.0latest2026/11/0313 天前
0.2.02026/10/2324 天前
0.1.12026/10/2224 天前
0.1.02026/10/2224 天前
0.0.0-stage2026/10/2224 天前

关于 @forwardpath/react 的常见问题

@forwardpath/react 是什么?

反应提供者、 钩子、 聊天和反馈部件用于ForwardPath录入 .

如何安装 @forwardpath/react?

在项目目录运行 npm install @forwardpath/react,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:ai(^7)、react(^19)、react-dom(^19)、@ai-sdk/react(^4)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@forwardpath/react 支持 TypeScript 吗?

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

@forwardpath/react 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@forwardpath/react 可以商用吗?

@forwardpath/react 使用 UNLICENSED 许可。作者声明为 UNLICENSED,即不授予公开使用许可(与公共领域的 Unlicense 不同)。使用前需获得作者授权。以上为概括,不构成法律意见,请以许可原文为准。

@forwardpath/react 的下载量有多少?

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

@forwardpath/react 还在维护吗?

最新版本 0.3.0 发布于 2026/11/03(13 天前);至今共发布 5 个版本,其中过去 12 个月发布了 5 个;首次发布于 2026/10/22。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。