@blade-hq/agent-react 1.2.1-beta.8 → 2608.0.0

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/README.md CHANGED
@@ -13,7 +13,7 @@ pnpm add @blade-hq/agent-client @blade-hq/agent-react
13
13
  ```tsx
14
14
  import { BladeClient } from "@blade-hq/agent-client"
15
15
  import { BladeProvider, ChatView } from "@blade-hq/agent-react"
16
- import "@blade-hq/agent-react/style.css"
16
+ import "@blade-hq/agent-react/style.full.css"
17
17
 
18
18
  const client = new BladeClient({ baseUrl: "https://blade.example.com" })
19
19
 
@@ -88,17 +88,28 @@ await session?.send("你好")
88
88
 
89
89
  全部 props 见 `ChatViewProps`。样式说明:
90
90
 
91
- - 必须引入 `@blade-hq/agent-react/style.css`。组件自带 `.blade-chat-*` 前缀的自包含样式,宿主没装 Tailwind 也开箱可用;颜色走 CSS 变量,可整体换肤/暗色。
91
+ - 必须引入一份样式,按宿主有没有 Tailwind 二选一:
92
+ - **`style.full.css`**(默认选它):布局兜底 + 编译好的 Tailwind 产物,自包含,宿主没装 Tailwind 也是完整视觉。
93
+ - **`style.css`**:只有 `.blade-chat-*` 布局兜底。宿主自己装了 Tailwind、且 `content` 配了扫描 `node_modules/@blade-hq/agent-react` 时用它,可以少一份重复 CSS。选错不会报错,只是工具块、思考块内部会退化成没有布局的裸 HTML。
94
+ - 两份都不含 Tailwind preflight 这类全局 reset,引入后不会影响宿主页面自己的排版;组件需要的那点重置限定在 `.blade-chat` 子树内(见 `src/scoped-preflight.css`)。Shadow DOM 版(`<blade-chat>`)不受此限,它注入的是带 preflight 的完整产物。
95
+ - 颜色走 CSS 变量,可整体换肤;深色页面要在根元素上写 `data-theme="dark"`,否则拿到的是默认的浅色变量。
92
96
  - `renderers.toolCall` 返回 `null` 时回落到默认工具卡片。
97
+ - **内边距按容器宽度伸缩**,嵌进窄侧栏(300–400px)时会自动收窄,不看浏览器视口。代价是聊天容器需要有确定宽度——放在 flex/grid 里被拉伸,或显式给宽度都可以;放进 `width: fit-content`、`inline-flex` 这类由内容决定宽度的父容器会塌缩。
93
98
 
94
99
  ## MarkdownContent
95
100
 
96
- 单独渲染一段智能体消息 Markdown(含代码复制按钮、XSS 消毒,不支持 raw HTML):
101
+ 单独渲染一段智能体消息 Markdown(含代码复制按钮、XSS 消毒;HTML 经 sanitize 白名单处理,不接受任意 raw HTML):
97
102
 
98
103
  ```tsx
99
104
  <MarkdownContent content={markdownText} />
100
105
  ```
101
106
 
107
+ 传了 `sessionId` 才会把智能体产出文件的 `MEDIA:` 行折叠成下载卡片(下载要用它)。`ChatView` 内部已经传好,只有单独用 `MarkdownContent` 时需要自己给:
108
+
109
+ ```tsx
110
+ <MarkdownContent sessionId={sessionId}>{markdownText}</MarkdownContent>
111
+ ```
112
+
102
113
  ## 选择模型
103
114
 
104
115
  SDK 的 ChatView / `<blade-chat>` 不内置模型选择器(默认用后端配置的模型)。指定模型有两种方式:
@@ -111,17 +122,19 @@ SDK 的 ChatView / `<blade-chat>` 不内置模型选择器(默认用后端配
111
122
 
112
123
  ## 样式定制
113
124
 
114
- 三个层次,按需选用:
125
+ 默认是浅色主题。四个层次,按需选用:
126
+
127
+ 1. **深浅主题**:`<ChatView theme="dark" />` / `<blade-chat theme="dark">` 切内置深色,不传或 `"light"` 为浅色。宿主已经在祖先元素上写了 `data-theme="dark"` 时不用传,`ChatView` 会跟着变。`<blade-chat>` 渲染在 Shadow DOM 内,页面上的 `data-theme` 对它无效,只认 `theme` 属性。
115
128
 
116
- 1. **CSS 变量换肤**(React 与 `<blade-chat>` 通用):所有颜色走 `--primary`、`--background`、`--muted` 等变量(完整清单见 style.css 开头)。页面直接覆盖即可穿透 Shadow DOM:
129
+ 2. **CSS 变量换肤**(React 与 `<blade-chat>` 通用):所有颜色走 `--primary`、`--background`、`--muted` 等变量(完整清单见 style.css 开头)。页面直接覆盖即可穿透 Shadow DOM:
117
130
 
118
131
  ```css
