@blade-hq/agent-react 2610.0.1 → 2612.0.0-beta.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.
Files changed (180) hide show
  1. package/README.md +88 -258
  2. package/dist/chat/AgentLoopBlock.d.ts +14 -0
  3. package/dist/{components → chat}/AskUserQuestionBlock.d.ts +3 -7
  4. package/dist/chat/AssistantTurnBlock.d.ts +50 -0
  5. package/dist/chat/AttachmentPreviewDialog.d.ts +26 -0
  6. package/dist/chat/ChatPanel.d.ts +64 -0
  7. package/dist/chat/CompactionCard.d.ts +6 -0
  8. package/dist/chat/ConnectionBanner.d.ts +10 -0
  9. package/dist/chat/CurrentPlanPanel.d.ts +20 -0
  10. package/dist/chat/FileDeliveryCards.d.ts +26 -0
  11. package/dist/chat/FinalArtifactCards.d.ts +8 -0
  12. package/dist/chat/ImageLightbox.d.ts +11 -0
  13. package/dist/chat/LightComposer.d.ts +7 -0
  14. package/dist/chat/LiteMessageList.d.ts +82 -0
  15. package/dist/chat/MessageActions.d.ts +6 -0
  16. package/dist/chat/MessageContextPills.d.ts +6 -0
  17. package/dist/chat/MessageFileAttachmentList.d.ts +13 -0
  18. package/dist/chat/MessageList.d.ts +54 -0
  19. package/dist/chat/PostChatFollowupBlock.d.ts +11 -0
  20. package/dist/{components → chat}/RenderErrorBoundary.d.ts +0 -1
  21. package/dist/chat/ResultFeedback.d.ts +11 -0
  22. package/dist/chat/SessionReplayBar.d.ts +12 -0
  23. package/dist/chat/TextAttachmentPills.d.ts +10 -0
  24. package/dist/chat/ToolCallBlock.d.ts +48 -0
  25. package/dist/chat/ToolUiCard.d.ts +6 -0
  26. package/dist/chat/TurnNavRail.d.ts +17 -0
  27. package/dist/chat/UserMessageBubble.d.ts +20 -0
  28. package/dist/chat/WorkflowRunBlock.d.ts +13 -0
  29. package/dist/chat/ai-elements/reasoning.d.ts +32 -0
  30. package/dist/chat/ai-elements/shimmer.d.ts +15 -0
  31. package/dist/chat/assistant-turn-questions.d.ts +14 -0
  32. package/dist/chat/card/CardContext.d.ts +7 -0
  33. package/dist/chat/chat-theme.d.ts +19 -0
  34. package/dist/chat/customization.d.ts +214 -0
  35. package/dist/chat/display-utils.d.ts +48 -0
  36. package/dist/{components/PostChatFollowupBlock.d.ts → chat/followup-interaction.d.ts} +5 -17
  37. package/dist/chat/index.d.ts +100 -0
  38. package/dist/chat/lib/citations.d.ts +30 -0
  39. package/dist/chat/lib/code-language.d.ts +5 -0
  40. package/dist/chat/lib/loopback.d.ts +8 -0
  41. package/dist/chat/lib/markdown-asset-url.d.ts +5 -0
  42. package/dist/chat/lib/preview-dispatch.d.ts +24 -0
  43. package/dist/chat/lib/skill-name.d.ts +9 -0
  44. package/dist/chat/lib/skill-visibility.d.ts +8 -0
  45. package/dist/chat/lib/ui-meta.d.ts +5 -0
  46. package/dist/chat/lib/use-async-value.d.ts +8 -0
  47. package/dist/chat/markdown/ExternalAnchor.d.ts +9 -0
  48. package/dist/chat/markdown/MarkdownContent.d.ts +40 -0
  49. package/dist/chat/markdown/text.d.ts +11 -0
  50. package/dist/chat/message-list-blocks.d.ts +92 -0
  51. package/dist/chat/plan/PlanSummaryCard.d.ts +10 -0
  52. package/dist/chat/plan/extract-plan-messages.d.ts +4 -0
  53. package/dist/chat/plan/parse-plan-messages.d.ts +10 -0
  54. package/dist/chat/plan/parse-plan-tree.d.ts +16 -0
  55. package/dist/chat/plan/types.d.ts +56 -0
  56. package/dist/chat/reasoning-visibility.d.ts +2 -0
  57. package/dist/chat/runtime/actions.d.ts +22 -0
  58. package/dist/chat/runtime/background-task-dismissals.d.ts +10 -0
  59. package/dist/chat/runtime/composer-channels.d.ts +46 -0
  60. package/dist/chat/runtime/environment.d.ts +152 -0
  61. package/dist/chat/runtime/input-cache-reset.d.ts +8 -0
  62. package/dist/chat/runtime/input-services.d.ts +111 -0
  63. package/dist/chat/runtime/session-source.d.ts +49 -0
  64. package/dist/chat/runtime/use-chat-actions.d.ts +19 -0
  65. package/dist/chat/runtime/use-session-replay.d.ts +16 -0
  66. package/dist/chat/scroll-anchor.d.ts +46 -0
  67. package/dist/chat/tool-renderers/BashRenderer.d.ts +2 -0
  68. package/dist/chat/tool-renderers/FileEditRenderer.d.ts +2 -0
  69. package/dist/chat/tool-renderers/FileReadRenderer.d.ts +2 -0
  70. package/dist/chat/tool-renderers/KbSearchRenderer.d.ts +2 -0
  71. package/dist/chat/tool-renderers/SearchRenderer.d.ts +2 -0
  72. package/dist/chat/tool-renderers/SubmitResultRenderer.d.ts +2 -0
  73. package/dist/chat/tool-renderers/kb-search-result.d.ts +19 -0
  74. package/dist/chat/tool-renderers/registry.d.ts +5 -0
  75. package/dist/chat/tool-renderers/shared.d.ts +30 -0
  76. package/dist/chat/tool-renderers/write-preview-scroll.d.ts +5 -0
  77. package/dist/chat-OCLOVB3H.css +175 -0
  78. package/dist/chat.css +175 -0
  79. package/dist/chunk-6ZDOQEWK.js +49365 -0
  80. package/dist/chunk-6ZDOQEWK.js.map +1 -0
  81. package/dist/chunk-FQQJP2GJ.js +26986 -0
  82. package/dist/chunk-FQQJP2GJ.js.map +1 -0
  83. package/dist/{chunk-G3PMV62Z.js → chunk-PR4QN5HX.js} +9 -2
  84. package/dist/chunk-WCMGQJLE.js +258 -0
  85. package/dist/chunk-WCMGQJLE.js.map +1 -0
  86. package/dist/components/AgentChat.d.ts +3 -3
  87. package/dist/components/ChatView.d.ts +2 -2
  88. package/dist/components/ConnectorPanel.d.ts +1 -1
  89. package/dist/components/ContextCard.d.ts +1 -1
  90. package/dist/components/LlmChat.d.ts +1 -1
  91. package/dist/components/McpAppCard.d.ts +1 -1
  92. package/dist/components/PlanUpdateBlock.d.ts +0 -8
  93. package/dist/components/PluginConnectorList.d.ts +1 -1
  94. package/dist/components/ReplayBar.d.ts +1 -1
  95. package/dist/components/SessionPluginConfigDialog.d.ts +1 -1
  96. package/dist/components/SessionPluginConfigForm.d.ts +1 -1
  97. package/dist/components/SessionPluginIcon.d.ts +1 -1
  98. package/dist/components/SessionPluginSelector.d.ts +1 -1
  99. package/dist/components/SessionQueuePanel.d.ts +1 -1
  100. package/dist/components/ToolUiCardView.d.ts +1 -1
  101. package/dist/components/plugin-config-draft.d.ts +1 -1
  102. package/dist/components/plugin-config-schema.d.ts +1 -1
  103. package/dist/components/plugin-connector.d.ts +1 -1
  104. package/dist/components/use-session-plugin-activation.d.ts +1 -1
  105. package/dist/context.d.ts +11 -2
  106. package/dist/embed/blade-chat-element.d.ts +14 -1
  107. package/dist/embed/entry.d.ts +8 -78
  108. package/dist/hooks/use-replay.d.ts +1 -1
  109. package/dist/hooks/use-turn-navigation.d.ts +1 -1
  110. package/dist/host.d.ts +54 -0
  111. package/dist/index.d.ts +11 -69
  112. package/dist/index.js +12 -63525
  113. package/dist/index.js.map +1 -1
  114. package/dist/internal.d.ts +60 -0
  115. package/dist/internal.js +656 -0
  116. package/dist/internal.js.map +1 -0
  117. package/dist/lib/mount-renderers.d.ts +25 -0
  118. package/dist/lib/use-effect-event.d.ts +3 -0
  119. package/dist/rich-input/BackgroundTasksPill.d.ts +3 -0
  120. package/dist/rich-input/ChatInput.d.ts +59 -0
  121. package/dist/rich-input/ComposerAttachmentViewport.d.ts +3 -0
  122. package/dist/rich-input/ConnectButton.d.ts +24 -0
  123. package/dist/rich-input/FileCompletionMenu.d.ts +44 -0
  124. package/dist/rich-input/FileSizeLimitDialog.d.ts +9 -0
  125. package/dist/rich-input/ModelSelector.d.ts +10 -0
  126. package/dist/rich-input/PlanningToggle.d.ts +7 -0
  127. package/dist/rich-input/ProgressCircle.d.ts +12 -0
  128. package/dist/rich-input/ReasoningModeSelect.d.ts +9 -0
  129. package/dist/rich-input/SkillCompletionMenu.d.ts +9 -0
  130. package/dist/rich-input/SkillStatusBar.d.ts +15 -0
  131. package/dist/rich-input/extensions/file-mention.d.ts +12 -0
  132. package/dist/rich-input/extensions/kb-mention.d.ts +18 -0
  133. package/dist/rich-input/extensions/skill-mention.d.ts +48 -0
  134. package/dist/rich-input/extensions/workflow-mention.d.ts +10 -0
  135. package/dist/rich-input/index.d.ts +48 -0
  136. package/dist/rich-input/input-keyboard.d.ts +13 -0
  137. package/dist/rich-input/lib/attachment-upload.d.ts +10 -0
  138. package/dist/rich-input/lib/background-tasks-view.d.ts +31 -0
  139. package/dist/rich-input/lib/client-query.d.ts +32 -0
  140. package/dist/rich-input/lib/composer-content.d.ts +42 -0
  141. package/dist/rich-input/lib/image-input-availability.d.ts +3 -0
  142. package/dist/rich-input/lib/kb-suggestions.d.ts +37 -0
  143. package/dist/rich-input/lib/reasoning-levels.d.ts +1 -0
  144. package/dist/rich-input/lib/session-data.d.ts +20 -0
  145. package/dist/rich-input/lib/skill-suggestions.d.ts +19 -0
  146. package/dist/rich-input/lib/token-estimate.d.ts +2 -0
  147. package/dist/rich-input/lib/token-pressure.d.ts +8 -0
  148. package/dist/rich-input/lib/upload-results.d.ts +8 -0
  149. package/dist/rich-input/lib/user-home.d.ts +33 -0
  150. package/dist/rich-input/model/model-data.d.ts +6 -0
  151. package/dist/rich-input/model/resolve-model.d.ts +59 -0
  152. package/dist/rich-input/model/use-composer-model.d.ts +24 -0
  153. package/dist/rich-input/services.d.ts +22 -0
  154. package/dist/rich-input/use-dismiss-skill-suggestions-on-mode-change.d.ts +3 -0
  155. package/dist/rich-input/use-input-history.d.ts +14 -0
  156. package/dist/rich-input/voice/VoiceWaveform.d.ts +10 -0
  157. package/dist/rich-input/voice/use-tiptap-voice-input.d.ts +47 -0
  158. package/dist/rich-input/voice/use-voice-input.d.ts +2 -0
  159. package/dist/rich-input/voice/voice-input-support.d.ts +5 -0
  160. package/dist/rich-input.js +29853 -0
  161. package/dist/rich-input.js.map +1 -0
  162. package/dist/style.css +30 -64
  163. package/dist/style.full.css +210 -65
  164. package/dist/{webapi-W3IB5DO4.js → webapi-E7K2CNM7.js} +2 -2
  165. package/package.json +12 -3
  166. package/public-api.md +206 -3603
  167. package/dist/components/AgentLoopBlock.d.ts +0 -8
  168. package/dist/components/AgentTaskCard.d.ts +0 -12
  169. package/dist/components/AssistantTurnBlock.d.ts +0 -36
  170. package/dist/components/ChatSurface.d.ts +0 -199
  171. package/dist/components/ConnectionBanner.d.ts +0 -8
  172. package/dist/components/MarkdownContent.d.ts +0 -30
  173. package/dist/components/MessageList.d.ts +0 -62
  174. package/dist/components/Shimmer.d.ts +0 -7
  175. package/dist/components/ToolCallBlock.d.ts +0 -41
  176. package/dist/components/TurnNavRail.d.ts +0 -23
  177. package/dist/components/UserMessageBubble.d.ts +0 -25
  178. package/dist/components/display-utils.d.ts +0 -4
  179. /package/dist/{chunk-G3PMV62Z.js.map → chunk-PR4QN5HX.js.map} +0 -0
  180. /package/dist/{webapi-W3IB5DO4.js.map → webapi-E7K2CNM7.js.map} +0 -0
