@blade-hq/agent-react 1.2.1-beta.1 → 1.2.1-beta.10
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 +8 -1
- package/dist/components/AssistantTurnBlock.d.ts +3 -1
- package/dist/components/FileCard.d.ts +16 -0
- package/dist/components/MarkdownContent.d.ts +8 -4
- package/dist/components/MessageList.d.ts +3 -1
- package/dist/index.js +399 -163
- package/dist/index.js.map +1 -1
- package/dist/lib/media-tags.d.ts +24 -0
- package/dist/style.css +146 -2
- package/package.json +2 -2
- package/public-api.md +2 -1
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MEDIA 行处理。后端提示词要求智能体产出文件时单独写一行 `MEDIA:<绝对路径>`
|
|
3
|
+
* (见 host/src/blade_agent/host/orchestrator/prompt.py),界面必须把它折叠成文件卡片——
|
|
4
|
+
* 这是内部标记,直接摆给用户看就是 bug。
|
|
5
|
+
*/
|
|
6
|
+
export declare const FILE_CARD_TAG = "blade-file-card";
|
|
7
|
+
/**
|
|
8
|
+
* 能不能拿这个路径去下载。绝对路径原样交给服务端解析(它会把工作区路径映射进沙盒、
|
|
9
|
+
* 并拒绝越界),所以这里只挡明显不该放过的:空路径和 `..`。
|
|
10
|
+
*/
|
|
11
|
+
export declare function isSafeMediaPath(path: string): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* 把 MEDIA 行折叠成文件卡片标签。
|
|
14
|
+
*
|
|
15
|
+
* `streaming` 时最后一行要特殊对待:MEDIA_LINE_RE 用 `$` 匹配行尾,而流式过程中最后一行
|
|
16
|
+
* 随时都是「行尾」,逐 token 折叠会依次闪出 `MEDIA:`、半截路径的卡片、再变成正确卡片。
|
|
17
|
+
* 所以正在写的那一行整行先不渲染,等它以换行结束、或消息转为 static 之后再折叠。
|
|
18
|
+
*
|
|
19
|
+
* 判据只能是 `streaming`,不能是「有没有尾随换行」:AssistantTurnBlock 传进来的文本是
|
|
20
|
+
* trim 过的,静态消息永远没有尾随换行,那样判断会导致 MEDIA 行永远不折叠。
|
|
21
|
+
*/
|
|
22
|
+
export declare function collapseMediaTags(text: string, options?: {
|
|
23
|
+
streaming?: boolean;
|
|
24
|
+
}): string;
|
package/dist/style.css
CHANGED
|
@@ -69,12 +69,23 @@
|
|
|
69
69
|
flex-direction: column;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
/* 聊天根容器。SDK 常被嵌进只有 300-400px 宽的侧栏,而宿主页面视口是全宽的,
|
|
73
|
+
* 所以内边距一律按「容器宽度」伸缩,不能用视口断点——那会在窄容器里反向命中最大值。
|
|
74
|
+
* container-type 建在这里(而不是消息区),是为了让消息区和输入区共享同一个 cqi
|
|
75
|
+
* 基准,两者左右边缘才对得齐。代价是内部内容不再向外传递固有宽度,所以宿主需要给
|
|
76
|
+
* 容器一个确定宽度(flex/grid 拉伸或显式宽度都可以)。 */
|
|
72
77
|
.blade-chat {
|
|
78
|
+
/* 具名容器:宿主或以后的子组件万一在中间又建了个匿名 query container,
|
|
79
|
+
* 下面的 @container 查询不会悄悄改成以那个为基准。 */
|
|
80
|
+
container: blade-chat / inline-size;
|
|
73
81
|
display: flex;
|
|
74
82
|
flex-direction: column;
|
|
75
83
|
flex: 1 1 0%;
|
|
76
84
|
min-height: 0;
|
|
85
|
+
min-width: 0;
|
|
77
86
|
overflow: hidden;
|
|
87
|
+
--blade-chat-gutter: 1rem;
|
|
88
|
+
--blade-chat-turn-gap: 1.5rem;
|
|
78
89
|
background: hsl(var(--background));
|
|
79
90
|
color: hsl(var(--foreground));
|
|
80
91
|
font-family:
|
|
@@ -87,12 +98,29 @@
|
|
|
87
98
|
sans-serif;
|
|
88
99
|
}
|
|
89
100
|
|
|
101
|
+
/* 上面两个变量的兜底值必须留在 @supports 外面。不能靠「同一个变量写两遍、让浏览器
|
|
102
|
+
* 丢掉无效的那条」降级:自定义属性在声明处不做类型校验,带 cqi 的值在旧浏览器里同样是
|
|
103
|
+
* 合法 token、照样覆盖兜底值,失效发生在 padding: var(...) 的使用处——结果是整条 padding
|
|
104
|
+
* 作废变成 0,而不是回落到兜底值。 */
|
|
105
|
+
@supports (container-type: inline-size) and (width: 1cqi) {
|
|
106
|
+
.blade-chat {
|
|
107
|
+
--blade-chat-gutter: clamp(0.875rem, 4cqi, 2.5rem);
|
|
108
|
+
--blade-chat-turn-gap: clamp(1.25rem, 3cqi, 2.25rem);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
90
112
|
.blade-chat-messages {
|
|
91
113
|
position: relative;
|
|
92
114
|
flex: 1 1 0%;
|
|
93
115
|
min-height: 0;
|
|
94
116
|
}
|
|
95
117
|
|
|
118
|
+
/* 滚动内容的内边距。这一层过去只有 Tailwind class,宿主没装 Tailwind 时消息完全贴边。 */
|
|
119
|
+
.blade-chat-messages-scroll {
|
|
120
|
+
padding: calc(var(--blade-chat-gutter) * 1.4) var(--blade-chat-gutter)
|
|
121
|
+
calc(var(--blade-chat-gutter) * 1.1);
|
|
122
|
+
}
|
|
123
|
+
|
|
96
124
|
.blade-chat-messages-content {
|
|
97
125
|
margin: 0 auto;
|
|
98
126
|
max-width: 748px;
|
|
@@ -101,10 +129,22 @@
|
|
|
101
129
|
.blade-chat-messages-content > div {
|
|
102
130
|
display: flex;
|
|
103
131
|
flex-direction: column;
|
|
104
|
-
gap:
|
|
132
|
+
gap: var(--blade-chat-turn-gap);
|
|
105
133
|
min-width: 0;
|
|
106
134
|
}
|
|
107
135
|
|
|
136
|
+
.blade-chat-empty {
|
|
137
|
+
display: flex;
|
|
138
|
+
flex-direction: column;
|
|
139
|
+
align-items: center;
|
|
140
|
+
justify-content: center;
|
|
141
|
+
gap: 0.75rem;
|
|
142
|
+
/* 这里的双写是有效降级:cqi 出现在属性值里,旧浏览器会丢掉整条声明并回落到上一条。 */
|
|
143
|
+
padding: 4rem 0;
|
|
144
|
+
padding: clamp(2.5rem, 12cqi, 6rem) 0;
|
|
145
|
+
color: hsl(var(--muted-foreground));
|
|
146
|
+
}
|
|
147
|
+
|
|
108
148
|
.blade-chat-login,
|
|
109
149
|
.blade-chat-version-mismatch {
|
|
110
150
|
display: flex;
|
|
@@ -129,6 +169,18 @@
|
|
|
129
169
|
max-width: 72%;
|
|
130
170
|
}
|
|
131
171
|
|
|
172
|
+
/* 窄容器里 72% 只剩 250px 左右,一句话就折三行,这里放宽。
|
|
173
|
+
* 这类需要跳变而非连续伸缩的值才用 @container 查询。 */
|
|
174
|
+
@container blade-chat (max-width: 480px) {
|
|
175
|
+
.blade-chat-user-col {
|
|
176
|
+
max-width: 88%;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.blade-chat-scroll-bottom-label {
|
|
180
|
+
display: none;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
132
184
|
.blade-chat-user-bubble {
|
|
133
185
|
max-width: 100%;
|
|
134
186
|
border: 1px solid hsl(var(--user-msg-border));
|
|
@@ -180,9 +232,10 @@
|
|
|
180
232
|
|
|
181
233
|
/* ---------------------------------------------------------------- 输入区 */
|
|
182
234
|
|
|
235
|
+
/* 左右内边距和消息区共用同一个 gutter,否则输入框与消息文字左边缘对不齐。 */
|
|
183
236
|
.blade-chat-input {
|
|
184
237
|
border-top: 1px solid hsl(var(--border));
|
|
185
|
-
padding: 0.75rem
|
|
238
|
+
padding: 0.75rem var(--blade-chat-gutter);
|
|
186
239
|
}
|
|
187
240
|
|
|
188
241
|
.blade-chat-input-inner {
|
|
@@ -217,6 +270,69 @@
|
|
|
217
270
|
border: 0;
|
|
218
271
|
}
|
|
219
272
|
|
|
273
|
+
/* ------------------------------------------------------------ 文件下载卡片 */
|
|
274
|
+
|
|
275
|
+
.blade-chat-file-card {
|
|
276
|
+
display: inline-flex;
|
|
277
|
+
max-width: 100%;
|
|
278
|
+
margin: 0.25rem 0.5rem 0.25rem 0;
|
|
279
|
+
align-items: center;
|
|
280
|
+
gap: 0.5rem;
|
|
281
|
+
vertical-align: middle;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.blade-chat-file-card button {
|
|
285
|
+
display: inline-flex;
|
|
286
|
+
min-width: 0;
|
|
287
|
+
align-items: center;
|
|
288
|
+
gap: 0.375rem;
|
|
289
|
+
cursor: pointer;
|
|
290
|
+
border: 1px solid hsl(var(--border));
|
|
291
|
+
border-radius: 0.375rem;
|
|
292
|
+
background: hsl(var(--card));
|
|
293
|
+
color: hsl(var(--card-foreground));
|
|
294
|
+
padding: 0.375rem 0.625rem;
|
|
295
|
+
font-size: 0.75rem;
|
|
296
|
+
font-weight: 500;
|
|
297
|
+
line-height: 1.25rem;
|
|
298
|
+
text-align: left;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
.blade-chat-file-card button:hover:not(:disabled) {
|
|
302
|
+
background: hsl(var(--accent) / 0.45);
|
|
303
|
+
border-color: hsl(var(--primary) / 0.45);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.blade-chat-file-card button:disabled {
|
|
307
|
+
cursor: not-allowed;
|
|
308
|
+
opacity: 0.6;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
.blade-chat-file-card-icon {
|
|
312
|
+
display: inline-flex;
|
|
313
|
+
flex-shrink: 0;
|
|
314
|
+
color: hsl(var(--primary));
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/* 窄容器里文件名不能写死上限,否则短名字留白、长名字仍然顶宽。 */
|
|
318
|
+
.blade-chat-file-card-name {
|
|
319
|
+
overflow: hidden;
|
|
320
|
+
text-overflow: ellipsis;
|
|
321
|
+
white-space: nowrap;
|
|
322
|
+
max-width: 15rem;
|
|
323
|
+
max-width: min(15rem, 60cqi);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.blade-chat-file-card-action {
|
|
327
|
+
flex-shrink: 0;
|
|
328
|
+
color: hsl(var(--muted-foreground));
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.blade-chat-file-card-error {
|
|
332
|
+
font-size: 0.6875rem;
|
|
333
|
+
color: hsl(var(--destructive));
|
|
334
|
+
}
|
|
335
|
+
|
|
220
336
|
/* ---------------------------------------------------------------- 工具块 */
|
|
221
337
|
|
|
222
338
|
.blade-chat-tool,
|
|
@@ -241,6 +357,34 @@
|
|
|
241
357
|
|
|
242
358
|
.blade-chat-markdown {
|
|
243
359
|
overflow-wrap: break-word;
|
|
360
|
+
min-width: 0;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/* 窄容器里真正把版面撑破的是内容而不是内边距:宽表格、大图、超长 URL 都会把整个
|
|
364
|
+
* 消息区顶宽,然后出现一条横向滚动条。表格自己滚,图片自己缩,长 token 强制断行。 */
|
|
365
|
+
.blade-chat-markdown [data-streamdown="table-wrapper"] {
|
|
366
|
+
max-width: 100%;
|
|
367
|
+
min-width: 0;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/* 横向滚动发生在 table 的父层。streamdown 用 Tailwind 的 overflow-x-auto 实现它,
|
|
371
|
+
* 宿主没装 Tailwind 时那个类是空的,所以这里用普通 CSS 兜住。 */
|
|
372
|
+
.blade-chat-markdown [data-streamdown="table-wrapper"] > div:last-child {
|
|
373
|
+
overflow-x: auto;
|
|
374
|
+
max-width: 100%;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
.blade-chat-markdown img,
|
|
378
|
+
.blade-chat-markdown video {
|
|
379
|
+
max-width: 100%;
|
|
380
|
+
height: auto;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/* 长 URL 和长内联代码是撑宽的另外两个常见肇事者。用 anywhere 而不是 break-word:
|
|
384
|
+
* 只有 anywhere 参与 min-content 计算,break-word 挡不住 flex item 被顶宽。 */
|
|
385
|
+
.blade-chat-markdown :not(pre) > code,
|
|
386
|
+
.blade-chat-markdown a {
|
|
387
|
+
overflow-wrap: anywhere;
|
|
244
388
|
}
|
|
245
389
|
|
|
246
390
|
.blade-chat-prose p {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blade-hq/agent-react",
|
|
3
|
-
"version": "1.2.1-beta.
|
|
3
|
+
"version": "1.2.1-beta.10",
|
|
4
4
|
"description": "Blade Agent React 绑定:BladeProvider、useAgentSession、开箱即用的 ChatView 聊天界面。",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"access": "public"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@blade-hq/agent-client": "1.2.1-beta.
|
|
31
|
+
"@blade-hq/agent-client": "1.2.1-beta.10"
|
|
32
32
|
},
|
|
33
33
|
"bundledDependencies": [],
|
|
34
34
|
"peerDependencies": {
|
package/public-api.md
CHANGED
|
@@ -593,7 +593,7 @@ user: { id?: string; username?: string; display_name?: string; } | undefined
|
|
|
593
593
|
## `MarkdownContent` (function)
|
|
594
594
|
|
|
595
595
|
```ts
|
|
596
|
-
MarkdownContent: ({ children, className, mode }: MarkdownContentProps) => JSX.Element
|
|
596
|
+
MarkdownContent: ({ children, className, mode, sessionId }: MarkdownContentProps) => JSX.Element
|
|
597
597
|
```
|
|
598
598
|
|
|
599
599
|
## `MarkdownContentProps` (interface)
|
|
@@ -602,6 +602,7 @@ MarkdownContent: ({ children, className, mode }: MarkdownContentProps) => JSX.El
|
|
|
602
602
|
children: string
|
|
603
603
|
className: string | undefined
|
|
604
604
|
mode: "streaming" | "static" | undefined
|
|
605
|
+
sessionId: string | undefined
|
|
605
606
|
```
|
|
606
607
|
|
|
607
608
|
## `MemoryRef` (interface)
|