@aintela/聊天
在 WebSocket 代理网关上建起可嵌入的 AI 聊天组件 。 此还原
是一个独立的家 对于以前
packages/library/src/components/AiChat/ 内 envision-abi ——被提取入a
真实库( 已建立、 版本化、 等同dep'd) , 而不是树上源别名,
并向公众npm登记机构公布.
名称历史 :
@envision/aichat→@aia/chat→@aintela/chat(单位:千美元) 无@aia狼人被带走了)。 总是安装和导入@aintela/chat。 。 。 .
版式
此 repo 是已发布的软件包( Name@aintela/chat其根源:
src/, (中文(简体) ),package.json, (中文(简体) ),vite.config.ts, (中文(简体) ),tsconfig.json——库来源+配置dist/- 已建成产出,已安装; 在 npm 沥青球中运输 (建造在prepack编号 :prepare通过vite build(中文(简体) )examples/demo/– Vite + React SPA 用于对假的库进行练习 代理网关, 可选择指向真正的 WSServer
开发
npm install
cd examples/demo && npm install && npm run dev # http://localhost:5174
在没有服务器的情况下预览幽灵. 平坦的情景过去 promptGhostDebugKey="|"
(单位:千美元) AiChat 编号 : AiChatProvider 道具,只开发:打字 | 在作曲家被吞并 并画
@ … 隐蔽处的幽灵——第一报刊上的位置,下一报刊上的人——从该报刊上发现的中期判决
caret,所以中刑卡可以通过将cet放入句子来查看. 塔布接受 Esc 开除,
而下一个键盘分析 澄清它,因为它会是一个真正的。 将道具放在生产中.
演示别名包到根 src/ 在开发过程中,HMR工作
跨越软件包边界。 以真实的方式验证构建的捆绑
消费者将:
npm run build
# then remove the alias in examples/demo/vite.config.ts (or use npm link)
消费
@aintela/chat 已公布 公共npm登记 - 安装它像
任何包并标出一个正常的 semver 范围:
npm install @aintela/chat
{
"dependencies": {
"@aintela/chat": "^0.2.16"
}
}
预造的柏油丸 dist/ (见《大会正式记录,第五十八届会议,补编第6号》) files 输入 package.json, (中文(简体) ),
消费者不会在安装上制造任何东西.
为重点进口品出口亚道出入口: @aintela/chat (基层),
加号 @aintela/chat/models, (中文(简体) ), /services, (中文(简体) ), /components, (中文(简体) ), /hooks, (中文(简体) ), /utils, (中文(简体) ),
/interfaces样式表 @aintela/chat/style.css。 。 。 .
每个同行 peerDependencies 消费者必须安装在
相容版本——这就是共享单子(React,MUI主题Context,
苏斯坦德商店, reflect-metadata'被补丁的反射, Notistack' s
Snackbar Provider)最终成为每个应用程序完全一个实例而不是两个实例.
UI 工具代码源( U)aia-gen-uitools(中文(简体) )
包裹装了个垃圾桶, aia-gen-uitools,使服务器的UI工具显示(JSON)
由Sdk探员写作 UiToolsManifest.PublishManifest(...)键入类型脚本 :
uiContracts.generated.ts (每个工具的参数/输入/回答/结果接口)和
aiaUiTools.generated.ts (一个打入的登记册建立器,每个工具有一个方法——询问用户和渲染——)
)),每个绑入其生成的接口. 一个消费者应用软件将 ONE npm 脚本串连在服务器上
显示导出和生成 :
"gen:uitools": "dotnet run --project ../path/to/Server.UiToolsManifest -- src/agent/generated/uitools.manifest.json && aia-gen-uitools src/agent/generated/uitools.manifest.json src/agent/generated"
每个 C#合同成为了One接口,以自有名. 清单载有每个物体的C#
类型名称为 JSON-Schema title (单位:千美元)UiToolsManifest 发电机将各升起
类型进入 $defs 并且从嵌入它的每个有效载荷中引用它 RescheduleQuoteCardArgs
获得 replacing?: RescheduleQuoteFlight[],以及 RescheduleQuoteFlight 被宣布一次,但数量多
工具携带一个.
这很重要,因为它取代了。 JSON Schema没有记录子对象来的类型
从,所以一个被嵌入的类型只能以其位置命名——以及每个阵列元素的位置
是关键 items。每个工具中的每个嵌入式列表都因此作为一个称为 Items, (中文(简体) ),
而声称姓名的第二个形状则被放弃,而第一个形状却只有一个警告:a
重排引用的飞行类型 检查为支出报告线, tsc 已接受 expenseId 在飞机上,
没有失败 两个不同的形状,现在一个名字 停止运行 写什么,
命名两者。 由旧服务器发布的列表没有标题;然后生成器命名 a
在其拥有者之后竖起的元素(RescheduleQuoteCardArgsReplacingItem而不是之后 items —— 说
正确的,丑陋的, 和迅速重写 清单.
TurnAwareButton ——在聊天信息中绘制控制
提供了UI工具组件 当代理仍然在流 轮到 联合国
present_tripstretch 卡片出现中刑,然后在它上演比赛
仍在给会议写信。 使用 TurnAwareButton 而不是MUI的电影 Button
用于聊天器中的任何控件: 当回合打开时
已禁用 旋转。旋转器是重点——有人在中转时点击一张牌
通常没有注意到代理正在写,所以按钮都拒绝
点击并显示原因,而不是坐在那里 死寂.
import { TurnAwareButton } from '@aintela/chat';
// Return the promise so the button keeps waiting across the gap between sending and
// the server's `open_turn` — otherwise it briefly offers itself for a second click.
<TurnAwareButton variant="contained" onClick={() => sendMessage('escolhi a opção 2')}>
selecionar ida
</TurnAwareButton>
外面一个 <AiChat> 提供商没有转弯,所以它的行为就像 Button —— 说
聊天和纯页之间共享的组件不需要分行。 同样的活
旗帜可以自行使用,因为 useTurnOpen()
(更喜欢它) UiToolContext.onGoing,即地表快照: false
永远挂在一张已经落成历史的名片上,即使后来的转折流也如此.
转过这个分页没有发送,一个解开的运行作为记录(AIA Issue 1548)
服务器每转一转就宣布 InteractionStarted 在它的第一个三角洲之前 A 类
打开此标签未发送—— WhatsApp 消息, 任务解决后的平台转接, 另一个
选项卡的转动——以其文字作为用户的发泡和小的发源地徽章("WhatsApp","WhatsApp")打开,
"Plataforma","API";将单词以 interactionOriginLabels) (中文(简体) ). 永远不要
本地转弯位置仍在流出中, 也没有打开 作曲者为
其它部分。 历史重载从会话读取相同来源(InteractionOriginContent) (中文(简体) ).
DetachedRunTranscript 绘制一个只读聊天的解开运行——相同的引擎和
ChatPane,由运行的帧流提供(GET /detached-runs/{id}/frames,SSE读取
fetch 因为路由需要一个载人:
import { DetachedRunTranscript } from '@aintela/chat';
<DetachedRunTranscript
runId={runId}
baseUrl={agentsServerUrl}
fetchImpl={authenticatedFetch} // or getToken={() => token}; default: user.access_token
getUser={readLiveUser} // whose token reads the run's artifacts
uiTools={uiTools} // any <AiChat> presentation prop passes through
onUnauthorized={refreshToken} // on a 401: refresh, resolve true ⇒ one retry with the fresh token
onError={(e) => setStopped(e.kind)} // 'notFound' | 'forbidden' | 'unauthorized' | 'gaveUp'
resumeKey={answersSent} // change it after answering: the stream ends when the run stops
footer={<AnswerComposer runId={runId} />}
/>
DetachedRunTaskBox 投票记录(真相来源) baseUrl + 键
fetchImpl编号 :getToken,在等待/运行时遵循框架:单行活性计
和任务列表,在代理更新时移动它。 "活生生地"会让跑步的
DetachedRunTranscript 内入( n)uiTools 编号 : partRenderers 通过). onSettled(run) 火灾
一旦每个和解,谈话没有被告知(run.announced === false); 以
engine.announceDetachedRun(run.id, run.settledAt),它发送 AnnounceDetachedRun 套接字
动作——在此分页打开转弯时举行, 解开每个结算, 以及服务器的公告
以平凡的方式到达 platform 转.
拥有自己的宿主 <AiChat> 包装器取下引擎
const { engine } = useDetachedRunTranscript({ runId, baseUrl, … }),则
<MyScopedAiChat engine={engine}><ChatPane /></MyScopedAiChat> 与 hidePromptInput编辑
读者自己是 streamDetachedRunFrames(…) (服务).
构成部分名称(破解于0.3.0)
每个 v2 组件在其下导出 普通名称 —— 说 AppBar, (中文(简体) ), Prompt, (中文(简体) ),
TaskList, (中文(简体) ), RunProgressStrip - 并再次在历史上 …V2 名称为
化名,所以没有现有的导入间断。 更取平平名相.
后缀的存在是为了将它们与已不存在的v1层相分离:
最后四个v1组件(Prompt, (中文(简体) ), LastPrompts, (中文(简体) ), TaskList, (中文(简体) ), DetachedRunBox曾经
在确认没有消耗后删除
AiChatFloating 执行合并为一个。 和他们一起走了
选择 v1 渲染器的道具—— compactPrompt, (中文(简体) ), showTaskList
财务报告和审定财务报表 showDetachedRuns。提示总是紧凑的;任务列表
在运行进展面板上运行.
1个发动机,1个代理(0.3.0)
这个 AgentContext ——哪个代理人的答案——属于 引擎,没有结果
还有 引擎和网关的邮票都供应了一次
AgentId 从它的每一帧。 在0.3.0之前,三种不同的公共投入接受了a
同一个对话的背景 只有其中一人决定什么 所以表面
可以捆绑、盖章和通过 expense-agent 到处转来转去
程序默认代理, 没有失败 .
// One hook per agent. The registry key is DERIVED from the agent, so "same key,
// different agent" cannot be expressed.
export const useExpenseChatEngine = () => useAgentEngine(expenseConfig()); // key: 'expense-agent'
const { engine } = useExpenseChatEngine();
await engine.openLiveSession(sessionId); // no context to pass, so none to get wrong
<AiChat engine={engine} /> // adopting: `agentContext` is a compile error here
<AiChat agentContext={ctx} … /> // building its own engine: the one place it belongs
过 useAgentEngine(config, { scope }) 两人 独立 与
不变 探员 在现场谈话中调换特工
engine.forceAgentContext(ctx) - 故意丑陋,因为会议已经举行
另一个代理商的历史和服务器邮票 Session.AgentId 在第一个转弯的时候,
所以谈话中不断报告它开始的经纪人 最好换个引擎.
常规的,非身份的改变有简单的设置: setCustomer, (中文(简体) ), setModel。 。 。 .
从0.2.x的迁移——每次移除都是呼叫站点的编译错误,按设计:
| 0.2.x (中文(简体) ) | 0.3.0 (中文(简体) ) |
|---|---|
useLiveSession(config, { key }) | useAgentEngine(config, { scope }) - 放下钥匙 |
<AiChat engine={e} agentContext={ctx} /> | <AiChat engine={e} /> |
engine.openLiveSession(ctx, id) | engine.openLiveSession(id) |
mgr.bindAndOpenLiveSession(ctx, id, opts) | mgr.bindAndOpenLiveSession(id, opts) |
mgr.createSession(ctx, id) 编号 : mgr.retrieveSession(ctx, id) | mgr.createSession(id) 编号 : mgr.retrieveSession(id) |
gateway.setAgentContext(ctx) 编号 : engine.setAgentContext(ctx) | forceAgentContext(ctx) ——大多数主机都不呼叫 |
| —— 说 | 新建 : engine.getAgentContext(), (中文(简体) ), engine.setCustomer(), (中文(简体) ), engineKeyFor() |
测试
Vitest运行单元+集成套房. 共用地点 *.test.ts 文件
住在他们覆盖的源头旁边; 共享固定装置+假物生活在下面
tests/ 并且通过 @tests/* 路径别名.
默认环境是 node;需要一个 DOM 的测试,每个文件选择一个
// @vitest-environment happy-dom pragma (参见 TurnAwareButton.test.tsx) (中文(简体) ).
npm test # one-shot run
npm run test:watch # watch mode
npm run test:coverage # generates coverage/ (html + lcov + json-summary)
两个假人坐在不同的深处 挑错一个是通常的原因 测试无法证明:
tests/fakes/makeGateway.ts+ 键fakeWebSocket.ts替换整个IWebSocketConnection当测试中的代码是 网关 或上面的任何东西 他们让你deliver()直接解析服务器事件.tests/fakes/fakeRawWebSocket.ts替换 浏览器WebSocket全球, (中文(简体) ), 低一层。 当测试中的代码是时使用WebSocketConnecionV2本身(拨号 URL,恢复光标,重新连接回路),所以connect()留下来 真实的.
test:coverage 执行 a 鼠标 (单位:千美元)thresholds 内 vitest.config.ts设置
只是今天的数字。 它的存在是为了阻止覆盖向后滑动,而不是
描述一个目标——当一批试验降落时提高它,决不降低到
转出红色跑道绿色.
中情局 (单位:千美元).github/workflows/ci.yml运行在每一个公关 和每一个推动 main数字 :
类型检查 → 测试 + 覆盖(鼠标,所以下降失败运行) → 库
建立 ~ 演示类型检查 。 由于Npm tarball船a
预建 dist/演示,因为它通过一个来源消耗库
别名, 因此抓取破损的 API 无法更改库本身的类型检查
看到没? 每跑的总结页都包含着覆盖表和十大漏洞
; HTML 报告全文作为文物附后.
VS 代码接线( 自动安装通过 .vscode/extensions.json:
- 维特 每条外沟旁通过/失效
it(...)和测试面板中的树视图. - 覆盖面 在源头一侧涂上绿色/红色条纹
文件一次
npm run test:coverage已经编制coverage/lcov.info。 。 。 . 来自命令的“ Coverage Gutters: 显示覆盖” 触发器 调色板.
打开 coverage/index.html 用于钻入报告浏览器.
释放
当您运送行为改变( 错误修正、 新道具、 断接) 时, 剪切释放
API更改). 出版内容为 标记驱动: 推一个 v<semver> 标记运行
publish-aia-chat.yml 工作流程,哪些 npm publisho 公众npm登记
通过 npm 受托出版 (OIDC——没有存储的活物) 有建筑出处.
access: public 来自 package.json是因为 publishConfig。 。 。 .
1. 弹出+承诺+标记+推
从"回波"根开始,在改变之后 main数字 :
# 1. bump version in package.json (semver: patch / minor / major)
npm version patch --no-git-tag-version # 0.2.16 → 0.2.17 (bugfix)
# npm version minor --no-git-tag-version # 0.2.x → 0.3.0 (new prop / feature)
# npm version major --no-git-tag-version # 0.x.y → 1.0.0 (breaking)
# 2. commit the bump
git add package.json
git commit -m "vX.Y.Z: <one-line summary of what changed>"
# 3. tag the commit + push branch and tag together
git tag -a vX.Y.Z -m "vX.Y.Z — <short release note>"
git push origin main vX.Y.Z
推着 vX.Y.Z 标签触发 CI (npm ci + 键 npm publish --provenance) (中文(简体) ). 这个
标签版本和 package.json 版本必须匹配。 您也可以运行
手工工作流程( e)工作流程( d))出版目前的任何版本
内 package.json。 。 。 .
--no-git-tag-version 打开 npm version 是故意的,它会撞倒 package.json
不创建自己的承诺/目标,所以您控制承诺消息和标记
明确注解(npm的默认值是模糊的,当颠倒的骑行在旁边
(b) 实质性变动.
一次性设置 (已完成,此处注明需要恢复):在npmjs.com上
@aintelaorg / 软件包注册一个可信任的出版商, 用于重播envision-tecnologia/aichat工作流程publish-aia-chat.yml。一个符号倒置 (单位:千美元)NPM_TOKEN秘密行动NODE_AUTH_TOKEN) 如果 OIDC 曾经被拖入工作流程 需要绕过.
2. 更新消费者信息
每个消费者都会撞出其熔体范围(或者只要重新安装,如果是现有范围的话) 已覆盖新版本 :
- "@aintela/chat": "^0.2.16",
+ "@aintela/chat": "^0.2.17",
npm install @aintela/chat
在标记前快速进行烟雾测试
v0.1.1 以演示在几秒钟内浮出水面的 part- event Type bug 运出 .
推出标签前,请稍候:
npm run build && npm run typecheck # at repo root
cd examples/demo && npm install && npm run dev
在演示中打开平板标签, 发送提示, 观看流回 一、导 言 留下来 已经完成。 切换标签和回。 如果有事情发生 并消失,修复还没有准备好标记.
范围
v0.1 从旧库中刻出聊天必需子集 :
- AiChat 组件 + ChatPane + 变种( Drawer, Floating)
- AgentGatewayWS + WebSocket 连接+事件总线
- 会期周期(会议国家管理事务)
autoCreateSession默认为false,与旧默认相反 - Llm 响应器 + 环境提供器 + LiveTsxfig 提供器
- 模式:互动,互动部分,聊天会,客户端信息等.
- 接口:会议服务、艺术服务、基础设施服务 图书馆船舶接口,执行中的主机插件
超出范围:管理员设置 UI,仪表板渲染原始,即库,
v2 app chrome, 节点/ 蒙戈/ Express 服务器捆绑. 居住(或移动)
恢复到) envision-abi/packages/dashboard-app。 。 。 .