npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@qx-wz/agent-embed-sdk

v0.4.1

Published

Agent Hub Web 嵌入 SDK(无头)— 基于 @ag-ui/client 封装的 /agui/run 通信层

Readme

@qxwz/agent-embed-sdk

Agent Hub Web 嵌入 SDK(无头)— 基于 @ag-ui/client 封装 /agui/web/send 端点。

公司内网使用。提供两种接入方式:<script> 标签 + npm 模块;只负责通信,不带 UI。 核心 API 继承自 @ag-ui/clientHttpAgent,完整支持 AG-UI 协议的消息管理、事件订阅、中断运行等能力。


一、能力概览

  • 标准 AG-UI 协议:继承 @ag-ui/clientHttpAgent,完整 SSE 事件解析
  • 渠道注入:自动把 channelId / embedCode / pageContext / sessionId 注入 POST 请求体
  • 认证注入:同域 SSO Cookie(credentials: 'include')/ 跨域 buc-auth-token Header
  • 页面上下文pageContext 透传到后端 P0.5 RuntimeLayer,支持模板替换
  • 双产物:UMD(<script> 即用,含 rxjs+zod 自包含)+ ESM/CJS(npm 引入,@ag-ui/client 为 peer dep)
  • 自动初始化:UMD 模式下通过 data-* 属性零代码接入
  • 完整类型:TypeScript 类型定义 + 重新导出 @ag-ui/core 事件类型

二、安装

方式 A:npm 模块(推荐)

pnpm add @qxwz/agent-embed-sdk

@ag-ui/client@ag-ui/core 作为依赖自动安装。

import { AgentEmbedClient } from '@qxwz/agent-embed-sdk';

const client = new AgentEmbedClient({
  baseUrl: 'https://agent-hub.intra.example.com',
  channelId: 1,
  embedCode: 'oa-pending',
});

方式 B:<script> 标签(无需构建工具)

<script src="https://your-cdn/agent-embed.umd.js"
        data-agent-embed
        data-base-url="https://agent-hub.intra.example.com"
        data-channel-id="1"
        data-embed-code="oa-pending"
        data-debug="true"></script>

加载完成后:

  • window.AgentEmbed.AgentEmbedClient — 客户端类
  • window.AgentEmbed.instance — 用 data-* 配置自动创建的默认实例
  • agent-embed:ready 事件 — 实例就绪通知

三、配置项

| 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | baseUrl | string | ✅ | 后端地址,例如 https://agent-hub.intra.example.com | | channelId | number | ✅ | 渠道 ID(数据库 agt_channel.id) | | embedCode | string | ✅ | 嵌入码(数据库 agt_channel_binding.source_id) | | authToken | string | 否 | 跨域用 buc-auth-token;同域走 SSO Cookie 可省略 | | aguiPathPrefix | string | 否 | AG-UI 端点前缀,默认 /api/agent-hub/agui | | debug | boolean | 否 | 打开调试日志 |

<script> 方式对应 data-* 属性:data-base-url / data-channel-id / data-embed-code / data-auth-token / data-agui-path-prefix / data-debug


四、API

继承自 @ag-ui/client 的标准 API

AgentEmbedClient 继承 HttpAgentAbstractAgent,完整支持:

| 方法/属性 | 说明 | |-----------|------| | client.messages | 当前消息列表(含 user + assistant) | | client.threadId | 当前线程 ID | | client.isRunning | 是否正在运行 | | client.addMessage(msg) | 添加消息到列表 | | client.runAgent(params?, subscriber?) | 运行 Agent,返回 Promise<RunAgentResult> | | client.subscribe(subscriber) | 订阅事件回调,返回 { unsubscribe } | | client.abortRun() | 中断当前运行 | | client.use(...middlewares) | 添加中间件 |

SDK 扩展 API

| 方法 | 说明 | |------|------| | client.setPageContext(ctx) | 设置默认页面上下文 | | client.chat(content, pageContext?) | 便捷方法:添加用户消息 + 运行 Agent | | init(config) | 模块级便捷工厂函数 |

subscribe 回调(AgentSubscriber)

