@alexkroman1/aai-ui

中文文档
0.18.2发布于 2026/10/30MITTypeScriptES Module构建来源已验证近 30 天下载 1741

Assembly Agent SDK代理的浏览器客户端:在框架-不可知会会话核心(WebSocket + 麦克风 + 播放回放)上反射出19个钩子和组件.

中文使用文档
文档目录9 节
  1. UI 整合
  2. 探员 agent.ts
  3. 工具 tools/get_quote.ts
  4. 工具的 UI 组件 quote-card.tsx
  5. 客户端 client.tsx
  6. 一个工作流程应用程序
  7. 包裹里有什么
  8. 其他子路径
  9. 文档

@alexkroman1/aai-ui (英语)

用于 Assembly SDK 代理的浏览器客户端: 反应 19 个钩和 框架不可知会话核心的组件(WebSocket + 麦克风+) (原始内容存档于2017-03-25). play back).

npm i @alexkroman1/aai-ui react react-dom

每个特工都免费拿到UI.. aai dev 和部署的特工 默认客户端从此软件包中构建 。 代理时直接安装 其本身 client.tsx。 。 。 .

UI 整合

这里的钩子是一页 读到一个代理: 活电话,状态 代理项目,工具在运行时调用,以及它开始的持久运行. 没有路可写. 代理服务器已经为会话服务 套接字和工作流程 HTTP API, 所以组件对一个没有 介于两者之间的粘结文件 — 客户端是一个 client.tsx 呼叫一个山.

两道正门 二道山. 一个语音代理的页面呼叫 mountClient() 财务报告和审定财务报表 和现场谈话 一个工作流程应用程序的页面( A)workflowApp(),或 agent({ mode: "workflow-app" })(电话) mountPage() 与工作流程交谈 HTTP API — 没有会话, 没有插座, 没有麦克风 。 都还在 client.tsx, (中文(简体) ), 仍为回放,仍为同名主题符号.

探员 agent.ts

会话状态处于一个档位,一个档位宣布 sync: true 这是什么 浏览器所看见的 —— 在每个工具调用后按下, 所以客户端永远不会重建它 来自事件 :

import { agent, sessionSlot } from "@alexkroman1/aai";

const desk = sessionSlot("desk", () => ({ symbols: [] as string[] }), {
  view: (state) => ({ symbols: state.symbols }),
  sync: true,
});

// The `sync: true` slot is collected; the prompt is the system-prompt.md beside this file.
export default agent({ name: "Market Desk" });

工具 tools/get_quote.ts

一个工具是 文件,用它自己的文件名命名。 没有登记 agent() 采取不 tools 字段 :

import { tool } from "@alexkroman1/aai";
import { z } from "zod";

export default tool({
  description: "Look up the latest price for one ticker symbol",
  inputSchema: z.object({ symbol: z.string() }),
  execute: async ({ symbol }, ctx) => {
    const res = await fetch(`https://api.example.com/quote/${symbol}`, {
      headers: { authorization: `Bearer ${ctx.env.QUOTES_API_KEY}` },
      signal: ctx.signal,
    });
    return (await res.json()) as { symbol: string; price: number };
  },
});

工具的 UI 组件 quote-card.tsx

useToolResult 每个定点调用一个命名工具时一次起火,结果 已解析 。 迟到的部分仍然收到通话结果 ——结果是一种UI驱动的值,而不是a 秒数 :

import { useState } from "react";
import { useToolResult } from "@alexkroman1/aai-ui";

type Quote = { symbol: string; price: number };

export default function QuoteCard() {
  const [quote, setQuote] = useState<Quote>();
  useToolResult<Quote>("get_quote", (result) => setQuote(result));

  if (!quote) return null;
  return (
    <p>
      {quote.symbol} — {quote.price.toFixed(2)}
    </p>
  );
}

useToolCallStart 对电话的另一端是同一个钩子——待发 引用及其论点,为一个旋转者而不是一个价值。 一个 以工具本身的形状作为类型参数,由工具模块导出 只类型 导入被擦除后将服务器代码拖入捆绑中 : useToolResult<InferToolOutput<typeof getQuote>>(…) 因此, useToolCallStart<InferToolInput<typeof getQuote>>(…) 用来辩论.

客户端 client.tsx

mountClient() 挂载默认聊天 shell — 启动屏幕、 记录, 控制器 里面有你的组件. sidebar 拿走组件,不是 元素 :

