项目正在快速迭代中,API 与视觉细节可能随版本调整,请勿用于生产环境。

@wil-works/evoke-chat AI 使用说明(v0.5.1) ​

本页由 packages/evoke-chat/scripts/gen-ai-docs.mjs 自动生成,勿手改(改了会被构建门拦下)。

给 AI 读:先看「硬规则」,再按「任务配方」找 API,最后用逐组件表核对字段名。 完整散文文档见 对话窗口;同内容的结构化契约见 evoke-chat.components.json。

硬规则 ​

  1. 组件只做呈现,任何请求都由宿主注入(transport / fetch / SDK),包内不发网络请求。
  2. 流式回写一律用 appendContent / appendThinkContent(自动转 streaming),不要自己拼字符串。
  3. 用户主动停止是 cancelled(cancelMessage),不是 error;中断后迟到的事件会被拒绝。
  4. 工具调用按 id 操作(startToolCall 返回 id),子调用同样按 id,写操作自动递归。
  5. 文案随包走(/locale),中英键位同构;宿主只覆盖,不改组件。
  6. 字段名以本文档的组件表为准;不确定就先查 JSON 契约,不要猜 prop 名。

任务配方 ​

流式回写模型输出 ​

API:useChatEngine.createAssistantMessage、appendContent、appendThinkContent、completeMessage

js
const engine = useChatEngine()
const msg = engine.createAssistantMessage()
// 逐片回写:appendContent 自动把消息转成 streaming 态(卡片露出光标)
engine.appendContent(msg.id, chunk)
engine.appendThinkContent(msg.id, reasoningChunk)   // 思维链与正文分开
engine.completeMessage(msg.id)                      // 收尾:settle 耗时、转 done

注意:

  • 不要自己拼字符串后 setMessageContent——那样没有 streaming 光标与贴底
  • 正文与思维链必须分开两个 API,混写会串行渲染

消息内交错(parts) ​

API:createAssistantMessage、appendContent、appendThinkContent、startToolCall

js
// appendContent / appendThinkContent / startToolCall 自动记录到达顺序(message.parts),
// 组件按 parts 交错渲染:正文 → 工具卡 → 正文。
engine.appendContent(msg.id, '查到近 6 个月的数据:')
engine.startToolCall(msg.id, { name: 'sql_query', label: '查询营收' })
engine.appendContent(msg.id, '对比行业均值来看…')   // 工具卡之后的正文段
// content / thinkContent / toolCalls 是 parts 的平面投影:复制、朗读等平面消费照旧

注意:

  • parts 是真相:{ id, type: text/reasoning/tool, text?, toolCallId? };连续同型增量合并进尾部 part
  • 落定覆写(assistant/message 的 content)只改投影不动 parts——渲染以 parts 为准
  • 子调用(addSubToolCall)不占消息级位置:它渲染在父卡内部;无 parts 的老消息走固定顺序

停止生成(用户点停止 / 双击 Esc) ​

API:cancelMessage

js
// 组件侧:EbAiPromptBox / EbChatSender 的 stop 事件
function onStop() {
  engine.cancelMessage(msg.id)
  transport.cancel()      // 后端协作式中断
}

注意:

  • 取消是 cancelled,不是 error:不要用 setMessageError 表达用户主动停止
  • cancelMessage 会把思考态标记为「思考已中断」,并把在跑/等待的工具调用落 cancelled
  • 中断后迟到的增量与收尾会被拒绝(appendContent / completeToolCall 返回空)

渲染工具调用(含流式输出) ​

API:startToolCall、appendToolCallArgs、appendToolCallResult、completeToolCall、failToolCall

js
const callId = engine.startToolCall(msg.id, { name: 'web_search', label: '联网检索' })
engine.appendToolCallArgs(msg.id, callId, '{"query":')     // 入参也流式:JSON 文本逐片拼,卡片边收边显示
engine.appendToolCallArgs(msg.id, callId, '"Q3 营收"}')
engine.appendToolCallResult(msg.id, callId, '命中 3 条…')   // 输出侧边跑边出
engine.completeToolCall(msg.id, callId)                     // 收尾:拼完的入参自动 parse 回对象

注意:

  • completeToolCall 第三参省略时保留流式输出,传空串才会清空
  • 失败用 failToolCall(错误首行会摘要显示),不要走 completeToolCall
  • 入参按 JSON 文本拼接,收尾自动 parse 回对象;半截 JSON parse 不动就保留原文(诚实展示)

工具调用里挂子步骤(并行派发 / PTC) ​

API:addSubToolCall、findToolCall

