@aikaara/chat-sdk (英语)
Aikaara AI代理平台的可嵌入式聊天部件和无头客户端.
安装
npm install @aikaara/chat-sdk
三个入口
| 导入路径 | 使用大小写 |
|---|---|
@aikaara/chat-sdk | 全包:部件+无头+ mount()编号 :unmount() |
@aikaara/chat-sdk/headless | 仅无头:无DOM依赖. 用于反应本地、 自定义 UI、 服务器侧 |
@aikaara/chat-sdk/ui | 仅网络组件 |
快速启动 — 聊天部件( CDN)
<script src="https://cdn.aikaara.com/chat-sdk/latest/aikaara-chat.iife.js"></script>
<script>
AikaaraChat.mount({
baseUrl: 'https://api.aikaara.com',
userToken: 'ut_...',
title: 'Support',
primaryColor: '#6366f1',
});
</script>
快速启动 — 无头客户端
import { AikaaraChatClient } from '@aikaara/chat-sdk/headless';
const client = new AikaaraChatClient({
baseUrl: 'https://api.aikaara.com',
userToken: 'ut_...',
apiKey: 'ak_...',
});
await client.connect();
client.on('message:received', (msg) => console.log(msg.content));
client.on('stream:update', ({ content }) => updateUI(content));
await client.sendMessage('Hello!');
快速启动- 无头与 JWT Auth( Dashboard / 内部 Apps)
import { AikaaraChatClient } from '@aikaara/chat-sdk/headless';
const client = new AikaaraChatClient({
baseUrl: 'https://api.aikaara.com',
userToken: 'ut_...',
authToken: jwtToken, // Bearer token for REST calls
channel: 'sidekick',
});
await client.connect();
App上下文——将代理连接到您的 App
SDK不知道你的应用路线,页面或实体. 您在运行时通过 setContext(),而代理则使用它来导航,编辑表格,并保持对用户所做所为的认识.
为什么这很重要
没有上下文,代理不知道:
- 用户在哪个页面上( W)
/products/42? 吗?/orders? ) (中文(中国大陆) - 您的应用程序中存在什么路径( 这样它就可以导航)
- 用户正在查看的哪个实体( 这样可以编辑正确的表单)
提供路由变化的背景
打电话 setContext() 当用户浏览您的应用程序时:
import { AikaaraChatClient } from '@aikaara/chat-sdk/headless';
const client = new AikaaraChatClient({
baseUrl: 'https://api.aikaara.com',
userToken: 'ut_...',
authToken: jwt,
channel: 'sidekick',
});
await client.connect();
// Call on every route change (e.g., in a React useEffect, Vue watch, etc.)
client.setContext({
currentPage: '/products/42',
entityType: 'product',
entityId: '42',
availableRoutes: {
'Product list': '/products',
'Order list': '/orders',
'Customer list': '/customers',
'Settings': '/settings',
'Analytics': '/analytics',
},
custom: {
formFields: ['name', 'price', 'description', 'category'],
userName: 'Jane',
},
});
兜帽下发生的事
setContext()发送 PATCH 到后端, 将上下文存储在对话元数据中- 后端内插
{{current_page}}, (中文(简体) ),{{available_routes}},以及{{custom_context}}进入代理系统的提示 - 代理现在知道你的应用程序的路线 可以打电话
navigate_to跟他们一起 - 代理商知道当前实体并可以打电话
edit_current_entity给它
AppContext 接口
interface AppContext {
/** Current page/route path in your app (e.g., '/products/42') */
currentPage: string;
/** Entity type on the current page (e.g., 'product', 'order') */
entityType?: string;
/** Entity ID on the current page */
entityId?: string | number;
/** Project/workspace ID if applicable */
projectId?: string | number;
/** Routes the agent can navigate to — map of label to path */
availableRoutes?: Record<string, string>;
/** Any additional context for the agent (form fields, user info, etc.) */
custom?: Record<string, unknown>;
}
处理导航
特工不控制你的路由器——它返回一个路径,你处理它:
client.on('action:navigate', ({ navigate_to }) => {
// Your router (React Router, Vue Router, Next.js, etc.)
router.push(navigate_to);
});
这个 navigate_to 值将成为您从您的路径之一 availableRoutes,或代理人从上下文构造的路径(例如, /products/42) (中文(简体) ).
框架实例
反应( 带有反应路由器)
import { useEffect } from 'react';
import { useLocation, useNavigate } from 'react-router';
function useSidekickContext(client: AikaaraChatClient) {
const location = useLocation();
const navigate = useNavigate();
// Update context on route change
useEffect(() => {
const match = location.pathname.match(/^\/(products|orders|customers)\/(\d+)/);
client.setContext({
currentPage: location.pathname,
entityType: match?.[1],
entityId: match?.[2],
availableRoutes: {
'Products': '/products',
'Orders': '/orders',
'Customers': '/customers',
'Analytics': '/analytics',
},
});
}, [location.pathname]);
// Handle navigation from agent
useEffect(() => {
const off = client.on('action:navigate', ({ navigate_to }) => {
navigate(navigate_to);
});
return off;
}, [navigate]);
}
Vue 3 (带有 Vue 路由器)
import { watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
function useSidekickContext(client: AikaaraChatClient) {
const route = useRoute();
const router = useRouter();
watch(() => route.fullPath, (path) => {
client.setContext({
currentPage: path,
entityType: route.params.type as string,
entityId: route.params.id as string,
availableRoutes: { Products: '/products', Orders: '/orders' },
});
}, { immediate: true });
client.on('action:navigate', ({ navigate_to }) => {
router.push(navigate_to);
});
}
香草联署材料/任何框架
// On route change (however your app detects it)
window.addEventListener('popstate', () => {
client.setContext({ currentPage: window.location.pathname });
});
// On navigation action from agent
client.on('action:navigate', ({ navigate_to }) => {
window.history.pushState(null, '', navigate_to);
// Trigger your app's route handler
});
FormBridge — AI- Driven 格式编辑器
这个 FormBridge 让 AI 代理在应用程序中视像编辑表格。 当代理调用工具 edit_current_entity,桥接会将字段更新推向您注册的表格——用户看到修改的活性,可以确认或拒绝.
如何运作
- 你的经纪人有工具
edit_current_entity, (中文(简体) ),save_current_entity,以及test_tool_by_id - 当代理机调用这些工具时,结果会以 WebSocket 的形式流出
tool_execution_end事件 - SDK的车
AikaaraChatClient解析结果并释放输入的动作事件 FormBridge监听这些事件,并将更新推到您的注册表格
一体化步骤
1. 从SDK进口表框
import { AikaaraChatClient, FormBridge } from '@aikaara/chat-sdk/headless';
2,通过它 你的"爱卡拉"ChatClient
const client = new AikaaraChatClient({
baseUrl: 'https://api.aikaara.com',
userToken: 'ut_...',
authToken: jwtToken,
channel: 'sidekick',
});
const bridge = new FormBridge(client);
await client.connect();
3. 将表格登记在 registerForm()
格式组件挂起时调用 。 一次只有一个表单可以活动(当前页).
bridge.registerForm({
entityType: 'product', // matches what the agent sends
entityId: 42, // the entity being edited
onFieldUpdate: (fields) => {
// Update your form UI — fields is FieldUpdate[]
for (const { field, value } of fields) {
formState[field] = value;
rerenderField(field); // your UI framework's update mechanism
}
},
onSave: async () => {
// Called when the agent triggers save_current_entity
await api.updateProduct(42, formState);
},
onTest: async (params) => {
// Optional: called when the agent triggers test_tool_by_id
await api.testProduct(42, params);
},
getCurrentValues: () => ({ ...formState }),
});
// Unregister when the form unmounts
bridge.unregisterForm('product', 42);
4. 桥梁自动处理工具结果
当代理调用这些后端工具时,桥会自动采取行动:
| 代理工具 | 桥梁行动 |
|---|---|
edit_current_entity | 电话 onFieldUpdate() 字段变化 |
save_current_entity | 电话 onSave() 在注册表格上 |
test_tool_by_id | 电话 onTest() 有参数 |
如果没有登记表格 edit_current_entity 结果到达,桥排队。 当一个匹配的表单随后注册时,队列编辑会被自动应用.
5. 利用桥梁事件建立你自己的确认
bridge.on('edit:applied', ({ entityType, entityId, fields }) => {
// Show a confirmation banner: "AI edited: name, description"
showBanner({
message: `AI edited: ${fields.map(f => f.field).join(', ')}`,
onConfirm: () => dismissBanner(),
onReject: () => {
// Revert fields using previousValue
revertFields(fields);
dismissBanner();
},
onSave: async () => {
await bridge.requestSave();
dismissBanner();
},
});
});
bridge.on('edit:pending', ({ entityType, entityId, fields }) => {
// Edits queued — no matching form registered yet
// Navigate the user to the right page, then the form will pick them up
});
bridge.on('save:success', () => toast.success('Saved by AI'));
bridge.on('save:error', ({ error }) => toast.error(`Save failed: ${error}`));
bridge.on('test:triggered', ({ toolId, parameters }) => {
// Show test UI if needed
});
下层: AikaaraChatClient 上的动作活动
如果你不需要的话 FormBridge 想要自己处理行动:
client.on('action:edit_entity', (action) => {
// action: { entity_type, entity_id, fields: FieldUpdate[] }
});
client.on('action:save_entity', () => {
// Trigger save
});
client.on('action:navigate', ({ navigate_to }) => {
// Route change: e.g., router.push(navigate_to)
});
client.on('action:test_tool', ({ tool_id, parameters }) => {
// Run a tool test
});
// Raw tool lifecycle events
client.on('tool:start', ({ toolName, args }) => showSpinner(toolName));
client.on('tool:end', ({ toolName, result, isError }) => hideSpinner(toolName));
反应钩子示例
import { useEffect, useRef } from 'react';
import type { FormBridge, FieldUpdate } from '@aikaara/chat-sdk/headless';
function useFormBridge(
bridge: FormBridge,
options: {
entityType: string;
entityId: string | number | undefined;
onFieldUpdate: (fields: FieldUpdate[]) => void;
onSave: () => Promise<void>;
onTest?: (params?: Record<string, unknown>) => Promise<void>;
getCurrentValues: () => Record<string, unknown>;
}
) {
const refs = useRef(options);
refs.current = options;
useEffect(() => {
if (!options.entityId) return;
bridge.registerForm({
entityType: options.entityType,
entityId: options.entityId,
onFieldUpdate: (f) => refs.current.onFieldUpdate(f),
onSave: () => refs.current.onSave(),
onTest: refs.current.onTest ? (p) => refs.current.onTest!(p) : undefined,
getCurrentValues: () => refs.current.getCurrentValues(),
});
return () => bridge.unregisterForm(options.entityType, options.entityId!);
}, [bridge, options.entityType, options.entityId]);
}
代理事件
从Aikaara铁路后端通过ActionCable广播的事件:
| 活动 | 说明 |
|---|---|
status | 处理状态(处理/完成) |
message_start/update/end | 流化反应生命周期 |
message_queued | 用户消息已确认 |
tool_execution_start/update/end | 工具调用生命周期 |
agent_start/end | 代理会话生命周期 |
turn_start/end | 对话转出生命周期 |
auto_retry_start/end | 失败时自动重试 |
cancelled | 处理已取消 |
类型脚本
所有类型都从 @aikaara/chat-sdk/headless数字 :
import type {
// Connection
ConnectionConfig, ConnectionState, ChatClientConfig,
// Messages
Message, ToolCall, ToolCallResult,
// Events
AgentEvent, AgentEventType, ChatEvents,
// App Context
AppContext,
// Form Bridge
FieldUpdate, FormRegistration, FormBridgeEvents,
// Actions
EditEntityAction, SaveEntityAction, TestToolAction, NavigateAction, AgentAction,
} from '@aikaara/chat-sdk/headless';
许可证
麻省理工学院