import "@alexkroman1/aai-ui/styles.css";
import { mountClient, useAgentState } from "@alexkroman1/aai-ui";
import QuoteCard from "./quote-card.tsx";

function Watchlist() {
  // The `desk` slot `syncState` projected, live. Null until the first push,
  // which is a moment the UI has to render.
  const desk = useAgentState<{ symbols: string[] }>("desk");
  return (
    <div>
      <QuoteCard />
      {desk?.symbols.map((symbol) => <div key={symbol}>{symbol}</div>)}
    </div>
  );
}

mountClient({
  name: "Market Desk",
  sidebar: Watchlist,
  // Icon and label per tool, for the transcript's tool rows.
  tools: { get_quote: { icon: "📈", label: "Fetching quote" } },
  theme: { primary: "#2f9e44" },
});

上面的类型参数重现了代理已知道的形状 。 移动槽 并投射为a shared.ts 两端导入, 通过投影 本身 - useAgentState(deskProjection) - 州从 投影和它产生的前先推框架,所以没有什么 重复,没有分支 对于第一个渲染.

过 component 改为 sidebar 替换整个外壳。 它让 在同一个供应商内部, 所以这里的每一个钩 工作不变.

一个工作流程应用程序

mountPage() 将窗体挂载在代理工作流程上,并安装无会话. <WorkflowFields> 使工作流程的每个平面属性有一个控制 输入 schema, 因此在 schema 中添加一个字段, 在页面中添加 :

import "@alexkroman1/aai-ui/styles.css";
import {
  Form,
  mountPage,
  SubmitButton,
  UploadProgressBar,
  useWorkflowSubmit,
  WorkflowFields,
  WorkflowProgress,
} from "@alexkroman1/aai-ui";

function App() {
  const { submitForm, run, pending, upload, error } =
    useWorkflowSubmit("digest");
  return (
    <main className="mx-auto flex max-w-2xl flex-col gap-6 p-8">
      <Form onSubmit={submitForm} error={error}>
        <WorkflowFields workflow="digest" />
        <SubmitButton pending={pending}>Summarize</SubmitButton>
      </Form>
      {/* The upload is its own wait: the run does not exist until the bytes
          are in, so nothing else on the page can describe it. */}
      <UploadProgressBar upload={upload} />
      {/* What the run has SAID, from `stepReport()` in its steps. */}
      <WorkflowProgress runId={run?.runId} />
      {run?.status === "completed" && <pre>{JSON.stringify(run.output)}</pre>}
    </main>
  );
}

mountPage({ name: "Digest", component: App });

将工作流程命名为 def —— useWorkflowSubmit<typeof digest>("digest")关闭 a 只类型 进口 agent.ts - 这才是 submit() 带所申报的 输入和 run.status === "completed" 缩小为已键入 run.output编辑 导入已被删除, 因此它不会将服务器代码拖入捆绑中 .

包裹里有什么

这个 API 参考 按类型编组 有点 这是同样的表面 组合它是什么.

挂载 —— 说 mountClient(), (中文(简体) ), mountPage(),每个配置和 处理每个返回( e)ClientConfig, (中文(简体) ), ClientHandle, (中文(简体) ), PageConfig, (中文(简体) ), PageHandle) (中文(简体) ). fetchClientConfig() {\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}看经纪人的申报 name编号 :greeting 在页面上 mountClient() 是为了自己.