js
const parent = engine.startToolCall(msg.id, { name: 'fetch_page' })
const child = engine.addSubToolCall(msg.id, parent, { name: 'parse_html' })  // 返回子调用 id
engine.completeToolCall(msg.id, child, '解析出 3 个小节')

注意:

  • append/complete/fail 都按 id 递归作用到子层,无需手动找父节点
  • 嵌套上限 16 层,超深返回 null

审批接管(危险操作前问一句) ​

API:EbChatApproval、useChatSession.respondApproval

js
<eb-chatbot :approval="approval" @approval-respond="onApprovalRespond" />

// 宿主侧
const answer = await askApproval({ id, toolName: 'web_search', reason: '需要联网' })
// answer: 'allowed-once' | 'rejected'
session.respondApproval('allowed-once')

注意:

  • 只有两种结论:allowed-once / rejected(没有「总是允许」——那属于会话级权限模式)
  • 审批非空时输入台让位给审批面板,优先级高于提问

提问接管(干活前澄清口径) ​

API:EbChatQuestion、useChatSession.respondQuestion

js
<eb-chatbot :question="question" @question-respond="onQuestionRespond" />

const answer = await askQuestion({
  id, items: [{ id: 'scope', question: '按哪个口径对比?', options: [{ key: 'mom', label: '环比', recommended: true }] }],
})
// answer: { status: 'answered' | 'cancelled', answers: [{ selected: ['mom'], custom, skipped }] }

注意:

  • 跳过算「已回答」(skipped: true),取消是整批作废(status: cancelled)
  • 单选互斥、多选累加、自定义输入同题互斥

显示上下文占用 ​

API:EbChatContextMeter、useChatSession.setContext

js
<eb-ai-console :context="{ used, capacity: 32000, breakdown: { system, tools, messages } }" />

// 或由事件驱动
session.setContext({ used: 12800, capacity: 32000 })

注意:

  • used 与 capacity 缺一不渲染——拿不到窗口容量时画环只会误导
  • 百分比封顶 100%,75% 警告 / 90% 危险

展示本轮改了哪些文件 ​

API:EbChatChanges、useChatEngine.setChanges

js
engine.setChanges(msg.id, {
  total: 3, added: 96, deleted: 18,
  files: [{ path: 'src/a.vue', display: 'a.vue', added: 88, deleted: 12 }, { path: 'assets/logo.png', binary: true }],
})

注意:

  • 单文件时标题直接给文件名;二进制/过大不给行数只给标记
  • 列表默认露 4 行,超出收在「全部 N 个文件」

接真实后端(会话日志层:断线可恢复) ​

API:useChatSession、createSessionLog、applySessionEvent

js
const transport = {
  open: ({ cursor, onEvent, onGap }) => subscribe({ cursor, onEvent, onGap }),  // 长连/轮询均可
  page: ({ from, limit }) => fetchRecords({ from, limit }),                    // 补页
  send: (payload) => post(payload), cancel: () => abort(),                     // 发送与中断
  approve: (outcome, request) => postApproval(outcome, request),
  answerQuestion: (answer, request) => postAnswer(answer, request),
}
const session = useChatSession({ transport })
session.open({ cursor: 0, records: [] })

注意:

  • 事件信封 { type, seq, time, data, ignorable?, surfaceOp? };seq 必须连续,缺口会缓冲并回调 onGap
  • 游标只被持久事件推进;瞬时事件(审批/提问/占用)不会推进也不会造成缺口
  • 不可忽略的未知事件会标记 degraded,宿主应重拉整窗
  • open() 必须在 submit 前调(忘调会自动补开但告警);切会话 = 再 open()(旧订阅迟到事件被代际守卫丢弃),彻底停用 dispose()
  • 结构化进度走 assistant/progress 瞬时事件 { messageId, label, detail?, elapsedMs?, percent? },别把阶段进度拼进 think 文本
  • 入参流式走 tool/args 瞬时事件 { messageId, callId, chunk };assistant/message 可带 model/provider(模型归属透传)

直接接 OpenAI / Anthropic ​

API:createChatTransport

js
const transport = createChatTransport({
  provider: 'anthropic',            // 'openai' | 'anthropic',或自定义 adapter 对象
  apiKey, model: 'claude-sonnet-4-5', system: '你是运营助手',
  tools: [{ name: 'web_search', description: '联网检索', parameters: {…} }],
  contextWindow: 32000,
  getMessages: () => session.messages.value,
  onExtension: ({ event, data, json }) => {      // RAG 引用/进度等非标准载荷
    if (json?.type === 'citations') { session.receive(mapCitations(json)); return true }
  },
})