client.subscribe({
  onRunStartedEvent: ({ event }) => { /* RUN_STARTED */ },
  onTextMessageStartEvent: ({ event }) => { /* TEXT_MESSAGE_START */ },
  onTextMessageContentEvent: ({ event, textMessageBuffer }) => {
    // event.delta = 文本增量
    // textMessageBuffer = 当前消息已累积的完整文本
  },
  onTextMessageEndEvent: ({ event, textMessageBuffer }) => {
    // textMessageBuffer = 本条消息的完整文本
  },
  onToolCallStartEvent: ({ event }) => { /* TOOL_CALL_START */ },
  onToolCallArgsEvent: ({ event, toolCallName, toolCallBuffer }) => {
    // event.args = 工具参数增量
  },
  onToolCallEndEvent: ({ event, toolCallName, toolCallArgs }) => {
    // toolCallArgs = 完整参数对象
  },
  onRunFinishedEvent: ({ event }) => { /* RUN_FINISHED */ },
  onRunErrorEvent: ({ event }) => {
    // event.message / event.code
  },
  onMessagesChanged: ({ messages }) => {
    // 消息列表变化时触发
  },
});

五、完整示例

5.1 npm 模块 — chat() 便捷方法

import { AgentEmbedClient } from '@qxwz/agent-embed-sdk';

const client = new AgentEmbedClient({
  baseUrl: 'https://agent-hub.intra.example.com',
  channelId: 1,
  embedCode: 'oa-pending',
  debug: true,
});

// 设置默认页面上下文
client.setPageContext({
  pageUrl: location.pathname,
  module: 'oa',
  objectIds: ['user-123'],
});

// 一行发送 + 运行
const newMessages = await client.chat('帮我查一下今天的待办');
console.log('助手回复:', newMessages);

5.2 npm 模块 — subscribe 流式回调

import { AgentEmbedClient } from '@qxwz/agent-embed-sdk';

const client = new AgentEmbedClient({
  baseUrl: 'https://agent-hub.intra.example.com',
  channelId: 1,
  embedCode: 'oa-pending',
});

// 订阅流式事件
client.subscribe({
  onTextMessageContentEvent: ({ event, textMessageBuffer }) => {
    process.stdout.write(event.delta); // 流式输出
  },
  onToolCallEndEvent: ({ toolCallName, toolCallArgs }) => {
    console.log('工具调用:', toolCallName, toolCallArgs);
  },
  onRunFinishedEvent: ({ event }) => {
    console.log('运行结束', event.threadId, event.runId);
  },
  onRunErrorEvent: ({ event }) => {
    if (event.code === 'UNAUTHORIZED') location.href = '/login';
    else console.error('运行错误:', event.message);
  },
});

// 添加消息并运行
client.addMessage({ id: 'msg-1', role: 'user', content: '你好' });
await client.runAgent();
console.log('完整消息列表:', client.messages);

5.3 npm 模块 — 带 pageContext 的运行

// 单次运行传入 pageContext(覆盖默认值)
const result = await client.runAgent({
  forwardedProps: {
    pageContext: {
      pageUrl: '/srm/contract/detail',
      module: 'srm',
      objectIds: ['contract-456'],
    },
  },
});

5.4 <script> 自动初始化

<!DOCTYPE html>
<html>
<head>
  <script src="/static/agent-embed.umd.js"
          data-agent-embed
          data-base-url="https://agent-hub.intra.example.com"
          data-channel-id="1"
          data-embed-code="oa-pending"></script>
</head>
<body>
  <button id="ask">问我</button>
  <pre id="out"></pre>

  <script>
    window.addEventListener('agent-embed:ready', ({ detail }) => {
      const client = detail.client;

      // 订阅流式文本
      client.subscribe({
        onTextMessageContentEvent: ({ event }) => {
          document.getElementById('out').textContent += event.delta;
        },
        onRunErrorEvent: ({ event }) => {
          alert('出错: ' + event.message);
        },
      });

      document.getElementById('ask').onclick = async () => {
        document.getElementById('out').textContent = '';
        client.addMessage({ id: 'msg-' + Date.now(), role: 'user', content: '帮我看下今天的代办' });
        await client.runAgent();
      };
    });
  </script>
</body>
</html>

