关于 adk-frontend
为使用 Botpress ADK 构建前端的开发者提供集成指导,涵盖认证、客户端管理、类型生成和 Bot 动作调用。内容围绕 TypeScript 模式及 React 相关状态管理方案组织。
主要功能
- 01Cookie 与 OAuth 认证模式
- 02使用 Zustand 缓存客户端
- 03导入 ADK 生成的类型
- 04类型安全地调用 Bot 动作
- 05错误处理与乐观更新
适用场景
- 01在前端实现 Botpress 登录与路由保护
- 02复用工作区或 Bot 级客户端
- 03同步 Bot 动作的 TypeScript 类型
- 04在界面中调用动作并处理异步状态
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ botpress/ skills --skill adk-frontend安装后在 Claude Code 中输入/adk-frontend确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/authentication.mdbotpress-client.mdcalling-actions.mddata-fetching.mdoverview.mdproject-setup.mdrealtime-updates.mdrecommended-stack.mdservice-layer.mdstate-management.mdtype-generation.md详细介绍
ADK 前端集成
当用户询问如何构建与 Botpress ADK 机器人连接的前端应用时,请使用此技能。内容涵盖身份验证模式、类型安全的 API 调用、客户端配置,以及集成生成的类型。
什么是 ADK 前端集成?
使用 Botpress ADK 构建机器人时,通常需要一个与其交互的前端应用。此技能提供经过生产环境验证的模式,用于:
- 身份验证 - 通过 OAuth 流程存储基于 Cookie 的 PAT
- 客户端管理 - 使用 Zustand store 模式缓存和复用客户端
- 类型生成 - 使用 ADK 生成的类型,确保完整的类型安全
- Action 调用 - 调用机器人 action,并妥善处理错误和乐观更新
关键技术
- @botpress/client - Botpress API 的官方 TypeScript 客户端
- 三斜线引用 - 用于导入生成类型的 TypeScript 模式
- React Query - 用于管理变更和缓存(可选,但推荐)
- Zustand - 用于客户端状态管理
何时使用此技能
当用户提出以下前端相关问题时,启用此技能:
身份验证问题
- “如何从前端向 Botpress 进行身份验证?”
- “个人访问令牌(PAT)是什么?”
- “令牌应该存储在 Cookie 还是 localStorage 中?”
- “如何实现 OAuth 登录流程?”
- “如何根据身份验证状态保护路由?”
- “如何处理令牌过期?”
客户端设置问题
- “如何初始化 Botpress 客户端?”
- “管理多个客户端实例的最佳方式是什么?”
- “为什么要使用客户端 store?”
- “如何创建工作区范围与机器人范围的客户端?”
- “普通客户端和 Zai 客户端有什么区别?”
类型生成问题
- “如何获取机器人 action 的类型?”
- “什么是三斜线引用?”
- “如何导入生成的类型?”
- “.adk 类型文件在哪里?”
- “如何保持机器人和前端的类型同步?”
- “为什么 TypeScript 找不到我的 action 类型?”
调用 Action 的问题
- “如何从前端调用机器人 action?”
- “client.callAction() 的语法是什么?”
- “调用 action 时如何处理错误?”
- “如何实现乐观更新?”
- “如何串联多个 action 调用?”
- “如何将 React Query 与机器人 action 配合使用?”
可用文档
./references/ 中的文档文件:
核心集成模式
- authentication.md - 完整的身份验证系统,涵盖 PAT、Cookie、OAuth 和路由保护
- botpress-client.md - 客户端初始化、Zustand store 模式和 Zai 客户端设置
- calling-actions.md - 类型安全的 action 调用、变更、错误处理和乐观更新
- type-generation.md - 三斜线引用、生成的类型和维护类型安全
架构与设置
- overview.md - 架构概述、何时使用 ADK 前端以及项目结构
- project-setup.md - Vite + React 脚手架、TypeScript 配置和环境设置
- recommended-stack.md - 推荐的技术栈及其理由
数据与状态模式
- service-layer.md - 用于封装带类型 API 调用的服务层模式
- data-fetching.md - TanStack Query 模式、变更和乐观更新
- state-management.md - Zustand 与 TanStack Query 的比较,以及何时使用各自方案
- realtime-updates.md - 轮询策略、间隔级别和性能注意事项
如何回答前端问题
前端问题通常属于以下类别:
1. 身份验证实现
当用户询问身份验证时,请参考 authentication.md 中的完整模式:
核心概念:
- 在 Botpress Cloud 中生成 PAT
- 基于 Cookie 的存储(而非 localStorage)
- 使用 React Context API 的 AuthContext
- 通过 cli-login 实现 OAuth 回调流程
- 使用 TanStack Router 保护路由
- 同时从 Botpress API 和机器人表中获取个人资料
回复模式:
- 说明身份验证策略(Cookie 与 localStorage)
- 展示 AuthProvider 的实现
- 演示 OAuth 流程
- 提供路由保护示例
- 强调安全最佳实践
2. 客户端设置与管理
当用户询问客户端配置时,请参考 botpress-client.md:
核心概念:
- 使用 apiUrl、workspaceId、token、botId 初始化客户端
- 使用 Zustand store 缓存客户端
- 用于复用的动态客户端键
- 工作区范围与机器人范围的客户端
- 为 Zai 操作延长超时时间
回复模式:
- 展示 clientsStore.ts 模式
- 说明客户端缓存的工作原理
- 演示 getApiClient() 的用法
- 展示何时使用工作区范围或机器人范围的客户端
- 说明用于 AI 操作的 getZaiClient()
3. 类型生成与导入
当用户询问类型时,请参考 type-generation.md:
核心概念:
- ADK 在开发/构建期间于
.adk/目录中生成类型 - 使用三斜杠指令引用外部类型
- 生成的文件:action-types.d.ts、table-types.d.ts、workflow-types.d.ts
- 创建类型别名以简化代码
- 通过 adk dev 保持类型同步
回复模式:
- 说明 ADK 如何生成类型
- 展示三斜杠引用语法
- 演示如何导入生成的类型
- 提供创建类型别名的示例
- 展示类型如何自动保持同步
4. 调用机器人操作
当用户询问如何调用操作时,请参考 calling-actions.md:
核心概念:
- client.callAction() 签名
- 使用 BotActionDefinitions 实现类型安全的输入/输出
- 可复用操作调用的服务层模式
- 使用 useMutation 管理加载状态和错误处理
- 使用乐观更新即时反馈 UI
- 链接多个操作(顺序执行与并行执行)
回复模式:
- 展示基本的 callAction() 语法
- 演示类型安全的服务函数
- 提供 useMutation 示例
- 展示错误处理模式
- 在适用时说明乐观更新
常见模式参考
身份验证流程
// 1. Cookie helpers
function setCookie(name: string, value: string, days = 365)
function getCookie(name: string): string | null
function deleteCookie(name: string)
// 2. AuthContext
interface AuthContextType {
token: string | null
isAuthenticated: boolean
userProfile: UserProfile | null
isLoadingProfile: boolean
login: (token: string) => void
logout: () => void
}
// 3. OAuth Flow
// Redirect: https://app.botpress.cloud/cli-login?redirect=...
// Callback: /auth/callback?pat=bp_pat_...
// Store PAT in cookie and navigate to app
客户端存储模式
// stores/clientsStore.ts
const useClientsStore = create<ClientsState>()((set, get) => ({
APIClients: {},
getAPIClient: (props) => {
const key = props?.botId ? `${props.workspaceId}-${props.botId}` : (props?.workspaceId ?? DEFAULT_API_CLIENT_KEY)
const cached = get().APIClients[key]
if (cached) return cached
const newClient = new APIClient({
apiUrl: API_BASE_URL,
workspaceId: props?.workspaceId,
token: getPat() ?? '',
botId: props?.botId,
})
set((state) => ({
APIClients: { ...state.APIClients, [key]: newClient },
}))
return newClient
},
}))
export const getApiClient = (props?) => useClientsStore.getState().getAPIClient(props)
类型导入模式
// types/index.ts
/// <reference path="../../../bot/.adk/action-types.d.ts" />
/// <reference path="../../../bot/.adk/table-types.d.ts" />
import type { BotActionDefinitions } from '@botpress/runtime/_types/actions'
import type { TableDefinitions } from '@botpress/runtime/_types/tables'
// Create type aliases
export type SendMessageAction = BotActionDefinitions['sendMessage']
export type TicketTableRow = TableDefinitions['TicketsTable']['Output']
操作调用模式
// services/bot-service.ts
export async function sendMessage(input: SendMessageAction['input']) {
const client = getApiClient({ botId, workspaceId })
const result = await client.callAction({
type: 'sendMessage',
input,
})
return result.output as SendMessageAction['output']
}
// Component usage with useMutation
const { mutate: send, isPending } = useMutation({
mutationFn: sendMessage,
onSuccess: () => {
toast.success('Message sent')
queryClient.invalidateQueries({ queryKey: ['messages'] })
},
onError: (error) => {
toast.error('Failed to send message')
},
})
此技能可回答的问题示例
入门问题
- “如何将我的 React 应用连接到 Botpress 机器人?”
- “什么是 Personal Access Token?”
- “在哪里可以找到我的 workspace ID 和 bot ID?”
- “如何安装 @botpress/client?”
身份验证问题
- “应该如何存储身份验证令牌?”
- “如何实现登录/登出?”
- “如何保护需要身份验证的路由?”
- “应该使用 Cookie 还是 localStorage?”
- “如何处理 OAuth 回调?”
类型安全问题
- “如何获取机器人的 TypeScript 类型?”
- “什么是三斜杠引用?”
- “为什么 TypeScript 找不到我的操作类型?”
- “如何保持类型同步?”
- “生成的类型文件在哪里?”
实现问题
- “如何调用机器人操作?”
- “如何从前端查询机器人表?”
- “如何处理加载状态?”
- “如何实现乐观更新?”
- “如何链接多个操作调用?”
高级问题
- “如何在前端使用 Zai?”
- “工作区范围的客户端和机器人范围的客户端有什么区别?”
- “如何实现客户端缓存?”
- “如何处理令牌过期?”
- “如何实现重试逻辑?”
响应格式
回答时:
- 先给出简洁的说明(1-2 个段落)
- 提供参考资料中的可运行代码示例
- 注明文件引用(例如:“来自 authentication.md:60-85”)
- 在相关时强调安全注意事项
- 指出常见陷阱以及避免方法
- 链接到相关主题,供读者深入探索
示例回答结构
Question: "How do I authenticate users in my frontend?"
Answer:
The recommended pattern uses cookie-based PAT storage with OAuth flow.
Here's the complete implementation:
1. Cookie Helpers (authentication.md:89-111)
[code example]
2. AuthContext Setup (authentication.md:64-76)
[code example]
3. OAuth Flow (authentication.md:473-533)
[code example]
Key Security Considerations:
- Use SameSite=Lax for CSRF protection
- Always use HTTPS in production
- Never log PATs to console
- Implement token expiration handling
Related Topics:
- Route protection: authentication.md:369-467
- Profile fetching: authentication.md:304-347
- Client initialization: botpress-client.md:29-51
始终需要引用的关键模式
回答问题时,务必对照文档确认以下模式:
1. 客户端管理
// ✅ CORRECT - Use client store
const client = getApiClient({ workspaceId, botId })
// ❌ WRONG - Create new client every time
const client = new Client({ apiUrl, workspaceId, token, botId })
2. 类型导入
// ✅ CORRECT - Triple-slash at top of file
/// <reference path="../../../bot/.adk/action-types.d.ts" />
import type { BotActionDefinitions } from '@botpress/runtime/_types/actions'
// ❌ WRONG - No triple-slash reference
import type { BotActionDefinitions } from '@botpress/runtime/_types/actions'
3. 操作调用
// ✅ CORRECT - Service layer with types
export async function sendMessage(input: SendMessageAction['input']) {
const client = getApiClient({ botId, workspaceId })
const result = await client.callAction({ type: 'sendMessage', input })
return result.output as SendMessageAction['output']
}
// ❌ WRONG - Direct call in component
const result = await client.callAction({ type: 'sendMessage', input: data })
4. 身份验证存储
// ✅ CORRECT - Cookie with SameSite
document.cookie = `token=${value};expires=${expires};path=/;SameSite=Lax`
// ❌ WRONG - localStorage without security
localStorage.setItem('token', value)
需要强调的最佳实践
回答时,务必提及相关的最佳实践:
安全
- 在生产环境中始终使用 HTTPS
- 使用启用了 SameSite 保护的 Cookie
- 切勿记录 PAT 或令牌
- 实现令牌过期处理
- 尽可能使用 HttpOnly Cookie(SSR)
类型安全
- 始终使用 ADK 生成的类型
- 创建类型别名,让代码更简洁
- 正确使用三斜杠引用
- 使用 adk dev 确保类型保持同步
- 为所有操作输入和输出添加类型
性能
- 使用 Zustand store 缓存客户端
- 无需执行 bot 操作时,使用限定于工作区的客户端
- 实现乐观更新,提升用户体验
- 使用 React Query 管理缓存
- 并行运行相互独立的操作
错误处理
- 始终处理 401(令牌过期)错误
- 在发生错误时向用户提供反馈
- 为暂时性故障实现重试逻辑
- 以恰当方式记录错误(切勿记录令牌)
- 异步操作期间显示加载状态
代码组织
- 使用服务层调用操作
- 将类型集中在单个文件中
- 将身份验证逻辑放在 context 中
- 将客户端配置与使用分开
- 在多个组件间复用服务函数
常见问题排查
请准备好协助解决以下常见问题:
“Cannot find module '@botpress/runtime/_types/actions'”
- 检查三斜杠引用路径
- 确认 .adk/ 目录存在
- 重启 TypeScript 服务器
- 确保已运行 adk dev/build
“修改 bot 后类型未更新”
- 重启 adk dev
- 删除 .adk/ 并重新构建
- 重启 TypeScript 服务器
- 检查 bot 是否存在编译错误
“重新加载后身份验证失败”
- 实现重新加载重试逻辑(authentication.md:191-220)
- 检查 Cookie 是否过期
- 确认令牌是否已正确获取
- 检查是否存在 CORS 问题
“长时间运行的操作导致客户端超时”
- 对 AI 操作使用带有延长超时时间的 getZaiClient()
- 不要对 Zai 操作使用常规客户端
- 考虑将操作拆分为更小的部分
总结
本技能涵盖了 Botpress ADK 前端集成的完整内容:
核心主题:
- 使用 PAT 和 Cookie 进行身份验证
- 使用 Zustand 管理客户端
- 使用三斜杠引用生成和导入类型
- 以完整的类型安全性调用 bot 操作
适用场景:
- 任何前端集成问题
- 身份验证和安全模式
- 类型安全和生成的类型
- 客户端设置和配置
- 操作调用和错误处理
核心原则: 始终提供可用于生产环境的模式,并强调类型安全、安全性和可维护性。
评论
支持 Markdown