注意:

  • 浏览器直连会暴露 key:生产走自己的后端代理(url 指到代理)
  • 这两家没有 follow/补页协议,历史要宿主自己存
  • 工具参数是分片 JSON,适配层已按 index 拼完再 parse
  • onExtension 返回 true = 本帧已被扩展消费,跳过标准映射;自研后端可给 provider 传实现 createState/buildRequest/headersOf/frameToEvents/finalize 契约的对象,不必手写 transport
  • 中断已接进 SSE 解析层:abort 解除挂起的 read 再补 turn/end(aborted),不会一直挂

正文行内引用(RAG 引用锚点) ​

API:anchorSource、EbChatSources、citation-click

js
// citations 是回合级语义(来源卡渲染在正文之后);行内关系用 source: 协议
engine.appendContent(msg.id, '根据' + anchorSource('doc-3', '3') + ' 篇文档…')
// 等价于正文里写 [3](source:doc-3):渲染成可点上标,点击 → EbChatSources 高亮对应卡片
// text 省略则按出现顺序自动编号;text 给数字则固定该序号

注意:

  • anchorSource(refId, text?) 返回 markdown 片段;refId 必须与 citations[].id 一一对应,否则点了没卡可高亮
  • citations 是回合级(消息级字段、渲染在正文后),行内锚点才是"这句来自哪篇"的表达
  • 纯文本 renderMode 下 source: 协议不渲染上标,只有 markdown 模式支持

内部流水线时间线(progressLog) ​

API:appendProgress、clearProgress、setProgress

js
// progress 是「当前一句话」;progressLog 是完整轨迹(理解→检索→核对→合成…)
engine.appendProgress(msg.id, { label: '检索知识库', detail: '命中 12 段', elapsedMs: 340 })
engine.appendProgress(msg.id, { label: '合成答案' })
// 追加联动更新当前行;历史阶段(≥2 条)收进「前 N 个阶段」折叠,展开是紧凑日志

注意:

  • setProgress 只更新当前行不记轨迹;appendProgress 记轨迹并联动当前行
  • progressLog 是系统轨迹,别当 plan 用——给用户看的计划走 setPlan
  • 收尾(completeMessage / cancelMessage / 出错)会清掉 progress;progressLog 默认也清(进度只属于进行中的轮),宿主要事后审计就用 useChatEngine({ keepProgressLog: true }) 或 clearProgress(id, { keepLog: true }) 留轨迹

记用量与模型归属 ​

API:useChatEngine.setUsage

js
engine.setUsage(msg.id, {
  promptTokens: 120, completionTokens: 380, totalTokens: 500,
  cost: 0.0032, currency: '$',            // 成本要价目表,是宿主业务数据;不给就不显示
  segments: [{ label: '检索阶段', tokens: 320 }, { label: '生成阶段', tokens: 180 }],
})
// 模型归属是消息级字段:message.model / message.provider,底部读数行显示 provider/model
engine.updateMessage(msg.id, { model: 'claude-sonnet-4-5', provider: 'anthropic' })

注意:

  • usage 字段面:prompt/completion/totalTokens、cacheRead/cacheWrite/reasoningTokens、ttftMs、tokensPerSecond、cost、currency、segments
  • segments 是分段记账(如检索 vs 生成),多条汇总时按 label 合并累加
  • model / provider 只透传不解析:引擎不猜路由,多模型时由后端在 assistant/message 事件里带上

自定义工具卡的参数/结果渲染 ​

API:EbChatToolCall 的 #args / #result 插槽

js
<eb-chat-tool-call :tool-call="call">
  <template #result="{ toolCall }"><eb-json-viewer :data="toolCall.result" /></template>
</eb-chat-tool-call>

注意:

  • 默认是带环检测的 JSON <pre>;只要换成插槽就不会丢默认的折叠/状态语义
  • resultType: text / json / image / file——image 认 { url, alt? }、file 认
  • 非文本 URL 只放行 http/https/data(与正文图片同款白名单),其余退回文本

多语言 ​

API:chatLabels、useChatLabels、@wil-works/evoke-chat/locale

js
import zhCN from '@wil-works/evoke-chat/locale/zh-CN'
app.use(EvokeChat, { locale: zhCN })

注意:

  • 文案随包走,中英键位必须同构(有测试守)
  • 宿主自定义文案用 chatLabels 覆盖,不要 fork 组件

组件契约 ​

