@blade-hq/agent-react 2610.0.0-beta.7 → 2610.0.0-beta.70
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 +148 -3
- package/dist/chunk-G3PMV62Z.js +36 -0
- package/dist/{chunk-ZXXLY4RM.js → chunk-MAAMCOAU.js} +8 -32
- package/dist/{chunk-ZXXLY4RM.js.map → chunk-MAAMCOAU.js.map} +1 -1
- package/dist/components/AgentChat.d.ts +3 -0
- package/dist/components/AgentLoopBlock.d.ts +1 -4
- package/dist/components/AskUserQuestionBlock.d.ts +9 -0
- package/dist/components/AssistantTurnBlock.d.ts +20 -6
- package/dist/components/ChatInput.d.ts +15 -1
- package/dist/components/ChatSurface.d.ts +29 -2
- package/dist/components/ConnectorPanel.d.ts +41 -0
- package/dist/components/ContextCard.d.ts +20 -0
- package/dist/components/MarkdownContent.d.ts +2 -0
- package/dist/components/McpAppCard.d.ts +14 -0
- package/dist/components/MessageList.d.ts +26 -1
- package/dist/components/PlanUpdateBlock.d.ts +31 -0
- package/dist/components/PluginConnectorList.d.ts +47 -0
- package/dist/components/PluginTriggerStack.d.ts +22 -0
- package/dist/components/SessionMemoryToggle.d.ts +19 -0
- package/dist/components/SessionPluginConfigDialog.d.ts +10 -0
- package/dist/components/SessionPluginConfigForm.d.ts +14 -0
- package/dist/components/SessionPluginIcon.d.ts +30 -0
- package/dist/components/SessionPluginSelector.d.ts +10 -0
- package/dist/components/SessionQueuePanel.d.ts +74 -0
- package/dist/components/ToolCallBlock.d.ts +4 -2
- package/dist/components/ToolUiCardView.d.ts +9 -0
- package/dist/components/UserMessageBubble.d.ts +1 -1
- package/dist/components/WhatIfUserBubble.d.ts +7 -0
- package/dist/components/connector-panel-types.d.ts +37 -0
- package/dist/components/display-utils.d.ts +10 -0
- package/dist/components/plugin-config-draft.d.ts +13 -0
- package/dist/components/plugin-config-schema.d.ts +6 -0
- package/dist/components/plugin-connector.d.ts +40 -0
- package/dist/components/queue-panel-adjacency.d.ts +1 -0
- package/dist/components/use-session-plugin-activation.d.ts +40 -0
- package/dist/context.d.ts +1 -0
- package/dist/embed/entry.d.ts +46 -0
- package/dist/{highlighted-body-B3W2YXNL-YD7FAP6V.js → highlighted-body-B3W2YXNL-IASCZDV2.js} +3 -2
- package/dist/{highlighted-body-B3W2YXNL-YD7FAP6V.js.map → highlighted-body-B3W2YXNL-IASCZDV2.js.map} +1 -1
- package/dist/hooks/use-agent-session.d.ts +5 -0
- package/dist/hooks/use-message-pin.d.ts +28 -0
- package/dist/hooks/use-typewriter-reveal.d.ts +32 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.js +44786 -1663
- package/dist/index.js.map +1 -1
- package/dist/lib/agent-computer-command.d.ts +34 -0
- package/dist/lib/random-id.d.ts +10 -0
- package/dist/lib/utils.d.ts +3 -1
- package/dist/lib/whatif-prompt.d.ts +18 -0
- package/dist/mermaid-3ZIDBTTL-BPVVWTVV.js +9 -0
- package/dist/mermaid-3ZIDBTTL-BPVVWTVV.js.map +1 -0
- package/dist/style.css +97 -5
- package/dist/style.full.css +98 -6
- package/dist/webapi-W3IB5DO4.js +2481 -0
- package/dist/webapi-W3IB5DO4.js.map +1 -0
- package/package.json +2 -2
- package/public-api.md +1287 -31
- package/dist/mermaid-3ZIDBTTL-N7YKJ3SM.js +0 -8
- /package/dist/{mermaid-3ZIDBTTL-N7YKJ3SM.js.map → chunk-G3PMV62Z.js.map} +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AgentSession, CreateSessionRequest } from "@blade-hq/agent-client";
|
|
2
|
+
import { type ReactNode } from "react";
|
|
2
3
|
import { type ChatPresentationProps } from "./ChatSurface";
|
|
3
4
|
import type { FollowupInteractionEvent } from "./PostChatFollowupBlock";
|
|
4
5
|
export interface AgentChatProps extends ChatPresentationProps {
|
|
@@ -13,6 +14,8 @@ export interface AgentChatProps extends ChatPresentationProps {
|
|
|
13
14
|
onSessionReady?: (session: AgentSession) => void;
|
|
14
15
|
/** 智能体下发给宿主页面的指令处理器(action → handler)。 */
|
|
15
16
|
commands?: Record<string, (data: unknown) => void>;
|
|
17
|
+
/** 覆盖默认会话插件选择器。 */
|
|
18
|
+
sessionPluginControls?: (sessionId: string) => ReactNode;
|
|
16
19
|
}
|
|
17
20
|
/**
|
|
18
21
|
* 智能体模式的聊天界面:连接(或新建)一个 Blade 会话,渲染消息流与输入框。
|
|
@@ -2,9 +2,6 @@ import type { ToolCallInfo } from "@blade-hq/agent-client";
|
|
|
2
2
|
interface Props {
|
|
3
3
|
toolCall: ToolCallInfo;
|
|
4
4
|
}
|
|
5
|
-
/**
|
|
6
|
-
* 子智能体(fork Agent)状态块的 SDK 简化版:只展示描述、状态与最终结果,
|
|
7
|
-
* 不再嵌套渲染子循环的完整消息流(那是第一方界面的能力)。
|
|
8
|
-
*/
|
|
5
|
+
/** SDK 没有第一方子循环消息流,只保留轻量意图行和可展开的最终结果。 */
|
|
9
6
|
export declare function AgentLoopBlock({ toolCall }: Props): import("react/jsx-runtime").JSX.Element;
|
|
10
7
|
export {};
|
|
@@ -28,4 +28,13 @@ interface Props {
|
|
|
28
28
|
export declare function AskUserQuestionBlock({ data, answered, toolCallId, sessionStatus, answerData, onAnswer, }: Props): import("react/jsx-runtime").JSX.Element;
|
|
29
29
|
/** 解析 AskUserQuestion 的工具结果/参数,容错 LLM 把 questions 输出为字符串的情况。 */
|
|
30
30
|
export declare function parseAskUserQuestion(toolResult: string | null | undefined): AskUserQuestionData | null;
|
|
31
|
+
export interface AskUserQuestionError {
|
|
32
|
+
message: string;
|
|
33
|
+
detail: string | null;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Keep this parser synchronized with apps/web/AskUserQuestionBlock.tsx.
|
|
37
|
+
* The built-in Web cannot import agent-react, and this is not a public SDK protocol API.
|
|
38
|
+
*/
|
|
39
|
+
export declare function parseAskUserQuestionError(toolResult: string | null | undefined): AskUserQuestionError | null;
|
|
31
40
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AskUserAnswerData, ChatMessage } from "@blade-hq/agent-client";
|
|
1
|
+
import type { AskUserAnswerData, ChatMessage, MemoryRefInfo } from "@blade-hq/agent-client";
|
|
2
2
|
import { type ToolCallRenderer } from "./ToolCallBlock";
|
|
3
3
|
interface Props {
|
|
4
4
|
messages: ChatMessage[];
|
|
@@ -7,12 +7,26 @@ interface Props {
|
|
|
7
7
|
onAnswer?: (answer: string, toolCallId: string, answerData: AskUserAnswerData) => void;
|
|
8
8
|
sessionStatus?: string;
|
|
9
9
|
toolCallRenderer?: ToolCallRenderer;
|
|
10
|
+
/** Agent 模式把 update_plan 收口到输入框上方的任务面板;纯 LLM 同名工具照常展示。 */
|
|
11
|
+
hidePlanUpdateTools?: boolean;
|
|
10
12
|
/** 会话 id;传给 Markdown 渲染的统一上下文。 */
|
|
11
13
|
sessionId?: string;
|
|
12
14
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
export type TurnDisplayMode = "compact" | "detail";
|
|
16
|
+
export declare function resolveTurnDisplayMode({ isStreaming: _isStreaming, displayMode, }: {
|
|
17
|
+
isStreaming: boolean;
|
|
18
|
+
displayMode: TurnDisplayMode;
|
|
19
|
+
}): TurnDisplayMode;
|
|
20
|
+
export declare function formatExecutionDuration(durationMs: number): string;
|
|
21
|
+
export declare function getExecutionDurationMs({ messages, isStreaming, now, }: {
|
|
22
|
+
messages: ChatMessage[];
|
|
23
|
+
isStreaming: boolean;
|
|
24
|
+
now?: number;
|
|
25
|
+
}): number;
|
|
26
|
+
/** 一轮助手回复:执行过程默认折叠,最终正文始终显示在摘要下方。 */
|
|
27
|
+
export declare function AssistantTurnBlock({ messages, isStreaming, askAnswers, onAnswer, sessionStatus, toolCallRenderer, hidePlanUpdateTools, sessionId, }: Props): import("react/jsx-runtime").JSX.Element;
|
|
28
|
+
export declare function collectMemoryRefs(messages: ChatMessage[]): MemoryRefInfo[];
|
|
29
|
+
export declare function MemoryRefsHint({ refs }: {
|
|
30
|
+
refs: MemoryRefInfo[];
|
|
31
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
18
32
|
export {};
|
|
@@ -6,13 +6,27 @@ interface Props {
|
|
|
6
6
|
onStop: () => void;
|
|
7
7
|
isStreaming: boolean;
|
|
8
8
|
isStopping?: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* 宿主是否渲染了队列面板。没有面板时不给"运行中提交"入口:消息进了队列却看不见,
|
|
11
|
+
* 比明确提示用户等一等更糟。ChatSurface 按 queuePanel 是否存在传入。
|
|
12
|
+
*/
|
|
13
|
+
queueWhileRunning?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* 上方紧贴着一个比自己窄的面板(队列面板)时置 true:上两角改直角。
|
|
16
|
+
*
|
|
17
|
+
* 面板比输入框窄一圈,输入框上角留圆弧的话,那两段弧会从面板两侧露出来,
|
|
18
|
+
* 看着就是两个尖角。跟内置 Web 的 ChatInput 是同一个判据。
|
|
19
|
+
*/
|
|
20
|
+
mergesWithPanelAbove?: boolean;
|
|
9
21
|
placeholder?: string;
|
|
10
22
|
className?: string;
|
|
23
|
+
queueKey?: string;
|
|
24
|
+
hasAttachments?: boolean;
|
|
11
25
|
}
|
|
12
26
|
/**
|
|
13
27
|
* 轻量聊天输入框:textarea(Enter 发送 / Shift+Enter 换行)+ 发送/停止按钮。
|
|
14
28
|
* 不含第一方版本的富文本编辑、@ 补全、技能菜单、语音输入与模型选择。
|
|
15
29
|
* 内容受控,session.attach() / insertText() 通过 ChatView 注入到这里。
|
|
16
30
|
*/
|
|
17
|
-
export declare function ChatInput({ value, onValueChange, onSend, onStop, isStreaming, isStopping, placeholder, className, }: Props): import("react/jsx-runtime").JSX.Element;
|
|
31
|
+
export declare function ChatInput({ value, onValueChange, onSend, onStop, isStreaming, isStopping, queueWhileRunning, mergesWithPanelAbove, placeholder, className, queueKey, hasAttachments, }: Props): import("react/jsx-runtime").JSX.Element;
|
|
18
32
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AskUserAnswerData, ChatMessage, ConnectionStatus, PostChatFollowup } from "@blade-hq/agent-client";
|
|
2
|
-
import type
|
|
2
|
+
import { type ReactNode } from "react";
|
|
3
3
|
import type { ToolCallRenderer } from "./ToolCallBlock";
|
|
4
4
|
import type { FollowupInteractionEvent } from "./PostChatFollowupBlock";
|
|
5
5
|
import type { ResultFeedback } from "@blade-hq/agent-client";
|
|
@@ -55,8 +55,35 @@ interface ChatSurfaceProps extends ChatPresentationProps {
|
|
|
55
55
|
onResultFeedbackSaved?: (feedback: ResultFeedback) => void;
|
|
56
56
|
/** 输入框上方的内部区域(纯 LLM 模式的高级设置用)。不传时不渲染任何节点。 */
|
|
57
57
|
beforeInput?: ReactNode;
|
|
58
|
+
/** 输入框上方的会话队列面板(智能体模式用)。不传时不渲染任何节点。 */
|
|
59
|
+
queuePanel?: ReactNode;
|
|
60
|
+
/**
|
|
61
|
+
* 队列面板此刻是否真的占位(由面板的 `onVisibleChange` 上报)。
|
|
62
|
+
*
|
|
63
|
+
* 不能用 `queuePanel != null` 代替:面板有本地编辑态(编辑到一半、那条等待
|
|
64
|
+
* 消息被服务端拿走时仍留在原地保住草稿),这时它显示但 snapshot 里没有条目,
|
|
65
|
+
* 光看节点是否存在判不出来,输入框上两角就会在面板还开着的时候恢复成圆角。
|
|
66
|
+
*/
|
|
67
|
+
queuePanelVisible?: boolean;
|
|
68
|
+
/** 仅 Agent 模式启用 Blade 的 update_plan 面板。 */
|
|
69
|
+
showPlanUpdates?: boolean;
|
|
70
|
+
/** 仅实时成功的 update_plan 递增;历史 hydration 不得改变。 */
|
|
71
|
+
planRevealRevision?: number;
|
|
72
|
+
historyPaging?: {
|
|
73
|
+
hasOlder: boolean;
|
|
74
|
+
loading: boolean;
|
|
75
|
+
/** Resolves true only when the paging cursor advanced. */
|
|
76
|
+
loadOlder: (beforeCommit?: () => void) => Promise<boolean>;
|
|
77
|
+
};
|
|
58
78
|
/** 连接状态条下方的横幅(回放模式条用)。不传时不渲染任何节点。 */
|
|
59
79
|
banner?: ReactNode;
|
|
80
|
+
/**
|
|
81
|
+
* 打字机式显示节流是否还没追平目标全文——调用方需要跟 isStreaming 做
|
|
82
|
+
* `||` 判断输入框"运行中"状态。
|
|
83
|
+
*/
|
|
84
|
+
onRevealingChange?: (revealing: boolean) => void;
|
|
85
|
+
/** 是否正在回放(演示 / 彩排)而非真正的实时直播——透传给 MessageList。 */
|
|
86
|
+
isReplay?: boolean;
|
|
60
87
|
}
|
|
61
88
|
/**
|
|
62
89
|
* 消息流 + 输入框:智能体模式与纯 LLM 模式共用同一套外观,差别只在谁喂数据。
|
|
@@ -64,5 +91,5 @@ interface ChatSurfaceProps extends ChatPresentationProps {
|
|
|
64
91
|
* 这里的 DOM 结构受 tests/chat-view-compat.test.tsx 的快照保护——接入方拿
|
|
65
92
|
* .blade-chat-* 类名写了自己的样式,结构一动他们的页面就歪。
|
|
66
93
|
*/
|
|
67
|
-
export declare function ChatSurface({ theme, classNames, renderers, slots, placeholder, connection, errorMessage, messages, postChatFollowup, isStreaming, isStopping, inputText, onInputChange, onSuggestion, onSend, onStop, sessionStatus, askAnswers, onAnswer, sessionId, isViewer, resultFeedbackByEntry, onResultFeedbackSaved, onFollowupInteraction, beforeInput, banner, }: ChatSurfaceProps): import("react/jsx-runtime").JSX.Element;
|
|
94
|
+
export declare function ChatSurface({ theme, classNames, renderers, slots, placeholder, connection, errorMessage, messages, postChatFollowup, isStreaming, isStopping, inputText, onInputChange, onSuggestion, onSend, onStop, sessionStatus, askAnswers, onAnswer, sessionId, isViewer, resultFeedbackByEntry, onResultFeedbackSaved, onFollowupInteraction, beforeInput, queuePanel, queuePanelVisible, showPlanUpdates, planRevealRevision, historyPaging, banner, onRevealingChange, isReplay, }: ChatSurfaceProps): import("react/jsx-runtime").JSX.Element;
|
|
68
95
|
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { BladeClient, SessionPluginActivation } from "@blade-hq/agent-client";
|
|
2
|
+
import { type ReactNode } from "react";
|
|
3
|
+
import { type PluginConnectorItem } from "./plugin-connector";
|
|
4
|
+
import { type PluginConnectorSelection } from "./connector-panel-types";
|
|
5
|
+
export interface ConnectorPanelProps {
|
|
6
|
+
client: BladeClient;
|
|
7
|
+
/**
|
|
8
|
+
* `null` 表示首页:插件开关只记下本次输入的待选,不激活任何东西、不建会话、
|
|
9
|
+
* 不启动沙盒或 MCP。待选项随首条消息一起交给宿主处理。
|
|
10
|
+
*/
|
|
11
|
+
sessionId: string | null;
|
|
12
|
+
/** 首页待选插件;`sessionId` 为 null 时使用。 */
|
|
13
|
+
pendingPlugins?: PluginConnectorSelection[];
|
|
14
|
+
onPendingPluginsChange?: (next: PluginConnectorSelection[]) => void;
|
|
15
|
+
/** 首页候选开关不可用时的说明(例如软件工厂模式会先建项目再启动)。 */
|
|
16
|
+
pendingDisabledReason?: string | null;
|
|
17
|
+
/** 会话内插件启用/停用结果;宿主据此刷新技能统计。 */
|
|
18
|
+
onPluginsChanged?: (plugin: SessionPluginActivation) => void;
|
|
19
|
+
/**
|
|
20
|
+
* 当前已选(首页待选 / 会话内已启用)的插件,按行原样报给宿主。
|
|
21
|
+
*
|
|
22
|
+
* 触发器要在不打开面板时就能显示「选了哪几个、几个」,它自己拿不到这份状态,
|
|
23
|
+
* 所以由面板单向汇报;面板未挂载时宿主保留上一次的结果。
|
|
24
|
+
*/
|
|
25
|
+
onSelectedChange?: (items: PluginConnectorItem[]) => void;
|
|
26
|
+
/** 宿主注入:电脑分区。参数是搜索词,宿主自己决定怎么过滤。 */
|
|
27
|
+
renderComputerSection?: (query: string) => ReactNode;
|
|
28
|
+
/** 宿主注入:外部账号分区(飞书 / GitHub 等固定连接入口)。 */
|
|
29
|
+
renderExternalAccounts?: (query: string) => ReactNode;
|
|
30
|
+
/** 宿主注入:底部操作区;不注入就不渲染这一块。 */
|
|
31
|
+
renderFooterActions?: () => ReactNode;
|
|
32
|
+
className?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 统一连接器面板:顶部搜索、按「电脑 / 插件 / 外部账号」分区、底部添加与管理。
|
|
36
|
+
*
|
|
37
|
+
* 插件分区是这一层唯一的共享实现:首页和会话用同一个列表、同一套启用判定,
|
|
38
|
+
* 判定不各写一份。电脑与外部账号由宿主注入——那些入口需要宿主的路由与 CLI
|
|
39
|
+
* 引导,SDK 不硬编码内部路径,也不替第三方决定跳到哪里。
|
|
40
|
+
*/
|
|
41
|
+
export declare function ConnectorPanel({ client, sessionId, pendingPlugins, onPendingPluginsChange, pendingDisabledReason, onPluginsChanged, onSelectedChange, renderComputerSection, renderExternalAccounts, renderFooterActions, className, }: ConnectorPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type ContextProjectionData } from "@blade-hq/agent-client";
|
|
2
|
+
export interface ContextCardProps {
|
|
3
|
+
context: ContextProjectionData;
|
|
4
|
+
className?: string;
|
|
5
|
+
}
|
|
6
|
+
/** Business-facing Context summary. Native details keeps every card collapsed by default. */
|
|
7
|
+
export declare function ContextCard({ context, className }: ContextCardProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export interface ContextGroupCardProps {
|
|
9
|
+
contexts: readonly ContextProjectionData[];
|
|
10
|
+
className?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 一批上下文注入折叠成一行。会话首轮会一次注入十几个原子,一条一张卡片会把
|
|
14
|
+
* 真正的对话挤出屏幕。
|
|
15
|
+
*
|
|
16
|
+
* 单条和多条**共用同一个 details 外壳**,不在数量变化时切换组件:流式时第二条
|
|
17
|
+
* 到达会让这一行从单条变成多条,组件类型一换 React 就重挂 <details>,
|
|
18
|
+
* 用户刚展开的行会被收起来。同理,key 由调用方按组内第一条给,不能带数量。
|
|
19
|
+
*/
|
|
20
|
+
export declare function ContextGroupCard({ contexts, className }: ContextGroupCardProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { BladeClient } from "@blade-hq/agent-client";
|
|
2
|
+
export interface McpAppMessage {
|
|
3
|
+
sessionId: string;
|
|
4
|
+
sourceId: string;
|
|
5
|
+
label: string;
|
|
6
|
+
content: string;
|
|
7
|
+
}
|
|
8
|
+
export declare const McpAppMessageContext: import("react").Context<((message: McpAppMessage) => void) | null>;
|
|
9
|
+
export declare function McpAppCard({ sessionId, sourceId, client: suppliedClient, onMessage: suppliedOnMessage }: {
|
|
10
|
+
sessionId: string;
|
|
11
|
+
sourceId: string;
|
|
12
|
+
client?: BladeClient;
|
|
13
|
+
onMessage?: (message: McpAppMessage) => void;
|
|
14
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -11,6 +11,7 @@ interface Props {
|
|
|
11
11
|
askAnswers?: Record<string, AskUserAnswerData>;
|
|
12
12
|
onAnswer?: (answer: string, toolCallId: string, answerData: AskUserAnswerData) => void;
|
|
13
13
|
toolCallRenderer?: ToolCallRenderer;
|
|
14
|
+
hidePlanUpdateTools?: boolean;
|
|
14
15
|
emptyState?: ReactNode;
|
|
15
16
|
className?: string;
|
|
16
17
|
/** 会话 id;传给助手消息的统一上下文。 */
|
|
@@ -19,10 +20,34 @@ interface Props {
|
|
|
19
20
|
onFollowupInteraction?: (event: FollowupInteractionEvent) => void;
|
|
20
21
|
resultFeedbackByEntry?: ReadonlyMap<string, ResultFeedback>;
|
|
21
22
|
onResultFeedbackSaved?: (feedback: ResultFeedback) => void;
|
|
23
|
+
historyPaging?: {
|
|
24
|
+
hasOlder: boolean;
|
|
25
|
+
loading: boolean;
|
|
26
|
+
/** Resolves true only when the paging cursor advanced. */
|
|
27
|
+
loadOlder: (beforeCommit?: () => void) => Promise<boolean>;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* 用户点了停止(还没等服务端确认)——打字机式显示节流要在这一刻立刻整段
|
|
31
|
+
* 显示已到达内容,不能等 chat:stop 的服务端回包才响应。跟 isStreaming
|
|
32
|
+
* 翻转成 false 不是一回事:那个信号来得晚,点击到服务端确认之间有一段
|
|
33
|
+
* 网络往返,这段时间里节流动画不该继续播。
|
|
34
|
+
*/
|
|
35
|
+
isStopping?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* 打字机式显示节流是否还没追平目标全文——调用方需要跟 isStreaming 做
|
|
38
|
+
* `||` 判断输入框"运行中"状态,否则输入框会先于文字播完就翻回可输入。
|
|
39
|
+
*/
|
|
40
|
+
onRevealingChange?: (revealing: boolean) => void;
|
|
41
|
+
/**
|
|
42
|
+
* 是否正在回放(演示 / 彩排)而非真正的实时直播——回放期间即使内容在
|
|
43
|
+
* 增长也不进入打字机式节流,直接整段显示:这是"流式与历史必须产生相同
|
|
44
|
+
* 结果"这条硬规则的一部分,节流只在真正的实时直播里生效。
|
|
45
|
+
*/
|
|
46
|
+
isReplay?: boolean;
|
|
22
47
|
}
|
|
23
48
|
/**
|
|
24
49
|
* 消息列表:use-stick-to-bottom 自动滚动 + 按轮次分组渲染。
|
|
25
50
|
* 相比第一方版本去掉了轮次导航栏、吸顶状态条与规划摘要卡片。
|
|
26
51
|
*/
|
|
27
|
-
export declare function MessageList({ messages, postChatFollowup, onSuggestion, isStreaming, sessionStatus, askAnswers, onAnswer, toolCallRenderer, emptyState, className, sessionId, isViewer, onFollowupInteraction, resultFeedbackByEntry, onResultFeedbackSaved, }: Props): import("react/jsx-runtime").JSX.Element;
|
|
52
|
+
export declare function MessageList({ messages, postChatFollowup, onSuggestion, isStreaming, sessionStatus, askAnswers, onAnswer, toolCallRenderer, hidePlanUpdateTools, emptyState, className, sessionId, isViewer, onFollowupInteraction, resultFeedbackByEntry, onResultFeedbackSaved, historyPaging, isStopping, onRevealingChange, isReplay, }: Props): import("react/jsx-runtime").JSX.Element;
|
|
28
53
|
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ChatMessage, ToolCallInfo } from "@blade-hq/agent-client";
|
|
2
|
+
export type PlanStepStatus = "pending" | "in_progress" | "completed";
|
|
3
|
+
export interface PlanUpdateData {
|
|
4
|
+
plan: Array<{
|
|
5
|
+
step: string;
|
|
6
|
+
status: PlanStepStatus;
|
|
7
|
+
}>;
|
|
8
|
+
}
|
|
9
|
+
export declare const PLAN_AUTO_COLLAPSE_MS = 5000;
|
|
10
|
+
export declare function isPlanUpdateTool(toolCall: Pick<ToolCallInfo, "name">): boolean;
|
|
11
|
+
export interface PlanUpdateDisplayState {
|
|
12
|
+
current: ToolCallInfo | null;
|
|
13
|
+
updating: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare function getPlanUpdateDisplayState(messages: ChatMessage[]): PlanUpdateDisplayState;
|
|
16
|
+
export declare function parsePlanUpdate(argumentsJson: string): PlanUpdateData | null;
|
|
17
|
+
export declare function pickCurrentPlanStep(plan: PlanUpdateData["plan"]): PlanUpdateData["plan"][number] | null;
|
|
18
|
+
export declare function PlanUpdateBlock({ toolCall, running, autoReveal, }: {
|
|
19
|
+
toolCall: ToolCallInfo;
|
|
20
|
+
running?: boolean;
|
|
21
|
+
/** 实时收到的新进度短暂展开;加载历史时保持默认收起。 */
|
|
22
|
+
autoReveal?: boolean;
|
|
23
|
+
}): import("react/jsx-runtime").JSX.Element | null;
|
|
24
|
+
export declare function CurrentPlanPanel({ messages, running, revealRevision, sessionId, className, }: {
|
|
25
|
+
messages: ChatMessage[];
|
|
26
|
+
running?: boolean;
|
|
27
|
+
/** 仅实时成功的 update_plan 递增;历史 hydration 不得改变。 */
|
|
28
|
+
revealRevision?: number;
|
|
29
|
+
sessionId?: string;
|
|
30
|
+
className?: string;
|
|
31
|
+
}): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { BladeClient, SessionPluginConfigState } from "@blade-hq/agent-client";
|
|
2
|
+
import type { PluginConnectorItem } from "./plugin-connector";
|
|
3
|
+
export interface ConfiguringPlugin {
|
|
4
|
+
name: string;
|
|
5
|
+
/**
|
|
6
|
+
* 这次打开表单是不是「为了启用它」。
|
|
7
|
+
*
|
|
8
|
+
* 只有用户在开关上表达了启用意图时才为 true:已经跑起来的插件再保存配置
|
|
9
|
+
* 不应该顺手重启 / 重新激活(见 SessionPluginSelector 的历史约定)。
|
|
10
|
+
*/
|
|
11
|
+
pendingActivation: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface PluginConnectorListProps {
|
|
14
|
+
client: BladeClient;
|
|
15
|
+
/** 会话内插件用会话接口取图标;首页候选(null)用账号级目录。 */
|
|
16
|
+
sessionId: string | null;
|
|
17
|
+
items: PluginConnectorItem[];
|
|
18
|
+
/** 正在提交意图的行;开关转圈,但仍然可点(点是取消)。 */
|
|
19
|
+
inFlight: Record<string, true>;
|
|
20
|
+
/** 有启用/停用请求在飞,会写服务端的行先锁住次要操作。 */
|
|
21
|
+
busy: boolean;
|
|
22
|
+
/** 上一次操作失败,给出重试入口。 */
|
|
23
|
+
mutationError: boolean;
|
|
24
|
+
onToggle: (item: PluginConnectorItem, next: boolean) => void;
|
|
25
|
+
onRetry: (item: PluginConnectorItem) => void;
|
|
26
|
+
onEditConfig: (item: PluginConnectorItem) => void;
|
|
27
|
+
configuring: ConfiguringPlugin | null;
|
|
28
|
+
onConfigSaved: (state: SessionPluginConfigState) => void;
|
|
29
|
+
onConfigClose: () => void;
|
|
30
|
+
/** 开关不可用时说明原因,而不是静默禁用。 */
|
|
31
|
+
disabledReason?: string | null;
|
|
32
|
+
/**
|
|
33
|
+
* 列表本身不可用(读取失败 / 搜索无结果)时的说明;有值时不再叠加「还没装插件」,
|
|
34
|
+
* 否则会把一次故障或一次没搜到说成「你这个账号没装东西」。
|
|
35
|
+
*/
|
|
36
|
+
unavailableText?: string | null;
|
|
37
|
+
emptyText: string;
|
|
38
|
+
/** 首页待选模式:开关的语义是"待选",不是"已经启用"。 */
|
|
39
|
+
draft?: boolean;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* 连接器面板里的插件列表。
|
|
43
|
+
*
|
|
44
|
+
* 首页与会话共用同一份渲染:开关是开关,候选是候选,行的存在与状态无关——
|
|
45
|
+
* 没启用、没图标也要显示名称和占位,不隐藏整行。
|
|
46
|
+
*/
|
|
47
|
+
export declare function PluginConnectorList({ client, sessionId, items, inFlight, busy, mutationError, onToggle, onRetry, onEditConfig, configuring, onConfigSaved, onConfigClose, disabledReason, unavailableText, emptyText, draft, }: PluginConnectorListProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { BladeClient } from "@blade-hq/agent-client";
|
|
2
|
+
import type { TriggerSummary } from "./connector-panel-types";
|
|
3
|
+
export interface PluginTriggerStackProps {
|
|
4
|
+
client: BladeClient;
|
|
5
|
+
/** 会话内图标走会话接口;首页待选传 `null`(走账号级目录图标)。 */
|
|
6
|
+
sessionId: string | null;
|
|
7
|
+
/** 折叠结果,来自 `triggerSummary`——折叠规则只有那一处。 */
|
|
8
|
+
summary: TriggerSummary;
|
|
9
|
+
className?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* 触发器上的插件头像堆叠:前三枚圆形头像 + 其余折成 `+N`。
|
|
13
|
+
*
|
|
14
|
+
* 没有图标 token 的插件也用显示名首字占一枚圆——它和别的插件长得不一样,
|
|
15
|
+
* 「我选过它」就看得见;早先把这类项直接剔掉,选中后入口毫无变化。
|
|
16
|
+
*
|
|
17
|
+
* 圆环色取 `--background`(盖住被压住的那枚),与整站头像堆叠同一约定,见
|
|
18
|
+
* `apps/web/src/components/agent-board/ProjectMembers.tsx`:容器没有自己的底色时,
|
|
19
|
+
* 环就等于容器露出来的那层底。图标裁成圆形:插件 logo 多是方的,套在圆按钮里
|
|
20
|
+
* 「方套圆」才是那个视觉冲突的来源。
|
|
21
|
+
*/
|
|
22
|
+
export declare function PluginTriggerStack({ client, sessionId, summary, className }: PluginTriggerStackProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { BladeClient } from "@blade-hq/agent-client";
|
|
2
|
+
export interface SessionMemoryToggleProps {
|
|
3
|
+
sessionId: string;
|
|
4
|
+
enabled: boolean;
|
|
5
|
+
/** 不在 BladeProvider 内使用时显式传入,与宿主现有 BladeClient 复用连接和鉴权。 */
|
|
6
|
+
client?: BladeClient;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
label?: string;
|
|
9
|
+
className?: string;
|
|
10
|
+
labelClassName?: string;
|
|
11
|
+
inputClassName?: string;
|
|
12
|
+
onSaved?: (sessionId: string, enabled: boolean) => void;
|
|
13
|
+
onError?: (error: unknown) => void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 当前会话记忆开关。同一 client + sessionId 的所有实例共享保存锁,避免多个聊天入口
|
|
17
|
+
* 或会话切换时发出乱序更新;服务端成功后才通过 onSaved 交还权威值。
|
|
18
|
+
*/
|
|
19
|
+
export declare function SessionMemoryToggle({ sessionId, enabled, client: clientProp, disabled, label, className, labelClassName, inputClassName, onSaved, onError, }: SessionMemoryToggleProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { BladeClient, SessionPlugin, SessionPluginConfigState } from "@blade-hq/agent-client";
|
|
2
|
+
export interface SessionPluginConfigDialogProps {
|
|
3
|
+
client: BladeClient;
|
|
4
|
+
sessionId: string;
|
|
5
|
+
plugin: Pick<SessionPlugin, "name" | "display_name" | "icon">;
|
|
6
|
+
/** Called after every successful save with the freshly published state. */
|
|
7
|
+
onSaved?: (state: SessionPluginConfigState) => void;
|
|
8
|
+
onClose: () => void;
|
|
9
|
+
}
|
|
10
|
+
export declare function SessionPluginConfigDialog({ client, sessionId, plugin, ...props }: SessionPluginConfigDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SessionPluginConfigError, SessionPluginConfigSet, SessionPluginConfigState } from "@blade-hq/agent-client";
|
|
2
|
+
export interface SessionPluginConfigDraft {
|
|
3
|
+
set: SessionPluginConfigSet[];
|
|
4
|
+
remove: string[];
|
|
5
|
+
}
|
|
6
|
+
export interface SessionPluginConfigFormProps {
|
|
7
|
+
config: SessionPluginConfigState;
|
|
8
|
+
submitting: boolean;
|
|
9
|
+
errors: SessionPluginConfigError[];
|
|
10
|
+
failure: string | null;
|
|
11
|
+
onSubmit: (draft: SessionPluginConfigDraft) => void;
|
|
12
|
+
onCancel: () => void;
|
|
13
|
+
}
|
|
14
|
+
export declare function SessionPluginConfigForm({ config, submitting, errors, failure, onSubmit, onCancel, }: SessionPluginConfigFormProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { BladeClient, SessionPlugin } from "@blade-hq/agent-client";
|
|
2
|
+
export interface SessionPluginIconProps {
|
|
3
|
+
client: BladeClient;
|
|
4
|
+
/**
|
|
5
|
+
* 会话内已准备的包。传 `null` 时改用账号级目录图标(`/api/plugins/{name}/icon`),
|
|
6
|
+
* 这样首页这种还没有会话的地方也能显示包内图标。
|
|
7
|
+
*/
|
|
8
|
+
sessionId: string | null;
|
|
9
|
+
plugin: Pick<SessionPlugin, "name" | "icon">;
|
|
10
|
+
/** 边长,默认 20。 */
|
|
11
|
+
size?: number;
|
|
12
|
+
/**
|
|
13
|
+
* 外框形状:`rounded`(默认,面板列表里的小方角)或 `circle`(触发器上的头像堆叠)。
|
|
14
|
+
* 默认值不动,避免改到列表与第三方接入方的观感。
|
|
15
|
+
*/
|
|
16
|
+
shape?: "rounded" | "circle";
|
|
17
|
+
className?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface SessionPluginLabelProps {
|
|
20
|
+
plugin: Pick<SessionPlugin, "name" | "display_name">;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Business name for a plugin, falling back to the technical ID.
|
|
24
|
+
*
|
|
25
|
+
* The ID stays authoritative for paths, authorization, caching and calls; this
|
|
26
|
+
* helper only decides what a user reads. Keep it shared — one place decides.
|
|
27
|
+
*/
|
|
28
|
+
export declare function sessionPluginLabel(plugin: Pick<SessionPlugin, "name" | "display_name">): string;
|
|
29
|
+
/** Package-local plugin icon, with a stable generic placeholder. */
|
|
30
|
+
export declare function SessionPluginIcon({ client, sessionId, plugin, size, shape, className }: SessionPluginIconProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { BladeClient, SessionPluginActivation } from "@blade-hq/agent-client";
|
|
2
|
+
export interface SessionPluginSelectorProps {
|
|
3
|
+
client: BladeClient;
|
|
4
|
+
sessionId: string;
|
|
5
|
+
className?: string;
|
|
6
|
+
side?: "top" | "bottom";
|
|
7
|
+
onChange?: (plugin: SessionPluginActivation) => void;
|
|
8
|
+
}
|
|
9
|
+
/** Shared selector for AgentChat and the built-in Web; no external query provider required. */
|
|
10
|
+
export declare function SessionPluginSelector(props: SessionPluginSelectorProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { type QueuedMessage, type SessionQueueSnapshot } from "@blade-hq/agent-client";
|
|
2
|
+
import { type JSX } from "react";
|
|
3
|
+
export interface SessionQueuePanelProps {
|
|
4
|
+
snapshot: SessionQueueSnapshot;
|
|
5
|
+
/** 当前是否有可接收补充的运行任务(决定「立刻发送」是否可用) */
|
|
6
|
+
canDeliver: boolean;
|
|
7
|
+
/** 正在等服务端确认的条目 id:禁用该条目的操作,避免重复提交 */
|
|
8
|
+
pendingItemId?: string | null;
|
|
9
|
+
/** 冲突/失败提示,例如「该消息已开始执行」;展示在面板顶部 */
|
|
10
|
+
notice?: string | null;
|
|
11
|
+
onResume: () => void;
|
|
12
|
+
onCancel: (item: QueuedMessage) => void;
|
|
13
|
+
onEdit: (item: QueuedMessage, content: string) => boolean | undefined | Promise<boolean>;
|
|
14
|
+
onRequeue?: (content: string) => Promise<boolean>;
|
|
15
|
+
onMove: (item: QueuedMessage, delta: -1 | 1) => void;
|
|
16
|
+
onReorder: (orderedIds: string[]) => void;
|
|
17
|
+
onDeliver: (item: QueuedMessage) => void;
|
|
18
|
+
/**
|
|
19
|
+
* 队列内容与外层留白的宽度类,要和下面输入框用同一个值。
|
|
20
|
+
*
|
|
21
|
+
* 队列卡片是"比输入框窄一圈、露在它上方"的形态,所以这里的宽度必须跟着
|
|
22
|
+
* 输入框走:输入框宽度由调用方决定(内置 Web 默认 max-w-3xl,软件工厂用
|
|
23
|
+
* `max-w-[748px]!` 覆盖,SDK 侧是 max-w-[748px])。写死一个值的话,两种
|
|
24
|
+
* 布局里总有一种对不齐——之前写死 max-w-[748px] 且外层 px-4,而输入框
|
|
25
|
+
* 外层是 px-5,软件工厂恰好都是 748 看着还行,普通聊天里输入框是 768,
|
|
26
|
+
* 队列连缩进一起窄了 22px。
|
|
27
|
+
*/
|
|
28
|
+
contentWidthClassName?: string;
|
|
29
|
+
/** 根节点附加类。宿主用它在根上重设 `--blade-chat-queue-gutter`(或别的变量)。 */
|
|
30
|
+
rootClassName?: string;
|
|
31
|
+
/**
|
|
32
|
+
* 面板占位状态变化时回调(true = 正在占位)。
|
|
33
|
+
*
|
|
34
|
+
* 面板有本地 `editing` 状态:用户编辑到一半、那条等待消息被服务端拿走后,
|
|
35
|
+
* 面板仍要留在原地保住没保存的正文(见 `detachedEdit`)。这时 `items` 是空的,
|
|
36
|
+
* 光凭 snapshot 判不出面板还在,宿主就会把输入框上两角恢复成圆角、接缝上露出
|
|
37
|
+
* 尖角。让面板自己上报,宿主不必也无法复刻这个判据。
|
|
38
|
+
*/
|
|
39
|
+
onVisibleChange?: (visible: boolean) => void;
|
|
40
|
+
/**
|
|
41
|
+
* 面板是否真的紧贴下面的输入框。
|
|
42
|
+
*
|
|
43
|
+
* 中间夹着别的内容时(MCP 暂存内容、内置 Web 的 `composerBanner`)两者并不
|
|
44
|
+
* 相接,这时面板下两角也要圆起来——直角是"被下面的输入框接住"的表示,露出
|
|
45
|
+
* 直角却下面空着一块,看起来像被削掉一角。
|
|
46
|
+
*
|
|
47
|
+
* 不传时读 context(见 `QueuePanelAdjacencyContext`):面板通常由宿主创建、
|
|
48
|
+
* 挂进 `ChatSurface`,而"中间有没有内容"是 `ChatSurface` 内部的 state,
|
|
49
|
+
* 宿主拿不到。内置 Web 自己管布局,直接把值传进来即可。
|
|
50
|
+
*/
|
|
51
|
+
mergesWithInputBelow?: boolean;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* 队列面板此刻会不会占位。
|
|
55
|
+
*
|
|
56
|
+
* 输入框要据此把自己的上两角改成直角:队列贴在它上方、而且比它窄一圈,
|
|
57
|
+
* 输入框上角若还是 22px 圆弧,那两段弧会从队列两侧露出来,形成两个尖角。
|
|
58
|
+
*
|
|
59
|
+
* 抽成一个函数而不是两边各判一次,是为了让"面板可见"和"输入框顶角改直角"
|
|
60
|
+
* 永远同步——这正是仓库里反复出现的"改了一个入口漏了另一个"。
|
|
61
|
+
* 传入的 `editing` 是面板自己的本地编辑态,默认 false。
|
|
62
|
+
*/
|
|
63
|
+
export declare function isQueuePanelVisible(snapshot: Pick<SessionQueueSnapshot, "items" | "paused">, notice: string | null | undefined, editing?: boolean): boolean;
|
|
64
|
+
/**
|
|
65
|
+
* 会话消息队列面板:输入框上方的「待执行 · N」区域。
|
|
66
|
+
*
|
|
67
|
+
* 一行一条:左边三条横向的拖动手柄、中间单行截断的正文、右边 hover 才出现的操作
|
|
68
|
+
* (立刻发送 / 编辑 / 删除)。顺序靠拖动整行调整,手柄上也能用 Alt+↑/↓ 调(键盘
|
|
69
|
+
* 可达性不能因为去掉上下箭头按钮就没了)。
|
|
70
|
+
*
|
|
71
|
+
* 纯展示组件,不持有会话状态;能否编辑/删除/补充全部用 agent-client 的判定函数,
|
|
72
|
+
* 不在本包重写一份。拖动与键盘调整最终都由调用方提交完整的 pending id 顺序。
|
|
73
|
+
*/
|
|
74
|
+
export declare function SessionQueuePanel({ snapshot, canDeliver, pendingItemId, notice, onResume, onCancel, onEdit, onRequeue, onMove, onReorder, onDeliver, contentWidthClassName, rootClassName, onVisibleChange, mergesWithInputBelow: mergesWithInputBelowProp, }: SessionQueuePanelProps): JSX.Element | null;
|
|
@@ -8,6 +8,7 @@ interface Props {
|
|
|
8
8
|
answered?: boolean;
|
|
9
9
|
answerData?: AskUserAnswerData;
|
|
10
10
|
sessionStatus?: string;
|
|
11
|
+
isActiveQuestion?: boolean;
|
|
11
12
|
renderer?: ToolCallRenderer;
|
|
12
13
|
}
|
|
13
14
|
/**
|
|
@@ -19,10 +20,11 @@ interface Props {
|
|
|
19
20
|
* 会同时把已经回答过的旧提问重新变成可作答(历史加载不会带回 answerData),
|
|
20
21
|
* 而且会盖住投影层的错误——这个 bug 就是这么藏住的。
|
|
21
22
|
*/
|
|
22
|
-
export declare function resolveAskQuestionState({ toolStatus, hasAnswerData, fallbackAnswered, }: {
|
|
23
|
+
export declare function resolveAskQuestionState({ toolStatus, hasAnswerData, fallbackAnswered, fallbackAwaiting, }: {
|
|
23
24
|
toolStatus: ToolCallInfo["status"];
|
|
24
25
|
hasAnswerData: boolean;
|
|
25
26
|
fallbackAnswered?: boolean;
|
|
27
|
+
fallbackAwaiting?: boolean;
|
|
26
28
|
}): {
|
|
27
29
|
awaitingAnswer: boolean;
|
|
28
30
|
answered: boolean;
|
|
@@ -31,5 +33,5 @@ export declare function resolveAskQuestionState({ toolStatus, hasAnswerData, fal
|
|
|
31
33
|
* 极简工具调用块:状态 + 展示名一行,点开后是参数/结果的 <pre> 折叠展示。
|
|
32
34
|
* AskUserQuestion 特殊处理为提问选项卡片。
|
|
33
35
|
*/
|
|
34
|
-
export declare function ToolCallBlock({ toolCall, onAnswer, answered, answerData, sessionStatus, renderer, }: Props): import("react/jsx-runtime").JSX.Element;
|
|
36
|
+
export declare function ToolCallBlock({ toolCall, onAnswer, answered, answerData, sessionStatus, isActiveQuestion, renderer, }: Props): import("react/jsx-runtime").JSX.Element;
|
|
35
37
|
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ToolUiCard } from "@blade-hq/agent-client";
|
|
2
|
+
/**
|
|
3
|
+
* MCP Apps 使用 SDK/Web 共享的 AppBridge;恢复只消费留档,不重读资源。
|
|
4
|
+
* 普通资源卡片仍使用 agent-client 的共享内容判定。
|
|
5
|
+
*/
|
|
6
|
+
export declare function ToolUiCardView({ card, sessionId }: {
|
|
7
|
+
card: ToolUiCard;
|
|
8
|
+
sessionId?: string;
|
|
9
|
+
}): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -11,7 +11,7 @@ interface UserMessageProps {
|
|
|
11
11
|
message: UserChatMessage;
|
|
12
12
|
className?: string;
|
|
13
13
|
}
|
|
14
|
-
/**
|
|
14
|
+
/** 用户消息气泡:文本、canonical 引用消息与图片/文件附件。 */
|
|
15
15
|
export declare function UserMessageBubble({ message, className }: UserMessageProps): import("react/jsx-runtime").JSX.Element;
|
|
16
16
|
/** 错误消息:居中红色提示条。 */
|
|
17
17
|
export declare function ErrorMessageBlock({ message, className, }: {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ParsedWhatIfPrompt } from "../lib/whatif-prompt";
|
|
2
|
+
export interface WhatIfUserBubbleProps {
|
|
3
|
+
parsed: ParsedWhatIfPrompt;
|
|
4
|
+
onQuoteClick?: (stepNumber: number) => void;
|
|
5
|
+
}
|
|
6
|
+
/** SDK 与内置 Web 共用的 canonical 引用消息渲染。 */
|
|
7
|
+
export declare function WhatIfUserBubble({ parsed, onQuoteClick }: WhatIfUserBubbleProps): import("react/jsx-runtime").JSX.Element;
|