@@ -0,0 +1,656 @@
1
+ import {
2
+ AgentChat,
3
+ BackgroundWakeNotice,
4
+ ChatView,
5
+ ContextCard,
6
+ ContextGroupCard,
7
+ DEFAULT_ALLOWED_TAGS,
8
+ LlmChat,
9
+ MarkdownContent,
10
+ MarkdownRenderer,
11
+ McpAppCard,
12
+ MessageImage,
13
+ ReplayBar,
14
+ ReplayMismatchPrompt,
15
+ SessionPluginSelector,
16
+ SessionQueuePanel,
17
+ TURN_NAV_HIGHLIGHT_CLASS,
18
+ ToolUiCardView,
19
+ WhatIfUserBubble,
20
+ isQueuePanelVisible,
21
+ latestUserSpeechEntryId,
22
+ parseWhatIfPrompt,
23
+ turnNavItemsFromMessages,
24
+ useAgentSession,
25
+ useLlmChat,
26
+ useMessagePin,
27
+ useReplay,
28
+ useTurnNavigation,
29
+ useTypewriterReveal
30
+ } from "./chunk-6ZDOQEWK.js";
31
+ import {
32
+ ConnectorPanel,
33
+ PluginTriggerStack,
34
+ TRIGGER_ICON_LIMIT,
35
+ selectionFromItem,
36
+ triggerSummary
37
+ } from "./chunk-WCMGQJLE.js";
38
+ import {
39
+ BladeProvider,
40
+ Content2,
41
+ PLAN_AUTO_COLLAPSE_MS,
42
+ PlanUpdateBlock,
43
+ PluginConnectorList,
44
+ Portal,
45
+ Provider,
46
+ Root3,
47
+ SessionPluginConfigDialog,
48
+ SessionPluginConfigForm,
49
+ SessionPluginIcon,
50
+ Trigger,
51
+ catalogToConnectorItems,
52
+ cn,
53
+ filterConnectorItems,
54
+ getPlanUpdateDisplayState,
55
+ isPlanUpdateTool,
56
+ mergeConnectorItems,
57
+ parsePlanUpdate,
58
+ pickCurrentPlanStep,
59
+ sessionPluginLabel,
60
+ useBladeClient,
61
+ useBladeHost,
62
+ useOptionalBladeClient,
63
+ useSessionPluginActivation
64
+ } from "./chunk-FQQJP2GJ.js";
65
+ import "./chunk-PR4QN5HX.js";
66
+
67
+ // src/internal.ts
68
+ export * from "./chat-OCLOVB3H.css";
69
+
70
+ // src/lib/mount-renderers.tsx
71
+ import { createContext, useContext, useId, useLayoutEffect, useRef } from "react";
72
+ import { jsx } from "react/jsx-runtime";
73
+ var MountHostContext = createContext(null);
74
+ function normalizeResult(result) {
75
+ if (typeof result === "function") return { destroy: result };
76
+ if (result && typeof result === "object") return result;
77
+ return { destroy: () => {
78
+ } };
79
+ }
80
+ function toObject(renderer) {
81
+ return typeof renderer === "function" ? { mount: renderer } : renderer;
82
+ }
83
+ function sameData(a, b) {
84
+ const aKeys = Object.keys(a);
85
+ if (aKeys.length !== Object.keys(b).length) return false;
86
+ return aKeys.every((key) => Object.is(a[key], b[key]));
87
+ }
88
+ function MountSlot({ renderer, data }) {
89
+ const host = useContext(MountHostContext);
90
+ const slotName = `blade-mount-${useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
91
+ const localRef = useRef(null);
92
+ const dataRef = useRef(data);
93
+ const mountedRef = useRef(null);
94
+ useLayoutEffect(() => {
95
+ dataRef.current = data;
96
+ });
97
+ useLayoutEffect(() => {
98
+ let target;
99
+ if (host) {
100
+ target = document.createElement("div");
101
+ target.slot = slotName;
102
+ host.appendChild(target);
103
+ } else {
104
+ if (!localRef.current) return;
105
+ target = localRef.current;
106
+ }
107
+ const initial = dataRef.current;
108
+ mountedRef.current = { target, handle: normalizeResult(renderer.mount(target, initial)), data: initial };
109
+ return () => {
110
+ const mounted = mountedRef.current;
111
+ mountedRef.current = null;
112
+ mounted?.handle.destroy();
113
+ if (host) target.remove();
114
+ else target.replaceChildren();
115
+ };
116
+ }, [host, renderer, slotName]);
117
+ useLayoutEffect(() => {
118
+ const mounted = mountedRef.current;
119
+ if (!mounted || sameData(mounted.data, data)) return;
120
+ mounted.data = data;
121
+ if (mounted.handle.update) {
122
+ mounted.handle.update(data);
123
+ return;
124
+ }
125
+ mounted.handle.destroy();
126
+ mounted.target.replaceChildren();
127
+ mounted.handle = normalizeResult(renderer.mount(mounted.target, data));
128
+ }, [data, renderer]);
129
+ return host ? /* @__PURE__ */ jsx("slot", { name: slotName }) : /* @__PURE__ */ jsx("div", { ref: localRef, "data-blade-mount": "" });
130
+ }
131
+ function slotFor(renderer, data) {
132
+ if (renderer.match && !renderer.match(data)) return null;
133
+ return /* @__PURE__ */ jsx(MountSlot, { renderer, data });
134
+ }
135
+ function mountRenderersToReact(renderers, context = {}) {
136
+ if (!renderers) return void 0;
137
+ const result = {};
138
+ if (renderers.toolCall) {
139
+ const renderer = toObject(renderers.toolCall);
140
+ result.toolCall = (toolCall) => slotFor(renderer, { toolCall, sessionId: context.sessionId });
141
+ }
142
+ if (renderers.userMessage) {
143
+ const renderer = toObject(renderers.userMessage);
144
+ result.userMessage = ({ message }) => slotFor(renderer, { message });
145
+ }
146
+ if (renderers.assistantText) {
147
+ const renderer = toObject(renderers.assistantText);
148
+ result.assistantText = ({ message, streaming, compact, sessionId }) => slotFor(renderer, { message, streaming, compact, sessionId });
149
+ }
150
+ return result;
151
+ }
152
+
153
+ // src/components/SessionMemoryToggle.tsx
154
+ import { useCallback, useEffect, useRef as useRef2, useState, useSyncExternalStore } from "react";
155
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
156
+ var saveStates = /* @__PURE__ */ new WeakMap();
157
+ function getSaveState(client, sessionId) {
158
+ let clientStates = saveStates.get(client);
159
+ if (!clientStates) {
160
+ clientStates = /* @__PURE__ */ new Map();
161
+ saveStates.set(client, clientStates);
162
+ }
163
+ let state = clientStates.get(sessionId);
164
+ if (!state) {
165
+ state = { saving: false, listeners: /* @__PURE__ */ new Set() };
166
+ clientStates.set(sessionId, state);
167
+ }
168
+ return state;
169
+ }
170
+ function notify(state) {
171
+ for (const listener of state.listeners) listener();
172
+ }
173
+ function cleanupSaveState(client, sessionId, state) {
174
+ if (state.saving || state.listeners.size > 0) return;
175
+ const clientStates = saveStates.get(client);
176
+ if (clientStates?.get(sessionId) === state) clientStates.delete(sessionId);
177
+ }
178
+ function SessionMemoryToggle({
179
+ sessionId,
180
+ enabled,
181
+ client: clientProp,
182
+ disabled = false,
183
+ label = "\u5F53\u524D\u4F1A\u8BDD\u4F7F\u7528\u8BB0\u5FC6",
184
+ className,
185
+ labelClassName,
186
+ inputClassName,
187
+ onSaved,
188
+ onError
189
+ }) {
190
+ const contextClient = useOptionalBladeClient();
191
+ const client = clientProp ?? contextClient;
192
+ if (!client) {
193
+ throw new Error("SessionMemoryToggle \u5FC5\u987B\u5728 <BladeProvider> \u5185\u4F7F\u7528\u6216\u663E\u5F0F\u4F20\u5165 client");
194
+ }
195
+ const saveState = getSaveState(client, sessionId);
196
+ const subscribe = useCallback(
197
+ (listener) => {
198
+ saveState.listeners.add(listener);
199
+ return () => {
200
+ saveState.listeners.delete(listener);
201
+ cleanupSaveState(client, sessionId, saveState);
202
+ };
203
+ },
204
+ [client, saveState, sessionId]
205
+ );
206
+ const getSaving = useCallback(() => saveState.saving, [saveState]);
207
+ const saving = useSyncExternalStore(
208
+ subscribe,
209
+ getSaving,
210
+ getSaving
211
+ );
212
+ const [draftEnabled, setDraftEnabled] = useState(enabled);
213
+ const activeSessionIdRef = useRef2(sessionId);
214
+ activeSessionIdRef.current = sessionId;
215
+ useEffect(() => {
216
+ setDraftEnabled(enabled);
217
+ }, [enabled, sessionId]);
218
+ const update = useCallback(
219
+ (nextEnabled) => {
220
+ const currentSaveState = getSaveState(client, sessionId);
221
+ if (currentSaveState.saving) return;
222
+ currentSaveState.saving = true;
223
+ notify(currentSaveState);
224
+ setDraftEnabled(nextEnabled);
225
+ void client.sessions.updateSessionMemory(sessionId, nextEnabled).then(
226
+ (updated) => {
227
+ if (activeSessionIdRef.current === sessionId) {
228
+ setDraftEnabled(updated.memory_enabled);
229
+ }
230
+ onSaved?.(sessionId, updated.memory_enabled);
231
+ },
232
+ (error) => {
233
+ if (activeSessionIdRef.current === sessionId) setDraftEnabled(enabled);
234
+ onError?.(error);
235
+ }
236
+ ).finally(() => {
237
+ currentSaveState.saving = false;
238
+ notify(currentSaveState);
239
+ cleanupSaveState(client, sessionId, currentSaveState);
240
+ });
241
+ },
242
+ [client, enabled, onError, onSaved, sessionId]
243
+ );
244
+ return /* @__PURE__ */ jsxs("label", { className: cn("flex items-center justify-between", className), children: [
245
+ /* @__PURE__ */ jsx2("span", { className: labelClassName, children: label }),
246
+ /* @__PURE__ */ jsx2(
247
+ "input",
248
+ {
249
+ type: "checkbox",
250
+ checked: draftEnabled,
251
+ onChange: (event) => update(event.target.checked),
252
+ disabled: disabled || saving,
253
+ className: inputClassName
254
+ }
255
+ )
256
+ ] });
257
+ }
258
+
259
+ // src/lib/agent-computer-command.ts
260
+ var COMPUTER_LAUNCH_COMMAND_PATTERN = /(?:^|[\n;&|(]\s*)computer\s+launch(?:\s|$)/;
261
+ function isAgentComputerCommand(command) {
262
+ return COMPUTER_LAUNCH_COMMAND_PATTERN.test(command);
263
+ }
264
+ function isAgentComputerToolCall(argumentsJson) {
265
+ if (!argumentsJson) return false;
266
+ let command;
267
+ try {
268
+ const parsed = JSON.parse(argumentsJson);
269
+ if (typeof parsed !== "object" || parsed === null) return false;
270
+ command = parsed.command;
271
+ } catch {
272
+ return false;
273
+ }
274
+ return typeof command === "string" && isAgentComputerCommand(command);
275
+ }
276
+ var LAUNCH_SUCCESS_MARKER = "\u5DF2\u542F\u52A8 ";
277
+ function resultContainsLaunchSuccessMarker(result, depth = 0) {
278
+ if (depth > 2) return false;
279
+ if (typeof result === "string") {
280
+ if (result.includes(LAUNCH_SUCCESS_MARKER)) return true;
281
+ try {
282
+ return resultContainsLaunchSuccessMarker(JSON.parse(result), depth + 1);
283
+ } catch {
284
+ return false;
285
+ }
286
+ }
287
+ if (typeof result === "object" && result !== null) {
288
+ for (const value of Object.values(result)) {
289
+ if (typeof value === "string" && value.includes(LAUNCH_SUCCESS_MARKER)) return true;
290
+ }
291
+ }
292
+ return false;
293
+ }
294
+ function classifyAgentComputerLaunchOutcome(toolCall) {
295
+ if (toolCall.status === "error" || toolCall.status === "cancelled") return "failed";
296
+ if (toolCall.status !== "done") return "pending";
297
+ if (toolCall.result === void 0 || toolCall.result === null) return "unknown";
298
+ return resultContainsLaunchSuccessMarker(toolCall.result) ? "succeeded" : "failed";
299
+ }
300
+
301
+ // src/components/SessionBranchPicker.tsx
302
+ import { useMemo, useState as useState2 } from "react";
303
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
304
+ var ROW_HEIGHT = 32;
305
+ var SVG_WIDTH = 44;
306
+ function SessionBranchPicker({
307
+ tree,
308
+ disabled = false,
309
+ onCheckout
310
+ }) {
311
+ const [checkoutError, setCheckoutError] = useState2(null);
312
+ const [pendingNodeId, setPendingNodeId] = useState2(null);
313
+ const hasHistory = tree.nodes.length > 0;
314
+ const layout = useMemo(() => buildLayoutNodes(tree), [tree]);
315
+ const nodeMap = useMemo(() => new Map(tree.nodes.map((node) => [node.id, node])), [tree]);
316
+ const isBusy = disabled || pendingNodeId !== null;
317
+ const graphHeight = Math.max((layout.maxRow + 1) * ROW_HEIGHT, ROW_HEIGHT);
318
+ const graphWidth = Math.max(SVG_WIDTH, getColumnX(layout.maxColumn) + 12);
319
+ async function checkoutNode(node, position) {
320
+ if (isBusy) return;
321
+ setCheckoutError(null);
322
+ setPendingNodeId(node.id);
323
+ try {
324
+ await onCheckout(node.id, position);
325
+ } catch (error) {
326
+ setCheckoutError(error instanceof Error ? error.message : "\u5207\u6362\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5");
327
+ } finally {
328
+ setPendingNodeId(null);
329
+ }
330
+ }
331
+ async function handleVirtualClick(node) {
332
+ if (isBusy || !node.isVirtual || node.isActive) return;
333
+ const sourceNode = nodeMap.get(node.content);
334
+ if (sourceNode) await checkoutNode(sourceNode, "turn_end");
335
+ }
336
+ async function handleNodeSelect(node) {
337
+ if (isBusy) return;
338
+ const sourceNode = nodeMap.get(node.id);
339
+ if (sourceNode) await checkoutNode(sourceNode, "before");
340
+ }
341
+ if (!hasHistory) return null;
342
+ return /* @__PURE__ */ jsxs2(Provider, { delayDuration: 200, children: [
343
+ checkoutError ? /* @__PURE__ */ jsx3("p", { role: "alert", className: "mb-2 text-xs text-destructive", children: checkoutError }) : null,
344
+ /* @__PURE__ */ jsx3("div", { className: "flex max-h-52 justify-center overflow-x-auto overflow-y-auto", children: /* @__PURE__ */ jsxs2("div", { className: "relative", style: { height: graphHeight, width: graphWidth }, children: [
345
+ /* @__PURE__ */ jsx3(
346
+ "svg",
347
+ {
348
+ "aria-hidden": "true",
349
+ className: "pointer-events-none absolute left-0 top-0 z-10 overflow-visible",
350
+ width: graphWidth,
351
+ height: graphHeight,
352
+ viewBox: `0 0 ${graphWidth} ${graphHeight}`,
353
+ fill: "none",
354
+ children: layout.nodes.map((node) => {
355
+ if (node.parentRow == null || node.parentColumn == null) {
356
+ return null;
357
+ }
358
+ const childStroke = node.isActive ? "hsl(var(--primary))" : "hsl(var(--muted-foreground))";
359
+ return /* @__PURE__ */ jsx3(
360
+ "path",
361
+ {
362
+ d: buildEdgePath(
363
+ getColumnX(node.parentColumn),
364
+ getRowY(node.parentRow),
365
+ getColumnX(node.column),
366
+ getRowY(node.row)
367
+ ),
368
+ stroke: childStroke,
369
+ strokeOpacity: node.isActive ? 0.95 : 0.45,
370
+ strokeWidth: node.isActive ? 1.8 : 1.4,
371
+ strokeLinecap: "round",
372
+ strokeLinejoin: "round",
373
+ strokeDasharray: node.isVirtual ? "3 3" : void 0
374
+ },
375
+ `path-${node.id}`
376
+ );
377
+ })
378
+ }
379
+ ),
380
+ /* @__PURE__ */ jsx3("div", { className: "relative z-0 h-full", children: layout.nodes.map((node) => {
381
+ const isPendingNode = pendingNodeId === node.id;
382
+ const color = node.isActive ? "hsl(var(--primary))" : "hsl(var(--muted-foreground))";
383
+ const previewText = node.isVirtual ? isPendingNode ? "\u5207\u6362\u4E2D..." : "" : isPendingNode ? "\u5207\u6362\u4E2D..." : node.preview;
384
+ const shouldShowTooltip = !node.isVirtual || Boolean(previewText);
385
+ const button = /* @__PURE__ */ jsx3(
386
+ "button",
387
+ {
388
+ type: "button",
389
+ onClick: () => void (node.isVirtual ? handleVirtualClick(node) : handleNodeSelect(node)),
390
+ disabled: isBusy,
391
+ "aria-current": !node.isVirtual && node.isCurrent ? "step" : void 0,
392
+ "aria-label": node.isVirtual ? "\u5207\u6362\u5230\u8BE5\u5206\u652F" : node.preview,
393
+ className: cn(
394
+ "absolute z-20 m-0 h-8 w-6 overflow-visible border-0 bg-transparent p-0",
395
+ isBusy ? "cursor-not-allowed opacity-60" : "cursor-pointer"
396
+ ),
397
+ style: {
398
+ top: node.row * ROW_HEIGHT,
399
+ left: getColumnX(node.column) - 12
400
+ },
401
+ children: /* @__PURE__ */ jsx3("span", { "aria-hidden": "true", className: "absolute left-0 top-0 h-8 w-6", children: /* @__PURE__ */ jsx3(
402
+ "svg",
403
+ {
404
+ "aria-hidden": "true",
405
+ role: "img",
406
+ className: "pointer-events-none absolute left-0 top-0 h-full w-full overflow-visible",
407
+ width: 24,
408
+ height: ROW_HEIGHT,
409
+ viewBox: `0 0 24 ${ROW_HEIGHT}`,
410
+ fill: "none",
411
+ children: node.isVirtual ? /* @__PURE__ */ jsx3(
412
+ "circle",
413
+ {
414
+ cx: 12,
415
+ cy: ROW_HEIGHT / 2,
416
+ r: 3.5,
417
+ fill: "none",
418
+ stroke: color,
419
+ strokeWidth: 1.2,
420
+ strokeDasharray: "2 2",
421
+ opacity: 0.7
422
+ }
423
+ ) : /* @__PURE__ */ jsxs2("g", { children: [
424
+ node.isCurrent ? /* @__PURE__ */ jsx3("circle", { cx: 12, cy: ROW_HEIGHT / 2, r: 9, fill: color, opacity: 0.18 }) : null,
425
+ /* @__PURE__ */ jsx3(
426
+ "circle",
427
+ {
428
+ cx: 12,
429
+ cy: ROW_HEIGHT / 2,
430
+ r: node.isCurrent ? 5.5 : 4,
431
+ fill: color
432
+ }
433
+ )
434
+ ] })
435
+ }
436
+ ) })
437
+ }
438
+ );
439
+ if (!shouldShowTooltip) {
440
+ return /* @__PURE__ */ jsx3("div", { children: button }, node.id);
441
+ }
442
+ return /* @__PURE__ */ jsxs2(Root3, { children: [
443
+ /* @__PURE__ */ jsx3(Trigger, { asChild: true, children: button }),
444
+ /* @__PURE__ */ jsx3(Portal, { children: /* @__PURE__ */ jsx3(
445
+ Content2,
446
+ {
447
+ side: "right",
448
+ sideOffset: 8,
449
+ className: cn(
450
+ // z-[60]:这张图会被放进回溯弹层(z-50 且背景不透明),
451
+ // 消息预览不抬到弹层之上就会被它的背景吃掉。
452
+ "z-[60] rounded-md border border-border bg-popover px-2 py-1 text-xs text-foreground shadow-md",
453
+ !node.isVirtual && node.isCurrent && "font-semibold"
454
+ ),
455
+ children: previewText
456
+ }
457
+ ) })
458
+ ] }, node.id);
459
+ }) })
460
+ ] }) })
461
+ ] });
462
+ }
463
+ function buildLayoutNodes(tree) {
464
+ if (!tree || tree.nodes.length === 0) {
465
+ return { nodes: [], hasCycle: false, maxColumn: 0, maxRow: 0 };
466
+ }
467
+ const nodeMap = new Map(tree.nodes.map((node) => [node.id, node]));
468
+ const order = new Map(tree.nodes.map((node, index) => [node.id, index]));
469
+ const childrenMap = /* @__PURE__ */ new Map();
470
+ for (const node of tree.nodes) {
471
+ const parentId = node.parent_id && nodeMap.has(node.parent_id) ? node.parent_id : null;
472
+ const siblings = childrenMap.get(parentId) ?? [];
473
+ siblings.push(node);
474
+ childrenMap.set(parentId, siblings);
475
+ }
476
+ const activeIds = /* @__PURE__ */ new Set();
477
+ const activeVisited = /* @__PURE__ */ new Set();
478
+ const leafId = tree.leaf_id;
479
+ let current = tree.leaf_id;
480
+ while (current && nodeMap.has(current) && !activeVisited.has(current)) {
481
+ activeIds.add(current);
482
+ activeVisited.add(current);
483
+ current = nodeMap.get(current)?.parent_id ?? null;
484
+ }
485
+ const layoutNodes = [];
486
+ const placed = /* @__PURE__ */ new Set();
487
+ const visiting = /* @__PURE__ */ new Set();
488
+ let nextColumn = 1;
489
+ let maxColumn = 0;
490
+ let maxRow = 0;
491
+ let hasCycle = false;
492
+ const rootSort = (a, b) => (order.get(a.id) ?? 0) - (order.get(b.id) ?? 0);
493
+ const childSort = (a, b) => (order.get(a.id) ?? 0) - (order.get(b.id) ?? 0);
494
+ const allocateColumn = () => {
495
+ const fresh = nextColumn;
496
+ nextColumn += 1;
497
+ return fresh;
498
+ };
499
+ function walk(node, parent, column, row) {
500
+ if (visiting.has(node.id)) {
501
+ hasCycle = true;
502
+ return;
503
+ }
504
+ if (placed.has(node.id)) {
505
+ return;
506
+ }
507
+ visiting.add(node.id);
508
+ maxColumn = Math.max(maxColumn, column);
509
+ maxRow = Math.max(maxRow, row);
510
+ const layoutNode = {
511
+ id: node.id,
512
+ column,
513
+ row,
514
+ parentRow: parent?.row ?? null,
515
+ parentColumn: parent?.column ?? null,
516
+ isActive: activeIds.has(node.id),
517
+ isCurrent: node.id === leafId,
518
+ isVirtual: false,
519
+ preview: formatPreview(node.content_preview),
520
+ content: node.content
521
+ };
522
+ layoutNodes.push(layoutNode);
523
+ placed.add(node.id);
524
+ const children = [...childrenMap.get(node.id) ?? []].sort(childSort);
525
+ if (children.length === 0) {
526
+ const virtualRow = row + 1;
527
+ maxRow = Math.max(maxRow, virtualRow);
528
+ layoutNodes.push({
529
+ id: `__virtual__${node.id}`,
530
+ column,
531
+ row: virtualRow,
532
+ parentRow: layoutNode.row,
533
+ parentColumn: layoutNode.column,
534
+ isActive: activeIds.has(node.id),
535
+ isCurrent: false,
536
+ isVirtual: true,
537
+ preview: "",
538
+ content: node.id
539
+ });
540
+ } else {
541
+ for (const [index, child] of children.entries()) {
542
+ if (visiting.has(child.id)) {
543
+ hasCycle = true;
544
+ continue;
545
+ }
546
+ const childColumn = index === 0 ? column : allocateColumn();
547
+ walk(child, layoutNode, childColumn, row + 1);
548
+ }
549
+ }
550
+ visiting.delete(node.id);
551
+ }
552
+ const roots = [...childrenMap.get(null) ?? []].sort(rootSort);
553
+ for (const [index, root] of roots.entries()) {
554
+ const rootColumn = index === 0 ? 0 : allocateColumn();
555
+ walk(root, null, rootColumn, 0);
556
+ }
557
+ for (const node of [...tree.nodes].sort(rootSort)) {
558
+ if (!placed.has(node.id)) {
559
+ hasCycle = true;
560
+ const rootColumn = layoutNodes.length === 0 ? 0 : allocateColumn();
561
+ walk(node, null, rootColumn, 0);
562
+ }
563
+ }
564
+ return {
565
+ nodes: layoutNodes,
566
+ hasCycle,
567
+ maxColumn,
568
+ maxRow
569
+ };
570
+ }
571
+ function formatPreview(preview) {
572
+ const normalized = preview.replace(/\s+/g, " ").trim();
573
+ return normalized.length > 0 ? normalized : "(\u7A7A\u6D88\u606F)";
574
+ }
575
+ function getColumnX(column) {
576
+ return 12 + column * 24;
577
+ }
578
+ function getRowY(row) {
579
+ return row * ROW_HEIGHT + ROW_HEIGHT / 2;
580
+ }
581
+ function buildEdgePath(fromX, fromY, toX, toY) {
582
+ if (fromX === toX || fromY === toY) {
583
+ return `M ${fromX} ${fromY} L ${toX} ${toY}`;
584
+ }
585
+ const r = Math.min(5, Math.abs(toX - fromX), Math.abs(toY - fromY));
586
+ const dx = toX > fromX ? 1 : -1;
587
+ return [
588
+ `M ${fromX} ${fromY}`,
589
+ `H ${toX - dx * r}`,
590
+ `A ${r} ${r} 0 0 ${dx > 0 ? 1 : 0} ${toX} ${fromY + r}`,
591
+ `V ${toY}`
592
+ ].join(" ");
593
+ }
594
+ export {
595
+ AgentChat,
596
+ BackgroundWakeNotice,
597
+ BladeProvider,
598
+ ChatView,
599
+ ConnectorPanel,
600
+ ContextCard,
601
+ ContextGroupCard,
602
+ DEFAULT_ALLOWED_TAGS,
603
+ LlmChat,
604
+ MarkdownContent,
605
+ MarkdownRenderer,
606
+ McpAppCard,
607
+ MessageImage,
608
+ MountHostContext,
609
+ MountSlot,
610
+ PLAN_AUTO_COLLAPSE_MS,
611
+ PlanUpdateBlock,
612
+ PluginConnectorList,
613
+ PluginTriggerStack,
614
+ ReplayBar,
615
+ ReplayMismatchPrompt,
616
+ SessionBranchPicker,
617
+ SessionMemoryToggle,
618
+ SessionPluginConfigDialog,
619
+ SessionPluginConfigForm,
620
+ SessionPluginIcon,
621
+ SessionPluginSelector,
622
+ SessionQueuePanel,
623
+ TRIGGER_ICON_LIMIT,
624
+ TURN_NAV_HIGHLIGHT_CLASS,
625
+ ToolUiCardView,
626
+ WhatIfUserBubble,
627
+ catalogToConnectorItems,
628
+ classifyAgentComputerLaunchOutcome,
629
+ filterConnectorItems,
630
+ getPlanUpdateDisplayState,
631
+ isAgentComputerCommand,
632
+ isAgentComputerToolCall,
633
+ isPlanUpdateTool,
634
+ isQueuePanelVisible,
635
+ latestUserSpeechEntryId,
636
+ mergeConnectorItems,
637
+ mountRenderersToReact,
638
+ parsePlanUpdate,
639
+ parseWhatIfPrompt,
640
+ pickCurrentPlanStep,
641
+ selectionFromItem,
642
+ sessionPluginLabel,
643
+ triggerSummary,
644
+ turnNavItemsFromMessages,
645
+ useAgentSession,
646
+ useBladeClient,
647
+ useBladeHost,
648
+ useLlmChat,
649
+ useMessagePin,
650
+ useOptionalBladeClient,
651
+ useReplay,
652
+ useSessionPluginActivation,
653
+ useTurnNavigation,
654
+ useTypewriterReveal
655
+ };
656
+ //# sourceMappingURL=internal.js.map