组件子路径入口文档
EbChatbot@wil-works/evoke-chat/chatbothttps://evoke-business-ui.wil-works.com/chat/chatbot
EbChatList@wil-works/evoke-chat/chat-listhttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatMessage@wil-works/evoke-chat/chat-messagehttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatSender@wil-works/evoke-chat/chat-senderhttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatContent@wil-works/evoke-chat/chat-contenthttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatMarkdown@wil-works/evoke-chat/chat-markdownhttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatThinking@wil-works/evoke-chat/chat-thinkinghttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatLoading@wil-works/evoke-chat/chat-loadinghttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatActionbar@wil-works/evoke-chat/chat-actionbarhttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatAttachments@wil-works/evoke-chat/chat-attachmentshttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatSuggestion@wil-works/evoke-chat/chat-suggestionhttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatFeedback@wil-works/evoke-chat/chat-feedbackhttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatMessageEdit@wil-works/evoke-chat/chat-message-edithttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatSources@wil-works/evoke-chat/chat-sourceshttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatToolCall@wil-works/evoke-chat/chat-tool-callhttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatThreads@wil-works/evoke-chat/chat-threadshttps://evoke-business-ui.wil-works.com/chat/chat-threads
EbChatWidget@wil-works/evoke-chat/chat-widgethttps://evoke-business-ui.wil-works.com/chat/chat-widget
EbChatPlan@wil-works/evoke-chat/chat-planhttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatConfirmation@wil-works/evoke-chat/chat-confirmationhttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatApproval@wil-works/evoke-chat/chat-approvalhttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatQuestion@wil-works/evoke-chat/chat-questionhttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatContextMeter@wil-works/evoke-chat/chat-context-meterhttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatChanges@wil-works/evoke-chat/chat-changeshttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatStatusBar@wil-works/evoke-chat/chat-status-barhttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatArtifact@wil-works/evoke-chat/chat-artifacthttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatDiff@wil-works/evoke-chat/chat-diffhttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatTerminal@wil-works/evoke-chat/chat-terminalhttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatFileTree@wil-works/evoke-chat/chat-file-treehttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatTestResults@wil-works/evoke-chat/chat-test-resultshttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatStackTrace@wil-works/evoke-chat/chat-stack-tracehttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatShare@wil-works/evoke-chat/chat-sharehttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatSpeak@wil-works/evoke-chat/chat-speakhttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatVoiceInput@wil-works/evoke-chat/chat-voice-inputhttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatQueue@wil-works/evoke-chat/chat-queuehttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatCommandMenu@wil-works/evoke-chat/chat-command-menuhttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatUsage@wil-works/evoke-chat/chat-usagehttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatSandbox@wil-works/evoke-chat/chat-sandboxhttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbChatWebPreview@wil-works/evoke-chat/chat-web-previewhttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents
EbAiPromptBox@wil-works/evoke-chat/ai-prompt-boxhttps://evoke-business-ui.wil-works.com/chat/ai-prompt-box
EbAiConsole@wil-works/evoke-chat/ai-consolehttps://evoke-business-ui.wil-works.com/chat/ai-console

EbChatbot ​

EbChatbot 之外的家族成员。绝大多数场景不需要直接用它们——EbChatbot 已经把这些组装好了。它们用于两种情形:只想要其中一块(比如独立渲染一段 Markdown),或要自己编排(ChatList + 自定义发送区)。

  • 入口:@wil-works/evoke-chat/chatbot 源码:src/components/chatbot/Chatbot.vue 文档:https://evoke-business-ui.wil-works.com/chat/chatbot
  • 插槽:header、empty、message-header、message、message-content、tool-result、tool-args、sender-menu、sender-prepend、sender-toolbar、sender-append、tip
