@blade-hq/agent-react 1.1.1

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 ADDED
@@ -0,0 +1,142 @@
1
+ # @blade-hq/agent-react
2
+
3
+ Blade Agent 的 React 绑定:`BladeProvider` + `useAgentSession` + 开箱即用的 `ChatView` 聊天界面。支持 React 18 与 19(CI 两个版本 matrix 验证)。
4
+
5
+ ```bash
6
+ pnpm add @blade-hq/agent-client @blade-hq/agent-react
7
+ ```
8
+
9
+ > 注意两个包都要装:`agent-client` 是运行时依赖,只装 `agent-react` 在 pnpm 下会直接报错。
10
+
11
+ ## 快速开始
12
+
13
+ ```tsx
14
+ import { BladeClient } from "@blade-hq/agent-client"
15
+ import { BladeProvider, ChatView } from "@blade-hq/agent-react"
16
+ import "@blade-hq/agent-react/style.css"
17
+
18
+ const client = new BladeClient({ baseUrl: "https://blade.example.com" })
19
+
20
+ export function App() {
21
+ return (
22
+ <BladeProvider client={client}>
23
+ <ChatView />
24
+ </BladeProvider>
25
+ )
26
+ }
27
+ ```
28
+
29
+ - 不传 `sessionId` 自动创建新会话;未登录时 `ChatView` 自己渲染登录按钮(弹窗授权,见 agent-client 的 `client.auth.login()`)。
30
+ - 同一 `BladeProvider` 下可以放多个 `ChatView`,各自独立会话、互不干扰。
31
+ - SDK 与 Server 版本不匹配时(见 agent-client「版本握手」),`ChatView` 会渲染可读的版本提示卡,而不是空白或报错堆栈。
32
+
33
+ ## BladeProvider
34
+
35
+ 只负责 client 级共享(一条 Socket 连接、一份鉴权),不含任何全局状态。
36
+
37
+ ```tsx
38
+ <BladeProvider client={client}>{children}</BladeProvider>
39
+ ```
40
+
41
+ Props 见 `BladeProviderProps`;在 Provider 外调用本包任何 hook 都会抛错。
42
+
43
+ ## useBladeClient
44
+
45
+ ```tsx
46
+ const client = useBladeClient() // 当前 Provider 的 BladeClient
47
+ ```
48
+
49
+ ## useAgentSession
50
+
51
+ 自建 UI 的入口:连接(或创建)会话并订阅其状态,内部使用 `useSyncExternalStore`。
52
+
53
+ ```tsx
54
+ const { session, state, error } = useAgentSession(sessionId, {
55
+ createOptions, // 不传 sessionId 时的建会话配置(UseAgentSessionOptions)
56
+ onSessionCreated: (id) => saveSomewhere(id),
57
+ })
58
+
59
+ state?.messages // ChatMessage[],直接渲染
60
+ state?.isStreaming // 是否正在流式回复
61
+ await session?.send("你好")
62
+ ```
63
+
64
+ 返回值见 `UseAgentSessionResult`。语义要点:
65
+
66
+ - 优先级:`sessionId`(连接既有会话)> `createOptions`(按配置新建)> 默认新建。
67
+ - 自动创建只发生一次(含 React StrictMode 双跑);创建出的 id 通过 `onSessionCreated` 交还,重挂载时把它作为 `sessionId` 传回即可复用会话。
68
+ - 同一 `sessionId` 的多次调用复用同一 `AgentSession` 实例(引用计数);卸载后延迟释放,路由抖动不会断连。
69
+
70
+ ## ChatView
71
+
72
+ 完整聊天界面:消息列表(Markdown、代码高亮、工具调用、提问卡片)+ 输入框 + 连接状态条 + 登录引导。
73
+
74
+ ```tsx
75
+ <ChatView
76
+ sessionId={id} // 可选;不传自动建会话
77
+ createOptions={{ intent: "..." }} // 自动建会话时的配置
78
+ onSessionCreated={(id) => ...} // 自动创建的会话 id 交还调用方
79
+ onSessionReady={(session) => ...} // 会话实例就绪(页面协作高级用法)
80
+ commands={{ "map.highlight": (data) => map.highlight(data) }} // 智能体 → 页面指令
81
+ placeholder="输入消息..."
82
+ classNames={{ root: "...", banner: "...", messages: "...", input: "..." }} // ChatViewClassNames
83
+ renderers={{ toolCall: (info) => <MyToolCard info={info} /> }} // ChatViewRenderers
84
+ slots={{ header: <MyHeader />, emptyState: <MyEmpty />, footer: <MyTip /> }} // ChatViewSlots
85
+ />
86
+ ```
87
+
88
+ 全部 props 见 `ChatViewProps`。样式说明:
89
+
90
+ - 必须引入 `@blade-hq/agent-react/style.css`。组件自带 `.blade-chat-*` 前缀的自包含样式,宿主没装 Tailwind 也开箱可用;颜色走 CSS 变量,可整体换肤/暗色。
91
+ - `renderers.toolCall` 返回 `null` 时回落到默认工具卡片。
92
+
93
+ ## MarkdownContent
94
+
95
+ 单独渲染一段智能体消息 Markdown(含代码复制按钮、XSS 消毒,不支持 raw HTML):
96
+
97
+ ```tsx
98
+ <MarkdownContent content={markdownText} />
99
+ ```
100
+
101
+ ## 选择模型
102
+
103
+ SDK 的 ChatView / `<blade-chat>` 不内置模型选择器(默认用后端配置的模型)。指定模型有两种方式:
104
+
105
+ - **建会话时指定**(React):`<ChatView createOptions={{ model: "..." }} />`
106
+ - **`<blade-chat>` 属性**(纯 HTML / Vue):`<blade-chat base-url="..." model="..."></blade-chat>`
107
+ - **自建 UI 时逐条覆盖**:`chat.send(text, { model: "..." })`
108
+
109
+ 可用模型清单由后端提供,接入方对照后端 Swagger(`<baseUrl>/docs`)自行获取。
110
+
111
+ ## 样式定制
112
+
113
+ 三个层次,按需选用:
114
+
115
+ 1. **CSS 变量换肤**(React 与 `<blade-chat>` 通用):所有颜色走 `--primary`、`--background`、`--muted` 等变量(完整清单见 style.css 开头)。页面直接覆盖即可穿透 Shadow DOM:
116
+
117
+ ```css
118
+ blade-chat { --primary: 262 83% 58%; height: 640px; }
119
+ ```
120
+
121
+ 2. **classNames props**(React):`ChatView` 的 `classNames` 把自定义 class(含你自己构建的 Tailwind 工具类)挂到根节点、消息区、输入区等关键节点上,见 `ChatViewClassNames`。
122
+
123
+ 3. **内嵌 `<style>`(纯 HTML / Vue)**:`<blade-chat>` 的直接 `<style>` 子元素会被注入 Shadow DOM、排在内置样式之后,可用 `.blade-chat-*` 类名做任意深度定制:
124
+
125
+ ```html
126
+ <blade-chat base-url="...">
127
+ <style>
128
+ .blade-chat-user-bubble { background: #eef2ff; }
129
+ .blade-chat-thinking { font-size: 15px; }
130
+ </style>
131
+ </blade-chat>
132
+ ```
133
+
134
+ ## 纯静态 HTML / Vue?
135
+
136
+ 不需要本包——用后端托管的单文件产物 `<script src=".../sdk/blade-agent.js">` + `<blade-chat>` 自定义元素,行为与 `ChatView` 一致;详见 agent-client README 与接入文档。
137
+
138
+ ## 附录:re-export 自 @blade-hq/agent-client
139
+
140
+ 为方便单包引入,本包 re-export 了 agent-client 的全部公开声明(`BladeClient`、`AgentSession`、`SessionState`、协议类型等),文档一律见 [agent-client 的 README](../agent-client/README.md)。完整签名见 [public-api.md](./public-api.md)。
141
+
142
+ 本包自有声明:`BladeProvider`、`BladeProviderProps`、`useBladeClient`、`useAgentSession`、`UseAgentSessionOptions`、`UseAgentSessionResult`、`ChatView`、`ChatViewProps`、`ChatViewClassNames`、`ChatViewRenderers`、`ChatViewSlots`、`ToolCallRenderer`、`MarkdownContent`、`MarkdownContentProps`。
@@ -0,0 +1,10 @@
1
+ import type { ToolCallInfo } from "@blade-hq/agent-client";
2
+ interface Props {
3
+ toolCall: ToolCallInfo;
4
+ }
5
+ /**
6
+ * 子智能体(fork Agent)状态块的 SDK 简化版:只展示描述、状态与最终结果,
7
+ * 不再嵌套渲染子循环的完整消息流(那是第一方界面的能力)。
8
+ */
9
+ export declare function AgentLoopBlock({ toolCall }: Props): import("react/jsx-runtime").JSX.Element;
10
+ export {};
@@ -0,0 +1,31 @@
1
+ import type { AskUserAnswerData } from "@blade-hq/agent-client";
2
+ interface OptionItem {
3
+ label: string;
4
+ description: string;
5
+ }
6
+ interface QuestionItem {
7
+ question: string;
8
+ options: OptionItem[];
9
+ multiSelect?: boolean;
10
+ }
11
+ interface SourceLoopInfo {
12
+ loop_name: string;
13
+ description: string;
14
+ }
15
+ export interface AskUserQuestionData {
16
+ questions: QuestionItem[];
17
+ source_loop?: SourceLoopInfo | null;
18
+ }
19
+ interface Props {
20
+ data: AskUserQuestionData;
21
+ answered: boolean;
22
+ toolCallId: string;
23
+ sessionStatus: string;
24
+ answerData?: AskUserAnswerData | undefined;
25
+ onAnswer?: (answer: string, toolCallId: string, answerData: AskUserAnswerData) => void;
26
+ }
27
+ /** 提问选项卡片:单选/多选 + 自定义输入,回答通过 onAnswer 回调交还 ChatView。 */
28
+ export declare function AskUserQuestionBlock({ data, answered, toolCallId, sessionStatus, answerData, onAnswer, }: Props): import("react/jsx-runtime").JSX.Element;
29
+ /** 解析 AskUserQuestion 的工具结果/参数,容错 LLM 把 questions 输出为字符串的情况。 */
30
+ export declare function parseAskUserQuestion(toolResult: string | null | undefined): AskUserQuestionData | null;
31
+ export {};
@@ -0,0 +1,16 @@
1
+ import type { AskUserAnswerData, ChatMessage } from "@blade-hq/agent-client";
2
+ import { type ToolCallRenderer } from "./ToolCallBlock";
3
+ interface Props {
4
+ messages: ChatMessage[];
5
+ isStreaming?: boolean;
6
+ askAnswers?: Record<string, AskUserAnswerData>;
7
+ onAnswer?: (answer: string, toolCallId: string, answerData: AskUserAnswerData) => void;
8
+ sessionStatus?: string;
9
+ toolCallRenderer?: ToolCallRenderer;
10
+ }
11
+ /**
12
+ * 一轮助手回复:按消息顺序渲染 thinking 折叠块、正文 Markdown 与工具调用。
13
+ * 相比第一方版本去掉了紧凑/详细模式切换、文件交付卡片与内联资源 iframe。
14
+ */
15
+ export declare function AssistantTurnBlock({ messages, isStreaming, askAnswers, onAnswer, sessionStatus, toolCallRenderer, }: Props): import("react/jsx-runtime").JSX.Element;
16
+ export {};
@@ -0,0 +1,18 @@
1
+ interface Props {
2
+ /** 受控输入内容(由 ChatView 持有,便于 attach/insertText 注入)。 */
3
+ value: string;
4
+ onValueChange: (value: string) => void;
5
+ onSend: (text: string) => void;
6
+ onStop: () => void;
7
+ isStreaming: boolean;
8
+ isStopping?: boolean;
9
+ placeholder?: string;
10
+ className?: string;
11
+ }
12
+ /**
13
+ * 轻量聊天输入框:textarea(Enter 发送 / Shift+Enter 换行)+ 发送/停止按钮。
14
+ * 不含第一方版本的富文本编辑、@ 补全、技能菜单、语音输入与模型选择。
15
+ * 内容受控,session.attach() / insertText() 通过 ChatView 注入到这里。
16
+ */
17
+ export declare function ChatInput({ value, onValueChange, onSend, onStop, isStreaming, isStopping, placeholder, className, }: Props): import("react/jsx-runtime").JSX.Element;
18
+ export {};
@@ -0,0 +1,41 @@
1
+ import type { AgentSession, CreateSessionRequest } from "@blade-hq/agent-client";
2
+ import { type ReactNode } from "react";
3
+ import type { ToolCallRenderer } from "./ToolCallBlock";
4
+ export interface ChatViewClassNames {
5
+ root?: string;
6
+ banner?: string;
7
+ messageList?: string;
8
+ chatInput?: string;
9
+ }
10
+ export interface ChatViewRenderers {
11
+ /** 自定义工具调用渲染;返回 null 走默认渲染。 */
12
+ toolCall?: ToolCallRenderer;
13
+ }
14
+ export interface ChatViewSlots {
15
+ /** 消息列表上方的自定义区域。 */
16
+ header?: ReactNode;
17
+ /** 无消息时的空状态。 */
18
+ emptyState?: ReactNode;
19
+ /** 输入框下方的自定义区域。 */
20
+ footer?: ReactNode;
21
+ }
22
+ export interface ChatViewProps {
23
+ /** 连接既有会话;不传则按 createOptions 自动新建。 */
24
+ sessionId?: string;
25
+ createOptions?: CreateSessionRequest;
26
+ /** 自动创建出的 sessionId 通过此回调交还调用方持有。 */
27
+ onSessionCreated?: (sessionId: string) => void;
28
+ /** 会话连接完成后回调(页面协作场景拿 AgentSession 实例用)。 */
29
+ onSessionReady?: (session: AgentSession) => void;
30
+ /** 智能体下发给宿主页面的指令处理器(action → handler)。 */
31
+ commands?: Record<string, (data: unknown) => void>;
32
+ classNames?: ChatViewClassNames;
33
+ renderers?: ChatViewRenderers;
34
+ slots?: ChatViewSlots;
35
+ placeholder?: string;
36
+ }
37
+ /**
38
+ * 开箱即用的聊天界面:连接(或新建)一个会话,渲染消息流与输入框。
39
+ * 状态全部来自 useAgentSession,不依赖任何全局 store。
40
+ */
41
+ export declare function ChatView(props: ChatViewProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,8 @@
1
+ import type { ConnectionStatus } from "@blade-hq/agent-client";
2
+ interface Props {
3
+ connection: ConnectionStatus;
4
+ className?: string;
5
+ }
6
+ /** 连接状态提示条:数据来自 SessionState.connection,正常连接时不渲染。 */
7
+ export declare function ConnectionBanner({ connection, className }: Props): import("react/jsx-runtime").JSX.Element | null;
8
+ export {};
@@ -0,0 +1,16 @@
1
+ import { type ComponentProps } from "react";
2
+ import { Streamdown } from "streamdown";
3
+ type StreamdownProps = ComponentProps<typeof Streamdown>;
4
+ export interface MarkdownContentProps {
5
+ children: string;
6
+ className?: string;
7
+ /** 流式渲染传 "streaming",历史静态内容默认 "static"。 */
8
+ mode?: StreamdownProps["mode"];
9
+ }
10
+ /**
11
+ * SDK 版 Markdown 渲染:Streamdown 默认转义/消毒(不开启任何 raw HTML),
12
+ * 附带代码块复制按钮;相比第一方版本去掉了 mermaid、外链确认弹窗、
13
+ * 会话文件卡片等第一方能力。
14
+ */
15
+ export declare function MarkdownContent({ children, className, mode }: MarkdownContentProps): import("react/jsx-runtime").JSX.Element;
16
+ export {};
@@ -0,0 +1,19 @@
1
+ import type { AskUserAnswerData, ChatMessage } from "@blade-hq/agent-client";
2
+ import { type ReactNode } from "react";
3
+ import type { ToolCallRenderer } from "./ToolCallBlock";
4
+ interface Props {
5
+ messages: ChatMessage[];
6
+ isStreaming: boolean;
7
+ sessionStatus?: string;
8
+ askAnswers?: Record<string, AskUserAnswerData>;
9
+ onAnswer?: (answer: string, toolCallId: string, answerData: AskUserAnswerData) => void;
10
+ toolCallRenderer?: ToolCallRenderer;
11
+ emptyState?: ReactNode;
12
+ className?: string;
13
+ }
14
+ /**
15
+ * 消息列表:use-stick-to-bottom 自动滚动 + 按轮次分组渲染。
16
+ * 相比第一方版本去掉了轮次导航栏、吸顶状态条与规划摘要卡片。
17
+ */
18
+ export declare function MessageList({ messages, isStreaming, sessionStatus, askAnswers, onAnswer, toolCallRenderer, emptyState, className, }: Props): import("react/jsx-runtime").JSX.Element;
19
+ export {};
@@ -0,0 +1,20 @@
1
+ import { Component, type ErrorInfo, type ReactNode } from "react";
2
+ interface Props {
3
+ label: string;
4
+ details?: string;
5
+ resetKey?: string;
6
+ children: ReactNode;
7
+ }
8
+ interface State {
9
+ componentStack: string;
10
+ error: Error | null;
11
+ }
12
+ /** 消息级渲染错误边界:单条消息渲染崩溃时降级为提示卡片,不拖垮整个列表。 */
13
+ export declare class RenderErrorBoundary extends Component<Props, State> {
14
+ state: State;
15
+ static getDerivedStateFromError(error: Error): State;
16
+ componentDidCatch(error: Error, info: ErrorInfo): void;
17
+ componentDidUpdate(prevProps: Props): void;
18
+ render(): string | number | bigint | boolean | import("react/jsx-runtime").JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | Iterable<ReactNode> | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | import("react").ReactPortal | null | undefined> | null | undefined;
19
+ }
20
+ export {};
@@ -0,0 +1,7 @@
1
+ interface ShimmerProps {
2
+ children?: string;
3
+ className?: string;
4
+ }
5
+ /** 流式等待时的呼吸文字效果(样式见 style.css 的 .blade-shimmer-text)。 */
6
+ export declare function Shimmer({ children, className }: ShimmerProps): import("react/jsx-runtime").JSX.Element;
7
+ export {};
@@ -0,0 +1,18 @@
1
+ import type { AskUserAnswerData, ToolCallInfo } from "@blade-hq/agent-client";
2
+ import { type ReactNode } from "react";
3
+ /** 接入方自定义渲染器:返回 null 时回落到默认渲染。 */
4
+ export type ToolCallRenderer = (info: ToolCallInfo) => ReactNode | null;
5
+ interface Props {
6
+ toolCall: ToolCallInfo;
7
+ onAnswer?: (answer: string, toolCallId: string, answerData: AskUserAnswerData) => void;
8
+ answered?: boolean;
9
+ answerData?: AskUserAnswerData;
10
+ sessionStatus?: string;
11
+ renderer?: ToolCallRenderer;
12
+ }
13
+ /**
14
+ * 极简工具调用块:状态 + 展示名一行,点开后是参数/结果的 <pre> 折叠展示。
15
+ * AskUserQuestion 特殊处理为提问选项卡片。
16
+ */
17
+ export declare function ToolCallBlock({ toolCall, onAnswer, answered, answerData, sessionStatus, renderer, }: Props): import("react/jsx-runtime").JSX.Element;
18
+ export {};
@@ -0,0 +1,21 @@
1
+ import type { ChatMessage } from "@blade-hq/agent-client";
2
+ export type UserChatMessage = ChatMessage & {
3
+ role: "user";
4
+ };
5
+ export type ErrorChatMessage = ChatMessage & {
6
+ role: "error";
7
+ };
8
+ export declare function isUserMessage(message: ChatMessage): message is UserChatMessage;
9
+ export declare function isErrorMessage(message: ChatMessage): message is ErrorChatMessage;
10
+ interface UserMessageProps {
11
+ message: UserChatMessage;
12
+ className?: string;
13
+ }
14
+ /** 用户消息气泡:文本 + 图片/文件附件展示(不含第一方的预览弹窗与 what-if 徽章)。 */
15
+ export declare function UserMessageBubble({ message, className }: UserMessageProps): import("react/jsx-runtime").JSX.Element;
16
+ /** 错误消息:居中红色提示条。 */
17
+ export declare function ErrorMessageBlock({ message, className, }: {
18
+ message: ErrorChatMessage;
19
+ className?: string;
20
+ }): import("react/jsx-runtime").JSX.Element;
21
+ export {};
@@ -0,0 +1,16 @@
1
+ import type { ToolCallInfo } from "@blade-hq/agent-client";
2
+ export type ToolTone = "emerald" | "blue" | "amber" | "red";
3
+ /** 归一化工具名:去掉命名空间前缀并映射到别名表(如 "fork:Agent" → "Agent")。 */
4
+ export declare function formatToolName(name: string): string;
5
+ /**
6
+ * 返回工具调用的中文展示标签:优先取参数里的 description,
7
+ * 其次取后端下发的 display_name / 系统工具中文名。
8
+ */
9
+ export declare function getToolDisplayLabel(toolCall: ToolCallInfo): string;
10
+ export declare function getToolTone(status?: ToolCallInfo["status"]): ToolTone;
11
+ export declare function getToolStatusLabel(status?: ToolCallInfo["status"]): string;
12
+ export declare function formatToolDuration(ms: number): string;
13
+ /** 参数 JSON 美化:无法解析时按原文展示。 */
14
+ export declare function formatToolArgs(args: string): string;
15
+ /** 工具结果的文本化 + 截断:长结果只在折叠面板里展示前若干字符。 */
16
+ export declare function formatToolResult(result: unknown): string;
@@ -0,0 +1,13 @@
1
+ import type { BladeClient } from "@blade-hq/agent-client";
2
+ import { type ReactNode } from "react";
3
+ export interface BladeProviderProps {
4
+ client: BladeClient;
5
+ children: ReactNode;
6
+ }
7
+ /**
8
+ * 提供 client 级共享(一条连接、一份鉴权)。不含任何全局状态:
9
+ * 同一 Provider 下多个 ChatView / useAgentSession 各自独立。
10
+ */
11
+ export declare function BladeProvider({ client, children }: BladeProviderProps): import("react/jsx-runtime").JSX.Element;
12
+ /** 读取当前 BladeProvider 提供的 client。不在 Provider 内使用时抛错。 */
13
+ export declare function useBladeClient(): BladeClient;
@@ -0,0 +1,33 @@
1
+ import { type AgentSession } from "@blade-hq/agent-client";
2
+ /**
3
+ * `<blade-chat base-url="https://..." session-id="可选">`
4
+ *
5
+ * 纯静态页面的聊天入口:Shadow DOM 内渲染完整 ChatView,
6
+ * 未登录时组件自带登录引导,不传 session-id 自动建会话。
7
+ */
8
+ export declare class BladeChatElement extends HTMLElement {
9
+ static observedAttributes: string[];
10
+ private root;
11
+ private shadow;
12
+ private mountPoint;
13
+ /** 当前会话(连接完成后可用);BladeAgent.getChat() 依赖它。 */
14
+ session: AgentSession | null;
15
+ private sessionWaiters;
16
+ /** 自动创建的会话 id:attribute 变化触发的重渲染要继续用它,避免重复建会话。 */
17
+ private autoCreatedSessionId;
18
+ connectedCallback(): void;
19
+ /**
20
+ * 自定义样式口子:<blade-chat> 的直接 <style> 子元素会被拷入 Shadow DOM,
21
+ * 排在内置样式之后(同优先级时后者胜)。配合内置的 .blade-chat-* 类名
22
+ * 与 CSS 变量(--primary / --background 等,页面直接对 blade-chat 元素
23
+ * 设置即可穿透),无需构建工具即可深度定制。
24
+ */
25
+ private adoptUserStyles;
26
+ disconnectedCallback(): void;
27
+ attributeChangedCallback(): void;
28
+ /** 等待会话就绪(页面协作用)。 */
29
+ waitForSession(): Promise<AgentSession>;
30
+ private handleSessionReady;
31
+ private render;
32
+ }
33
+ export declare function registerBladeChatElement(): void;
@@ -0,0 +1,94 @@
1
+ /**
2
+ * blade-agent.js(IIFE)入口:纯静态 HTML 的接入方式。
3
+ *
4
+ * ```html
5
+ * <script src="https://blade.example.com/sdk/blade-agent.js"></script>
6
+ * <blade-chat base-url="https://blade.example.com"></blade-chat>
7
+ * <script>
8
+ * const chat = await BladeAgent.getChat(document.querySelector("blade-chat"))
9
+ * chat.onCommand("map.highlight", (data) => { ... })
10
+ * </script>
11
+ * ```
12
+ */
13
+ import * as agentClient from "@blade-hq/agent-client";
14
+ import type { AgentSession } from "@blade-hq/agent-client";
15
+ import { BladeChatElement } from "./blade-chat-element";
16
+ /** 取某个 `<blade-chat>` 元素背后的会话对象(等待连接就绪)。 */
17
+ declare function getChat(element: Element | null): Promise<AgentSession>;
18
+ declare const BladeAgent: {
19
+ BladeClient: typeof agentClient.BladeClient;
20
+ BladeApiError: typeof agentClient.BladeApiError;
21
+ VersionMismatchError: typeof agentClient.VersionMismatchError;
22
+ SDK_NAME: "agent-client";
23
+ SDK_VERSION: "2.0.0";
24
+ MIN_SERVER_VERSION: "1.1.1";
25
+ AgentSession: typeof AgentSession;
26
+ SessionHub: typeof agentClient.SessionHub;
27
+ createInitialSessionState: typeof agentClient.createInitialSessionState;
28
+ connectEmbedded: typeof agentClient.connectEmbedded;
29
+ isCommandEnvelope: typeof agentClient.isCommandEnvelope;
30
+ isInboundEnvelope: typeof agentClient.isInboundEnvelope;
31
+ buildMessageContent: typeof agentClient.buildMessageContent;
32
+ contentPreview: typeof agentClient.contentPreview;
33
+ extractTextAttachments: typeof agentClient.extractTextAttachments;
34
+ getFileParts: typeof agentClient.getFileParts;
35
+ getImageParts: typeof agentClient.getImageParts;
36
+ getTextContent: typeof agentClient.getTextContent;
37
+ groupMessagesByLoop: typeof agentClient.groupMessagesByLoop;
38
+ isHiddenInternalMessage: typeof agentClient.isHiddenInternalMessage;
39
+ normalizeMessageContent: typeof agentClient.normalizeMessageContent;
40
+ transformSlashCommand: typeof agentClient.transformSlashCommand;
41
+ SessionInfo: import("arktype/internal/variants/object.ts").ObjectType<{
42
+ id: string;
43
+ intent: string;
44
+ status: "completed" | "created" | "failed" | "interrupted" | "running" | "waiting_for_input";
45
+ created_at: string;
46
+ updated_at: string;
47
+ shared?: boolean | undefined;
48
+ memory_enabled?: boolean | undefined;
49
+ is_persistent?: boolean | undefined;
50
+ is_headless?: boolean | undefined;
51
+ viewer_role?: "owner" | "viewer" | undefined;
52
+ template_id?: string | null | undefined;
53
+ model?: string | null | undefined;
54
+ enable_thinking?: boolean | null | undefined;
55
+ solution_id?: string | null | undefined;
56
+ biz_role_id?: string | null | undefined;
57
+ solution?: unknown;
58
+ plan_summary?: string | null | undefined;
59
+ primary_skill_id?: string | null | undefined;
60
+ bound_skill_id?: string | null | undefined;
61
+ replay_state?: unknown;
62
+ is_pinned?: boolean | undefined;
63
+ pinned_at?: string | null | undefined;
64
+ is_example?: boolean | undefined;
65
+ ports?: unknown;
66
+ disable_tools?: string[] | undefined;
67
+ runtime_type?: string | null | undefined;
68
+ daemon_id?: string | null | undefined;
69
+ match?: unknown;
70
+ }, {}>;
71
+ SessionStatus: import("arktype/internal/variants/string.ts").StringType<"completed" | "created" | "failed" | "interrupted" | "running" | "waiting_for_input", {}>;
72
+ LayoutType: typeof agentClient.LayoutType;
73
+ Task: import("arktype/internal/variants/object.ts").ObjectType<{
74
+ id: string;
75
+ goal: string;
76
+ skills: string[];
77
+ depends_on: string[];
78
+ status: "done" | "failed" | "in_progress" | "pending" | "skipped";
79
+ result_summary: string;
80
+ number: string;
81
+ }, {}>;
82
+ TaskStatus: import("arktype/internal/variants/string.ts").StringType<"done" | "failed" | "in_progress" | "pending" | "skipped", {}>;
83
+ ClientProjectionBuilder: typeof agentClient.ClientProjectionBuilder;
84
+ createSocket: typeof agentClient.createSocket;
85
+ getChat: typeof getChat;
86
+ BladeChatElement: typeof BladeChatElement;
87
+ };
88
+ declare global {
89
+ interface Window {
90
+ BladeAgent: typeof BladeAgent;
91
+ }
92
+ }
93
+ export type { AgentSession };
94
+ export { BladeAgent };
@@ -0,0 +1,29 @@
1
+ import type { AgentSession, CreateSessionRequest, SessionState } from "@blade-hq/agent-client";
2
+ export interface UseAgentSessionOptions {
3
+ /** 不传 sessionId 时按此配置新建会话;两者都不传则新建默认对话。 */
4
+ createOptions?: CreateSessionRequest;
5
+ /** 自动创建出的 sessionId 通过此回调交还调用方持有(重挂载复用的依据)。 */
6
+ onSessionCreated?: (sessionId: string) => void;
7
+ }
8
+ export interface UseAgentSessionResult {
9
+ /** 连接/创建完成前为 null。 */
10
+ session: AgentSession | null;
11
+ /** 会话状态快照;session 未就绪时为 null。 */
12
+ state: SessionState | null;
13
+ /** 连接或创建失败的错误(含 VersionMismatchError)。 */
14
+ error: Error | null;
15
+ }
16
+ /**
17
+ * 连接(或创建)一个会话并订阅其状态。
18
+ *
19
+ * - 优先级:sessionId(连接既有会话)> createOptions(按配置新建)> 默认新建。
20
+ * - 同一 sessionId 重复调用复用同一 AgentSession 实例(SessionHub 引用计数)。
21
+ * - 自动创建只发生一次(含 StrictMode 双跑);创建出的 id 经 onSessionCreated
22
+ * 交还调用方。
23
+ *
24
+ * **连接与 sessionId 变更分离**:连接在挂载时建立、仅在卸载时释放;只有
25
+ * 当 sessionId 明确切到一个「与当前已连接会话不同」的 id 时才重连。这样宿主
26
+ * (如 Vue 把自动创建的 id 写回 `session-id` 属性)回填同一个 id 不会触发
27
+ * 拆–重连——否则会把正在流式的会话换成新实例、当前渲染整个丢失。
28
+ */
29
+ export declare function useAgentSession(sessionId?: string, options?: UseAgentSessionOptions): UseAgentSessionResult;
@@ -0,0 +1,10 @@
1
+ export { BladeProvider, useBladeClient } from "./context";
2
+ export type { BladeProviderProps } from "./context";
3
+ export { useAgentSession } from "./hooks/use-agent-session";
4
+ export type { UseAgentSessionOptions, UseAgentSessionResult } from "./hooks/use-agent-session";
5
+ export { ChatView } from "./components/ChatView";
6
+ export type { ChatViewClassNames, ChatViewProps, ChatViewRenderers, ChatViewSlots, } from "./components/ChatView";
7
+ export { MarkdownContent } from "./components/MarkdownContent";
8
+ export type { MarkdownContentProps } from "./components/MarkdownContent";
9
+ export type { ToolCallRenderer } from "./components/ToolCallBlock";
10
+ export * from "@blade-hq/agent-client";