@qfei-design/make-ai-assistant 0.1.8 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/PUBLIC_API.md +17 -9
- package/README.md +19 -8
- package/dist/react/make-ai-assistant.d.ts +1 -1
- package/dist/react.cjs +4 -4
- package/dist/react.mjs +656 -582
- package/dist/styles.css +142 -19
- package/package.ai.json +4 -4
- package/package.json +1 -1
package/PUBLIC_API.md
CHANGED
|
@@ -37,11 +37,14 @@ Fetch SSE 实现时,从 `/sse` 入口导入 `createSseAssistantTransport`。
|
|
|
37
37
|
|
|
38
38
|
## React exports
|
|
39
39
|
|
|
40
|
-
- `MakeAiAssistant
|
|
40
|
+
- `MakeAiAssistant`:默认右侧居中浮动入口与右侧抽屉;支持受控开关、自定义 launcher,以及
|
|
41
41
|
`brandName` 对默认“{品牌名} AI 助手”标题的覆盖。`title` 可覆盖完整标题;`assistantName` /
|
|
42
42
|
`userName` / `userAvatarUrl` 可显示当前登录人的名称和头像;未传入时用户侧不显示身份信息。
|
|
43
|
-
`privacyNotice`
|
|
44
|
-
|
|
43
|
+
`privacyNotice` 可展示宿主传入的广播提示内容;未传入时不展示广播。浮动入口位置可通过
|
|
44
|
+
`--make-ai-launcher-top`、`--make-ai-launcher-right` 和 `--make-ai-launcher-mobile-right` 覆盖。
|
|
45
|
+
首次打开后关闭抽屉只隐藏 Drawer,不卸载 `AssistantPanel`,不会中断正在进行的生成。
|
|
46
|
+
重新打开时会恢复消息滚动意图;空闲时聚焦输入框,生成中聚焦停止按钮。
|
|
47
|
+
省略 `suggestions` 时显示包内默认推荐问题,传入 `[]` 时隐藏推荐问题。
|
|
45
48
|
- `AssistantPanel`:不带 Drawer 的嵌入式会话面板;支持 `brandName`、`title`、`assistantName` /
|
|
46
49
|
`userName` / `userAvatarUrl` / `privacyNotice`。默认品牌为“Make”,默认显示“AI 助手”;
|
|
47
50
|
用户侧默认不展示名称或头像,广播提示默认不展示。这些字段只参与本地 React 渲染,不会进入 transport 请求。嵌入式面板包含图标化复制回答、
|
|
@@ -59,12 +62,12 @@ Fetch SSE 实现时,从 `/sse` 入口导入 `createSseAssistantTransport`。
|
|
|
59
62
|
Promise rejection。`onActionError` 自身同步抛错或返回 rejected Promise 时也会被包隔离,
|
|
60
63
|
不会污染宿主的全局未处理异常。
|
|
61
64
|
|
|
62
|
-
|
|
63
|
-
的文本内容;复制失败只在本地 UI 反馈并记录不含回答正文的错误类型。AI
|
|
64
|
-
|
|
65
|
+
成功回答的复制操作以图标按钮展示,悬浮或聚焦时显示“复制”提示,保留“复制回答”的无障碍名称,
|
|
66
|
+
只复制该 assistant message 的文本内容;复制失败只在本地 UI 反馈并记录不含回答正文的错误类型。AI 回答正文会按标题、
|
|
67
|
+
段落、列表、强调、反引号代码片段和 Markdown 表格行做轻量结构化展示;该渲染不执行 HTML、JSX、
|
|
65
68
|
CSS 或 JavaScript。默认内容字号为 12px,Markdown-like 回答正文默认字号为 11px,可通过
|
|
66
69
|
`--make-ai-font-size-body` 和 `--make-ai-font-size-markdown` 覆盖。只有当
|
|
67
|
-
`transport.regenerate()` 存在且 `features.regeneration`
|
|
70
|
+
`transport.regenerate()` 存在且 `features.regeneration` 没有显式关闭时,图标化“重新生成”才会显示;
|
|
68
71
|
它会复用该回答前一条用户消息和旧 assistant message 发起替换请求,并在当前 UI 中替换旧回答,
|
|
69
72
|
不额外插入重复的用户气泡。用户滚离底部时,UI 不会强制自动跳到底部,而是显示仅含图标且保留
|
|
70
73
|
“回到最新消息”无障碍名称的按钮。
|
|
@@ -97,13 +100,18 @@ interface AssistantTransport {
|
|
|
97
100
|
`loadConversation` 存在时,面板会先进入初始化状态并恢复历史;失败时展示可重试状态。
|
|
98
101
|
`regenerate` 存在时,面板才会展示成功回答的“重新生成”。该请求必须具备服务端替换旧回答或
|
|
99
102
|
不追加重复用户消息的语义,不能简单映射到普通 `sendMessage`。`features` 决定 UI 是否展示
|
|
100
|
-
|
|
103
|
+
新建会话、是否关闭重新生成,以及停止按钮应表达“远程取消”还是仅“停止接收”。默认会显示头部
|
|
104
|
+
“新建对话”图标按钮,`features.newConversation === false` 时隐藏;点击新建对话会取消当前生成、
|
|
105
|
+
清空本地会话,并调用可选的 `onNewConversation`。
|
|
101
106
|
历史快照最多接受 200 条消息、1,000,000 字符正文和 500 个 Artifact;同一条历史消息内
|
|
102
107
|
Artifact id 必须唯一,避免恢复后产生重复渲染 key。
|
|
103
108
|
|
|
104
109
|
传输边界支持中断。UI 在停止时会立即回到可输入状态、忽略迟到事件,并尝试关闭
|
|
105
110
|
AsyncIterator,因此即使自定义 transport 没有及时响应 `AbortSignal`,也不会一直卡在
|
|
106
|
-
streaming
|
|
111
|
+
streaming。停止按钮会通过 hover/focus tooltip 展示“停止生成”或“停止接收”。关闭
|
|
112
|
+
`MakeAiAssistant` 抽屉只隐藏 Drawer,不触发 active run cancel;取消只由停止、新建会话、
|
|
113
|
+
切换 App/reinitialize 或根组件卸载触发。真实实现可以读取 fetch SSE,也可以把 AG-UI
|
|
114
|
+
runtime 事件归一化为包事件。
|
|
107
115
|
UI 不直接请求固定 URL。
|
|
108
116
|
|
|
109
117
|
`/sse` 的 `createSseAssistantTransport` 实现 `docs/backend-contract.md` 中的标准命名 SSE
|
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# @qfei-design/make-ai-assistant
|
|
2
2
|
|
|
3
|
-
面向 Make Console 与所有 Make App 的 AI
|
|
3
|
+
面向 Make Console 与所有 Make App 的 AI 助手前端包。它提供统一的右侧居中浮动入口、右侧抽屉、流式会话状态、版本化 Artifact 协议、平台默认结果模板和 App 扩展机制。
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
pnpm add @qfei-design/make-ai-assistant@^0.1.
|
|
8
|
+
pnpm add @qfei-design/make-ai-assistant@^0.1.9
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Quick start
|
|
@@ -33,7 +33,12 @@ export function AppAssistant() {
|
|
|
33
33
|
}
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
`MakeAiAssistant`
|
|
36
|
+
`MakeAiAssistant` 默认渲染右侧居中的动效入口和右侧抽屉。宿主可以使用 `open` / `onOpenChange`
|
|
37
|
+
受控管理开关,也可以用 `AssistantPanel` 嵌入自己的容器;浮动入口位置可通过
|
|
38
|
+
`--make-ai-launcher-top`、`--make-ai-launcher-right` 和 `--make-ai-launcher-mobile-right`
|
|
39
|
+
覆盖。浮动入口首次打开后,关闭抽屉只隐藏 Drawer,不卸载 `AssistantPanel`,因此不会中断
|
|
40
|
+
正在进行的生成;重新打开时会按用户关闭前的滚动意图恢复消息位置,空闲时聚焦输入框,生成中
|
|
41
|
+
聚焦停止按钮。只有点击“停止生成”、新建对话、切换 App/reinitialize 或宿主卸载根组件时才会取消当前请求。
|
|
37
42
|
|
|
38
43
|
默认会话会显示“AI 助手”身份;用户侧默认不显示名称,宿主传入 `userName` 或
|
|
39
44
|
`userAvatarUrl` 后才会在用户气泡上方展示当前登录人的名称或头像。宿主可通过 `brandName`
|
|
@@ -43,12 +48,13 @@ AI transport;进度和可重试错误会显示在对应的 AI 回合中。
|
|
|
43
48
|
宿主传入 `privacyNotice` 时,面板会展示内置广播图标和该提示内容;不传入或传入空白内容时,
|
|
44
49
|
默认不展示广播提示。
|
|
45
50
|
|
|
46
|
-
成功的 AI
|
|
47
|
-
|
|
48
|
-
|
|
51
|
+
成功的 AI 回答会显示仅含图标的复制按钮,鼠标悬浮或键盘聚焦时显示“复制”提示,按钮保留
|
|
52
|
+
“复制回答”的无障碍名称;复制只处理该回答的文本内容,失败时会在本地 UI 内提示,不会把回答正文写入日志。AI 回答正文会按标题、
|
|
53
|
+
段落、列表、强调、代码片段和 Markdown 表格行做轻量结构化展示,不执行 HTML,也不引入 Markdown
|
|
49
54
|
运行时依赖。默认内容字号为 12px,Markdown-like 回答正文默认字号为 11px,宿主可通过
|
|
50
55
|
`--make-ai-font-size-body` 与 `--make-ai-font-size-markdown` 覆盖。只有当宿主 transport
|
|
51
|
-
实现可安全替换旧回答的 `regenerate()` 时,UI
|
|
56
|
+
实现可安全替换旧回答的 `regenerate()` 时,UI 才显示仅含图标的“重新生成”按钮,悬浮或聚焦时
|
|
57
|
+
显示“重新生成”提示,并复用该回答前一条用户问题
|
|
52
58
|
替换旧回答,不额外插入重复的用户气泡。用户滚离底部后,面板会显示仅含图标的“回到最新消息”
|
|
53
59
|
按钮,避免在阅读历史时强制跳到底部。
|
|
54
60
|
|
|
@@ -57,6 +63,10 @@ AI transport;进度和可重试错误会显示在对应的 AI 回合中。
|
|
|
57
63
|
超限会进入可重试错误状态。`suggestions` 省略时使用包内默认推荐问题,传入自定义数组时使用
|
|
58
64
|
宿主内容,传入 `[]` 时隐藏推荐问题。
|
|
59
65
|
|
|
66
|
+
默认头部右侧会展示“新建对话”图标按钮;宿主将 `transport.features.newConversation` 显式设为
|
|
67
|
+
`false` 时隐藏该按钮。点击新建对话会取消当前生成、清空本地会话,并调用可选的
|
|
68
|
+
`onNewConversation` 回调。
|
|
69
|
+
|
|
60
70
|
## Package provides
|
|
61
71
|
|
|
62
72
|
- Artifact V1 类型、运行时校验与 JSON Schema;
|
|
@@ -192,7 +202,8 @@ Console BFF 与 Make App Browser API 是两个独立宿主协议,不应只替
|
|
|
192
202
|
需要兼容已有事件协议时,在宿主内实现薄 adapter;不要修改聊天组件或复制 Artifact 模板。
|
|
193
203
|
|
|
194
204
|
流必须以 `run.complete`、`run.cancelled` 或 `error` 终止;异常断流会进入可重试错误状态。
|
|
195
|
-
|
|
205
|
+
停止生成按钮悬浮或键盘聚焦时会显示“停止生成”提示;点击后会立即解除输入锁定并丢弃迟到事件,
|
|
206
|
+
标准 SSE transport 会同步取消底层 reader。关闭抽屉只隐藏 UI,不会触发该取消流程。
|
|
196
207
|
`/sse` 的公开类型不依赖 TypeScript `DOM` lib,现代 Node 宿主也可直接消费。
|
|
197
208
|
调用前已经取消的 `AbortSignal` 不会触发网络请求。
|
|
198
209
|
助手只发送宿主提供的上下文,实际数据权限始终由宿主 Service 在服务端重新校验。
|
|
@@ -18,7 +18,7 @@ export interface AssistantPanelProps {
|
|
|
18
18
|
onClose?: () => void;
|
|
19
19
|
onNewConversation?: () => void;
|
|
20
20
|
}
|
|
21
|
-
export declare function AssistantPanel(
|
|
21
|
+
export declare function AssistantPanel(props: AssistantPanelProps): import("react").JSX.Element;
|
|
22
22
|
export interface MakeAiAssistantProps extends Omit<AssistantPanelProps, "onClose"> {
|
|
23
23
|
open?: boolean;
|
|
24
24
|
defaultOpen?: boolean;
|
package/dist/react.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),R=require("./index.cjs"),p=require("react"),l=require("./conversation-Cv1wdvCR.cjs");function Ce({artifact:s,context:t,fallback:a,onAction:r,onActionError:i,registry:o}){const d=R.resolveArtifactTemplate(o,s,t);if(!d)return a?a(s):e.jsxs("section",{className:"make-ai-artifact make-ai-artifact--unsupported",role:"status",children:[e.jsx("strong",{children:"暂不支持展示此结果"}),e.jsxs("span",{children:["结果类型:",s.kind]})]});const u={context:t,onAction:r,onActionError:i};return d.template.render(s,t,u)}const C=(s,t,a)=>{if(s==null||s==="")return"—";if(typeof s=="boolean")return s?"是":"否";if(typeof s!="number")return`${s}${t?.unit??""}`;const r=t?.precision,i={maximumFractionDigits:r??2,minimumFractionDigits:r};t?.style==="currency"&&t.currency?(i.style="currency",i.currency=t.currency):t?.style==="percent"&&(i.style="percent");try{const o=t?.style==="percent"?s/100:s;return`${new Intl.NumberFormat(a,i).format(o)}${t?.unit??""}`}catch{return`${s}${t?.unit??""}`}},Re=s=>{let t=Number.POSITIVE_INFINITY,a=Number.NEGATIVE_INFINITY;for(const r of s)t=Math.min(t,r),a=Math.max(a,r);return Number.isFinite(t)&&Number.isFinite(a)?{min:t,max:a}:{min:0,max:0}},$e=(s,t,a)=>{if(!a.onAction)return;const r=o=>{console.error("[make-ai-assistant] host action error handler failed",{actionId:s.id,artifactId:t.artifact.id,errorType:o instanceof Error?o.name:typeof o,intent:s.intent})},i=o=>{if(a.onActionError){try{Promise.resolve(a.onActionError(o,s,t)).catch(r)}catch(d){r(d)}return}console.error("[make-ai-assistant] host action failed",{actionId:s.id,artifactId:t.artifact.id,errorType:o instanceof Error?o.name:typeof o,intent:s.intent})};try{Promise.resolve(a.onAction(s,t)).catch(i)}catch(o){i(o)}},z=(s,t)=>s.actions?.length&&t.onAction?e.jsx("div",{className:"make-ai-artifact__actions",children:s.actions.map(a=>e.jsxs("button",{className:`make-ai-artifact__action make-ai-artifact__action--${a.appearance??"link"}`,type:"button",onClick:()=>$e(a,{artifact:s,context:t.context},t),children:[a.label,e.jsx("span",{"aria-hidden":"true",children:"→"})]},a.id))}):null,Z=(s,t,a="")=>e.jsxs("section",{"aria-label":s.title??`${s.kind} result`,className:`make-ai-artifact ${a}`.trim(),"data-artifact-density":s.presentation?.density,"data-artifact-kind":s.kind,children:[s.title?e.jsx("h4",{className:"make-ai-artifact__title",children:s.title}):null,s.summary?e.jsx("p",{className:"make-ai-artifact__summary",children:s.summary}):null,t]}),rs=({artifact:s,renderContext:t})=>{const a=s.data.delta,r=a?C(a.value,a.format==="percent"?{style:"percent"}:void 0,t.context.locale):void 0;return Z(s,e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"make-ai-artifact__metric-value",children:C(s.data.value,s.data.format,t.context.locale)}),a?e.jsxs("div",{className:`make-ai-artifact__delta make-ai-artifact__delta--${a.direction??"flat"}`,children:[e.jsx("span",{"aria-hidden":"true",children:a.direction==="up"?"↗":a.direction==="down"?"↘":"→"}),e.jsx("span",{children:r}),a.label?e.jsx("span",{children:a.label}):null]}):null,s.data.context?e.jsx("p",{className:"make-ai-artifact__context",children:s.data.context}):null,z(s,t)]}),"make-ai-artifact--metric")},is=({artifact:s,renderContext:t})=>Z(s,e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"make-ai-artifact__comparison",children:s.data.items.map(a=>e.jsxs("div",{className:"make-ai-artifact__comparison-item",children:[e.jsx("span",{children:a.label}),e.jsx("strong",{children:C(a.value,a.format,t.context.locale)}),a.hint?e.jsx("small",{children:a.hint}):null]},a.id))}),z(s,t)]}),"make-ai-artifact--comparison"),os=({artifact:s,renderContext:t})=>{const a=s.data.series.flatMap(d=>d.points.map(u=>u.y)),{max:r,min:i}=Re(a),o=r-i||1;return Z(s,e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"make-ai-artifact__trend",children:s.data.series.map(d=>e.jsxs("div",{className:"make-ai-artifact__trend-series",children:[e.jsx("div",{className:"make-ai-artifact__trend-label",children:d.label}),e.jsx("div",{className:"make-ai-artifact__trend-bars",children:d.points.map((u,f)=>{const v=18+(u.y-i)/o*70;return e.jsxs("div",{className:"make-ai-artifact__trend-point",children:[e.jsx("span",{"aria-label":`${u.x}: ${C(u.y,d.format,t.context.locale)}`,className:"make-ai-artifact__trend-bar",role:"img",style:{height:`${v}%`},title:`${u.x}: ${C(u.y,d.format,t.context.locale)}`}),e.jsx("small",{children:u.x})]},`${u.x}-${f}`)})})]},d.id))}),z(s,t)]}),"make-ai-artifact--trend")},cs=({artifact:s,renderContext:t})=>{const{max:a}=Re(s.data.items.map(i=>Math.abs(i.value))),r=Math.max(a,1);return Z(s,e.jsxs(e.Fragment,{children:[e.jsx("ol",{className:"make-ai-artifact__ranking",children:s.data.items.map((i,o)=>e.jsxs("li",{children:[e.jsx("span",{className:"make-ai-artifact__rank",children:o+1}),e.jsxs("span",{className:"make-ai-artifact__ranking-label",children:[e.jsx("span",{children:i.label}),i.description?e.jsx("small",{children:i.description}):null]}),e.jsx("span",{className:"make-ai-artifact__ranking-track","aria-hidden":"true",children:e.jsx("span",{style:{width:`${Math.abs(i.value)/r*100}%`}})}),e.jsx("strong",{children:C(i.value,i.format,t.context.locale)})]},i.id))}),z(s,t)]}),"make-ai-artifact--ranking")},ls=(s,t)=>t.action??{id:`open-${t.id}`,label:t.title??t.id,intent:"open-record",target:{entityKey:s.data.entity.key,recordId:t.id}},ds=({artifact:s,renderContext:t})=>Z(s,e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"make-ai-artifact__record-list",children:s.data.records.length===0?e.jsx("p",{className:"make-ai-artifact__empty",children:"没有符合条件的记录"}):s.data.records.map(a=>{const r=ls(s,a),i=e.jsxs(e.Fragment,{children:[e.jsx("strong",{children:a.title??a.id}),e.jsx("span",{className:"make-ai-artifact__record-values",children:s.data.columns.map(o=>e.jsxs("span",{children:[e.jsx("small",{children:o.label}),C(a.values[o.key],o.format,t.context.locale)]},o.key))}),t.onAction?e.jsx("span",{"aria-hidden":"true",children:"›"}):null]});return t.onAction?e.jsx("button",{className:"make-ai-artifact__record",type:"button",onClick:()=>$e(r,{artifact:s,context:t.context},t),children:i},a.id):e.jsx("div",{className:"make-ai-artifact__record",children:i},a.id)})}),s.data.total!==void 0?e.jsxs("p",{className:"make-ai-artifact__record-total",children:["共 ",s.data.total," 条"]}):null,z(s,t)]}),"make-ai-artifact--record-list"),ms=({artifact:s,renderContext:t})=>Z(s,e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:`make-ai-artifact__notice make-ai-artifact__notice--${s.data.tone}`,children:[e.jsx("span",{"aria-hidden":"true",children:s.data.tone==="success"?"✓":s.data.tone==="warning"?"!":s.data.tone==="danger"?"×":"i"}),e.jsx("p",{children:s.data.body})]}),z(s,t)]}),"make-ai-artifact--notice"),H=(s,t,a)=>({id:s,kinds:[t],priority:0,render:a}),us=[H("platform.metric.default","metric",(s,t,a)=>e.jsx(rs,{artifact:s,renderContext:a})),H("platform.comparison.default","comparison",(s,t,a)=>e.jsx(is,{artifact:s,renderContext:a})),H("platform.trend.default","trend",(s,t,a)=>e.jsx(os,{artifact:s,renderContext:a})),H("platform.ranking.default","ranking",(s,t,a)=>e.jsx(cs,{artifact:s,renderContext:a})),H("platform.record-list.default","record-list",(s,t,a)=>e.jsx(ds,{artifact:s,renderContext:a})),H("platform.notice.default","notice",(s,t,a)=>e.jsx(ms,{artifact:s,renderContext:a}))],Le=R.createArtifactTemplateRegistry(us).templates,Oe=(s=Le)=>R.createArtifactTemplateRegistry(s),ps=s=>`${s}-${Date.now()}-${Math.random().toString(36).slice(2,9)}`,hs="Make",fs=["总结当前页面数据","找出需要关注的记录","列出我有权限查看的数据对象"],Fe=(s,t)=>t??`${s?.trim()||hs} AI 助手`,gs=s=>s??fs;class g extends Error{}const Ee=s=>{try{const t=s?.return?.();if(!t)return;Promise.resolve(t).catch(a=>{console.error("[make-ai-assistant] transport iterator close failed",{errorType:a instanceof Error?a.name:typeof a})})}catch(t){console.error("[make-ai-assistant] transport iterator close failed",{errorType:t instanceof Error?t.name:typeof t})}},_s=async s=>{if(globalThis.navigator?.clipboard?.writeText){await globalThis.navigator.clipboard.writeText(s);return}if(typeof document>"u"||!document.body)throw new Error("Clipboard API is unavailable");const t=document.createElement("textarea");t.value=s,t.setAttribute("readonly",""),t.style.position="fixed",t.style.inset="0 auto auto 0",t.style.opacity="0",document.body.append(t),t.select();const a=document.execCommand("copy");if(t.remove(),!a)throw new Error("Clipboard copy failed")},Ke=()=>e.jsxs("svg",{"aria-hidden":"true",viewBox:"0 0 24 24",children:[e.jsx("path",{d:"M12 2.8c.5 4.4 2.8 6.8 7.2 7.2-4.4.5-6.8 2.8-7.2 7.2-.5-4.4-2.8-6.8-7.2-7.2 4.4-.5 6.8-2.8 7.2-7.2Z"}),e.jsx("path",{d:"M18.3 16.1c.2 1.8 1.2 2.8 3 3-1.8.2-2.8 1.2-3 3-.2-1.8-1.2-2.8-3-3 1.8-.2 2.8-1.2 3-3Z"})]}),xs=()=>e.jsx("svg",{"aria-hidden":"true",viewBox:"0 0 24 24",children:e.jsx("path",{d:"m6 6 12 12M18 6 6 18"})}),As=()=>e.jsxs("svg",{"aria-hidden":"true",viewBox:"0 0 24 24",children:[e.jsx("path",{d:"M8 8h10v12H8z"}),e.jsx("path",{d:"M6 16H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"})]}),js=()=>e.jsxs("svg",{"aria-hidden":"true",viewBox:"0 0 24 24",children:[e.jsx("path",{d:"M5 10v4"}),e.jsx("path",{d:"M8 9v6l6 3V6L8 9Z"}),e.jsx("path",{d:"M17 9.2a4.2 4.2 0 0 1 0 5.6"}),e.jsx("path",{d:"M19.4 6.8a7.6 7.6 0 0 1 0 10.4"})]}),vs=()=>e.jsxs("svg",{"aria-hidden":"true",viewBox:"0 0 24 24",children:[e.jsx("path",{d:"M12 4v11"}),e.jsx("path",{d:"m7 10 5 5 5-5"}),e.jsx("path",{d:"M5 20h14"})]}),Is=()=>e.jsx("svg",{"aria-hidden":"true",viewBox:"0 0 24 24",children:e.jsx("path",{d:"M12 5v14M5 12h14"})}),ys=()=>e.jsxs("svg",{"aria-hidden":"true",viewBox:"0 0 24 24",children:[e.jsx("path",{d:"m4 4 17 8-17 8 3-8-3-8Z"}),e.jsx("path",{d:"M7 12h14"})]}),ee=({className:s=""})=>e.jsx("span",{className:`make-ai-assistant__avatar ${s}`.trim(),"aria-hidden":"true",children:e.jsx(Ke,{})}),ks=({src:s})=>s?e.jsx("span",{className:"make-ai-assistant__user-avatar","aria-hidden":"true",children:e.jsx("img",{alt:"",src:s})}):null,bs=({userAvatarUrl:s,userName:t})=>{const a=t?.trim();return!a&&!s?null:e.jsxs("div",{className:"make-ai-assistant__message-identity",children:[a?e.jsx("span",{className:"make-ai-assistant__message-sender",children:a}):null,e.jsx(ks,{src:s})]})},Ns=s=>{const t=[],a=[],r=[],i=[],o=()=>{const f=a.join(`
|
|
2
|
-
`).trim();a.length=0,
|
|
3
|
-
`).trim();
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),O=require("./index.cjs"),u=require("react"),l=require("./conversation-Cv1wdvCR.cjs");function Ke({artifact:s,context:t,fallback:a,onAction:n,onActionError:r,registry:i}){const d=O.resolveArtifactTemplate(i,s,t);if(!d)return a?a(s):e.jsxs("section",{className:"make-ai-artifact make-ai-artifact--unsupported",role:"status",children:[e.jsx("strong",{children:"暂不支持展示此结果"}),e.jsxs("span",{children:["结果类型:",s.kind]})]});const h={context:t,onAction:n,onActionError:r};return d.template.render(s,t,h)}const L=(s,t,a)=>{if(s==null||s==="")return"—";if(typeof s=="boolean")return s?"是":"否";if(typeof s!="number")return`${s}${t?.unit??""}`;const n=t?.precision,r={maximumFractionDigits:n??2,minimumFractionDigits:n};t?.style==="currency"&&t.currency?(r.style="currency",r.currency=t.currency):t?.style==="percent"&&(r.style="percent");try{const i=t?.style==="percent"?s/100:s;return`${new Intl.NumberFormat(a,r).format(i)}${t?.unit??""}`}catch{return`${s}${t?.unit??""}`}},Pe=s=>{let t=Number.POSITIVE_INFINITY,a=Number.NEGATIVE_INFINITY;for(const n of s)t=Math.min(t,n),a=Math.max(a,n);return Number.isFinite(t)&&Number.isFinite(a)?{min:t,max:a}:{min:0,max:0}},Be=(s,t,a)=>{if(!a.onAction)return;const n=i=>{console.error("[make-ai-assistant] host action error handler failed",{actionId:s.id,artifactId:t.artifact.id,errorType:i instanceof Error?i.name:typeof i,intent:s.intent})},r=i=>{if(a.onActionError){try{Promise.resolve(a.onActionError(i,s,t)).catch(n)}catch(d){n(d)}return}console.error("[make-ai-assistant] host action failed",{actionId:s.id,artifactId:t.artifact.id,errorType:i instanceof Error?i.name:typeof i,intent:s.intent})};try{Promise.resolve(a.onAction(s,t)).catch(r)}catch(i){r(i)}},W=(s,t)=>s.actions?.length&&t.onAction?e.jsx("div",{className:"make-ai-artifact__actions",children:s.actions.map(a=>e.jsxs("button",{className:`make-ai-artifact__action make-ai-artifact__action--${a.appearance??"link"}`,type:"button",onClick:()=>Be(a,{artifact:s,context:t.context},t),children:[a.label,e.jsx("span",{"aria-hidden":"true",children:"→"})]},a.id))}):null,J=(s,t,a="")=>e.jsxs("section",{"aria-label":s.title??`${s.kind} result`,className:`make-ai-artifact ${a}`.trim(),"data-artifact-density":s.presentation?.density,"data-artifact-kind":s.kind,children:[s.title?e.jsx("h4",{className:"make-ai-artifact__title",children:s.title}):null,s.summary?e.jsx("p",{className:"make-ai-artifact__summary",children:s.summary}):null,t]}),ms=({artifact:s,renderContext:t})=>{const a=s.data.delta,n=a?L(a.value,a.format==="percent"?{style:"percent"}:void 0,t.context.locale):void 0;return J(s,e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"make-ai-artifact__metric-value",children:L(s.data.value,s.data.format,t.context.locale)}),a?e.jsxs("div",{className:`make-ai-artifact__delta make-ai-artifact__delta--${a.direction??"flat"}`,children:[e.jsx("span",{"aria-hidden":"true",children:a.direction==="up"?"↗":a.direction==="down"?"↘":"→"}),e.jsx("span",{children:n}),a.label?e.jsx("span",{children:a.label}):null]}):null,s.data.context?e.jsx("p",{className:"make-ai-artifact__context",children:s.data.context}):null,W(s,t)]}),"make-ai-artifact--metric")},ps=({artifact:s,renderContext:t})=>J(s,e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"make-ai-artifact__comparison",children:s.data.items.map(a=>e.jsxs("div",{className:"make-ai-artifact__comparison-item",children:[e.jsx("span",{children:a.label}),e.jsx("strong",{children:L(a.value,a.format,t.context.locale)}),a.hint?e.jsx("small",{children:a.hint}):null]},a.id))}),W(s,t)]}),"make-ai-artifact--comparison"),hs=({artifact:s,renderContext:t})=>{const a=s.data.series.flatMap(d=>d.points.map(h=>h.y)),{max:n,min:r}=Pe(a),i=n-r||1;return J(s,e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"make-ai-artifact__trend",children:s.data.series.map(d=>e.jsxs("div",{className:"make-ai-artifact__trend-series",children:[e.jsx("div",{className:"make-ai-artifact__trend-label",children:d.label}),e.jsx("div",{className:"make-ai-artifact__trend-bars",children:d.points.map((h,_)=>{const y=18+(h.y-r)/i*70;return e.jsxs("div",{className:"make-ai-artifact__trend-point",children:[e.jsx("span",{"aria-label":`${h.x}: ${L(h.y,d.format,t.context.locale)}`,className:"make-ai-artifact__trend-bar",role:"img",style:{height:`${y}%`},title:`${h.x}: ${L(h.y,d.format,t.context.locale)}`}),e.jsx("small",{children:h.x})]},`${h.x}-${_}`)})})]},d.id))}),W(s,t)]}),"make-ai-artifact--trend")},fs=({artifact:s,renderContext:t})=>{const{max:a}=Pe(s.data.items.map(r=>Math.abs(r.value))),n=Math.max(a,1);return J(s,e.jsxs(e.Fragment,{children:[e.jsx("ol",{className:"make-ai-artifact__ranking",children:s.data.items.map((r,i)=>e.jsxs("li",{children:[e.jsx("span",{className:"make-ai-artifact__rank",children:i+1}),e.jsxs("span",{className:"make-ai-artifact__ranking-label",children:[e.jsx("span",{children:r.label}),r.description?e.jsx("small",{children:r.description}):null]}),e.jsx("span",{className:"make-ai-artifact__ranking-track","aria-hidden":"true",children:e.jsx("span",{style:{width:`${Math.abs(r.value)/n*100}%`}})}),e.jsx("strong",{children:L(r.value,r.format,t.context.locale)})]},r.id))}),W(s,t)]}),"make-ai-artifact--ranking")},gs=(s,t)=>t.action??{id:`open-${t.id}`,label:t.title??t.id,intent:"open-record",target:{entityKey:s.data.entity.key,recordId:t.id}},_s=({artifact:s,renderContext:t})=>J(s,e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"make-ai-artifact__record-list",children:s.data.records.length===0?e.jsx("p",{className:"make-ai-artifact__empty",children:"没有符合条件的记录"}):s.data.records.map(a=>{const n=gs(s,a),r=e.jsxs(e.Fragment,{children:[e.jsx("strong",{children:a.title??a.id}),e.jsx("span",{className:"make-ai-artifact__record-values",children:s.data.columns.map(i=>e.jsxs("span",{children:[e.jsx("small",{children:i.label}),L(a.values[i.key],i.format,t.context.locale)]},i.key))}),t.onAction?e.jsx("span",{"aria-hidden":"true",children:"›"}):null]});return t.onAction?e.jsx("button",{className:"make-ai-artifact__record",type:"button",onClick:()=>Be(n,{artifact:s,context:t.context},t),children:r},a.id):e.jsx("div",{className:"make-ai-artifact__record",children:r},a.id)})}),s.data.total!==void 0?e.jsxs("p",{className:"make-ai-artifact__record-total",children:["共 ",s.data.total," 条"]}):null,W(s,t)]}),"make-ai-artifact--record-list"),xs=({artifact:s,renderContext:t})=>J(s,e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:`make-ai-artifact__notice make-ai-artifact__notice--${s.data.tone}`,children:[e.jsx("span",{"aria-hidden":"true",children:s.data.tone==="success"?"✓":s.data.tone==="warning"?"!":s.data.tone==="danger"?"×":"i"}),e.jsx("p",{children:s.data.body})]}),W(s,t)]}),"make-ai-artifact--notice"),Y=(s,t,a)=>({id:s,kinds:[t],priority:0,render:a}),js=[Y("platform.metric.default","metric",(s,t,a)=>e.jsx(ms,{artifact:s,renderContext:a})),Y("platform.comparison.default","comparison",(s,t,a)=>e.jsx(ps,{artifact:s,renderContext:a})),Y("platform.trend.default","trend",(s,t,a)=>e.jsx(hs,{artifact:s,renderContext:a})),Y("platform.ranking.default","ranking",(s,t,a)=>e.jsx(fs,{artifact:s,renderContext:a})),Y("platform.record-list.default","record-list",(s,t,a)=>e.jsx(_s,{artifact:s,renderContext:a})),Y("platform.notice.default","notice",(s,t,a)=>e.jsx(xs,{artifact:s,renderContext:a}))],qe=O.createArtifactTemplateRegistry(js).templates,De=(s=qe)=>O.createArtifactTemplateRegistry(s),As=s=>`${s}-${Date.now()}-${Math.random().toString(36).slice(2,9)}`,vs="Make",Is=["总结当前页面数据","找出需要关注的记录","列出我有权限查看的数据对象"],Ue=(s,t)=>t??`${s?.trim()||vs} AI 助手`,ys=s=>s??Is;class j extends Error{}const Oe=s=>{try{const t=s?.return?.();if(!t)return;Promise.resolve(t).catch(a=>{console.error("[make-ai-assistant] transport iterator close failed",{errorType:a instanceof Error?a.name:typeof a})})}catch(t){console.error("[make-ai-assistant] transport iterator close failed",{errorType:t instanceof Error?t.name:typeof t})}},ks=async s=>{if(globalThis.navigator?.clipboard?.writeText){await globalThis.navigator.clipboard.writeText(s);return}if(typeof document>"u"||!document.body)throw new Error("Clipboard API is unavailable");const t=document.createElement("textarea");t.value=s,t.setAttribute("readonly",""),t.style.position="fixed",t.style.inset="0 auto auto 0",t.style.opacity="0",document.body.append(t),t.select();const a=document.execCommand("copy");if(t.remove(),!a)throw new Error("Clipboard copy failed")},He=()=>e.jsxs("svg",{"aria-hidden":"true",viewBox:"0 0 24 24",children:[e.jsx("path",{d:"M12 2.8c.5 4.4 2.8 6.8 7.2 7.2-4.4.5-6.8 2.8-7.2 7.2-.5-4.4-2.8-6.8-7.2-7.2 4.4-.5 6.8-2.8 7.2-7.2Z"}),e.jsx("path",{d:"M18.3 16.1c.2 1.8 1.2 2.8 3 3-1.8.2-2.8 1.2-3 3-.2-1.8-1.2-2.8-3-3 1.8-.2 2.8-1.2 3-3Z"})]}),bs=()=>e.jsx("svg",{"aria-hidden":"true",viewBox:"0 0 24 24",children:e.jsx("path",{d:"m6 6 12 12M18 6 6 18"})}),Ns=()=>e.jsxs("svg",{"aria-hidden":"true",viewBox:"0 0 24 24",children:[e.jsx("path",{d:"M8 8h10v12H8z"}),e.jsx("path",{d:"M6 16H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"})]}),Ts=()=>e.jsxs("svg",{"aria-hidden":"true",viewBox:"0 0 24 24",children:[e.jsx("path",{d:"M20 11a8 8 0 0 0-14.7-4.4L4 8"}),e.jsx("path",{d:"M4 4v4h4"}),e.jsx("path",{d:"M4 13a8 8 0 0 0 14.7 4.4L20 16"}),e.jsx("path",{d:"M20 20v-4h-4"})]}),Ms=()=>e.jsxs("svg",{"aria-hidden":"true",viewBox:"0 0 24 24",children:[e.jsx("path",{d:"M5 10v4"}),e.jsx("path",{d:"M8 9v6l6 3V6L8 9Z"}),e.jsx("path",{d:"M17 9.2a4.2 4.2 0 0 1 0 5.6"}),e.jsx("path",{d:"M19.4 6.8a7.6 7.6 0 0 1 0 10.4"})]}),Es=()=>e.jsxs("svg",{"aria-hidden":"true",viewBox:"0 0 24 24",children:[e.jsx("path",{d:"M12 4v11"}),e.jsx("path",{d:"m7 10 5 5 5-5"}),e.jsx("path",{d:"M5 20h14"})]}),ws=()=>e.jsx("svg",{"aria-hidden":"true",viewBox:"0 0 24 24",children:e.jsx("path",{d:"M12 5v14M5 12h14"})}),Ss=()=>e.jsxs("svg",{"aria-hidden":"true",viewBox:"0 0 24 24",children:[e.jsx("path",{d:"m4 4 17 8-17 8 3-8-3-8Z"}),e.jsx("path",{d:"M7 12h14"})]}),ae=({className:s=""})=>e.jsx("span",{className:`make-ai-assistant__avatar ${s}`.trim(),"aria-hidden":"true",children:e.jsx(He,{})}),Cs=({src:s})=>s?e.jsx("span",{className:"make-ai-assistant__user-avatar","aria-hidden":"true",children:e.jsx("img",{alt:"",src:s})}):null,Rs=({userAvatarUrl:s,userName:t})=>{const a=t?.trim();return!a&&!s?null:e.jsxs("div",{className:"make-ai-assistant__message-identity",children:[a?e.jsx("span",{className:"make-ai-assistant__message-sender",children:a}):null,e.jsx(Cs,{src:s})]})},$s=s=>{const t=[],a=[],n=[],r=[],i=()=>{const _=a.join(`
|
|
2
|
+
`).trim();a.length=0,_&&t.push({type:"paragraph",text:_})},d=()=>{n.length&&t.push({type:"list",items:n.splice(0)})},h=()=>{const _=r.join(`
|
|
3
|
+
`).trim();r.length=0,_&&t.push({type:"pre",text:_})};for(const _ of s.replace(/\r\n?/g,`
|
|
4
4
|
`).split(`
|
|
5
|
-
`)){const v=f.trim();if(!v){o(),d(),u();continue}if(/^\s*\|.+\|\s*$/.test(f)){o(),d(),i.push(f.trim());continue}const x=/^\s*[-*]\s+(.+)$/.exec(f);if(x){o(),u(),r.push(x[1]?.trim()??"");continue}d(),u(),a.push(v)}return o(),d(),u(),t},Se=s=>{const t=[],a=/(\*\*[^*]+\*\*|`[^`]+`)/g;let r=0;for(const i of s.matchAll(a)){const o=i[0],d=i.index??0;d>r&&t.push(s.slice(r,d)),o.startsWith("**")?t.push(e.jsx("strong",{children:o.slice(2,-2)},`${d}-strong`)):t.push(e.jsx("code",{children:o.slice(1,-1)},`${d}-code`)),r=d+o.length}return r<s.length&&t.push(s.slice(r)),t},Ts=({content:s})=>{const t=Ns(s);return t.length?e.jsx("div",{className:"make-ai-assistant__bubble make-ai-assistant__assistant-text",children:t.map((a,r)=>a.type==="paragraph"?e.jsx("p",{children:Se(a.text)},`${r}-paragraph`):a.type==="pre"?e.jsx("pre",{children:e.jsx("code",{children:a.text})},`${r}-pre`):e.jsx("ul",{children:a.items.map((i,o)=>e.jsx("li",{children:Se(i)},`${o}-${i}`))},`${r}-list`))}):null},Ve=({assistantName:s})=>e.jsxs("div",{className:"make-ai-assistant__message-identity",children:[e.jsx(ee,{className:"make-ai-assistant__avatar--message"}),e.jsx("span",{className:"make-ai-assistant__message-sender",children:s})]}),Pe=s=>{for(let t=s.messages.length-1;t>=0;t-=1){const a=s.messages[t];if(a.role==="assistant"&&a.status==="streaming")return a.id}},Ms=s=>{for(let t=s.messages.length-1;t>=0;t-=1)if(s.messages[t].role==="user")return t;return-1},De=s=>{const t=Ms(s);if(!(t<0))for(let a=s.messages.length-1;a>t;a-=1){const r=s.messages[a];if(r.role==="assistant")return r.id}},Es=s=>{if(s.status==="idle")for(let t=s.messages.length-1;t>=0;t-=1){const a=s.messages[t];if(a.role==="assistant"&&a.status==="complete")return a.id}},Ss=s=>{for(let t=s.messages.length-1;t>=0;t-=1){const a=s.messages[t];if(a.role==="user")return a}},ws=(s,t)=>{const a=s.messages.findIndex(r=>r.id===t&&r.role==="user");return{...s,error:void 0,progress:void 0,status:"streaming",messages:a<0?s.messages:s.messages.slice(0,a+1)}},Cs=s=>s.scrollHeight-s.scrollTop-s.clientHeight<=48,Rs=(s="smooth")=>globalThis.matchMedia?.("(prefers-reduced-motion: reduce)").matches?"auto":s,Ue=({error:s,onRetry:t})=>e.jsxs("div",{className:"make-ai-assistant__message-status make-ai-assistant__message-status--error",role:"alert",children:[e.jsx("strong",{children:"本次请求未完成"}),e.jsx("span",{children:s.message}),s.retryable&&t?e.jsx("button",{className:"make-ai-assistant__retry",type:"button",onClick:t,children:"重新发送"}):null]}),Be=({active:s,steps:t})=>{if(!t?.length)return null;const a=t[t.length-1]??"处理中";return e.jsxs("details",{className:"make-ai-assistant__process",open:s,children:[e.jsxs("summary",{children:[s?e.jsxs("span",{className:"make-ai-assistant__progress",role:"status",children:[e.jsx("span",{"aria-hidden":"true"}),e.jsx("span",{children:a})]}):e.jsx("span",{className:"make-ai-assistant__process-title",children:"处理过程"}),e.jsxs("span",{className:"make-ai-assistant__process-count",children:[t.length," 步"]})]}),e.jsx("ol",{children:t.map((r,i)=>e.jsxs("li",{"data-step-active":s&&i===t.length-1?!0:void 0,children:[e.jsx("span",{"aria-hidden":"true"}),e.jsx("span",{children:r})]},`${i}-${r}`))})]})},$s=({copyFeedback:s,onCopy:t,onRegenerate:a})=>!t&&!a?null:e.jsxs("div",{className:"make-ai-assistant__reply-actions","aria-label":"回复操作",children:[t?e.jsx("button",{"aria-label":"复制回答",className:"make-ai-assistant__reply-action make-ai-assistant__reply-copy",type:"button",onClick:t,children:e.jsx(As,{})}):null,a?e.jsx("button",{className:"make-ai-assistant__reply-action make-ai-assistant__reply-regenerate",type:"button",onClick:a,children:"重新生成"}):null,s?e.jsx("span",{className:"make-ai-assistant__reply-feedback","data-copy-status":s.status,role:"status",children:s.message}):null]}),we=({assistantName:s,error:t,onRetry:a,progress:r})=>{const i=t?"error":"progress";return t?.message??r?.message?e.jsx("article",{"aria-label":`${s}的${i==="error"?"错误消息":"状态消息"}`,className:`make-ai-assistant__message make-ai-assistant__message--assistant make-ai-assistant__message--${i}`,"data-message-role":"assistant","data-message-state":i,children:e.jsxs("div",{className:"make-ai-assistant__message-turn",children:[e.jsx(Ve,{assistantName:s}),e.jsx("div",{className:"make-ai-assistant__message-stack",children:t?e.jsx(Ue,{error:t,onRetry:a}):e.jsx(Be,{active:!0,steps:r?.steps})})]})}):null},Ls=(s,t,a,r,i,o,d,u,f,v,x,$,j)=>{const N=De(s),G=Pe(s),Y=Es(s);let W;return s.messages.map(m=>{const y=m.role==="assistant",h=W;y||(W=m);const T=m.id===G,F=m.id===N?s.error:void 0,M=m.error??F,E=!y&&!!(u?.trim()||f),me=y?o:u?.trim()||"用户",L=y&&m.status==="complete"&&!M&&(m.content.trim()||m.id===Y);return e.jsx("article",{"aria-label":`${me}的消息`,className:`make-ai-assistant__message make-ai-assistant__message--${m.role}`,"data-message-role":m.role,"data-message-state":M?"error":void 0,"data-message-status":m.status,"data-message-has-identity":y||E?!0:void 0,children:e.jsxs("div",{className:"make-ai-assistant__message-turn",children:[y?e.jsx(Ve,{assistantName:o}):E?e.jsx(bs,{userAvatarUrl:f,userName:u}):null,e.jsxs("div",{className:"make-ai-assistant__message-stack",children:[m.content?y?e.jsx(Ts,{content:m.content}):e.jsx("div",{className:"make-ai-assistant__bubble",children:m.content}):m.status==="streaming"?e.jsxs("div",{className:"make-ai-assistant__typing","aria-label":`${o}正在思考`,children:[e.jsx("span",{}),e.jsx("span",{}),e.jsx("span",{})]}):null,y?e.jsx(Be,{active:T&&s.status==="streaming",steps:m.progressSteps}):null,M?e.jsx(Ue,{error:M,onRetry:F?d:void 0}):null,m.artifacts.map(se=>e.jsx(Ce,{artifact:se,context:t,onAction:r,onActionError:i,registry:a},se.id)),L?e.jsx($s,{copyFeedback:v?.messageId===m.id?{message:v.message,status:v.status}:void 0,onCopy:m.content.trim()?()=>$(m.id,m.content):void 0,onRegenerate:x&&m.id===Y&&h?()=>j({userMessage:h,assistantMessage:m}):void 0}):null]})]})},m.id)})};function qe({assistantName:s="AI 助手",brandName:t,context:a,onAction:r,onActionError:i,onClose:o,onNewConversation:d,privacyNotice:u,registry:f,subtitle:v,suggestions:x,title:$,transport:j,userAvatarUrl:N,userName:G}){const Y=Fe(t,$),W=u?.trim(),[m,y]=p.useState(""),[h,T]=p.useState(l.createAssistantConversationState),F=p.useRef(h);F.current=h;const[M,E]=p.useState(void 0),[me,L]=p.useState(void 0),[se,He]=p.useState(0),[K,te]=p.useState(()=>j.loadConversation?"loading":"ready"),[ze,V]=p.useState(!1),P=p.useRef(void 0),D=p.useRef(void 0),U=p.useRef(0),ae=p.useRef(null),O=p.useRef(!0),fe=p.useRef(a.app.id),ge=p.useMemo(()=>f??Oe(),[f]),_e=p.useMemo(()=>gs(x),[x]),ne=n=>{const _=P.current,A=D.current?.iterator;return!_&&!A?!1:(U.current+=1,P.current=void 0,D.current=void 0,console.info("[make-ai-assistant] local run cancellation requested",{reason:n}),_?.abort(),Ee(A),!0)};p.useEffect(()=>()=>{ne("unmount")},[]),p.useEffect(()=>{const n=j.loadConversation,_=fe.current!==a.app.id;if(fe.current=a.app.id,ne("reinitialize"),_&&(y(""),O.current=!0),E(void 0),L(void 0),V(!1),T(l.createAssistantConversationState()),!n){te("ready");return}const A=new AbortController;return te("loading"),console.info("[make-ai-assistant] conversation load start",{appId:a.app.id}),n.call(j,a,{signal:A.signal}).then(k=>{A.signal.aborted||(T(l.createAssistantConversationState(k)),te("ready"),console.info("[make-ai-assistant] conversation load success",{appId:a.app.id,messageCount:k.messages.length}))}).catch(k=>{A.signal.aborted||(console.error("[make-ai-assistant] conversation load failed",{appId:a.app.id,errorType:k instanceof Error?k.name:typeof k}),te("error"))}),()=>A.abort()},[a.app.id,se,j]),p.useEffect(()=>{const n=ae.current;if(!n||!O.current)return;V(!1);const _=requestAnimationFrame(()=>{if(!O.current)return;const A=h.status==="streaming"||globalThis.matchMedia?.("(prefers-reduced-motion: reduce)").matches?"auto":"smooth";typeof n.scrollTo=="function"?n.scrollTo({top:n.scrollHeight,behavior:A}):n.scrollTop=n.scrollHeight});return()=>cancelAnimationFrame(_)},[h.messages,h.progress,h.status]);const Ze=()=>{const n=ae.current;if(!n)return;const _=Cs(n);O.current=_,V(!_&&F.current.messages.length>0)},Ge=()=>{const n=ae.current;if(!n)return;O.current=!0,V(!1);const _=Rs();typeof n.scrollTo=="function"?n.scrollTo({top:n.scrollHeight,behavior:_}):n.scrollTop=n.scrollHeight},xe=async(n,_)=>{const A=n.trim(),k=F.current,S=_?.regenerateFrom,ue=j.regenerate;if(!A||K!=="ready"||k.status==="streaming"||P.current||S&&!ue)return;if(l.countCodePointsUpTo(A,l.MAKE_AI_CONVERSATION_LIMITS.messageCharacters)>l.MAKE_AI_CONVERSATION_LIMITS.messageCharacters){E(`输入内容过长,请控制在 ${l.MAKE_AI_CONVERSATION_LIMITS.messageCharacters} 个字符以内`);return}const oe={id:S?.userMessage.id??ps("user"),content:A},ce=S?ws(k,S.userMessage.id):l.appendUserMessage(k,oe),le=new AbortController,B=U.current+1;U.current=B,P.current=le,E(void 0),L(void 0),V(!O.current&&k.messages.length>0),S||y(""),T(ce);try{let w=!1,I,je=0,ve=0,Ie=0,pe=0,J=0;const Q=new Map,ye=new Set,ke=new Set([...ce.messages.map(de=>de.id),oe.id]),X=new Set,be=R.createArtifactCapabilities(ge),Ne={signal:le.signal};let he;if(S){if(!ue)throw new g("当前 AI 助手不支持重新生成");he=ue({threadId:ce.threadId,message:oe,assistantMessage:{id:S.assistantMessage.id,content:S.assistantMessage.content},context:a,capabilities:be},Ne)}else he=j.run({threadId:ce.threadId,message:oe,context:a,capabilities:be},Ne);const Te=he[Symbol.asyncIterator]();for(D.current={iterator:Te,requestVersion:B};;){const de=await Te.next();if(U.current!==B||de.done)break;let c;try{c=l.parseAssistantEvent(de.value)}catch(b){throw new g(b instanceof Error?b.message:"Invalid assistant event")}if(c.type==="message.start"){if(I!==void 0&&I!==c.runId)throw new g("AI 助手响应 run id 不一致");if(I??=c.runId,ve+=1,ve>l.MAKE_AI_CONVERSATION_LIMITS.assistantMessagesPerRun)throw new g("AI 助手单次响应消息数量超过限制");if(ke.has(c.messageId))throw new g("AI 助手响应包含重复的 message id");ke.add(c.messageId),X.add(c.messageId),Q.set(c.messageId,0)}if(c.type==="message.delta"){if(!X.has(c.messageId))throw new g("AI 助手响应事件顺序无效");const b=Q.get(c.messageId)??0,q=l.countCodePointsUpTo(c.delta,l.MAKE_AI_CONVERSATION_LIMITS.messageCharacters-J);if(J+q>l.MAKE_AI_CONVERSATION_LIMITS.messageCharacters)throw new g("AI 助手响应文本超过大小限制");J+=q,Q.set(c.messageId,b+q)}if(c.type==="message.replace"){if(!X.has(c.messageId))throw new g("AI 助手响应事件顺序无效");const b=Q.get(c.messageId)??0,q=l.countCodePointsUpTo(c.content,l.MAKE_AI_CONVERSATION_LIMITS.messageCharacters),Me=J-b+q;if(Me>l.MAKE_AI_CONVERSATION_LIMITS.messageCharacters)throw new g("AI 助手响应文本超过大小限制");J=Me,Q.set(c.messageId,q)}if(c.type==="run.progress"){if(I!==void 0&&I!==c.runId)throw new g("AI 助手响应 run id 不一致");if(I??=c.runId,Ie+=1,Ie>l.MAKE_AI_CONVERSATION_LIMITS.progressStepsPerRun)throw new g("AI 助手处理过程数量超过限制");const b=l.countCodePointsUpTo(c.message,l.MAKE_AI_CONVERSATION_LIMITS.progressCharactersPerRun-pe);if(pe+b>l.MAKE_AI_CONVERSATION_LIMITS.progressCharactersPerRun)throw new g("AI 助手处理过程文本超过大小限制");pe+=b}if(c.type==="artifact"){if(!X.has(c.messageId))throw new g("AI 助手响应事件顺序无效");if(je+=1,je>l.MAKE_AI_CONVERSATION_LIMITS.artifactsPerRun)throw new g("AI 助手单次响应 Artifact 数量超过限制");if(ye.has(c.artifact.id))throw new g("AI 助手响应包含重复的 Artifact id");ye.add(c.artifact.id)}if(c.type==="message.complete"&&!X.delete(c.messageId))throw new g("AI 助手响应事件顺序无效");if(c.type==="run.complete"&&I!==void 0&&I!==c.runId)throw new g("AI 助手响应 run id 不一致");if(c.type==="run.cancelled"&&c.runId!==void 0&&I!==void 0&&I!==c.runId)throw new g("AI 助手响应 run id 不一致");if(T(b=>l.reduceAssistantEvent(b,c)),c.type==="error"||c.type==="run.cancelled"||c.type==="run.complete"){w=!0;break}}if(!w)throw new g("AI 助手流式响应在终止事件前结束")}catch(w){if(U.current!==B)return;if(le.signal.aborted){T(I=>l.reduceAssistantEvent(I,{type:"run.cancelled"}));return}console.error("[make-ai-assistant] assistant run failed",{appId:a.app.id,errorType:w instanceof Error?w.name:typeof w}),T(I=>l.reduceAssistantEvent(I,{type:"error",code:"TRANSPORT_ERROR",message:w instanceof g?w.message:"连接失败,请重试",retryable:!0}))}finally{U.current===B&&P.current===le&&(P.current=void 0),D.current?.requestVersion===B&&(Ee(D.current.iterator),D.current=void 0)}},re=n=>xe(n),Ye=n=>xe(n.userMessage.content,{regenerateFrom:n}),We=async(n,_)=>{try{await _s(_),L({messageId:n,message:"已复制",status:"success"})}catch(A){console.error("[make-ai-assistant] copy answer failed",{errorType:A instanceof Error?A.name:typeof A}),L({messageId:n,message:"复制失败",status:"error"})}},Je=n=>{n.preventDefault(),re(m)},Qe=n=>{n.key==="Enter"&&!n.shiftKey&&!n.nativeEvent.isComposing&&(n.preventDefault(),re(m))},Xe=()=>{ne("stop")&&T(n=>l.reduceAssistantEvent(n,{type:"run.cancelled"}))},es=()=>{ne("new-conversation"),y(""),E(void 0),L(void 0),V(!1),O.current=!0,T(l.createAssistantConversationState()),d?.()},ss=j.features?.remoteCancellation===!1?"停止接收":"停止生成",ts=Pe(h),as=De(h),ie=Ss(h),ns=typeof j.regenerate=="function"&&j.features?.regeneration!==!1,Ae=()=>{ie&&re(ie.content)};return e.jsxs("section",{className:"make-ai-assistant make-ai-assistant__panel",children:[e.jsxs("header",{className:"make-ai-assistant__header",children:[e.jsx(ee,{}),e.jsxs("div",{children:[e.jsx("h2",{children:Y}),e.jsx("p",{children:v??`当前应用:${a.app.name??"未命名应用"}`})]}),e.jsxs("div",{className:"make-ai-assistant__header-actions",children:[j.features?.newConversation!==!1?e.jsx("button",{"aria-label":"新建对话",className:"make-ai-assistant__icon-button",type:"button",onClick:es,children:e.jsx(Is,{})}):null,o?e.jsx("button",{"aria-label":`关闭 ${Y}`,className:"make-ai-assistant__icon-button",type:"button",onClick:o,children:e.jsx(xs,{})}):null]})]}),W?e.jsxs("div",{className:"make-ai-assistant__privacy-note",role:"note",children:[e.jsx("span",{className:"make-ai-assistant__privacy-icon","aria-hidden":"true",children:e.jsx(js,{})}),e.jsx("span",{children:W})]}):null,e.jsxs("div",{className:"make-ai-assistant__body","aria-live":"polite","aria-relevant":"additions text",ref:ae,role:"log",onScroll:Ze,children:[K==="loading"?e.jsxs("div",{className:"make-ai-assistant__empty",role:"status",children:[e.jsx(ee,{}),e.jsx("h3",{children:"正在恢复对话"}),e.jsx("p",{children:"正在读取当前 App 的历史消息…"})]}):K==="error"?e.jsxs("div",{className:"make-ai-assistant__empty",role:"alert",children:[e.jsx(ee,{}),e.jsx("h3",{children:"暂时无法加载对话"}),e.jsx("p",{children:"请检查网络后重试。"}),e.jsx("button",{className:"make-ai-assistant__retry",type:"button",onClick:()=>He(n=>n+1),children:"重新加载"})]}):h.messages.length===0?e.jsxs("div",{className:"make-ai-assistant__empty",children:[e.jsx(ee,{}),e.jsx("h3",{children:"有什么可以帮你?"}),e.jsx("p",{children:"我会结合当前 App、页面位置和宿主允许的上下文回答,并把过程与结果分开展示。"})]}):Ls(h,a,ge,r,i,s,ie?Ae:void 0,G,N,me,ns,(n,_)=>{We(n,_)},n=>{Ye(n)}),h.progress&&!ts?e.jsx(we,{assistantName:s,progress:h.progress}):null,h.error&&!as?e.jsx(we,{assistantName:s,error:h.error,onRetry:ie?Ae:void 0}):null]}),ze?e.jsx("button",{"aria-label":"回到最新消息",className:"make-ai-assistant__back-to-latest",type:"button",onClick:Ge,children:e.jsx(vs,{})}):null,e.jsxs("footer",{className:"make-ai-assistant__composer-region",children:[K==="ready"&&_e.length>0&&h.messages.length===0?e.jsx("div",{className:"make-ai-assistant__suggestions","aria-label":"推荐问题",children:_e.map((n,_)=>e.jsx("button",{type:"button",onClick:()=>{re(n)},children:n},`${_}-${n}`))}):null,e.jsxs("form",{className:"make-ai-assistant__composer",onSubmit:Je,children:[e.jsx("textarea",{"aria-label":`向 ${s} 提问`,"aria-describedby":M?"make-ai-composer-error":void 0,"aria-invalid":M?!0:void 0,autoFocus:!0,disabled:K!=="ready"||h.status==="streaming",placeholder:`询问当前 ${a.app.name??"App"} 中的数据…`,rows:2,value:m,onChange:n=>{y(n.currentTarget.value),E(void 0)},onKeyDown:Qe}),h.status==="streaming"?e.jsx("button",{"aria-label":ss,className:"make-ai-assistant__send make-ai-assistant__send--stop",type:"button",onClick:Xe,children:e.jsx("span",{"aria-hidden":"true"})}):e.jsx("button",{"aria-label":"发送",className:"make-ai-assistant__send",disabled:K!=="ready"||!m.trim(),type:"submit",children:e.jsx(ys,{})})]}),M?e.jsx("p",{id:"make-ai-composer-error",role:"alert",children:M}):null,e.jsx("p",{children:"AI 生成的结果可能存在偏差,重要数据请核对明细。"})]})]})}function Os({defaultOpen:s=!1,hideLauncher:t=!1,launcher:a,onOpenChange:r,open:i,...o}){const d=Fe(o.brandName,o.title),[u,f]=p.useState(s),v=p.useRef(null),x=i??u,$=N=>{i===void 0&&f(N),r?.(N),N||requestAnimationFrame(()=>v.current?.focus())},j=()=>$(!x);return p.useEffect(()=>{if(!x)return;const N=G=>{G.key==="Escape"&&($(!1),requestAnimationFrame(()=>v.current?.focus()))};return document.addEventListener("keydown",N),()=>document.removeEventListener("keydown",N)},[r,x]),e.jsxs("div",{className:"make-ai-assistant","data-open":x||void 0,children:[!t&&(!x||a)?a?a({open:x,toggle:j}):e.jsxs("button",{"aria-label":x?`关闭 ${d}`:`打开 ${d}`,"aria-expanded":x,className:"make-ai-assistant__launcher",ref:v,type:"button",onClick:j,children:[e.jsx("span",{className:"make-ai-assistant__launcher-orbit","aria-hidden":"true"}),e.jsx(Ke,{})]}):null,x?e.jsx("aside",{"aria-label":d,"aria-modal":"false",className:"make-ai-assistant__drawer",role:"dialog",children:e.jsx(qe,{...o,onClose:()=>$(!1)})}):null]})}exports.createArtifactCapabilities=R.createArtifactCapabilities;exports.createArtifactTemplateRegistry=R.createArtifactTemplateRegistry;exports.extendArtifactTemplateRegistry=R.extendArtifactTemplateRegistry;exports.resolveArtifactTemplate=R.resolveArtifactTemplate;exports.MAKE_AI_ARTIFACT_KINDS=l.MAKE_AI_ARTIFACT_KINDS;exports.MAKE_AI_ARTIFACT_LIMITS=l.MAKE_AI_ARTIFACT_LIMITS;exports.MAKE_AI_ARTIFACT_SCHEMA_VERSION=l.MAKE_AI_ARTIFACT_SCHEMA_VERSION;exports.MAKE_AI_CONVERSATION_LIMITS=l.MAKE_AI_CONVERSATION_LIMITS;exports.appendUserMessage=l.appendUserMessage;exports.createAssistantConversationState=l.createAssistantConversationState;exports.parseArtifact=l.parseArtifact;exports.parseAssistantEvent=l.parseAssistantEvent;exports.reduceAssistantEvent=l.reduceAssistantEvent;exports.validateArtifact=l.validateArtifact;exports.ArtifactRenderer=Ce;exports.AssistantPanel=qe;exports.MakeAiAssistant=Os;exports.createPlatformArtifactRegistry=Oe;exports.formatArtifactValue=C;exports.platformArtifactTemplates=Le;
|
|
5
|
+
`)){const y=_.trim();if(!y){i(),d(),h();continue}const T=/^(#{1,6})\s+(.+)$/.exec(y);if(T){i(),d(),h();const m=(T[2]??"").replace(/\s+#+\s*$/,"").trim();m&&t.push({type:"heading",level:T[1]?.length,text:m});continue}if(/^\s*\|.+\|\s*$/.test(_)){i(),d(),r.push(_.trim());continue}const M=/^\s*[-*]\s+(.+)$/.exec(_);if(M){i(),h(),n.push(M[1]?.trim()??"");continue}d(),h(),a.push(y)}return i(),d(),h(),t},fe=s=>{const t=[],a=/(\*\*[^*]+\*\*|`[^`]+`)/g;let n=0;for(const r of s.matchAll(a)){const i=r[0],d=r.index??0;d>n&&t.push(s.slice(n,d)),i.startsWith("**")?t.push(e.jsx("strong",{children:i.slice(2,-2)},`${d}-strong`)):t.push(e.jsx("code",{children:i.slice(1,-1)},`${d}-code`)),n=d+i.length}return n<s.length&&t.push(s.slice(n)),t},Ls=({content:s})=>{const t=$s(s);return t.length?e.jsx("div",{className:"make-ai-assistant__bubble make-ai-assistant__assistant-text",children:t.map((a,n)=>{if(a.type==="heading"){const r=a.level<=2?"h3":"h4";return e.jsx(r,{className:`make-ai-assistant__markdown-heading make-ai-assistant__markdown-heading--${a.level}`,children:fe(a.text)},`${n}-heading`)}return a.type==="paragraph"?e.jsx("p",{children:fe(a.text)},`${n}-paragraph`):a.type==="pre"?e.jsx("pre",{children:e.jsx("code",{children:a.text})},`${n}-pre`):e.jsx("ul",{children:a.items.map((r,i)=>e.jsx("li",{children:fe(r)},`${i}-${r}`))},`${n}-list`)})}):null},ze=({assistantName:s})=>e.jsxs("div",{className:"make-ai-assistant__message-identity",children:[e.jsx(ae,{className:"make-ai-assistant__avatar--message"}),e.jsx("span",{className:"make-ai-assistant__message-sender",children:s})]}),Ze=s=>{for(let t=s.messages.length-1;t>=0;t-=1){const a=s.messages[t];if(a.role==="assistant"&&a.status==="streaming")return a.id}},Os=s=>{for(let t=s.messages.length-1;t>=0;t-=1)if(s.messages[t].role==="user")return t;return-1},Ge=s=>{const t=Os(s);if(!(t<0))for(let a=s.messages.length-1;a>t;a-=1){const n=s.messages[a];if(n.role==="assistant")return n.id}},Fs=s=>{if(s.status==="idle")for(let t=s.messages.length-1;t>=0;t-=1){const a=s.messages[t];if(a.role==="assistant"&&a.status==="complete")return a.id}},Vs=s=>{for(let t=s.messages.length-1;t>=0;t-=1){const a=s.messages[t];if(a.role==="user")return a}},Ks=(s,t)=>{const a=s.messages.findIndex(n=>n.id===t&&n.role==="user");return{...s,error:void 0,progress:void 0,status:"streaming",messages:a<0?s.messages:s.messages.slice(0,a+1)}},Ps=s=>s.scrollHeight-s.scrollTop-s.clientHeight<=48,Fe=(s="smooth")=>globalThis.matchMedia?.("(prefers-reduced-motion: reduce)").matches?"auto":s,ge=(s,t)=>{typeof s.scrollTo=="function"?s.scrollTo({top:s.scrollHeight,behavior:t}):s.scrollTop=s.scrollHeight},Ye=({error:s,onRetry:t})=>e.jsxs("div",{className:"make-ai-assistant__message-status make-ai-assistant__message-status--error",role:"alert",children:[e.jsx("strong",{children:"本次请求未完成"}),e.jsx("span",{children:s.message}),s.retryable&&t?e.jsx("button",{className:"make-ai-assistant__retry",type:"button",onClick:t,children:"重新发送"}):null]}),We=({active:s,steps:t})=>{if(!t?.length)return null;const a=t[t.length-1]??"处理中";return e.jsxs("details",{className:"make-ai-assistant__process",open:s,children:[e.jsxs("summary",{children:[s?e.jsxs("span",{className:"make-ai-assistant__progress",role:"status",children:[e.jsx("span",{"aria-hidden":"true"}),e.jsx("span",{children:a})]}):e.jsx("span",{className:"make-ai-assistant__process-title",children:"处理过程"}),e.jsxs("span",{className:"make-ai-assistant__process-count",children:[t.length," 步"]})]}),e.jsx("ol",{children:t.map((n,r)=>e.jsxs("li",{"data-step-active":s&&r===t.length-1?!0:void 0,children:[e.jsx("span",{"aria-hidden":"true"}),e.jsx("span",{children:n})]},`${r}-${n}`))})]})},Bs=({copyFeedback:s,onCopy:t,onRegenerate:a})=>!t&&!a?null:e.jsxs("div",{className:"make-ai-assistant__reply-actions","aria-label":"回复操作",children:[t?e.jsx("button",{"aria-label":"复制回答",className:"make-ai-assistant__reply-action make-ai-assistant__reply-copy","data-tooltip":"复制",type:"button",onClick:t,children:e.jsx(Ns,{})}):null,a?e.jsx("button",{"aria-label":"重新生成",className:"make-ai-assistant__reply-action make-ai-assistant__reply-regenerate","data-tooltip":"重新生成",type:"button",onClick:a,children:e.jsx(Ts,{})}):null,s?e.jsx("span",{className:"make-ai-assistant__reply-feedback","data-copy-status":s.status,role:"status",children:s.message}):null]}),Ve=({assistantName:s,error:t,onRetry:a,progress:n})=>{const r=t?"error":"progress";return t?.message??n?.message?e.jsx("article",{"aria-label":`${s}的${r==="error"?"错误消息":"状态消息"}`,className:`make-ai-assistant__message make-ai-assistant__message--assistant make-ai-assistant__message--${r}`,"data-message-role":"assistant","data-message-state":r,children:e.jsxs("div",{className:"make-ai-assistant__message-turn",children:[e.jsx(ze,{assistantName:s}),e.jsx("div",{className:"make-ai-assistant__message-stack",children:t?e.jsx(Ye,{error:t,onRetry:a}):e.jsx(We,{active:!0,steps:n?.steps})})]})}):null},qs=(s,t,a,n,r,i,d,h,_,y,T,M,m)=>{const F=Ge(s),q=Ze(s),v=Fs(s);let V;return s.messages.map(p=>{const k=p.role==="assistant",K=V;k||(V=p);const x=p.id===q,b=p.id===F?s.error:void 0,E=p.error??b,P=!k&&!!(h?.trim()||_),B=k?i:h?.trim()||"用户",me=k&&p.status==="complete"&&!E&&(p.content.trim()||p.id===v);return e.jsx("article",{"aria-label":`${B}的消息`,className:`make-ai-assistant__message make-ai-assistant__message--${p.role}`,"data-message-role":p.role,"data-message-state":E?"error":void 0,"data-message-status":p.status,"data-message-has-identity":k||P?!0:void 0,children:e.jsxs("div",{className:"make-ai-assistant__message-turn",children:[k?e.jsx(ze,{assistantName:i}):P?e.jsx(Rs,{userAvatarUrl:_,userName:h}):null,e.jsxs("div",{className:"make-ai-assistant__message-stack",children:[p.content?k?e.jsx(Ls,{content:p.content}):e.jsx("div",{className:"make-ai-assistant__bubble",children:p.content}):p.status==="streaming"?e.jsxs("div",{className:"make-ai-assistant__typing","aria-label":`${i}正在思考`,children:[e.jsx("span",{}),e.jsx("span",{}),e.jsx("span",{})]}):null,k?e.jsx(We,{active:x&&s.status==="streaming",steps:p.progressSteps}):null,E?e.jsx(Ye,{error:E,onRetry:b?d:void 0}):null,p.artifacts.map(S=>e.jsx(Ke,{artifact:S,context:t,onAction:n,onActionError:r,registry:a},S.id)),me?e.jsx(Bs,{copyFeedback:y?.messageId===p.id?{message:y.message,status:y.status}:void 0,onCopy:p.content.trim()?()=>M(p.id,p.content):void 0,onRegenerate:T&&p.id===v&&K?()=>m({userMessage:K,assistantMessage:p}):void 0}):null]})]})},p.id)})};function Je({assistantName:s="AI 助手",brandName:t,context:a,onAction:n,onActionError:r,onClose:i,onNewConversation:d,privacyNotice:h,registry:_,subtitle:y,suggestions:T,title:M,transport:m,userAvatarUrl:F,userName:q,visible:v}){const V=Ue(t,M),p=h?.trim(),[k,K]=u.useState(""),[x,b]=u.useState(l.createAssistantConversationState),E=u.useRef(x);E.current=x;const[P,B]=u.useState(void 0),[me,S]=u.useState(void 0),[Qe,Xe]=u.useState(0),[D,ne]=u.useState(()=>m.loadConversation?"loading":"ready"),[es,C]=u.useState(!1),U=u.useRef(void 0),H=u.useRef(void 0),z=u.useRef(0),_e=u.useRef(null),Q=u.useRef(null),xe=u.useRef(null),je=u.useRef(null),R=u.useRef(!0),Ae=u.useRef(a.app.id),ve=u.useRef(v),Ie=u.useMemo(()=>_??De(),[_]),ye=u.useMemo(()=>ys(T),[T]),re=o=>{const f=U.current,g=H.current?.iterator;return!f&&!g?!1:(z.current+=1,U.current=void 0,H.current=void 0,console.info("[make-ai-assistant] local run cancellation requested",{reason:o}),f?.abort(),Oe(g),!0)};u.useEffect(()=>()=>{re("unmount")},[]),u.useEffect(()=>{const o=m.loadConversation,f=Ae.current!==a.app.id;if(Ae.current=a.app.id,re("reinitialize"),f&&(K(""),R.current=!0),B(void 0),S(void 0),C(!1),b(l.createAssistantConversationState()),!o){ne("ready");return}const g=new AbortController;return ne("loading"),console.info("[make-ai-assistant] conversation load start",{appId:a.app.id}),o.call(m,a,{signal:g.signal}).then(A=>{g.signal.aborted||(b(l.createAssistantConversationState(A)),ne("ready"),console.info("[make-ai-assistant] conversation load success",{appId:a.app.id,messageCount:A.messages.length}))}).catch(A=>{g.signal.aborted||(console.error("[make-ai-assistant] conversation load failed",{appId:a.app.id,errorType:A instanceof Error?A.name:typeof A}),ne("error"))}),()=>g.abort()},[a.app.id,Qe,m]),u.useEffect(()=>{const o=Q.current;if(!o||!R.current)return;C(!1);const f=requestAnimationFrame(()=>{if(!R.current)return;const g=x.status==="streaming"||globalThis.matchMedia?.("(prefers-reduced-motion: reduce)").matches?"auto":"smooth";ge(o,g)});return()=>cancelAnimationFrame(f)},[x.messages,x.progress,x.status]),u.useEffect(()=>{const o=v&&!ve.current;if(ve.current=v,!o)return;const f=requestAnimationFrame(()=>{const g=Q.current;if(g&&R.current){C(!1);const X=E.current.status==="streaming"?"auto":Fe();ge(g,X)}else g&&C(E.current.messages.length>0);const A=xe.current;(A&&!A.disabled?A:je.current??_e.current?.querySelector("button:not(:disabled)"))?.focus()});return()=>cancelAnimationFrame(f)},[v]);const ss=()=>{const o=Q.current;if(!o)return;const f=Ps(o);R.current=f,C(!f&&E.current.messages.length>0)},ts=()=>{const o=Q.current;if(!o)return;R.current=!0,C(!1);const f=Fe();ge(o,f)},ke=async(o,f)=>{const g=o.trim(),A=E.current,w=f?.regenerateFrom,X=m.regenerate;if(!g||D!=="ready"||A.status==="streaming"||U.current||w&&!X)return;if(l.countCodePointsUpTo(g,l.MAKE_AI_CONVERSATION_LIMITS.messageCharacters)>l.MAKE_AI_CONVERSATION_LIMITS.messageCharacters){B(`输入内容过长,请控制在 ${l.MAKE_AI_CONVERSATION_LIMITS.messageCharacters} 个字符以内`);return}const ce={id:w?.userMessage.id??As("user"),content:g},le=w?Ks(A,w.userMessage.id):l.appendUserMessage(A,ce),de=new AbortController,Z=z.current+1;z.current=Z,U.current=de,B(void 0),S(void 0),C(!R.current&&A.messages.length>0),w||K(""),b(le);try{let $=!1,I,Te=0,Me=0,Ee=0,pe=0,ee=0;const se=new Map,we=new Set,Se=new Set([...le.messages.map(ue=>ue.id),ce.id]),te=new Set,Ce=O.createArtifactCapabilities(Ie),Re={signal:de.signal};let he;if(w){if(!X)throw new j("当前 AI 助手不支持重新生成");he=X({threadId:le.threadId,message:ce,assistantMessage:{id:w.assistantMessage.id,content:w.assistantMessage.content},context:a,capabilities:Ce},Re)}else he=m.run({threadId:le.threadId,message:ce,context:a,capabilities:Ce},Re);const $e=he[Symbol.asyncIterator]();for(H.current={iterator:$e,requestVersion:Z};;){const ue=await $e.next();if(z.current!==Z||ue.done)break;let c;try{c=l.parseAssistantEvent(ue.value)}catch(N){throw new j(N instanceof Error?N.message:"Invalid assistant event")}if(c.type==="message.start"){if(I!==void 0&&I!==c.runId)throw new j("AI 助手响应 run id 不一致");if(I??=c.runId,Me+=1,Me>l.MAKE_AI_CONVERSATION_LIMITS.assistantMessagesPerRun)throw new j("AI 助手单次响应消息数量超过限制");if(Se.has(c.messageId))throw new j("AI 助手响应包含重复的 message id");Se.add(c.messageId),te.add(c.messageId),se.set(c.messageId,0)}if(c.type==="message.delta"){if(!te.has(c.messageId))throw new j("AI 助手响应事件顺序无效");const N=se.get(c.messageId)??0,G=l.countCodePointsUpTo(c.delta,l.MAKE_AI_CONVERSATION_LIMITS.messageCharacters-ee);if(ee+G>l.MAKE_AI_CONVERSATION_LIMITS.messageCharacters)throw new j("AI 助手响应文本超过大小限制");ee+=G,se.set(c.messageId,N+G)}if(c.type==="message.replace"){if(!te.has(c.messageId))throw new j("AI 助手响应事件顺序无效");const N=se.get(c.messageId)??0,G=l.countCodePointsUpTo(c.content,l.MAKE_AI_CONVERSATION_LIMITS.messageCharacters),Le=ee-N+G;if(Le>l.MAKE_AI_CONVERSATION_LIMITS.messageCharacters)throw new j("AI 助手响应文本超过大小限制");ee=Le,se.set(c.messageId,G)}if(c.type==="run.progress"){if(I!==void 0&&I!==c.runId)throw new j("AI 助手响应 run id 不一致");if(I??=c.runId,Ee+=1,Ee>l.MAKE_AI_CONVERSATION_LIMITS.progressStepsPerRun)throw new j("AI 助手处理过程数量超过限制");const N=l.countCodePointsUpTo(c.message,l.MAKE_AI_CONVERSATION_LIMITS.progressCharactersPerRun-pe);if(pe+N>l.MAKE_AI_CONVERSATION_LIMITS.progressCharactersPerRun)throw new j("AI 助手处理过程文本超过大小限制");pe+=N}if(c.type==="artifact"){if(!te.has(c.messageId))throw new j("AI 助手响应事件顺序无效");if(Te+=1,Te>l.MAKE_AI_CONVERSATION_LIMITS.artifactsPerRun)throw new j("AI 助手单次响应 Artifact 数量超过限制");if(we.has(c.artifact.id))throw new j("AI 助手响应包含重复的 Artifact id");we.add(c.artifact.id)}if(c.type==="message.complete"&&!te.delete(c.messageId))throw new j("AI 助手响应事件顺序无效");if(c.type==="run.complete"&&I!==void 0&&I!==c.runId)throw new j("AI 助手响应 run id 不一致");if(c.type==="run.cancelled"&&c.runId!==void 0&&I!==void 0&&I!==c.runId)throw new j("AI 助手响应 run id 不一致");if(b(N=>l.reduceAssistantEvent(N,c)),c.type==="error"||c.type==="run.cancelled"||c.type==="run.complete"){$=!0;break}}if(!$)throw new j("AI 助手流式响应在终止事件前结束")}catch($){if(z.current!==Z)return;if(de.signal.aborted){b(I=>l.reduceAssistantEvent(I,{type:"run.cancelled"}));return}console.error("[make-ai-assistant] assistant run failed",{appId:a.app.id,errorType:$ instanceof Error?$.name:typeof $}),b(I=>l.reduceAssistantEvent(I,{type:"error",code:"TRANSPORT_ERROR",message:$ instanceof j?$.message:"连接失败,请重试",retryable:!0}))}finally{z.current===Z&&U.current===de&&(U.current=void 0),H.current?.requestVersion===Z&&(Oe(H.current.iterator),H.current=void 0)}},ie=o=>ke(o),as=o=>ke(o.userMessage.content,{regenerateFrom:o}),ns=async(o,f)=>{try{await ks(f),S({messageId:o,message:"已复制",status:"success"})}catch(g){console.error("[make-ai-assistant] copy answer failed",{errorType:g instanceof Error?g.name:typeof g}),S({messageId:o,message:"复制失败",status:"error"})}},rs=o=>{o.preventDefault(),ie(k)},is=o=>{o.key==="Enter"&&!o.shiftKey&&!o.nativeEvent.isComposing&&(o.preventDefault(),ie(k))},os=()=>{re("stop")&&b(o=>l.reduceAssistantEvent(o,{type:"run.cancelled"}))},cs=()=>{re("new-conversation"),K(""),B(void 0),S(void 0),C(!1),R.current=!0,b(l.createAssistantConversationState()),d?.()},be=m.features?.remoteCancellation===!1?"停止接收":"停止生成",ls=Ze(x),ds=Ge(x),oe=Vs(x),us=typeof m.regenerate=="function"&&m.features?.regeneration!==!1,Ne=()=>{oe&&ie(oe.content)};return e.jsxs("section",{className:"make-ai-assistant make-ai-assistant__panel",ref:_e,children:[e.jsxs("header",{className:"make-ai-assistant__header",children:[e.jsx(ae,{}),e.jsxs("div",{children:[e.jsx("h2",{children:V}),e.jsx("p",{children:y??`当前应用:${a.app.name??"未命名应用"}`})]}),e.jsxs("div",{className:"make-ai-assistant__header-actions",children:[m.features?.newConversation!==!1?e.jsx("button",{"aria-label":"新建对话",className:"make-ai-assistant__icon-button",type:"button",onClick:cs,children:e.jsx(ws,{})}):null,i?e.jsx("button",{"aria-label":`关闭 ${V}`,className:"make-ai-assistant__icon-button",type:"button",onClick:i,children:e.jsx(bs,{})}):null]})]}),p?e.jsxs("div",{className:"make-ai-assistant__privacy-note",role:"note",children:[e.jsx("span",{className:"make-ai-assistant__privacy-icon","aria-hidden":"true",children:e.jsx(Ms,{})}),e.jsx("span",{children:p})]}):null,e.jsxs("div",{className:"make-ai-assistant__body","aria-live":"polite","aria-relevant":"additions text",ref:Q,role:"log",onScroll:ss,children:[D==="loading"?e.jsxs("div",{className:"make-ai-assistant__empty",role:"status",children:[e.jsx(ae,{}),e.jsx("h3",{children:"正在恢复对话"}),e.jsx("p",{children:"正在读取当前 App 的历史消息…"})]}):D==="error"?e.jsxs("div",{className:"make-ai-assistant__empty",role:"alert",children:[e.jsx(ae,{}),e.jsx("h3",{children:"暂时无法加载对话"}),e.jsx("p",{children:"请检查网络后重试。"}),e.jsx("button",{className:"make-ai-assistant__retry",type:"button",onClick:()=>Xe(o=>o+1),children:"重新加载"})]}):x.messages.length===0?e.jsxs("div",{className:"make-ai-assistant__empty",children:[e.jsx(ae,{}),e.jsx("h3",{children:"有什么可以帮你?"}),e.jsx("p",{children:"我会结合当前 App、页面位置和宿主允许的上下文回答,并把过程与结果分开展示。"})]}):qs(x,a,Ie,n,r,s,oe?Ne:void 0,q,F,me,us,(o,f)=>{ns(o,f)},o=>{as(o)}),x.progress&&!ls?e.jsx(Ve,{assistantName:s,progress:x.progress}):null,x.error&&!ds?e.jsx(Ve,{assistantName:s,error:x.error,onRetry:oe?Ne:void 0}):null]}),es?e.jsx("button",{"aria-label":"回到最新消息",className:"make-ai-assistant__back-to-latest",type:"button",onClick:ts,children:e.jsx(Es,{})}):null,e.jsxs("footer",{className:"make-ai-assistant__composer-region",children:[D==="ready"&&ye.length>0&&x.messages.length===0?e.jsx("div",{className:"make-ai-assistant__suggestions","aria-label":"推荐问题",children:ye.map((o,f)=>e.jsx("button",{type:"button",onClick:()=>{ie(o)},children:o},`${f}-${o}`))}):null,e.jsxs("form",{className:"make-ai-assistant__composer",onSubmit:rs,children:[e.jsx("textarea",{"aria-label":`向 ${s} 提问`,"aria-describedby":P?"make-ai-composer-error":void 0,"aria-invalid":P?!0:void 0,autoFocus:!0,disabled:D!=="ready"||x.status==="streaming",placeholder:`询问当前 ${a.app.name??"App"} 中的数据…`,ref:xe,rows:2,value:k,onChange:o=>{K(o.currentTarget.value),B(void 0)},onKeyDown:is}),x.status==="streaming"?e.jsx("button",{"aria-label":be,className:"make-ai-assistant__send make-ai-assistant__send--stop","data-tooltip":be,ref:je,type:"button",onClick:os,children:e.jsx("span",{"aria-hidden":"true"})}):e.jsx("button",{"aria-label":"发送",className:"make-ai-assistant__send",disabled:D!=="ready"||!k.trim(),type:"submit",children:e.jsx(Ss,{})})]}),P?e.jsx("p",{id:"make-ai-composer-error",role:"alert",children:P}):null,e.jsx("p",{children:"AI 生成的结果可能存在偏差,重要数据请核对明细。"})]})]})}function Ds(s){return e.jsx(Je,{...s,visible:!0})}function Us({defaultOpen:s=!1,hideLauncher:t=!1,launcher:a,onOpenChange:n,open:r,...i}){const d=Ue(i.brandName,i.title),[h,_]=u.useState(s),[y,T]=u.useState(()=>s||r===!0),M=u.useRef(null),m=r??h,F=v=>{r===void 0&&_(v),n?.(v),v||requestAnimationFrame(()=>M.current?.focus())},q=()=>F(!m);return u.useEffect(()=>{m&&T(!0)},[m]),u.useEffect(()=>{if(!m)return;const v=V=>{V.key==="Escape"&&(F(!1),requestAnimationFrame(()=>M.current?.focus()))};return document.addEventListener("keydown",v),()=>document.removeEventListener("keydown",v)},[n,m]),e.jsxs("div",{className:"make-ai-assistant","data-open":m||void 0,children:[!t&&(!m||a)?a?a({open:m,toggle:q}):e.jsxs("button",{"aria-label":m?`关闭 ${d}`:`打开 ${d}`,"aria-expanded":m,className:"make-ai-assistant__launcher",ref:M,type:"button",onClick:q,children:[e.jsx("span",{className:"make-ai-assistant__launcher-orbit","aria-hidden":"true"}),e.jsx(He,{})]}):null,y?e.jsx("aside",{"aria-label":d,"aria-modal":"false",className:"make-ai-assistant__drawer",hidden:!m,role:"dialog",children:e.jsx(Je,{...i,onClose:()=>F(!1),visible:m})}):null]})}exports.createArtifactCapabilities=O.createArtifactCapabilities;exports.createArtifactTemplateRegistry=O.createArtifactTemplateRegistry;exports.extendArtifactTemplateRegistry=O.extendArtifactTemplateRegistry;exports.resolveArtifactTemplate=O.resolveArtifactTemplate;exports.MAKE_AI_ARTIFACT_KINDS=l.MAKE_AI_ARTIFACT_KINDS;exports.MAKE_AI_ARTIFACT_LIMITS=l.MAKE_AI_ARTIFACT_LIMITS;exports.MAKE_AI_ARTIFACT_SCHEMA_VERSION=l.MAKE_AI_ARTIFACT_SCHEMA_VERSION;exports.MAKE_AI_CONVERSATION_LIMITS=l.MAKE_AI_CONVERSATION_LIMITS;exports.appendUserMessage=l.appendUserMessage;exports.createAssistantConversationState=l.createAssistantConversationState;exports.parseArtifact=l.parseArtifact;exports.parseAssistantEvent=l.parseAssistantEvent;exports.reduceAssistantEvent=l.reduceAssistantEvent;exports.validateArtifact=l.validateArtifact;exports.ArtifactRenderer=Ke;exports.AssistantPanel=Ds;exports.MakeAiAssistant=Us;exports.createPlatformArtifactRegistry=De;exports.formatArtifactValue=L;exports.platformArtifactTemplates=qe;
|