prop类型默认
modelValueArray() => []
placeholderStringvoid 0
loadingBooleanfalse
disabledBooleanfalse
showThinkingBooleantrue
allowAttachmentsBooleantrue
maxAttachmentsNumber5
maxLengthNumber2e3
showWordCountBooleanfalse
sendOnEnterBooleantrue
actionsArray() => []
editableBooleanfalse
editMaxLengthNumber0
feedbackBooleanfalse
feedbackReasonsArray() => []
toolRetryableBooleantrue
speechBooleanfalse
traceUrlString""
virtualBooleanfalse
virtualThresholdNumber60
estimatedItemSizeNumber120
acceptString""
maxFileSizeNumber0
allowDropBooleantrue
queueableBooleanfalse
menuOpenBooleanfalse
height[String"600px"
width[String"100%"
avatarUserString""
avatarAssistantString""
userNameStringvoid 0
assistantNameStringvoid 0
showAvatar[Booleantrue
showName[Booleantrue
showTimeBooleantrue
renderModeString"markdown"
autoScrollBooleantrue
showTipBooleantrue
stoppableBooleanfalse
approvalObjectnull
questionObjectnull
contextObjectnull
statusObjectnull
statusStoppableBooleanfalse
inputValueString""

事件:send、stop、copy、regenerate、action、edit、feedback

EbChatList ​

消息滚动容器。负责自动贴底、role="log" 流式播报、回到底部钮、空态;不负责发送。

prop类型默认
messagesArray() => []
showThinkingBooleantrue
avatarUserString""
avatarAssistantString""
userNameStringvoid 0
assistantNameStringvoid 0
showAvatar[Booleantrue
showName[Booleantrue
showTimeBooleantrue
renderModeString"markdown"
actionsArray() => []
autoScrollBooleantrue
editableBooleanfalse
editMaxLengthNumber0
feedbackBooleanfalse
feedbackReasonsArray() => []
toolRetryableBooleantrue
speechBooleanfalse
traceUrlString""
virtualBooleanfalse
virtualThresholdNumber60
estimatedItemSizeNumber120

事件:copy、regenerate、action、edit、feedback、scroll

EbChatMessage ​

单条消息。按 role 分流:user / assistant 是对话气泡,system / notice 是居中弱化的系统提示(无头像、昵称、动作条)。

prop类型默认
messagenull—
showThinkingBooleantrue
avatarUserString""
avatarAssistantString""
userNameStringvoid 0
assistantNameStringvoid 0
renderModeString"markdown"
showAvatar[Booleantrue
showName[Booleantrue
showTimeBooleantrue
actionsArray() => []
editableBooleanfalse
editMaxLengthNumber0
feedbackBooleanfalse
feedbackReasonsArray() => []
toolRetryableBooleantrue
speechBooleanfalse
traceUrlString""

事件:copy、regenerate、action、edit、feedback

EbChatSender ​

输入区:自增高、Enter 发送、IME 组字安全、附件(点选 / 拖拽 / 粘贴)、字数限制、发送↔停止变形。EbChatbot 内部用它。

prop类型默认
modelValueString""
placeholderStringvoid 0
disabledBooleanfalse
loadingBooleanfalse
allowAttachmentsBooleantrue
maxAttachmentsNumber5
maxLengthNumber2e3
showWordCountBooleanfalse
minRowsNumber1
maxRowsNumber6
sendOnEnterBooleantrue
stoppableBooleanfalse
acceptString""
maxFileSizeNumber0
allowDropBooleantrue
queueableBooleanfalse
menuOpenBooleanfalse

事件:send、stop

EbChatContent ​

面板外壳:固定尺寸、可选边框、头部/底部槽位。EbChatbot 用它包住消息区与输入区。

prop类型默认
height[String"100%"
width[String"100%"
borderedBooleanfalse

EbChatMarkdown ​

Markdown 渲染器:GFM 表格与任务列表、代码块工具条(语言标签 + 复制)、自定义协议引用芯片、source: 行内引用上标、流式拖尾。原文 HTML 一律转义为纯文本;图片 src 只放行 http / https / data。

prop类型默认
contentString""
streamingBooleanfalse

EbChatThinking ​

思考过程折叠块。流式期间强制展开,结束后回到用户可控的折叠态。{ content, thinking, duration, interrupted }(duration 为思考耗时,显示成「(用时 X)」;消息上下文里取 message.thinkDuration;interrupted 为真时标题说「思考已中断」,用

prop类型默认
contentString""
thinkingBooleanfalse
durationNumber0
interruptedBooleanfalse

EbChatLoading ​

三点起伏的打字指示。可选 text 文案。

prop类型默认
textString""

EbChatActionbar ​

消息动作条:复制(内置,含已复制回执)、重新生成(仅 assistant)、编辑(仅 user)、自定义动作。默认悬停显示,:focus-within 与触屏常显。自定义动作给了 icon 就是图标按钮,没给则回落成文字按钮;每颗按钮悬浮都出库内 Tooltip(Teleport 到 body,消息列表滚动时不会被裁切

prop类型默认
messagenull—
actionsArray() => []
showCopyBooleantrue
showRegenerateBooleantrue
showEditBooleanfalse
showSpeechBooleanfalse
traceUrlString""

事件:copy、regenerate、edit、action

EbChatAttachments ​

附件卡片列表:图片预览或按后缀匹配的专用图标(pdf / word / excel / ppt / zip / image / music / video / code / text,认不出退 MIME 大类、再退通用文档图标)、文件名、体积、移除钮;图标默认按类型染色(pdf 红 / word 蓝 / excel 绿

prop类型默认
attachmentsArray() => []
removableBooleanfalse
coloredBooleantrue

事件:remove

EbChatSuggestion ​

追问 chips。items 接受 string 或 { text, prompt? };layout 取 row(消息尾部)或 column(欢迎区);icon 传图标名则每枚前置。抛 pick({ text, prompt })。

prop类型默认
itemsArray() => []
layoutString"row"
iconString""
disabledBooleanfalse

事件:pick

EbChatFeedback ​

点赞点踩。点赞立即提交;点踩展开结构化原因面板与备注。取消评价也会交出 { value: null }——否则宿主存下来的评价清不掉。

prop类型默认
valueStringnull
reasonsArray() => []
showNoteBooleantrue
disabledBooleanfalse

事件:submit

EbChatMessageEdit ​

用户消息的原地编辑器。Esc 取消、Enter 保存、IME 安全、maxlength 生效。{ modelValue, placeholder, maxLength, sendOnEnter },抛 save(text) / cancel。

prop类型默认
modelValueString""
placeholderStringvoid 0
maxLengthNumber0
sendOnEnterBooleantrue

事件:save、cancel

EbChatSources ​

EbChatSources

prop类型默认
itemsArray() => []
collapsibleBooleantrue
defaultOpenBooleantrue

EbChatToolCall ​

工具调用卡:状态标记(等待/执行/失败/完成/已停止)、耗时、参数与结果的折叠展开,失败态给重试钮。支持子调用:toolCall.subCalls 是同一形状的数组(并行派发 / PTC 子步),展开后按层级递归渲染、左侧细轨标出从属关系,折叠时头部给子调用计数;嵌套上限 16 层(引擎与组件两侧都设了,异常自引用数据

prop类型默认
toolCallObject() => ({})
expandedBooleanundefined
retryableBooleantrue
depthNumber0

事件:toggle、retry

EbChatThreads ​

不想要 Console 那套编排时,EbChatThreads 可以单独用;#item 插槽整条接管,itemProps 用于回落默认渲染(与 ChatList#message 同款约定):

prop类型默认
threadsArray() => []
activeString""
streamingArray() => []
searchableBooleantrue
showCreateBooleantrue
groupByDateBooleantrue
renamableBooleantrue
removableBooleantrue
timeFormatFunctionnull

事件:select、create、rename、remove、pin、archive、search

EbChatWidget ​

导出名为 EbChatWidget。v-model 管开合;内容完全由你放——常见就是一颗 EbChatbot 或 EbAiConsole:

prop类型默认
modelValueBooleanfalse
titleString""
iconString"customer-service"
launcherTooltipString""
badgeNumbernull
placementString"bottom-right"
width[String380
height[String560
mobileModeString"drawer"
drawerSize[String"80%"
disclaimerString""
defaultConsentedBooleanfalse
appendToBodyBooleantrue

事件:open、close、consent

EbChatPlan ​

EbChatPlan · EbChatConfirmation · EbChatArtifact

prop类型默认
planObject() => ({ steps: [] })
expandedBooleanundefined

事件:toggle

EbChatConfirmation ​

EbChatPlan · EbChatConfirmation · EbChatArtifact

prop类型默认
confirmationObject() => ({})

事件:respond

EbChatApproval ​

审批面板:agent 要执行越权动作(跑命令、联网、改文件)时接管输入区——待审批期间发送台让位,用户只需做一个决定。{ id, toolName, reason?, detail?, status? }:给了 reason 就用它当标题,否则显示「工具 X 请求越权执行」;detail 常放被拦命令原文(等宽、限高可

prop类型默认
requestObject() => ({})
answeredBooleanundefined

事件:respond

EbChatQuestion ​

提问面板:agent 需要澄清时接管输入区(审批优先——越权动作必须先答)。{ id, items: [{ id, question, header?, multiSelect?, allowCustom?, options: [{ key, label, recommended?, description? }] }

prop类型默认
requestObject() => ({})
answeredBooleanundefined

事件:respond

EbChatContextMeter ​

输入台工具栏右侧的占用环(EbAiConsole 经 #toolbar-meta 传进输入台,不再占输入区一行):{ used, capacity, breakdown? },环 + 百分比,点开给「已用 / 窗口」与三段构成(系统提示词 / 工具定义 / 对话消息)。两侧缺一就不显示——拿不到窗口容量时画个环只会误导

prop类型默认
usedNumber0
capacityNumber0
breakdownObjectnull

EbChatChanges ​

本轮改动汇总卡:标题给「已编辑 N 个文件」(单文件时直接给文件名),右侧 +A -R;展开后逐行列文件,每行带自己的增删数,二进制 / 过大不给行数只给标记。超出 collapsedRows(默认 4)折叠,给「全部 N 个文件」。路径等宽、不折行(保住目录层级),过长省略并留 title;点行抛 select(宿主

prop类型默认
filesArray() => []
summaryObjectnull
collapsedRowsNumber4
defaultOpenBooleanfalse

事件:select

EbChatStatusBar ​

「AI 现在在做什么」此前只能靠 aria-busy 猜。状态条把它变成一句话 + 一个可点的动作,常驻在输入台上方。

prop类型默认
statusObjectnull
stoppableBooleanfalse

事件:stop

EbChatArtifact ​

EbChatPlan · EbChatConfirmation · EbChatArtifact

prop类型默认
artifactsArray() => []
copyableBooleantrue

事件:open、copy

EbChatDiff ​

吃标准统一 diff 文本(git diff 与各家 agent 输出的那种),按文件分组,头部给路径与 +N −M,行按增/删/上下文着色,带 old/new 双行号栅格。

prop类型默认
diffString""
showLineNumbersBooleantrue
collapsibleBooleantrue
defaultOpenBooleantrue
maxHeight[String"360px"

事件:toggle、copy

EbChatTerminal ​

命令输出卡:头部给命令与退出码,正文等宽渲染且不折行(保住终端列结构,横向滚动交给容器),status: 'running' 时末尾有光标。长输出只渲染尾部(默认 40 行),给省略数与展开入口——命令输出动辄上千行,全渲染会拖垮消息列。

prop类型默认
commandString""
outputString""
statusString"done"
exitCode[Numbernull
collapsibleBooleantrue
defaultOpenBooleantrue
maxHeight[String"320px"
tailLinesNumber40

事件:toggle、copy

EbChatFileTree ​

扁平路径列表 → 嵌套树。目录在前、名称升序;文件带类型图标、状态徽标(新增/修改/删除/重命名)与增删行数。目录默认展开,折叠状态 aria-expanded 完整。

prop类型默认
filesArray() => []
defaultExpandAllBooleantrue

事件:select、toggle

EbChatTestResults ​

EbChatTestResults · EbChatStackTrace。两张都是纯数据渲染,无额外依赖。

prop类型默认
resultsObject() => ({})
casesArraynull
expandStacksBooleanfalse

EbChatStackTrace ​

吃 stack 字符串或已解析的 frames,认三种常见形态:

prop类型默认
stack[String""
collapseDependenciesBooleantrue
maxAppFramesNumber0

EbChatShare ​

收集「可见范围 + 有效期」,链接的生成与权限校验由你的服务端负责——组件不发请求;link 为空是配置态、非空是已创建态。

prop类型默认
modelValueBooleanfalse
titleString""
linkString""
creatingBooleanfalse
scopesArray() => []
scopeString"anyone"
expiriesArray() => []
expiryString"7d"
appendToBodyBooleantrue

事件:create、revoke、copy

EbChatSpeak ​

朗读(useSpeech · EbChatSpeak) ​

prop类型默认
textString""
langString""
rateNumber1

事件:start、stop、end

EbChatVoiceInput ​

口述(useSpeechInput · EbChatVoiceInput) ​

prop类型默认
langString""
continuousBooleanfalse
emitInterimBooleantrue

事件:interim、result、error、start、end

EbChatQueue ​

input-prepend | 输入区顶部(状态条之上) | 待发送队列(EbChatQueue)、附件条这类贴着输入台的内容 |

prop类型默认
itemsArray() => []

事件:remove、clear、recall

EbChatCommandMenu ​

useTriggerMenu(判定)+ EbChatCommandMenu(渲染)+ 输入区让出键盘,三件拼起来。键盘不放在弹层里是刻意的——焦点始终在输入框,弹层不该抢走输入。

prop类型默认
itemsArray() => []
highlightNumber0
visibleBooleanfalse
titleString""

事件:select、hover

EbChatUsage ​

EbChatUsage 只展示宿主给的用量——成本要价目表,那是宿主的业务数据,组件与引擎都不猜。

prop类型默认
usageObjectnull
itemsArraynull
sizeString"compact"
bareBooleantrue
disclosureBooleantrue

EbChatSandbox ​

组件不执行代码,只把一个隔离 iframe 管起来:宿主给 HTML → 组件拼 bootstrap → srcdoc + sandbox 属性 → iframe;console 与错误经 postMessage 上来,组件只转发不解析。

prop类型默认
htmlString""
srcString""
titleString""
height[String260
autoHeightBooleanfalse
extraSandboxArray() => []
allowString""
bootConsoleBooleantrue

事件:console、error、ready、resize

EbChatWebPreview ​

iframe + 截图双模式。有一个绕不过去的硬限制:目标站返回 X-Frame-Options: DENY 或 frame-ancestors 时浏览器显示空白错误页,而跨域下脚本无法可靠区分「禁嵌的空白页」与「真的空白内容」——load 两种情况都触发。

prop类型默认
srcString""
screenshotString""
embeddableBooleannull
titleString""
screenshotAltString""
height[String320
extraSandboxArray() => []
allowString""

EbAiPromptBox ​

EbAiPromptBox 侧同理走 #toolbar-extra。

prop类型默认
modelValueString''
placeholderStringvoid 0
disabledBooleanfalse
loadingBooleanfalse
queueableBooleanfalse
scenesArray() => []
sceneString''
capabilitiesArray() => []
activeCapabilitiesArray() => []
modelsArray() => []
modelString''
quota[Stringnull
showSettingsBooleanfalse
allowAttachmentsBooleantrue
maxAttachmentsNumber5
acceptString''
maxFileSizeNumber0
allowDropBooleantrue
maxLengthNumberundefined
showWordCountBooleanfalse
maxRowsNumber8
sendOnEnterBooleantrue
stoppableBooleanfalse

事件:send、stop

EbAiConsole ​

EbChatbot / EbAiConsole 的 question prop 传了就接管输入区,响应经 question-respond(answer, request) 抛出;useChatSession 的 question + respondQuestion(answer) 已把链路接好(question/re

  • 入口:@wil-works/evoke-chat/ai-console 源码:src/components/ai-console/index.vue 文档:https://evoke-business-ui.wil-works.com/chat/ai-console
  • 插槽:threads、empty、input-prepend、toolbar-extra、tip
  • 实例方法(ref 调用):engine、clear、setDraft、send、focus
prop类型默认
engineObjectnull
sessionsObjectnull
transportFunctionnull
welcomeObjectnull
examplesArray() => []
exampleActionString'send'
placeholderStringvoid 0
disabledBooleanfalse
loadingBooleanfalse
scenesArray() => []
capabilitiesArray() => []
modelsArray() => []
quota[Stringnull
showSettingsBooleanfalse
allowAttachmentsBooleantrue
maxAttachmentsNumber5
maxLengthNumber2000
sendOnEnterBooleantrue
stoppableBooleanfalse
approvalObjectnull
questionObjectnull
contextObjectnull
statusObjectnull
statusStoppableBooleanfalse
queueableBooleanfalse
showThinkingBooleantrue
renderModeString'markdown'
autoScrollBooleantrue
userNameStringvoid 0
assistantNameStringvoid 0
showAvatar[Booleantrue
showName[Booleantrue
showTimeBooleantrue
avatarUserString''
avatarAssistantString''
actionsArray() => []
editableBooleanfalse
editMaxLengthNumber0
feedbackBooleanfalse
feedbackReasonsArray() => []
toolRetryableBooleantrue
speechBooleanfalse
traceUrlString""
chatHeight[Number420
showTipBooleantrue

事件:send、stop、copy、regenerate、action、edit、feedback

组合式 API ​

名称入口文档
useChatEngine@wil-works/evoke-chathttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents#usechatengine
useChatSessions@wil-works/evoke-chathttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents#usechatsessions
createSessionLog@wil-works/evoke-chathttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents#createsessionlog
isEnvelope@wil-works/evoke-chathttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents#isenvelope
isTransient@wil-works/evoke-chathttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents#istransient
useChatSession@wil-works/evoke-chathttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents#usechatsession
applySessionEvent@wil-works/evoke-chathttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents#applysessionevent
useTriggerMenu@wil-works/evoke-chathttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents#usetriggermenu
useSpeech@wil-works/evoke-chathttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents#usespeech
useSpeechInput@wil-works/evoke-chathttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents#usespeechinput
chatLabels@wil-works/evoke-chathttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents#chatlabels
useChatLabels@wil-works/evoke-chathttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents#usechatlabels
anchorSource@wil-works/evoke-chathttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents#anchorsource
createChatTransport@wil-works/evoke-chathttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents#createchattransport
openai@wil-works/evoke-chathttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents#openai
anthropic@wil-works/evoke-chathttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents#anthropic
readSseFrames@wil-works/evoke-chathttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents#readsseframes
sseFramesOf@wil-works/evoke-chathttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents#sseframesof
parseSseText@wil-works/evoke-chathttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents#parsessetext
parseSseFrame@wil-works/evoke-chathttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents#parsesseframe
streamChunks@wil-works/evoke-chathttps://evoke-business-ui.wil-works.com/chat/chat-subcomponents#streamchunks