现场通话 —— 说 useSession() 整个快照加上控件 (单位:千美元)start, (中文(简体) ), toggle, (中文(简体) ), cancel, (中文(简体) ), reset, (中文(简体) ), resetState, (中文(简体) ), restart, (中文(简体) ), disconnect, (中文(简体) ), end(三); useSessionSelector() 一个切片,用 useSessionStatus(), (中文(简体) ), useSessionError() 财务报告和审定财务报表 useSessionActions() 因为狭义读取了一个习惯 铬重复; useUserTranscript() {\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}因为呼叫者正在转弯 保留 null (沉闷)和 "" (口出相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相相相相去相相去相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相; useConversation() 连结的笔录都没有. createBrowserSession() 与普通商店相同,每起变化都有不可改变的快照 非反应客户端. SessionSnapshot, (中文(简体) ), AgentState, (中文(简体) ), ChatMessage, (中文(简体) ), ToolCallInfo, (中文(简体) ), SessionError 财务报告和审定财务报表 SessionErrorCode 带着它.

经纪人推着什么 —— 说 useAgentState(slot.projected) (该插槽的条目) 在经纪人的 syncState· ; selectAgentState(slot) 页:1 useSessionSelector, (中文(简体) ), useToolResult() 编号 : useToolCallStart() (工具唤作跑道) useEvent() (来自 ctx.send,在新代码中更喜欢的 在阅读工具结果之后).

聊天铬 —— 说 ChatView 整个地表; ConsoleShell, (中文(简体) ), MessageList, (中文(简体) ), Controls, (中文(简体) ), Markdown, (中文(简体) ), ToolCallRow, (中文(简体) ), SessionErrorBanner, (中文(简体) ), StartScreen, (中文(简体) ), SidebarLayout, (中文(简体) ), AutoScroll, (中文(简体) ), BulletList, (中文(简体) ), Facts 财务报告和审定财务报表 Button 是它的部件,出口到一个定制的铬再利用它们而不是近似 他们. AutoScroll 这是直接接触的:这是唯一的 在这里滚动连接执行,它需要一个 边界高度。 。 。 . AGENT_STATE_LABELS 财务报告和审定财务报表 WORKFLOW_STATUS_LABELS 是默认状态的单词, 所以一个铬 超过一个词 它有一个更好的词.

表单 —— 说 Form 提交时从 DOM 中收集输入的值. Field, (中文(简体) ), TextField, (中文(简体) ), NumberField, (中文(简体) ), TextAreaField, (中文(简体) ), SelectField, (中文(简体) ), CheckboxField, (中文(简体) ), FileField 财务报告和审定财务报表 SubmitButton 是控件; WorkflowFields 生成它们 从一个计划。 一个平地 <input name="x"> 一样的工作.

工作流量 —— 说 createWorkflowApi() 是客户端; useWorkflowSubmit() 编号 : useWorkflowStream() 开始看它, useWorkflowRun() (观看一个 页:1, useWorkflowRuns() (历史), useWorkflowProgress() (跑步有什麽事) 写作, useWorkflows() (清单), useDownloadUrl() (上传运行) 作为DOM元素接受的URL生产, useRunKey() (存储后键) (a) 提交材料由收回). <WorkflowProgress> 财务报告和审定财务报表 <UploadProgressBar> 即所化为二分之一. WorkflowRun, (中文(简体) ), WorkflowSummary, (中文(简体) ), WorkflowInputOf, (中文(简体) ), WorkflowOutputOf 财务报告和审定财务报表 isTerminal() 是词汇.

主题 —— 说 useTheme() 财务报告和审定财务报表 ClientTheme。 。 。 .

其他子路径

根导出是整个客户端 API. 两条子道都坐在旁边,两个都没有 他们的东西 client.tsx 达到:

子路径找到它的时候
/client-dir从节点服务预建的默认客户端 - defaultClientDir(),文件系统路径 createServerForRuntime({ clientDir }) 想要吗
/internal从来没有,从应用程序代码:管道 mountClient() 为自己安装(会话和主题提供者,默认 shell 的 URL 芯片,工具配置上下文,预连接查询). 不是公共的API,不是Semver覆盖

文档

完整 API 参考 : https://alexkroman.github.io/ agent/ 页面存档备份,存于互联网档案馆

版本与发布记录

@alexkroman1/aai-ui 共发布 138 个版本,首次发布于 2026/03/25;过去 12 个月发布了 138 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.18.2latest2026/10/3010 天前
0.18.12026/10/3011 天前
0.18.02026/10/2911 天前
0.17.02026/10/2317 天前
0.16.02026/10/2318 天前
0.15.52026/10/1525 天前

关于 @alexkroman1/aai-ui 的常见问题

@alexkroman1/aai-ui 是什么?

Assembly Agent SDK代理的浏览器客户端:在框架-不可知会会话核心(WebSocket + 麦克风 + 播放回放)上反射出19个钩子和组件.

如何安装 @alexkroman1/aai-ui?

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

@alexkroman1/aai-ui 支持 TypeScript 吗?

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

@alexkroman1/aai-ui 支持 ESM 还是 CommonJS?

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

@alexkroman1/aai-ui 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=24。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@alexkroman1/aai-ui 可以商用吗?

@alexkroman1/aai-ui 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@alexkroman1/aai-ui 的下载量有多少?

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

@alexkroman1/aai-ui 还在维护吗?

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