@ 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 或从自己的路线上薄荷会议.
快开始
-
在 FrontPath 门户网站中,为您的项目创建可发布密钥 。 添加 每一个来源您的应用程序运行( 例如 ).
https://app.acme.com, (中文(简体) ),http://localhost:3000)并选择如何收集电子邮件。 复制密钥 (单位:千美元)fppk_…) (中文(简体) ). -
将您的应用程序包入提供者并导入样式一次 .
// 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>
);
}
- 将部件添加到您的布局中, 在提供者内部 .
// 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 财务报告和审定财务报表 userHash | verified | 您的服务器在用户签名 . |
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 | 说明 |
|---|---|
baseUrl | FPOS起源,例如:. https://app.forwardpath.ai。 。 。 . |
publishableKey | 可公布的密钥( E)fppk_…) (中文(简体) ). 浏览器薄荷会与之相会. |
user | { id, email?, name? } 用于登录用户,或 null 给匿名访客 使用过的 publishableKey。 。 。 . |
userHash | createUserHash() 从您的服务器输出 。 制造 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 | 说明 |
|---|---|
position | bottom-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-* 主题变量. |
feedback | A 类 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}你也可以把它们放在下面
你的黑暗模式选择者.