119
132
  blade-chat { --primary: 262 83% 58%; height: 640px; }
120
133
  ```
121
134
 
122
- 2. **classNames props**(React):`ChatView` 的 `classNames` 把自定义 class(含你自己构建的 Tailwind 工具类)挂到根节点、消息区、输入区等关键节点上,见 `ChatViewClassNames`。
135
+ 3. **classNames props**(React):`ChatView` 的 `classNames` 把自定义 class(含你自己构建的 Tailwind 工具类)挂到根节点、消息区、输入区等关键节点上,见 `ChatViewClassNames`。
123
136
 
124
- 3. **内嵌 `<style>`(纯 HTML / Vue)**:`<blade-chat>` 的直接 `<style>` 子元素会被注入 Shadow DOM、排在内置样式之后,可用 `.blade-chat-*` 类名做任意深度定制:
137
+ 4. **内嵌 `<style>`(纯 HTML / Vue)**:`<blade-chat>` 的直接 `<style>` 子元素会被注入 Shadow DOM、排在内置样式之后,可用 `.blade-chat-*` 类名做任意深度定制:
125
138
 
126
139
  ```html
127
140
  <blade-chat base-url="...">
@@ -7,10 +7,12 @@ interface Props {
7
7
  onAnswer?: (answer: string, toolCallId: string, answerData: AskUserAnswerData) => void;
8
8
  sessionStatus?: string;
9
9
  toolCallRenderer?: ToolCallRenderer;
10
+ /** 传给 Markdown 渲染,用于把 MEDIA 行折叠成文件下载卡片。 */
11
+ sessionId?: string;
10
12
  }
11
13
  /**
12
14
  * 一轮助手回复:按消息顺序渲染 thinking 折叠块、正文 Markdown 与工具调用。
13
15
  * 相比第一方版本去掉了紧凑/详细模式切换、文件交付卡片与内联资源 iframe。
14
16
  */
15
- export declare function AssistantTurnBlock({ messages, isStreaming, askAnswers, onAnswer, sessionStatus, toolCallRenderer, }: Props): import("react/jsx-runtime").JSX.Element;
17
+ export declare function AssistantTurnBlock({ messages, isStreaming, askAnswers, onAnswer, sessionStatus, toolCallRenderer, sessionId, }: Props): import("react/jsx-runtime").JSX.Element;
16
18
  export {};
@@ -33,6 +33,8 @@ export interface ChatViewProps {
33
33
  renderers?: ChatViewRenderers;
34
34
  slots?: ChatViewSlots;
35
35
  placeholder?: string;
36
+ /** 配色主题,默认浅色。宿主已经在祖先元素上写了 data-theme 时不用传。 */
37
+ theme?: "light" | "dark";
36
38
  }
37
39
  /**
38
40
  * 开箱即用的聊天界面:连接(或新建)一个会话,渲染消息流与输入框。
@@ -0,0 +1,16 @@
1
+ import { type ComponentPropsWithRef } from "react";
2
+ import type { ExtraProps } from "streamdown";
3
+ export type FileCardProps = ComponentPropsWithRef<"span"> & ExtraProps & {
4
+ "data-path"?: string;
5
+ "data-name"?: string;
6
+ dataPath?: string;
7
+ dataName?: string;
8
+ sessionId?: string;
9
+ };
10
+ /**
11
+ * 智能体产出文件的下载卡片(由 MEDIA 行折叠而来)。
12
+ *
13
+ * 整张卡片只有一个动作:下载。第一方界面点卡片是「在右侧预览」,那依赖 app 的 artifact
14
+ * 面板,SDK 里没有这块,所以不摆预览入口也不写预览文案——UI 不能承诺不存在的能力。
15
+ */
16
+ export declare function FileCard({ node, "data-path": pathAttribute, "data-name": nameAttribute, dataPath, dataName, sessionId, children, className, ...props }: FileCardProps): import("react/jsx-runtime").JSX.Element;
@@ -3,10 +3,14 @@ export interface MarkdownContentProps {
3
3
  className?: string;
4
4
  /** 流式渲染传 "streaming",历史静态内容默认 "static"。 */
5
5
  mode?: "streaming" | "static";
6
+ /**
7
+ * 会话 id。传了才会把 `MEDIA:` 行折叠成文件下载卡片——下载要用它。
8
+ * 不要给用户消息传:用户自己在输入框打一行 `MEDIA:` 不该被当成平台产物。
9
+ */
10
+ sessionId?: string;
6
11
  }