5.5 <script> 手动初始化(不用 data-*

<script src="/static/agent-embed.umd.js"></script>
<script>
  const { AgentEmbedClient } = window.AgentEmbed;
  const client = new AgentEmbedClient({
    baseUrl: 'https://agent-hub.intra.example.com',
    channelId: 1,
    embedCode: 'oa-pending',
  });
  // ...同上
</script>

5.6 React 中接入

import { useEffect, useRef, useState } from 'react';
import { AgentEmbedClient } from '@qxwz/agent-embed-sdk';

export function useAgent(config: ConstructorParameters<typeof AgentEmbedClient>[0]) {
  const clientRef = useRef<AgentEmbedClient>();
  if (!clientRef.current) {
    clientRef.current = new AgentEmbedClient(config);
  }
  return clientRef.current;
}

export function Chat() {
  const client = useAgent({
    baseUrl: 'https://agent-hub.intra.example.com',
    channelId: 1,
    embedCode: 'oa-pending',
  });
  const [text, setText] = useState('');

  useEffect(() => {
    const sub = client.subscribe({
      onTextMessageContentEvent: ({ event }) => setText((t) => t + event.delta),
      onRunFinishedEvent: () => setText(client.messages.filter(m => m.role === 'assistant').pop()?.content || ''),
    });
    return () => sub.unsubscribe();
  }, [client]);

  const send = (prompt: string) => {
    setText('');
    client.addMessage({ id: 'msg-' + Date.now(), role: 'user', content: prompt });
    client.runAgent();
  };

  return (
    <div>
      <pre>{text}</pre>
      <button onClick={() => send('你好')}>发送</button>
      <button onClick={() => client.abortRun()}>取消</button>
    </div>
  );
}

六、错误码

AgentEmbedError.code

| code | 含义 | |------|------| | CONFIG_ERROR | 初始化配置缺失或格式错误 | | UNAUTHORIZED | 认证失败(401 / RUN_ERROR code=UNAUTHORIZED) | | RUN_ERROR | 后端发出 RUN_ERROR 事件(业务错误) | | ABORTED | 调用方主动 abortRun() |

@ag-ui/clientrunAgent() 内部遇到 HTTP 错误会抛出标准 Error,可通过 try/catch 捕获。


七、与后端约定

  • 端点:POST {baseUrl}{aguiPathPrefix}/agui/web/send
  • 请求体(JSON):{ channelId, embedCode, content, sessionId?, pageContext? }
  • SDK 自动将 RunAgentInput.messages 中最后一条 user 消息提取为 content
  • 响应:text/event-stream,事件序列按 AG-UI 协议
  • 认证:
    • 同域:浏览器自动带 BUC SSO Cookie(credentials: 'include'
    • 跨域:传 authToken → SDK 自动加 buc-auth-token Header
  • 401 处理:后端 AG-UI 端点认证失败时输出 RUN_STARTED → RUN_ERROR(code=UNAUTHORIZED) 事件流

八、构建 / 发布

pnpm install
pnpm typecheck        # 类型检查
pnpm build:lib        # 构建 ESM + CJS(@ag-ui/client 为外部依赖)
pnpm build:umd        # 构建 UMD(@ag-ui/client + rxjs + zod 全部打包,自包含)
pnpm build:types      # 生成 .d.ts
pnpm build            # 上述全部

产物:

  • dist/agent-embed.es.js — ESM(npm import,~4KB)
  • dist/agent-embed.cjs.js — CJS(require,~4KB)
  • dist/agent-embed.umd.js — UMD(<script>,~199KB 含 rxjs+zod 自包含,带 auto-init,已压缩)
  • dist/*.d.ts — TypeScript 类型

九、版本

当前版本:0.2.0(基于 @ag-ui/client,走 /agui/web/send 端点)。

变更:

  • 0.2.0 — 基于 @ag-ui/clientHttpAgent 重构,覆写 requestInit() 将 RunAgentInput 转换为 WebChatRequest,走 /agui/web/send 端点;SSE 解析复用 @ag-ui/client 内置能力
  • 0.1.0 — 初始版本,自建 fetch+SSE 解析,使用 /agui/web/send 端点