7
12
  /**
8
- * SDK 版 Markdown 渲染:Streamdown 默认转义/消毒(不开启任何 raw HTML),
9
- * 附带代码块复制按钮;相比第一方版本去掉了 mermaid、外链确认弹窗、
10
- * 会话文件卡片等第一方能力。
13
+ * SDK 版 Markdown 渲染:附带代码块复制按钮、智能体产出文件的下载卡片;
14
+ * 相比第一方版本去掉了 mermaid、外链确认弹窗与文件预览。
11
15
  */
12
- export declare function MarkdownContent({ children, className, mode }: MarkdownContentProps): import("react/jsx-runtime").JSX.Element;
16
+ export declare function MarkdownContent({ children, className, mode, sessionId }: MarkdownContentProps): import("react/jsx-runtime").JSX.Element;
@@ -10,10 +10,12 @@ interface Props {
10
10
  toolCallRenderer?: ToolCallRenderer;
11
11
  emptyState?: ReactNode;
12
12
  className?: string;
13
+ /** 传给助手消息的 Markdown 渲染,用于把 MEDIA 行折叠成文件下载卡片。 */
14
+ sessionId?: string;
13
15
  }
14
16
  /**
15
17
  * 消息列表:use-stick-to-bottom 自动滚动 + 按轮次分组渲染。
16
18
  * 相比第一方版本去掉了轮次导航栏、吸顶状态条与规划摘要卡片。
17
19
  */
18
- export declare function MessageList({ messages, isStreaming, sessionStatus, askAnswers, onAnswer, toolCallRenderer, emptyState, className, }: Props): import("react/jsx-runtime").JSX.Element;
20
+ export declare function MessageList({ messages, isStreaming, sessionStatus, askAnswers, onAnswer, toolCallRenderer, emptyState, className, sessionId, }: Props): import("react/jsx-runtime").JSX.Element;
19
21
  export {};
@@ -10,6 +10,23 @@ interface Props {
10
10
  sessionStatus?: string;
11
11
  renderer?: ToolCallRenderer;
12
12
  }
13
+ /**
14
+ * 判断提问卡片该等待作答还是展示成已作答,只认工具状态。
15
+ * 与 apps/web 的 ToolCallBlock 里同名函数保持一致:两处算出不同结果时,
16
+ * 同一份会话在内置页面能点、在 SDK 里点不动。
17
+ *
18
+ * 不要再拿 sessionStatus 兜底。历史投影算错时用 waiting_for_input 补救,
19
+ * 会同时把已经回答过的旧提问重新变成可作答(历史加载不会带回 answerData),
20
+ * 而且会盖住投影层的错误——这个 bug 就是这么藏住的。
21
+ */
22
+ export declare function resolveAskQuestionState({ toolStatus, hasAnswerData, fallbackAnswered, }: {
23
+ toolStatus: ToolCallInfo["status"];
24
+ hasAnswerData: boolean;
25
+ fallbackAnswered?: boolean;
26
+ }): {
27
+ awaitingAnswer: boolean;
28
+ answered: boolean;
29
+ };
13
30
  /**
14
31
  * 极简工具调用块:状态 + 展示名一行,点开后是参数/结果的 <pre> 折叠展示。
15
32
  * AskUserQuestion 特殊处理为提问选项卡片。
@@ -1,6 +1,6 @@
1
1
  import { type AgentSession } from "@blade-hq/agent-client";
2
2
  /**
3
- * `<blade-chat base-url="https://..." session-id="可选">`
3
+ * `<blade-chat base-url="https://..." session-id="可选" theme="light|dark">`
4
4
  *
5
5
  * 纯静态页面的聊天入口:Shadow DOM 内渲染完整 ChatView,
6
6
  * 未登录时组件自带登录引导,不传 session-id 自动建会话。