@blade-hq/agent-react 2612.0.0-beta.7 → 2612.0.0-beta.71

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 (164) hide show
  1. package/README.md +33 -0
  2. package/dist/chat/AgentLoopBlock.d.ts +0 -2
  3. package/dist/chat/AskUserQuestionBlock.d.ts +3 -20
  4. package/dist/chat/AssistantTurnBlock.d.ts +1 -9
  5. package/dist/chat/AttachmentPreviewDialog.d.ts +0 -1
  6. package/dist/chat/ChatLoadingIndicator.d.ts +7 -0
  7. package/dist/chat/ContextAttachmentPills.d.ts +4 -0
  8. package/dist/chat/CurrentPlanPanel.d.ts +0 -3
  9. package/dist/chat/FileDeliveryCards.d.ts +0 -4
  10. package/dist/chat/FinalArtifactCards.d.ts +0 -1
  11. package/dist/chat/ImageLightbox.d.ts +1 -1
  12. package/dist/chat/LiteMessageList.d.ts +1 -3
  13. package/dist/chat/MessageFileAttachmentList.d.ts +0 -5
  14. package/dist/chat/QuestionnaireQuestionBlock.d.ts +11 -0
  15. package/dist/chat/SessionReplayBar.d.ts +0 -1
  16. package/dist/chat/TextAttachmentPills.d.ts +0 -3
  17. package/dist/chat/TurnNavRail.d.ts +0 -3
  18. package/dist/chat/WorkflowRunBlock.d.ts +21 -4
  19. package/dist/chat/ai-elements/shimmer.d.ts +0 -4
  20. package/dist/chat/customization.d.ts +1 -1
  21. package/dist/chat/index.d.ts +1 -1
  22. package/dist/chat/markdown/ExternalAnchor.d.ts +2 -2
  23. package/dist/chat/markdown/MarkdownContent.d.ts +3 -0
  24. package/dist/chat/message-list-blocks.d.ts +0 -1
  25. package/dist/chat/runtime/actions.d.ts +2 -2
  26. package/dist/chat/runtime/background-task-dismissals.d.ts +0 -1
  27. package/dist/chat/runtime/composer-channels.d.ts +0 -3
  28. package/dist/chat/runtime/input-cache-reset.d.ts +0 -5
  29. package/dist/chat/runtime/input-services.d.ts +10 -0
  30. package/dist/chat/runtime/session-source.d.ts +0 -5
  31. package/dist/chat/runtime/use-chat-actions.d.ts +0 -4
  32. package/dist/{chat-OCLOVB3H.css → chat-IHPRU35X.css} +5 -18
  33. package/dist/chat.css +5 -18
  34. package/dist/{chunk-MERN5XEM.js → chunk-2DPLLZOU.js} +2162 -13284
  35. package/dist/chunk-2DPLLZOU.js.map +1 -0
  36. package/dist/chunk-7MCGQH34.js +605 -0
  37. package/dist/chunk-7MCGQH34.js.map +1 -0
  38. package/dist/{chunk-67GHJQK5.js → chunk-HCW7SI5Q.js} +3897 -26116
  39. package/dist/chunk-HCW7SI5Q.js.map +1 -0
  40. package/dist/chunk-J72ZLILV.js +2317 -0
  41. package/dist/chunk-J72ZLILV.js.map +1 -0
  42. package/dist/chunk-QIR73CES.js +7917 -0
  43. package/dist/chunk-QIR73CES.js.map +1 -0
  44. package/dist/chunk-WRIMPZPN.js +4031 -0
  45. package/dist/chunk-WRIMPZPN.js.map +1 -0
  46. package/dist/chunk-XJ6ZA6LN.js +9480 -0
  47. package/dist/chunk-XJ6ZA6LN.js.map +1 -0
  48. package/dist/chunk-XP6T6SHZ.js +13622 -0
  49. package/dist/chunk-XP6T6SHZ.js.map +1 -0
  50. package/dist/components/AccountConnectors.d.ts +13 -0
  51. package/dist/components/BrowserConnectionDialog.d.ts +7 -0
  52. package/dist/components/ChatInput.d.ts +1 -15
  53. package/dist/components/ConnectorAuthorizationProgress.d.ts +6 -0
  54. package/dist/components/ConnectorConnection.d.ts +4 -0
  55. package/dist/components/ConnectorPanel.d.ts +3 -1
  56. package/dist/components/ConnectorRuntimeDiagnostics.d.ts +5 -0
  57. package/dist/components/DeviceConnection.d.ts +15 -0
  58. package/dist/components/FeishuCapabilitySelection.d.ts +14 -0
  59. package/dist/components/FeishuPermissionStatus.d.ts +5 -0
  60. package/dist/components/LlmAdvancedSettings.d.ts +0 -1
  61. package/dist/components/ManagedConnection.d.ts +9 -0
  62. package/dist/components/McpAppFrame.d.ts +17 -0
  63. package/dist/components/PlanUpdateBlock.d.ts +0 -1
  64. package/dist/components/SessionPluginConfigForm.d.ts +3 -1
  65. package/dist/components/SessionPluginIcon.d.ts +1 -0
  66. package/dist/components/plugin-connector.d.ts +1 -0
  67. package/dist/connectors.d.ts +2 -0
  68. package/dist/connectors.js +11 -0
  69. package/dist/connectors.js.map +1 -0
  70. package/dist/embed/blade-chat-element.d.ts +0 -8
  71. package/dist/embed/entry.d.ts +8 -19
  72. package/dist/hooks/use-message-pin.d.ts +1 -1
  73. package/dist/index.d.ts +2 -0
  74. package/dist/index.js +14 -3
  75. package/dist/internal.d.ts +6 -2
  76. package/dist/internal.js +49 -70
  77. package/dist/internal.js.map +1 -1
  78. package/dist/lib/message-shortcuts.d.ts +5 -0
  79. package/dist/questions.d.ts +7 -0
  80. package/dist/questions.js +908 -0
  81. package/dist/questions.js.map +1 -0
  82. package/dist/rich-input/ConnectButton.d.ts +7 -5
  83. package/dist/rich-input/FileCompletionMenu.d.ts +1 -2
  84. package/dist/rich-input/InputActionSubmenu.d.ts +10 -0
  85. package/dist/rich-input/SkillActionMenu.d.ts +10 -0
  86. package/dist/rich-input/SkillStatusBar.d.ts +0 -6
  87. package/dist/rich-input/extensions/skill-mention.d.ts +3 -20
  88. package/dist/rich-input/index.d.ts +3 -2
  89. package/dist/rich-input/lib/composer-content.d.ts +5 -1
  90. package/dist/rich-input/lib/plugin-suggestions.d.ts +5 -5
  91. package/dist/rich-input/lib/reference-candidates.d.ts +0 -1
  92. package/dist/rich-input/lib/skill-suggestions.d.ts +1 -1
  93. package/dist/rich-input/lib/user-home.d.ts +0 -17
  94. package/dist/rich-input/services.d.ts +1 -1
  95. package/dist/rich-input/voice/VoiceWaveform.d.ts +0 -3
  96. package/dist/rich-input.js +768 -1065
  97. package/dist/rich-input.js.map +1 -1
  98. package/dist/style.css +16 -55
  99. package/dist/style.full.css +23 -77
  100. package/dist/tool-details.d.ts +8 -0
  101. package/dist/tool-details.js +24 -0
  102. package/dist/tool-details.js.map +1 -0
  103. package/node_modules/@modelcontextprotocol/ext-apps/LICENSE +216 -0
  104. package/node_modules/@modelcontextprotocol/ext-apps/README.md +284 -0
  105. package/node_modules/@modelcontextprotocol/ext-apps/dist/docs/patterns.d.ts +9 -0
  106. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/app-bridge.d.ts +1348 -0
  107. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/app-bridge.examples.d.ts +9 -0
  108. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/app-bridge.js +39 -0
  109. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/app-bridge.test.d.ts +1 -0
  110. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/app-with-deps.js +82 -0
  111. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/app.d.ts +1214 -0
  112. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/app.examples.d.ts +9 -0
  113. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/app.js +39 -0
  114. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/app.test.d.ts +1 -0
  115. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/constants.d.ts +65 -0
  116. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/events.d.ts +47 -0
  117. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/events.test.d.ts +1 -0
  118. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/generated/schema.d.ts +1047 -0
  119. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/generated/schema.json +6170 -0
  120. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/generated/schema.test.d.ts +41 -0
  121. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/interop-v1.test.d.ts +1 -0
  122. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/legacy-handlers.d.ts +66 -0
  123. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/legacy-handlers.test.d.ts +1 -0
  124. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/message-transport.d.ts +126 -0
  125. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/message-transport.examples.d.ts +9 -0
  126. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/message-transport.test.d.ts +1 -0
  127. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/react/index.d.ts +37 -0
  128. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/react/index.examples.d.ts +6 -0
  129. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/react/index.js +39 -0
  130. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/react/react-with-deps.js +82 -0
  131. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/react/useApp.d.ts +115 -0
  132. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/react/useApp.examples.d.ts +6 -0
  133. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/react/useAutoResize.d.ts +54 -0
  134. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/react/useAutoResize.examples.d.ts +6 -0
  135. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/react/useDocumentTheme.d.ts +44 -0
  136. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/react/useDocumentTheme.examples.d.ts +6 -0
  137. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/react/useHostStyles.d.ts +113 -0
  138. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/react/useHostStyles.examples.d.ts +6 -0
  139. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/server/index.d.ts +381 -0
  140. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/server/index.examples.d.ts +9 -0
  141. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/server/index.js +1 -0
  142. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/server/index.test.d.ts +1 -0
  143. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/spec.types.d.ts +698 -0
  144. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/standard-schema.d.ts +23 -0
  145. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/styles.d.ts +184 -0
  146. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/styles.examples.d.ts +9 -0
  147. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/types.d.ts +33 -0
  148. package/node_modules/@modelcontextprotocol/ext-apps/dist/src/wire-compat.test.d.ts +1 -0
  149. package/node_modules/@modelcontextprotocol/ext-apps/package.json +144 -0
  150. package/node_modules/@standard-schema/spec/LICENSE +21 -0
  151. package/node_modules/@standard-schema/spec/README.md +198 -0
  152. package/node_modules/@standard-schema/spec/dist/index.cjs +18 -0
  153. package/node_modules/@standard-schema/spec/dist/index.d.cts +119 -0
  154. package/node_modules/@standard-schema/spec/dist/index.d.ts +119 -0
  155. package/node_modules/@standard-schema/spec/dist/index.js +0 -0
  156. package/node_modules/@standard-schema/spec/package.json +52 -0
  157. package/package.json +19 -3
  158. package/public-api.md +16 -4
  159. package/dist/chunk-67GHJQK5.js.map +0 -1
  160. package/dist/chunk-DPDXGYGM.js +0 -258
  161. package/dist/chunk-DPDXGYGM.js.map +0 -1
  162. package/dist/chunk-MERN5XEM.js.map +0 -1
  163. package/dist/lib/agent-computer-command.d.ts +0 -32
  164. package/dist/rich-input/extensions/workflow-mention.d.ts +0 -10
@@ -3,7 +3,60 @@ import {
3
3
  PluginTriggerStack,
4
4
  selectionFromItem,
5
5
  triggerSummary
6
- } from "./chunk-DPDXGYGM.js";
6
+ } from "./chunk-7MCGQH34.js";
7
+ import {
8
+ MODEL_REASONING_LEVELS_KEY,
9
+ PREFERRED_MODEL_KEY,
10
+ RichInputServicesProvider,
11
+ chatTone,
12
+ fetchClientQuery,
13
+ getInputHistoryGeneration,
14
+ getPluginSuggestionItems,
15
+ isQueueShortcut,
16
+ onInputCachesReset,
17
+ pluginRefsForSend,
18
+ queueShortcutLabel,
19
+ refreshClientQuery,
20
+ refreshClientSessionSkills,
21
+ sendToSession,
22
+ setClientQueryData,
23
+ useBackgroundTaskList,
24
+ useClientBackgroundTasks,
25
+ useClientContextStats,
26
+ useClientModelCatalog,
27
+ useClientModelPreferences,
28
+ useClientQuery,
29
+ useClientSessionModel,
30
+ useClientSessionSkills,
31
+ useClientSkillStats,
32
+ useComposerConnection,
33
+ useComposerConnectionInfo,
34
+ useContextStats,
35
+ useEffectEvent,
36
+ useModelCatalog,
37
+ useModelPreferences,
38
+ useRefreshWhenRunEnds,
39
+ useRichInputServices,
40
+ useSessionDataInvalidation,
41
+ useSessionSkills,
42
+ useSkillStats
43
+ } from "./chunk-2DPLLZOU.js";
44
+ import "./chunk-J72ZLILV.js";
45
+ import {
46
+ Dialog,
47
+ DialogClose,
48
+ DialogContent,
49
+ DialogTitle,
50
+ cn,
51
+ notifyChat,
52
+ useBladeClient,
53
+ useChatEnvironment,
54
+ useChatRenderMode,
55
+ useChatSessionDetail,
56
+ useCurrentChatSessionId,
57
+ useSessionHandle,
58
+ useSessionSource
59
+ } from "./chunk-WRIMPZPN.js";
7
60
  import {
8
61
  Archive,
9
62
  BookOpen,
@@ -11,10 +64,6 @@ import {
11
64
  Check,
12
65
  ChevronDown,
13
66
  ChevronRight,
14
- Dialog,
15
- DialogClose,
16
- DialogContent,
17
- DialogTitle,
18
67
  Download,
19
68
  EyeOff,
20
69
  File,
@@ -37,32 +86,17 @@ import {
37
86
  Rocket,
38
87
  RotateCcw,
39
88
  Scissors,
89
+ Search,
40
90
  Send,
41
91
  Share2,
42
92
  Sparkles,
43
93
  Square,
44
94
  Terminal,
45
95
  X,
46
- chatTone,
47
- cn,
48
- cn2,
49
- dist_exports2 as dist_exports,
50
- getInputHistoryGeneration,
51
- getPluginSuggestionItems,
52
- notifyChat,
53
- onInputCachesReset,
54
- pluginRefsForSend,
55
- sendToSession,
56
- useBladeClient,
57
- useChatEnvironment,
58
- useChatRenderMode,
59
- useChatSessionDetail,
60
- useCurrentChatSessionId,
61
- useEffectEvent,
62
- usePortalContainer,
63
- useSessionHandle,
64
- useSessionState
65
- } from "./chunk-MERN5XEM.js";
96
+ cn as cn2,
97
+ dist_exports6 as dist_exports,
98
+ usePortalContainer
99
+ } from "./chunk-QIR73CES.js";
66
100
  import {
67
101
  __commonJS,
68
102
  __require,
@@ -88,7 +122,7 @@ var require_use_sync_external_store_shim_development = __commonJS({
88
122
  "The result of getSnapshot should be cached to avoid an infinite loop"
89
123
  ), didWarnUncachedGetSnapshot = true);
90
124
  }
91
- cachedValue = useState12({
125
+ cachedValue = useState13({
92
126
  inst: { value, getSnapshot }
93
127
  });
94
128
  var inst = cachedValue[0].inst, forceUpdate = cachedValue[1];
@@ -126,7 +160,7 @@ var require_use_sync_external_store_shim_development = __commonJS({
126
160
  return getSnapshot();
127
161
  }
128
162
  "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
129
- var React2 = __require("react"), objectIs = "function" === typeof Object.is ? Object.is : is, useState12 = React2.useState, useEffect10 = React2.useEffect, useLayoutEffect3 = React2.useLayoutEffect, useDebugValue3 = React2.useDebugValue, didWarnOld18Alpha = false, didWarnUncachedGetSnapshot = false, shim = "undefined" === typeof window || "undefined" === typeof window.document || "undefined" === typeof window.document.createElement ? useSyncExternalStore$1 : useSyncExternalStore$2;
163
+ var React2 = __require("react"), objectIs = "function" === typeof Object.is ? Object.is : is, useState13 = React2.useState, useEffect10 = React2.useEffect, useLayoutEffect3 = React2.useLayoutEffect, useDebugValue3 = React2.useDebugValue, didWarnOld18Alpha = false, didWarnUncachedGetSnapshot = false, shim = "undefined" === typeof window || "undefined" === typeof window.document || "undefined" === typeof window.document.createElement ? useSyncExternalStore$1 : useSyncExternalStore$2;
130
164
  exports.useSyncExternalStore = void 0 !== React2.useSyncExternalStore ? React2.useSyncExternalStore : shim;
131
165
  "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
132
166
  })();
@@ -154,14 +188,14 @@ var require_with_selector_development = __commonJS({
154
188
  return x === y && (0 !== x || 1 / x === 1 / y) || x !== x && y !== y;
155
189
  }
156
190
  "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
157
- var React2 = __require("react"), shim = require_shim(), objectIs = "function" === typeof Object.is ? Object.is : is, useSyncExternalStore5 = shim.useSyncExternalStore, useRef10 = React2.useRef, useEffect10 = React2.useEffect, useMemo9 = React2.useMemo, useDebugValue3 = React2.useDebugValue;
191
+ var React2 = __require("react"), shim = require_shim(), objectIs = "function" === typeof Object.is ? Object.is : is, useSyncExternalStore5 = shim.useSyncExternalStore, useRef8 = React2.useRef, useEffect10 = React2.useEffect, useMemo8 = React2.useMemo, useDebugValue3 = React2.useDebugValue;
158
192
  exports.useSyncExternalStoreWithSelector = function(subscribe, getSnapshot, getServerSnapshot, selector, isEqual) {
159
- var instRef = useRef10(null);
193
+ var instRef = useRef8(null);
160
194
  if (null === instRef.current) {
161
195
  var inst = { hasValue: false, value: null };
162
196
  instRef.current = inst;
163
197
  } else inst = instRef.current;
164
- instRef = useMemo9(
198
+ instRef = useMemo8(
165
199
  function() {
166
200
  function memoizedSelector(nextSnapshot) {
167
201
  if (!hasMemo) {
@@ -225,7 +259,7 @@ var require_with_selector = __commonJS({
225
259
  });
226
260
 
227
261
  // src/rich-input/BackgroundTasksPill.tsx
228
- import { useMemo as useMemo2, useState } from "react";
262
+ import { useMemo, useState } from "react";
229
263
 
230
264
  // src/chat/runtime/background-task-dismissals.ts
231
265
  import { useSyncExternalStore } from "react";
@@ -249,7 +283,6 @@ var backgroundTaskDismissals = {
249
283
  state = { ...state, [sessionId]: [...existing, taskId] };
250
284
  emit();
251
285
  },
252
- /** 换身份:清空。 */
253
286
  reset() {
254
287
  state = {};
255
288
  emit();
@@ -263,331 +296,6 @@ function useDismissedBackgroundTasks(sessionId) {
263
296
  );
264
297
  }
265
298
 
266
- // src/rich-input/services.tsx
267
- import { useMemo, useRef as useRef2 } from "react";
268
-
269
- // src/chat/runtime/input-services.tsx
270
- import { createContext, useContext } from "react";
271
- import { jsx } from "react/jsx-runtime";
272
- function parseModelReasoningLevels(value) {
273
- if (!value) return {};
274
- try {
275
- const parsed = JSON.parse(value);
276
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
277
- return Object.fromEntries(
278
- Object.entries(parsed).filter(
279
- (entry) => Boolean(entry[0]) && typeof entry[1] === "string" && Boolean(entry[1])
280
- )
281
- );
282
- } catch {
283
- return {};
284
- }
285
- }
286
- var RichInputServicesContext = createContext({});
287
- function RichInputServicesProvider({ value, children }) {
288
- return /* @__PURE__ */ jsx(RichInputServicesContext.Provider, { value, children });
289
- }
290
- function useRichInputServices() {
291
- return useContext(RichInputServicesContext);
292
- }
293
-
294
- // src/rich-input/lib/session-data.ts
295
- import { useEffect as useEffect2, useRef } from "react";
296
-
297
- // src/rich-input/lib/client-query.ts
298
- import { useCallback, useEffect, useSyncExternalStore as useSyncExternalStore2 } from "react";
299
- var EMPTY = { data: void 0, error: null, isLoading: false, isFetching: false };
300
- var caches = /* @__PURE__ */ new WeakMap();
301
- function entryFor(client, key) {
302
- let cache = caches.get(client);
303
- if (!cache) {
304
- const created = /* @__PURE__ */ new Map();
305
- cache = created;
306
- caches.set(client, created);
307
- onInputCachesReset(client, () => {
308
- for (const [key2, entry2] of created) {
309
- entry2.request = null;
310
- entry2.fetchedAt = 0;
311
- update(entry2, EMPTY);
312
- const load = loadersFor(client).get(key2);
313
- if (load && entry2.listeners.size > 0) void fetchClientQuery(client, key2, load, { force: true }).catch(() => {
314
- });
315
- }
316
- });
317
- }
318
- let entry = cache.get(key);
319
- if (!entry) {
320
- entry = { snapshot: EMPTY, fetchedAt: 0, request: null, listeners: /* @__PURE__ */ new Set() };
321
- cache.set(key, entry);
322
- }
323
- return entry;
324
- }
325
- function update(entry, patch) {
326
- entry.snapshot = { ...entry.snapshot, ...patch };
327
- for (const listener of [...entry.listeners]) listener();
328
- }
329
- function fetchClientQuery(client, key, load, { staleMs = 3e4, force = false } = {}) {
330
- const entry = entryFor(client, key);
331
- if (entry.request) return entry.request;
332
- if (!force && entry.snapshot.data !== void 0 && Date.now() - entry.fetchedAt < staleMs) {
333
- return Promise.resolve(entry.snapshot.data);
334
- }
335
- const request = Promise.resolve().then(() => load(client));
336
- entry.request = request;
337
- update(entry, { isFetching: true, isLoading: entry.snapshot.data === void 0 });
338
- request.then(
339
- (data) => {
340
- if (entry.request !== request) return;
341
- entry.request = null;
342
- entry.fetchedAt = Date.now();
343
- update(entry, { data, error: null, isFetching: false, isLoading: false });
344
- },
345
- (error) => {
346
- if (entry.request !== request) return;
347
- entry.request = null;
348
- update(entry, { error, isFetching: false, isLoading: false });
349
- }
350
- );
351
- return request;
352
- }
353
- function setClientQueryData(client, key, updater) {
354
- const entry = entryFor(client, key);
355
- if (entry.snapshot.data === void 0) return;
356
- update(entry, { data: updater(entry.snapshot.data) });
357
- }
358
- function useClientQuery(key, load, { staleMs = 3e4 } = {}) {
359
- const client = useBladeClient();
360
- const subscribe = useCallback(
361
- (listener) => {
362
- if (!key) return () => {
363
- };
364
- const entry = entryFor(client, key);
365
- entry.listeners.add(listener);
366
- return () => {
367
- entry.listeners.delete(listener);
368
- };
369
- },
370
- [client, key]
371
- );
372
- const snapshot = useSyncExternalStore2(
373
- subscribe,
374
- () => key ? entryFor(client, key).snapshot : EMPTY,
375
- () => key ? entryFor(client, key).snapshot : EMPTY
376
- );
377
- if (key) loadersFor(client).set(key, load);
378
- useEffect(() => {
379
- if (!key) return;
380
- const registered = loadersFor(client).get(key);
381
- if (registered) void fetchClientQuery(client, key, registered, { staleMs }).catch(() => {
382
- });
383
- }, [client, key, staleMs]);
384
- const refetch = useCallback(async () => {
385
- if (!key) return void 0;
386
- const registered = loadersFor(client).get(key);
387
- if (!registered) return void 0;
388
- return fetchClientQuery(client, key, registered, { force: true }).catch(() => void 0);
389
- }, [client, key]);
390
- return { ...snapshot, refetch };
391
- }
392
- var loaderRegistry = /* @__PURE__ */ new WeakMap();
393
- function loadersFor(client) {
394
- let loaders = loaderRegistry.get(client);
395
- if (!loaders) {
396
- loaders = /* @__PURE__ */ new Map();
397
- loaderRegistry.set(client, loaders);
398
- }
399
- return loaders;
400
- }
401
- function refreshClientQuery(client, key) {
402
- const entry = caches.get(client)?.get(key);
403
- if (!entry) return;
404
- entry.fetchedAt = 0;
405
- const load = loadersFor(client).get(key);
406
- if (load && entry.listeners.size > 0) void fetchClientQuery(client, key, load, { force: true }).catch(() => {
407
- });
408
- }
409
-
410
- // src/rich-input/lib/session-data.ts
411
- var sessionPath = (sessionId, rest) => `/api/sessions/${encodeURIComponent(sessionId)}/${rest}`;
412
- function useRefreshWhenRunEnds(sessionId, keys3) {
413
- const client = useBladeClient();
414
- const streaming = useSessionState(sessionId, (state3) => state3.isStreaming);
415
- const wasStreaming = useRef(streaming);
416
- useEffect2(() => {
417
- if (wasStreaming.current && !streaming) {
418
- for (const key of keys3) refreshClientQuery(client, key);
419
- }
420
- wasStreaming.current = streaming;
421
- });
422
- }
423
- function useClientSessionSkills(sessionId) {
424
- const key = sessionId ? `session-skills:${sessionId}` : null;
425
- const query = useClientQuery(
426
- key,
427
- (client) => client.json("GET", sessionPath(sessionId ?? "", "skills"))
428
- );
429
- useRefreshWhenRunEnds(sessionId, key ? [key] : []);
430
- return { data: query.data, loading: query.isLoading, error: query.error };
431
- }
432
- function useClientSkillStats(sessionId) {
433
- const key = sessionId ? `skill-stats:${sessionId}` : null;
434
- const query = useClientQuery(key, (client) => client.json("GET", sessionPath(sessionId ?? "", "skill-stats")), {
435
- staleMs: 3e5
436
- });
437
- useRefreshWhenRunEnds(sessionId, key ? [key] : []);
438
- return { data: query.data, loading: query.isLoading, error: query.error };
439
- }
440
- function useClientContextStats(sessionId) {
441
- const key = sessionId ? `context-stats:${sessionId}` : null;
442
- const query = useClientQuery(
443
- key,
444
- (client) => client.json("GET", sessionPath(sessionId ?? "", "context-stats"))
445
- );
446
- useRefreshWhenRunEnds(sessionId, key ? [key] : []);
447
- return { data: query.data, loading: query.isLoading, error: query.error };
448
- }
449
- function useClientBackgroundTasks(sessionId) {
450
- const client = useBladeClient();
451
- const key = sessionId ? `background-tasks:${sessionId}` : null;
452
- const query = useClientQuery(key, (c) => c.sessions.listBackgroundTasks(sessionId ?? ""));
453
- const session = useSessionHandle(sessionId);
454
- useEffect2(() => {
455
- if (!session || !key) return;
456
- return session.on("backgroundTask", () => refreshClientQuery(client, key));
457
- }, [client, key, session]);
458
- return { data: query.data, loading: query.isLoading, error: query.error };
459
- }
460
- function refreshClientSessionSkills(client, sessionId) {
461
- refreshClientQuery(client, `session-skills:${sessionId}`);
462
- refreshClientQuery(client, `skill-stats:${sessionId}`);
463
- }
464
- function useClientSessionModel(sessionId) {
465
- const key = sessionId ? `session-detail:${sessionId}` : null;
466
- const query = useClientQuery(key, (client) => client.sessions.getSession(sessionId ?? ""));
467
- useRefreshWhenRunEnds(sessionId, key ? [key] : []);
468
- return query.data?.model ?? null;
469
- }
470
-
471
- // src/rich-input/model/model-data.ts
472
- var EMPTY_MODELS = [];
473
- var EMPTY_IDS = [];
474
- var CATALOG_KEY = "model-catalog";
475
- function useClientModelCatalog() {
476
- const { data, isLoading, isFetching, refetch } = useClientQuery(
477
- CATALOG_KEY,
478
- (client) => client.json("GET", "/api/config/models"),
479
- // 模型服务在设置里随时可改:打开选择器时总是重新拉一次(见 ModelSelector)
480
- { staleMs: 0 }
481
- );
482
- return {
483
- models: data?.models ?? EMPTY_MODELS,
484
- defaultModel: data?.default ?? "",
485
- thinkingAvailable: data?.thinkingAvailable ?? false,
486
- unavailableProviderIds: data?.unavailableProviderIds ?? EMPTY_IDS,
487
- unavailableModelIds: data?.unavailableModelIds ?? EMPTY_IDS,
488
- isLoading,
489
- isFetching,
490
- refresh: async () => {
491
- await refetch();
492
- }
493
- };
494
- }
495
- var PREFERRED_MODEL_KEY = "preferred_model";
496
- var MODEL_REASONING_LEVELS_KEY = "llm.model_thinking_preferences";
497
- var PREFERENCES_KEY = "model-preferences";
498
- function loadPreferences(client) {
499
- const query = new URLSearchParams();
500
- query.append("key", PREFERRED_MODEL_KEY);
501
- query.append("key", MODEL_REASONING_LEVELS_KEY);
502
- return client.json("GET", `/api/user/preferences?${query.toString()}`).then((response) => response.values ?? {});
503
- }
504
- async function writePreference(client, key, value) {
505
- const previous = await fetchClientQuery(client, PREFERENCES_KEY, loadPreferences, { staleMs: 6e4 }).catch(
506
- () => ({})
507
- );
508
- setClientQueryData(client, PREFERENCES_KEY, (current) => ({ ...current, [key]: value }));
509
- try {
510
- await client.json("PUT", `/api/user/preferences/${encodeURIComponent(key)}`, { value });
511
- } catch {
512
- setClientQueryData(client, PREFERENCES_KEY, (current) => ({ ...current, [key]: previous[key] ?? null }));
513
- }
514
- }
515
- var EMPTY_LEVELS = {};
516
- function useClientModelPreferences() {
517
- const client = useBladeClient();
518
- const { data } = useClientQuery(PREFERENCES_KEY, loadPreferences, { staleMs: 6e4 });
519
- const rawLevels = data?.[MODEL_REASONING_LEVELS_KEY] ?? null;
520
- const reasoningLevels = rawLevels ? parseModelReasoningLevels(rawLevels) : EMPTY_LEVELS;
521
- return {
522
- preferredModel: data?.[PREFERRED_MODEL_KEY] ?? null,
523
- setPreferredModel: (modelId) => void writePreference(client, PREFERRED_MODEL_KEY, modelId),
524
- reasoningLevels,
525
- setReasoningLevel: (modelId, level) => {
526
- if (!modelId) return;
527
- void writePreference(
528
- client,
529
- MODEL_REASONING_LEVELS_KEY,
530
- JSON.stringify({ ...reasoningLevels, [modelId]: level })
531
- );
532
- }
533
- };
534
- }
535
-
536
- // src/rich-input/services.tsx
537
- function useModelCatalog() {
538
- const use = useRichInputServices().useModelCatalog ?? useClientModelCatalog;
539
- return use();
540
- }
541
- function useModelPreferences() {
542
- const use = useRichInputServices().useModelPreferences ?? useClientModelPreferences;
543
- return use();
544
- }
545
- function useSessionConnection(sessionId) {
546
- const connection = useSessionState(sessionId, (state3) => state3.connection);
547
- const status = sessionId ? connection : "connected";
548
- const everConnected = useRef2(false);
549
- if (status === "connected") everConnected.current = true;
550
- return { status, reconnectAttempt: 0, hasEverConnected: everConnected.current };
551
- }
552
- function useComposerConnectionInfo(sessionId) {
553
- const use = useRichInputServices().useConnection ?? useSessionConnection;
554
- return use(sessionId);
555
- }
556
- function useComposerConnection(sessionId) {
557
- return useComposerConnectionInfo(sessionId).status;
558
- }
559
- function useSessionSkills(sessionId) {
560
- const use = useRichInputServices().useSessionSkills ?? useClientSessionSkills;
561
- return use(sessionId);
562
- }
563
- function useSkillStats(sessionId) {
564
- const use = useRichInputServices().useSkillStats ?? useClientSkillStats;
565
- return use(sessionId);
566
- }
567
- function useContextStats(sessionId) {
568
- const use = useRichInputServices().useContextStats ?? useClientContextStats;
569
- return use(sessionId);
570
- }
571
- function useBackgroundTaskList(sessionId) {
572
- const use = useRichInputServices().useBackgroundTasks ?? useClientBackgroundTasks;
573
- return use(sessionId);
574
- }
575
- function useClientSessionDataInvalidation() {
576
- const client = useBladeClient();
577
- return useMemo(
578
- () => ({
579
- filesUploaded: (_sessionId) => {
580
- },
581
- pluginsChanged: (sessionId) => refreshClientSessionSkills(client, sessionId)
582
- }),
583
- [client]
584
- );
585
- }
586
- function useSessionDataInvalidation() {
587
- const use = useRichInputServices().useSessionDataInvalidation ?? useClientSessionDataInvalidation;
588
- return use();
589
- }
590
-
591
299
  // src/rich-input/lib/background-tasks-view.ts
592
300
  var LIVE_STATUSES = /* @__PURE__ */ new Set(["starting", "running", "cancelling"]);
593
301
  var ATTENTION_STATUSES = /* @__PURE__ */ new Set(["failed", "lost"]);
@@ -599,7 +307,6 @@ var STATUS_LABELS = {
599
307
  succeeded: "\u5DF2\u5B8C\u6210",
600
308
  cancelled: "\u5DF2\u505C\u6B62",
601
309
  failed: "\u5931\u8D25",
602
- // 不是失败:平台只是不再能追踪这个进程,它可能还在跑。
603
310
  lost: "\u72B6\u6001\u672A\u77E5"
604
311
  };
605
312
  function statusLabel(status) {
@@ -648,7 +355,7 @@ function formatStartedAt(value, now = /* @__PURE__ */ new Date()) {
648
355
  }
649
356
 
650
357
  // src/rich-input/BackgroundTasksPill.tsx
651
- import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
358
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
652
359
  var NO_TASKS = [];
653
360
  function TaskCard({
654
361
  task,
@@ -658,8 +365,8 @@ function TaskCard({
658
365
  }) {
659
366
  return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-[hsl(var(--border))] p-2", children: [
660
367
  /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2", children: [
661
- /* @__PURE__ */ jsx2("div", { className: "min-w-0 break-words text-[hsl(var(--foreground))]", children: task.description || task.command }),
662
- /* @__PURE__ */ jsx2(
368
+ /* @__PURE__ */ jsx("div", { className: "min-w-0 break-words text-[hsl(var(--foreground))]", children: task.description || task.command }),
369
+ /* @__PURE__ */ jsx(
663
370
  "span",
664
371
  {
665
372
  className: cn(
@@ -670,10 +377,10 @@ function TaskCard({
670
377
  }
671
378
  )
672
379
  ] }),
673
- task.status === "lost" ? /* @__PURE__ */ jsx2("div", { className: "mt-1 text-[11px] text-[hsl(var(--swf-warning))]", children: "\u5E73\u53F0\u91CD\u542F\u540E\u8DDF\u4E22\u4E86\uFF0C\u7A0B\u5E8F\u53EF\u80FD\u4ECD\u5728\u8FD0\u884C" }) : null,
380
+ task.status === "lost" ? /* @__PURE__ */ jsx("div", { className: "mt-1 text-[11px] text-[hsl(var(--swf-warning))]", children: "\u5E73\u53F0\u91CD\u542F\u540E\u8DDF\u4E22\u4E86\uFF0C\u7A0B\u5E8F\u53EF\u80FD\u4ECD\u5728\u8FD0\u884C" }) : null,
674
381
  /* @__PURE__ */ jsxs("div", { className: "mt-1 flex items-center gap-1.5 text-[10px] text-[hsl(var(--muted-foreground))]/60", children: [
675
- /* @__PURE__ */ jsx2("span", { children: formatStartedAt(task.started_at) }),
676
- /* @__PURE__ */ jsx2("span", { className: "truncate font-mono", children: task.id })
382
+ /* @__PURE__ */ jsx("span", { children: formatStartedAt(task.started_at) }),
383
+ /* @__PURE__ */ jsx("span", { className: "truncate font-mono", children: task.id })
677
384
  ] }),
678
385
  /* @__PURE__ */ jsxs("div", { className: "mt-2 flex items-center gap-1.5", children: [
679
386
  /* @__PURE__ */ jsxs(
@@ -683,7 +390,7 @@ function TaskCard({
683
390
  onClick: onOpenLog,
684
391
  className: "inline-flex h-6 items-center gap-1 rounded-md border border-[hsl(var(--border))] px-2 text-[11px] hover:bg-[hsl(var(--accent))]",
685
392
  children: [
686
- /* @__PURE__ */ jsx2(FileText, { size: 12 }),
393
+ /* @__PURE__ */ jsx(FileText, { size: 12 }),
687
394
  "\u65E5\u5FD7"
688
395
  ]
689
396
  }
@@ -695,7 +402,7 @@ function TaskCard({
695
402
  onClick: onStop,
696
403
  className: "inline-flex h-6 items-center gap-1 rounded-[6px] border border-[hsl(var(--swf-danger)/0.35)] px-2 text-[11px] text-[hsl(var(--swf-danger))] hover:bg-[hsl(var(--swf-danger-soft))]",
697
404
  children: [
698
- /* @__PURE__ */ jsx2(Square, { size: 10 }),
405
+ /* @__PURE__ */ jsx(Square, { size: 10 }),
699
406
  "\u505C\u6B62"
700
407
  ]
701
408
  }
@@ -707,7 +414,7 @@ function TaskCard({
707
414
  onClick: onDismiss,
708
415
  className: "inline-flex h-6 items-center gap-1 rounded-md border border-[hsl(var(--border))] px-2 text-[11px] hover:bg-[hsl(var(--accent))]",
709
416
  children: [
710
- /* @__PURE__ */ jsx2(EyeOff, { size: 12 }),
417
+ /* @__PURE__ */ jsx(EyeOff, { size: 12 }),
711
418
  "\u9690\u85CF"
712
419
  ]
713
420
  }
@@ -724,7 +431,7 @@ function BackgroundTasksPill({ sessionId }) {
724
431
  const [historyOverride, setHistoryOverride] = useState(null);
725
432
  const [logTask, setLogTask] = useState(null);
726
433
  const [logDialogOpen, setLogDialogOpen] = useState(false);
727
- const { activeTasks, historyTasks, runningCount, attentionCount } = useMemo2(
434
+ const { activeTasks, historyTasks, runningCount, attentionCount } = useMemo(
728
435
  () => splitTasks(tasks, dismissed),
729
436
  [tasks, dismissed]
730
437
  );
@@ -758,7 +465,6 @@ function BackgroundTasksPill({ sessionId }) {
758
465
  title,
759
466
  output: "",
760
467
  loading: false,
761
- // 跟丢或过期的任务,控制目录可能已经被回收,报错串对用户没有意义。
762
468
  error: "\u65E5\u5FD7\u5DF2\u65E0\u6CD5\u8BFB\u53D6\uFF0C\u53EF\u80FD\u5DF2\u88AB\u6E05\u7406"
763
469
  });
764
470
  }
@@ -771,7 +477,7 @@ function BackgroundTasksPill({ sessionId }) {
771
477
  closePanel();
772
478
  };
773
479
  return /* @__PURE__ */ jsxs(Fragment, { children: [
774
- /* @__PURE__ */ jsx2(
480
+ /* @__PURE__ */ jsx(
775
481
  Dialog,
776
482
  {
777
483
  open: logDialogOpen,
@@ -786,10 +492,10 @@ function BackgroundTasksPill({ sessionId }) {
786
492
  children: [
787
493
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 border-b border-[hsl(var(--border))] px-4 py-3", children: [
788
494
  /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
789
- /* @__PURE__ */ jsx2(DialogTitle, { className: "truncate text-sm font-medium text-[hsl(var(--foreground))]", children: logTask?.title }),
790
- /* @__PURE__ */ jsx2("div", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: "\u540E\u53F0\u4EFB\u52A1\u65E5\u5FD7" })
495
+ /* @__PURE__ */ jsx(DialogTitle, { className: "truncate text-sm font-medium text-[hsl(var(--foreground))]", children: logTask?.title }),
496
+ /* @__PURE__ */ jsx("div", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: "\u540E\u53F0\u4EFB\u52A1\u65E5\u5FD7" })
791
497
  ] }),
792
- /* @__PURE__ */ jsx2(
498
+ /* @__PURE__ */ jsx(
793
499
  "button",
794
500
  {
795
501
  type: "button",
@@ -799,7 +505,7 @@ function BackgroundTasksPill({ sessionId }) {
799
505
  }
800
506
  )
801
507
  ] }),
802
- /* @__PURE__ */ jsx2("pre", { className: "min-h-64 flex-1 overflow-auto whitespace-pre-wrap p-4 font-mono text-xs leading-5 text-[hsl(var(--foreground))]", children: logTask?.loading ? "\u52A0\u8F7D\u4E2D..." : logTask?.error || logTask?.output })
508
+ /* @__PURE__ */ jsx("pre", { className: "min-h-64 flex-1 overflow-auto whitespace-pre-wrap p-4 font-mono text-xs leading-5 text-[hsl(var(--foreground))]", children: logTask?.loading ? "\u52A0\u8F7D\u4E2D..." : logTask?.error || logTask?.output })
803
509
  ]
804
510
  }
805
511
  )
@@ -821,8 +527,8 @@ function BackgroundTasksPill({ sessionId }) {
821
527
  title: summary,
822
528
  className: "relative flex h-9 w-9 shrink-0 items-center justify-center rounded-full text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
823
529
  children: [
824
- /* @__PURE__ */ jsx2(Terminal, { size: 16 }),
825
- runningCount > 0 ? /* @__PURE__ */ jsx2("span", { className: "absolute right-1 top-1 flex h-3.5 min-w-3.5 items-center justify-center rounded-full bg-[hsl(var(--muted))] px-1 text-[9px] font-medium leading-none text-[hsl(var(--muted-foreground))]", children: runningCount }) : attentionCount > 0 ? /* @__PURE__ */ jsx2(
530
+ /* @__PURE__ */ jsx(Terminal, { size: 16 }),
531
+ runningCount > 0 ? /* @__PURE__ */ jsx("span", { className: "absolute right-1 top-1 flex h-3.5 min-w-3.5 items-center justify-center rounded-full bg-[hsl(var(--muted))] px-1 text-[9px] font-medium leading-none text-[hsl(var(--muted-foreground))]", children: runningCount }) : attentionCount > 0 ? /* @__PURE__ */ jsx(
826
532
  "span",
827
533
  {
828
534
  "data-attention-dot": "true",
@@ -832,64 +538,59 @@ function BackgroundTasksPill({ sessionId }) {
832
538
  ]
833
539
  }
834
540
  ),
835
- open ? (
836
- // before 那层透明桥接盖住浮层和按钮之间 mb-2 的空隙:没有它,鼠标从按钮
837
- // 移向浮层会先穿过一段"两者都不在"的空白,onMouseLeave 立刻收起浮层,
838
- // 里面的日志/停止按钮根本点不到。
839
- /* @__PURE__ */ jsx2("div", { className: "absolute bottom-full left-0 z-40 mb-2 w-[min(24rem,calc(100vw-2rem))] rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-2 text-xs text-[hsl(var(--popover-foreground))] shadow-[var(--swf-shadow-overlay)] before:absolute before:inset-x-0 before:top-full before:h-2 before:content-['']", children: /* @__PURE__ */ jsxs("div", { className: "max-h-72 space-y-2 overflow-y-auto", children: [
840
- activeTasks.map((task) => /* @__PURE__ */ jsx2(
841
- TaskCard,
842
- {
843
- task,
844
- onOpenLog: () => void openTaskLog(task),
845
- onStop: () => requestStopTask(task),
846
- onDismiss: ATTENTION_STATUSES.has(task.status) ? () => hideTask(task.id) : null
847
- },
848
- task.id
849
- )),
850
- historyTasks.length > 0 ? /* @__PURE__ */ jsxs(
851
- "div",
852
- {
853
- className: cn(
854
- activeTasks.length > 0 && "border-t border-[hsl(var(--border))] pt-2"
541
+ open ? /* @__PURE__ */ jsx("div", { className: "absolute bottom-full left-0 z-40 mb-2 w-[min(24rem,calc(100vw-2rem))] rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-2 text-xs text-[hsl(var(--popover-foreground))] shadow-[var(--swf-shadow-overlay)] before:absolute before:inset-x-0 before:top-full before:h-2 before:content-['']", children: /* @__PURE__ */ jsxs("div", { className: "max-h-72 space-y-2 overflow-y-auto", children: [
542
+ activeTasks.map((task) => /* @__PURE__ */ jsx(
543
+ TaskCard,
544
+ {
545
+ task,
546
+ onOpenLog: () => void openTaskLog(task),
547
+ onStop: () => requestStopTask(task),
548
+ onDismiss: ATTENTION_STATUSES.has(task.status) ? () => hideTask(task.id) : null
549
+ },
550
+ task.id
551
+ )),
552
+ historyTasks.length > 0 ? /* @__PURE__ */ jsxs(
553
+ "div",
554
+ {
555
+ className: cn(
556
+ activeTasks.length > 0 && "border-t border-[hsl(var(--border))] pt-2"
557
+ ),
558
+ children: [
559
+ /* @__PURE__ */ jsxs(
560
+ "button",
561
+ {
562
+ type: "button",
563
+ onClick: () => setHistoryOverride(!historyOpen),
564
+ "aria-expanded": historyOpen,
565
+ className: "flex w-full items-center gap-1 px-1 py-1 text-[11px] text-[hsl(var(--muted-foreground))] transition-colors hover:text-[hsl(var(--foreground))]",
566
+ children: [
567
+ /* @__PURE__ */ jsx(
568
+ ChevronDown,
569
+ {
570
+ size: 12,
571
+ className: cn("transition-transform", historyOpen ? "" : "-rotate-90")
572
+ }
573
+ ),
574
+ "\u5386\u53F2\u540E\u53F0\u4EFB\u52A1\uFF08",
575
+ historyTasks.length,
576
+ "\uFF09"
577
+ ]
578
+ }
855
579
  ),
856
- children: [
857
- /* @__PURE__ */ jsxs(
858
- "button",
859
- {
860
- type: "button",
861
- onClick: () => setHistoryOverride(!historyOpen),
862
- "aria-expanded": historyOpen,
863
- className: "flex w-full items-center gap-1 px-1 py-1 text-[11px] text-[hsl(var(--muted-foreground))] transition-colors hover:text-[hsl(var(--foreground))]",
864
- children: [
865
- /* @__PURE__ */ jsx2(
866
- ChevronDown,
867
- {
868
- size: 12,
869
- className: cn("transition-transform", historyOpen ? "" : "-rotate-90")
870
- }
871
- ),
872
- "\u5386\u53F2\u540E\u53F0\u4EFB\u52A1\uFF08",
873
- historyTasks.length,
874
- "\uFF09"
875
- ]
876
- }
877
- ),
878
- historyOpen ? /* @__PURE__ */ jsx2("div", { className: "mt-2 space-y-2", children: historyTasks.map((task) => /* @__PURE__ */ jsx2(
879
- TaskCard,
880
- {
881
- task,
882
- onOpenLog: () => void openTaskLog(task),
883
- onStop: () => requestStopTask(task),
884
- onDismiss: null
885
- },
886
- task.id
887
- )) }) : null
888
- ]
889
- }
890
- ) : null
891
- ] }) })
892
- ) : null
580
+ historyOpen ? /* @__PURE__ */ jsx("div", { className: "mt-2 space-y-2", children: historyTasks.map((task) => /* @__PURE__ */ jsx(
581
+ TaskCard,
582
+ {
583
+ task,
584
+ onOpenLog: () => void openTaskLog(task),
585
+ onStop: () => requestStopTask(task),
586
+ onDismiss: null
587
+ },
588
+ task.id
589
+ )) }) : null
590
+ ]
591
+ }
592
+ ) : null
593
+ ] }) }) : null
893
594
  ]
894
595
  }
895
596
  )
@@ -12254,7 +11955,7 @@ function resolveSelection(view, doc3, parsedSel) {
12254
11955
  }
12255
11956
  function isMarkChange(cur, prev) {
12256
11957
  let curMarks = cur.firstChild.marks, prevMarks = prev.firstChild.marks;
12257
- let added = curMarks, removed = prevMarks, type, mark, update2;
11958
+ let added = curMarks, removed = prevMarks, type, mark, update;
12258
11959
  for (let i = 0; i < prevMarks.length; i++)
12259
11960
  added = prevMarks[i].removeFromSet(added);
12260
11961
  for (let i = 0; i < curMarks.length; i++)
@@ -12262,17 +11963,17 @@ function isMarkChange(cur, prev) {
12262
11963
  if (added.length == 1 && removed.length == 0) {
12263
11964
  mark = added[0];
12264
11965
  type = "add";
12265
- update2 = (node) => node.mark(mark.addToSet(node.marks));
11966
+ update = (node) => node.mark(mark.addToSet(node.marks));
12266
11967
  } else if (added.length == 0 && removed.length == 1) {
12267
11968
  mark = removed[0];
12268
11969
  type = "remove";
12269
- update2 = (node) => node.mark(mark.removeFromSet(node.marks));
11970
+ update = (node) => node.mark(mark.removeFromSet(node.marks));
12270
11971
  } else {
12271
11972
  return null;
12272
11973
  }
12273
11974
  let updated = [];
12274
11975
  for (let i = 0; i < prev.childCount; i++)
12275
- updated.push(update2(prev.child(i)));
11976
+ updated.push(update(prev.child(i)));
12276
11977
  if (Fragment2.from(updated).eq(cur))
12277
11978
  return { mark, type };
12278
11979
  }
@@ -18948,7 +18649,7 @@ var PluginMention = index_default.extend({
18948
18649
  });
18949
18650
 
18950
18651
  // src/rich-input/lib/composer-content.ts
18951
- import { normalizePluginRefs, normalizeTopicAssetRefs } from "@blade-hq/agent-client";
18652
+ import { normalizePluginRefs, normalizeMessageRefs, normalizeTopicAssetRefs } from "@blade-hq/agent-client";
18952
18653
  function serializeEditorContent(node) {
18953
18654
  if (!node) return "";
18954
18655
  if (node.type === "text") {
@@ -18963,11 +18664,7 @@ function serializeEditorContent(node) {
18963
18664
  }
18964
18665
  if (node.type === "skillMention") {
18965
18666
  const skillId = typeof node.attrs?.skillId === "string" ? node.attrs.skillId : "";
18966
- return skillId ? `<skill>${skillId}</skill>` : "";
18967
- }
18968
- if (node.type === "workflowMention") {
18969
- const name = typeof node.attrs?.name === "string" ? node.attrs.name : "";
18970
- return name ? `\u8FD0\u884C\u5DE5\u4F5C\u6D41 ${name}` : "";
18667
+ return skillId ? `@${node.attrs?.displayName || skillId}` : "";
18971
18668
  }
18972
18669
  if (node.type === "pluginMention") return `@${node.attrs?.label ?? ""}`;
18973
18670
  if (node.type === "topicAssetMention") {
@@ -18987,7 +18684,7 @@ function scanLeadingSkillMention(node, seenContent) {
18987
18684
  if (node.type === "text") {
18988
18685
  return { skill: null, seenContent: seenContent || /\S/.test(node.text ?? "") };
18989
18686
  }
18990
- if (node.type === "hardBreak" || node.type === "fileMention" || node.type === "workflowMention") {
18687
+ if (node.type === "hardBreak" || node.type === "fileMention") {
18991
18688
  return { skill: null, seenContent: true };
18992
18689
  }
18993
18690
  if (node.type === "pluginMention") return { skill: null, seenContent };
@@ -19069,6 +18766,27 @@ function collectPluginMentions(node) {
19069
18766
  function buildEditorDocument(text) {
19070
18767
  return { type: "doc", content: text.split("\n").map((line) => ({ type: "paragraph", content: line ? [{ type: "text", text: line }] : [] })) };
19071
18768
  }
18769
+ function collectMessageMentions(node) {
18770
+ const refs = [];
18771
+ const visit = (current) => {
18772
+ if (!current) return;
18773
+ if (current.type === "pluginMention") refs.push(current.attrs);
18774
+ if (current.type === "skillMention") refs.push({
18775
+ provider: "skill",
18776
+ id: current.attrs?.skillId,
18777
+ label: current.attrs?.displayName || current.attrs?.skillId
18778
+ });
18779
+ current.content?.forEach(visit);
18780
+ };
18781
+ visit(node);
18782
+ return normalizeMessageRefs(refs);
18783
+ }
18784
+ function buildPluginSelectionDocument(refs) {
18785
+ return { type: "doc", content: [{ type: "paragraph", content: normalizePluginRefs(refs).flatMap((ref) => [
18786
+ { type: "pluginMention", attrs: { ...ref } },
18787
+ { type: "text", text: " " }
18788
+ ]) }] };
18789
+ }
19072
18790
 
19073
18791
  // src/rich-input/extensions/topic-asset-mention.ts
19074
18792
  function isTopicAssetSuggestionItem(value) {
@@ -19092,7 +18810,7 @@ var TopicAssetMention = index_default.extend({
19092
18810
  class: "file-mention-pill topic-asset-mention-pill",
19093
18811
  "data-topic-id": node.attrs.topic_id,
19094
18812
  "data-path": node.attrs.path,
19095
- title: `\u4E3B\u9898\u8D44\u4EA7\uFF1A${node.attrs.path}`
18813
+ title: `\u5DE5\u4F5C\u7A7A\u95F4\u8D44\u4EA7\uFF1A${node.attrs.path}`
19096
18814
  }, `@${node.attrs.path}`]
19097
18815
  };
19098
18816
  },
@@ -19109,7 +18827,7 @@ var TopicAssetMention = index_default.extend({
19109
18827
 
19110
18828
  // src/chat/runtime/composer-channels.ts
19111
18829
  import { normalizeTopicAssetRefs as normalizeTopicAssetRefs2 } from "@blade-hq/agent-client";
19112
- import { useSyncExternalStore as useSyncExternalStore3 } from "react";
18830
+ import { useSyncExternalStore as useSyncExternalStore2 } from "react";
19113
18831
  function buildSignalId() {
19114
18832
  if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
19115
18833
  return crypto.randomUUID();
@@ -19131,8 +18849,8 @@ var state2 = {
19131
18849
  rewindDrafts: {}
19132
18850
  };
19133
18851
  var listeners2 = /* @__PURE__ */ new Set();
19134
- function setState(update2) {
19135
- const next = update2(state2);
18852
+ function setState(update) {
18853
+ const next = update(state2);
19136
18854
  if (next === state2) return;
19137
18855
  state2 = next;
19138
18856
  for (const listener of [...listeners2]) listener();
@@ -19217,13 +18935,11 @@ var composerChannels = {
19217
18935
  clearModelDraft(sessionId) {
19218
18936
  setState((current) => ({ ...current, modelDrafts: withoutKey(current.modelDrafts, sessionId) }));
19219
18937
  },
19220
- /** 回退到某一步后,把那一步的用户原话放回输入框(null 清除)。 */
19221
18938
  setRewindDraft(sessionId, text) {
19222
18939
  setState(
19223
18940
  (current) => text === null ? { ...current, rewindDrafts: withoutKey(current.rewindDrafts, sessionId) } : { ...current, rewindDrafts: { ...current.rewindDrafts, [sessionId]: text } }
19224
18941
  );
19225
18942
  },
19226
- /** 会话被关闭 / 删除:清掉它还没被取走的信号。 */
19227
18943
  clearSession(sessionId) {
19228
18944
  setState((current) => ({
19229
18945
  ...current,
@@ -19233,13 +18949,12 @@ var composerChannels = {
19233
18949
  sendRequests: withoutKey(current.sendRequests, sessionId)
19234
18950
  }));
19235
18951
  },
19236
- /** 换身份:清空全部通道。 */
19237
18952
  reset() {
19238
18953
  setState(() => ({ topicAssetReferences: {}, pendingContexts: {}, draftAppends: {}, sendRequests: {}, modelDrafts: {}, rewindDrafts: {} }));
19239
18954
  }
19240
18955
  };
19241
18956
  function useComposerChannels(selector) {
19242
- return useSyncExternalStore3(
18957
+ return useSyncExternalStore2(
19243
18958
  composerChannels.subscribe,
19244
18959
  () => selector(state2),
19245
18960
  () => selector(state2)
@@ -19253,7 +18968,7 @@ async function getTopicAssetSuggestionItems(client, topicId, query) {
19253
18968
  const result = await client.chatGroups.listAssets(topicId);
19254
18969
  return result.items.filter((asset) => !asset.is_dir && asset.path.toLowerCase().includes(query.toLowerCase())).map((asset) => ({ kind: "topicAsset", topic_id: topicId, path: asset.path, name: asset.path }));
19255
18970
  } catch {
19256
- return [{ kind: "topicAssetError", message: "\u4E3B\u9898\u8D44\u4EA7\u6682\u65F6\u65E0\u6CD5\u52A0\u8F7D\uFF0C\u8BF7\u91CD\u65B0\u8F93\u5165 @ \u91CD\u8BD5" }];
18971
+ return [{ kind: "topicAssetError", message: "\u5DE5\u4F5C\u7A7A\u95F4\u8D44\u4EA7\u6682\u65F6\u65E0\u6CD5\u52A0\u8F7D\uFF0C\u8BF7\u91CD\u65B0\u8F93\u5165 @ \u91CD\u8BD5" }];
19257
18972
  }
19258
18973
  }
19259
18974
  function queueTopicAssetReference(sessionId, ref) {
@@ -19261,22 +18976,9 @@ function queueTopicAssetReference(sessionId, ref) {
19261
18976
  }
19262
18977
 
19263
18978
  // src/rich-input/use-dismiss-skill-suggestions-on-mode-change.ts
19264
- import { useEffect as useEffect3, useRef as useRef3 } from "react";
18979
+ import { useEffect, useRef } from "react";
19265
18980
 
19266
18981
  // src/rich-input/extensions/skill-mention.ts
19267
- function workflowParamsTail(item) {
19268
- const params = (item.inputs ?? []).filter((p) => p.name);
19269
- if (params.length === 0) return " ";
19270
- const filled = params.map((p) => {
19271
- const hasDefault = p.default !== void 0 && p.default !== null;
19272
- const value = hasDefault ? typeof p.default === "string" ? p.default : JSON.stringify(p.default) : `<${p.description || "\u586B\u503C"}>`;
19273
- return `${p.name}=${value}`;
19274
- }).join(" ");
19275
- return ` ${filled} `;
19276
- }
19277
- function workflowRunText(item) {
19278
- return `\u8FD0\u884C\u5DE5\u4F5C\u6D41 ${item.name}${workflowParamsTail(item)}`.trimEnd();
19279
- }
19280
18982
  var skillMentionSuggestionKey = new PluginKey("skillMentionSuggestion");
19281
18983
  function getSkillMentionName(attrs) {
19282
18984
  return attrs.displayName || attrs.skillId || "";
@@ -19358,8 +19060,8 @@ var SkillMention = index_default.extend({
19358
19060
  // src/rich-input/use-dismiss-skill-suggestions-on-mode-change.ts
19359
19061
  function useDismissSkillSuggestionsOnModeChange(editor) {
19360
19062
  const renderMode = useChatRenderMode();
19361
- const previousRef = useRef3(renderMode);
19362
- useEffect3(() => {
19063
+ const previousRef = useRef(renderMode);
19064
+ useEffect(() => {
19363
19065
  if (previousRef.current === renderMode) return;
19364
19066
  previousRef.current = renderMode;
19365
19067
  if (editor && !editor.isDestroyed && skillMentionSuggestionKey.getState(editor.state)?.active) {
@@ -19370,12 +19072,12 @@ function useDismissSkillSuggestionsOnModeChange(editor) {
19370
19072
 
19371
19073
  // ../../node_modules/.pnpm/@tiptap+react@3.20.4_@floating-ui+dom@1.7.6_@tiptap+core@3.20.4_@tiptap+pm@3.20.4__@tip_1ce9f35538141630e675758ebf46eb2f/node_modules/@tiptap/react/dist/index.js
19372
19074
  var import_shim = __toESM(require_shim(), 1);
19373
- import { createContext as createContext2, useContext as useContext2, useMemo as useMemo3 } from "react";
19075
+ import { createContext, useContext, useMemo as useMemo2 } from "react";
19374
19076
  import React, { forwardRef } from "react";
19375
19077
  import ReactDOM from "react-dom";
19376
- import { Fragment as Fragment3, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
19078
+ import { Fragment as Fragment3, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
19377
19079
  var import_shim2 = __toESM(require_shim(), 1);
19378
- import { useDebugValue as useDebugValue2, useEffect as useEffect22, useRef as useRef4, useState as useState2 } from "react";
19080
+ import { useDebugValue as useDebugValue2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
19379
19081
 
19380
19082
  // ../../node_modules/.pnpm/fast-equals@5.4.0/node_modules/fast-equals/dist/es/index.mjs
19381
19083
  var { getOwnPropertyNames, getOwnPropertySymbols } = Object;
@@ -19817,10 +19519,10 @@ function createCustomEqual(options = {}) {
19817
19519
 
19818
19520
  // ../../node_modules/.pnpm/@tiptap+react@3.20.4_@floating-ui+dom@1.7.6_@tiptap+core@3.20.4_@tiptap+pm@3.20.4__@tip_1ce9f35538141630e675758ebf46eb2f/node_modules/@tiptap/react/dist/index.js
19819
19521
  var import_with_selector = __toESM(require_with_selector(), 1);
19820
- import { useDebugValue, useEffect as useEffect4, useLayoutEffect, useState as useState3 } from "react";
19522
+ import { useDebugValue, useEffect as useEffect3, useLayoutEffect, useState as useState3 } from "react";
19821
19523
  import { jsx as jsx22, jsxs as jsxs22 } from "react/jsx-runtime";
19822
- import { createContext as createContext22, createElement, useContext as useContext22 } from "react";
19823
- import { jsx as jsx32 } from "react/jsx-runtime";
19524
+ import { createContext as createContext2, createElement, useContext as useContext2 } from "react";
19525
+ import { jsx as jsx3 } from "react/jsx-runtime";
19824
19526
  import React3 from "react";
19825
19527
  import { jsx as jsx4 } from "react/jsx-runtime";
19826
19528
  import React4 from "react";
@@ -19850,7 +19552,7 @@ var Portals = ({ contentComponent }) => {
19850
19552
  contentComponent.getSnapshot,
19851
19553
  contentComponent.getServerSnapshot
19852
19554
  );
19853
- return /* @__PURE__ */ jsx3(Fragment3, { children: Object.values(renderers) });
19555
+ return /* @__PURE__ */ jsx2(Fragment3, { children: Object.values(renderers) });
19854
19556
  };
19855
19557
  function getInstance() {
19856
19558
  const subscribers = /* @__PURE__ */ new Set();
@@ -19971,8 +19673,8 @@ var PureEditorContent = class extends React.Component {
19971
19673
  render() {
19972
19674
  const { editor, innerRef, ...rest } = this.props;
19973
19675
  return /* @__PURE__ */ jsxs2(Fragment3, { children: [
19974
- /* @__PURE__ */ jsx3("div", { ref: mergeRefs(innerRef, this.editorContentRef), ...rest }),
19975
- (editor == null ? void 0 : editor.contentComponent) && /* @__PURE__ */ jsx3(Portals, { contentComponent: editor.contentComponent })
19676
+ /* @__PURE__ */ jsx2("div", { ref: mergeRefs(innerRef, this.editorContentRef), ...rest }),
19677
+ (editor == null ? void 0 : editor.contentComponent) && /* @__PURE__ */ jsx2(Portals, { contentComponent: editor.contentComponent })
19976
19678
  ] });
19977
19679
  }
19978
19680
  };
@@ -19989,7 +19691,7 @@ var EditorContentWithKey = forwardRef(
19989
19691
  }
19990
19692
  );
19991
19693
  var EditorContent = React.memo(EditorContentWithKey);
19992
- var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect4;
19694
+ var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect3;
19993
19695
  var EditorStateManager = class {
19994
19696
  constructor(initialEditor) {
19995
19697
  this.transactionNumber = 0;
@@ -20297,7 +19999,7 @@ var EditorInstanceManager = class _EditorInstanceManager {
20297
19999
  }
20298
20000
  };
20299
20001
  function useEditor(options = {}, deps = []) {
20300
- const mostRecentOptions = useRef4(options);
20002
+ const mostRecentOptions = useRef2(options);
20301
20003
  mostRecentOptions.current = options;
20302
20004
  const [instanceManager] = useState2(() => new EditorInstanceManager(mostRecentOptions));
20303
20005
  const editor = (0, import_shim2.useSyncExternalStore)(
@@ -20306,7 +20008,7 @@ function useEditor(options = {}, deps = []) {
20306
20008
  instanceManager.getServerSnapshot
20307
20009
  );
20308
20010
  useDebugValue2(editor);
20309
- useEffect22(instanceManager.onRender(deps));
20011
+ useEffect2(instanceManager.onRender(deps));
20310
20012
  useEditorState({
20311
20013
  editor,
20312
20014
  selector: ({ transactionNumber }) => {
@@ -20321,18 +20023,18 @@ function useEditor(options = {}, deps = []) {
20321
20023
  });
20322
20024
  return editor;
20323
20025
  }
20324
- var EditorContext = createContext2({
20026
+ var EditorContext = createContext({
20325
20027
  editor: null
20326
20028
  });
20327
20029
  var EditorConsumer = EditorContext.Consumer;
20328
- var ReactNodeViewContext = createContext22({
20030
+ var ReactNodeViewContext = createContext2({
20329
20031
  onDragStart: () => {
20330
20032
  },
20331
20033
  nodeViewContentChildren: void 0,
20332
20034
  nodeViewContentRef: () => {
20333
20035
  }
20334
20036
  });
20335
- var useReactNodeView = () => useContext22(ReactNodeViewContext);
20037
+ var useReactNodeView = () => useContext2(ReactNodeViewContext);
20336
20038
  var NodeViewWrapper = React3.forwardRef((props, ref) => {
20337
20039
  const { onDragStart } = useReactNodeView();
20338
20040
  const Tag = props.as || "div";
@@ -25395,8 +25097,8 @@ var index_default2 = StarterKit;
25395
25097
 
25396
25098
  // src/rich-input/ChatInput.tsx
25397
25099
  import {
25398
- useEffect as useEffect9,
25399
- useRef as useRef9,
25100
+ useEffect as useEffect8,
25101
+ useRef as useRef7,
25400
25102
  useState as useState11
25401
25103
  } from "react";
25402
25104
  import { createRoot } from "react-dom/client";
@@ -25411,7 +25113,7 @@ function skillDisplayName(skill) {
25411
25113
  }
25412
25114
 
25413
25115
  // src/rich-input/voice/use-tiptap-voice-input.ts
25414
- import { useCallback as useCallback2, useEffect as useEffect5, useRef as useRef5 } from "react";
25116
+ import { useCallback, useEffect as useEffect4, useRef as useRef3 } from "react";
25415
25117
  var IDLE_VOICE = {
25416
25118
  status: "idle",
25417
25119
  error: null,
@@ -25427,8 +25129,8 @@ function useNoVoiceInput() {
25427
25129
  function useTiptapVoiceInput(options) {
25428
25130
  const { editorRef, workletUrl, onError } = options;
25429
25131
  const useVoiceInput2 = options.useVoiceInput ?? useNoVoiceInput;
25430
- const partialRangeRef = useRef5(null);
25431
- const lastPartialLenRef = useRef5(0);
25132
+ const partialRangeRef = useRef3(null);
25133
+ const lastPartialLenRef = useRef3(0);
25432
25134
  const handlePartial = useEffectEvent((text) => {
25433
25135
  const ed = editorRef.current;
25434
25136
  if (!ed) return;
@@ -25478,18 +25180,18 @@ function useTiptapVoiceInput(options) {
25478
25180
  onError: handleError
25479
25181
  });
25480
25182
  const isRecording = voice.status === "recording";
25481
- useEffect5(() => {
25183
+ useEffect4(() => {
25482
25184
  const ed = editorRef.current;
25483
25185
  if (!ed) return;
25484
25186
  ed.setEditable(!isRecording);
25485
25187
  }, [isRecording, editorRef]);
25486
- useEffect5(() => {
25188
+ useEffect4(() => {
25487
25189
  if (voice.status === "idle" || voice.status === "error") {
25488
25190
  partialRangeRef.current = null;
25489
25191
  lastPartialLenRef.current = 0;
25490
25192
  }
25491
25193
  }, [voice.status]);
25492
- const toggle = useCallback2(() => {
25194
+ const toggle = useCallback(() => {
25493
25195
  if (voice.status === "recording" || voice.status === "starting") {
25494
25196
  void voice.stop();
25495
25197
  } else {
@@ -25546,7 +25248,7 @@ function VoiceWaveform({ level, color = "currentColor", size = 16 }) {
25546
25248
  }
25547
25249
 
25548
25250
  // src/rich-input/model/resolve-model.ts
25549
- import { useMemo as useMemo4 } from "react";
25251
+ import { useMemo as useMemo3 } from "react";
25550
25252
  var MODEL_LOADING_SEND_HINT = "\u6B63\u5728\u52A0\u8F7D\u6A21\u578B\u914D\u7F6E\uFF0C\u8BF7\u7A0D\u540E\u518D\u53D1\u9001";
25551
25253
  function gateSendWhileModelLoading(isModelLoading, hasContent) {
25552
25254
  if (!isModelLoading) return { blocked: false };
@@ -25615,7 +25317,7 @@ function resolveModelChoice({
25615
25317
  function useResolvedModel(activeSessionModel) {
25616
25318
  const { models, defaultModel, thinkingAvailable, isLoading, unavailableProviderIds, unavailableModelIds } = useModelCatalog();
25617
25319
  const { preferredModel } = useModelPreferences();
25618
- const resolved = useMemo4(() => {
25320
+ const resolved = useMemo3(() => {
25619
25321
  return resolveModelChoice({
25620
25322
  activeSessionModel,
25621
25323
  preferredModel,
@@ -25635,9 +25337,6 @@ function useResolvedModel(activeSessionModel) {
25635
25337
  reasoningLevels: selectedModel?.reasoningLevels ?? [],
25636
25338
  defaultReasoningLevel: selectedModel?.defaultReasoningLevel ?? "",
25637
25339
  modelAvailabilityMessage,
25638
- // Undefined means the catalog is still loading or the model does not
25639
- // publish this optional capability. In either case keep existing upload
25640
- // behavior until the server has explicitly said images are unsupported.
25641
25340
  supportsImage: selectedModel?.supportsImage ?? selectedModel?.inputModalities?.includes("image")
25642
25341
  };
25643
25342
  }
@@ -25652,17 +25351,21 @@ function useReasoningLevelPreference(modelId) {
25652
25351
  }
25653
25352
 
25654
25353
  // src/rich-input/model/use-composer-model.ts
25655
- import { useEffect as useEffect6, useRef as useRef6, useState as useState4 } from "react";
25354
+ import { useEffect as useEffect5, useRef as useRef4, useState as useState4 } from "react";
25656
25355
  function useInjectedSessionModel(sessionId) {
25657
25356
  return useChatSessionDetail(sessionId)?.model ?? null;
25658
25357
  }
25659
25358
  function useComposerModel(activeSessionId) {
25660
25359
  const [newSessionModelSelection, setNewSessionModelSelection] = useState4(null);
25661
- const newSessionModelSelectionRef = useRef6(null);
25360
+ const newSessionModelSelectionRef = useRef4(null);
25662
25361
  const { setPreferredModel } = useModelPreferences();
25663
25362
  const { models: modelCatalog } = useModelCatalog();
25664
25363
  const useSessionModel = useChatEnvironment().useSessionDetail ? useInjectedSessionModel : useClientSessionModel;
25665
25364
  const activeSessionModel = useSessionModel(activeSessionId);
25365
+ const session = useSessionHandle(activeSessionId);
25366
+ const source = useSessionSource();
25367
+ const [selectingSession, setSelectingSession] = useState4(null);
25368
+ const selectingRef = useRef4(null);
25666
25369
  const sharedModelDraft = useComposerChannels(
25667
25370
  (state3) => activeSessionId ? state3.modelDrafts[activeSessionId] : void 0
25668
25371
  );
@@ -25677,18 +25380,18 @@ function useComposerModel(activeSessionId) {
25677
25380
  isLoading
25678
25381
  } = useResolvedModel(resolveComposerModel(activeSessionId, activeSessionModel, explicitModelSelection));
25679
25382
  const { reasoningLevelPreference, setReasoningLevelPreference } = useReasoningLevelPreference(selectedModel);
25680
- useEffect6(() => {
25383
+ useEffect5(() => {
25681
25384
  if (!activeSessionId || !newSessionModelSelectionRef.current) return;
25682
25385
  newSessionModelSelectionRef.current = null;
25683
25386
  setNewSessionModelSelection(null);
25684
25387
  }, [activeSessionId]);
25685
- useEffect6(() => {
25388
+ useEffect5(() => {
25686
25389
  if (!activeSessionId || !sharedModelDraft || isLoading || modelCatalog.length === 0) return;
25687
25390
  if (!modelCatalog.some((model) => model.id === sharedModelDraft)) {
25688
25391
  composerChannels.clearModelDraft(activeSessionId);
25689
25392
  }
25690
25393
  }, [activeSessionId, sharedModelDraft, isLoading, modelCatalog]);
25691
- useEffect6(() => {
25394
+ useEffect5(() => {
25692
25395
  if (!activeSessionId || sharedModelDraft !== activeSessionModel) return;
25693
25396
  composerChannels.clearModelDraft(activeSessionId);
25694
25397
  }, [activeSessionId, activeSessionModel, sharedModelDraft]);
@@ -25696,7 +25399,7 @@ function useComposerModel(activeSessionId) {
25696
25399
  return {
25697
25400
  selectedModel,
25698
25401
  hasAvailableModel,
25699
- isLoading,
25402
+ isLoading: isLoading || !!activeSessionId && (selectingSession === activeSessionId || !session),
25700
25403
  availabilityMessage: modelAvailabilityMessage,
25701
25404
  thinkingAvailable,
25702
25405
  reasoningLevels,
@@ -25704,7 +25407,22 @@ function useComposerModel(activeSessionId) {
25704
25407
  setReasoningLevel: setReasoningLevelPreference,
25705
25408
  selectModel(model) {
25706
25409
  if (activeSessionId) {
25410
+ if (selectingRef.current === activeSessionId) return;
25411
+ selectingRef.current = activeSessionId;
25412
+ setSelectingSession(activeSessionId);
25707
25413
  composerChannels.setModelDraft(activeSessionId, model);
25414
+ const select = (ready) => ready.selectModel(model);
25415
+ const pending = source.whenReady ? source.whenReady(activeSessionId, select) : session ? select(session) : Promise.resolve(false);
25416
+ void pending.catch(() => false).then((ok) => {
25417
+ if (!ok && composerChannels.getState().modelDrafts[activeSessionId] === model) {
25418
+ composerChannels.clearModelDraft(activeSessionId);
25419
+ }
25420
+ }).finally(() => {
25421
+ if (selectingRef.current === activeSessionId) {
25422
+ selectingRef.current = null;
25423
+ setSelectingSession(null);
25424
+ }
25425
+ });
25708
25426
  } else {
25709
25427
  const selection = { sessionId: activeSessionId, model };
25710
25428
  newSessionModelSelectionRef.current = selection;
@@ -25768,7 +25486,7 @@ function PopoverContent({
25768
25486
  }
25769
25487
 
25770
25488
  // src/rich-input/ModelSelector.tsx
25771
- import { useMemo as useMemo5, useState as useState5 } from "react";
25489
+ import { useMemo as useMemo4, useState as useState5 } from "react";
25772
25490
  import { jsx as jsx12, jsxs as jsxs3 } from "react/jsx-runtime";
25773
25491
  var inputModalityLabels = {
25774
25492
  text: "\u6587\u672C",
@@ -25810,7 +25528,7 @@ function ModelSelector({
25810
25528
  }
25811
25529
  void refresh();
25812
25530
  }
25813
- const filteredModels = useMemo5(() => {
25531
+ const filteredModels = useMemo4(() => {
25814
25532
  const normalized = query.trim().toLowerCase();
25815
25533
  if (!normalized) return models;
25816
25534
  return models.filter(
@@ -25837,10 +25555,7 @@ function ModelSelector({
25837
25555
  className: `flex min-w-0 items-center gap-1 rounded-lg py-[5px] text-muted-foreground ${compact ? "ml-auto px-1.5" : "px-2.5"}`,
25838
25556
  title: selectorTitle,
25839
25557
  children: [
25840
- isLoading ? /* @__PURE__ */ jsx12(LoaderCircle, { size: 14, className: "animate-spin", "aria-hidden": "true" }) : compact ? null : (
25841
- // compact 用于「+」菜单的「模型」行,行首已有图标,触发器内不再重复。
25842
- /* @__PURE__ */ jsx12(Sparkles, { size: 14, "aria-hidden": "true" })
25843
- ),
25558
+ isLoading ? /* @__PURE__ */ jsx12(LoaderCircle, { size: 14, className: "animate-spin", "aria-hidden": "true" }) : compact ? null : /* @__PURE__ */ jsx12(Sparkles, { size: 14, "aria-hidden": "true" }),
25844
25559
  /* @__PURE__ */ jsx12(
25845
25560
  "span",
25846
25561
  {
@@ -25946,7 +25661,7 @@ function ModelSelector({
25946
25661
  }
25947
25662
 
25948
25663
  // src/rich-input/SkillStatusBar.tsx
25949
- import { useMemo as useMemo6 } from "react";
25664
+ import { useMemo as useMemo5 } from "react";
25950
25665
 
25951
25666
  // src/chat/lib/skill-visibility.ts
25952
25667
  function visibleSkills(skills, mode) {
@@ -26124,7 +25839,7 @@ function SkillStatusBar({
26124
25839
  const { status: connectionStatus, reconnectAttempt, hasEverConnected } = useComposerConnectionInfo(sessionId);
26125
25840
  const statsReady = !loading && !error;
26126
25841
  const skillStoreConnected = statsReady && skillStats.remote_connected;
26127
- const connectionMeta = useMemo6(
25842
+ const connectionMeta = useMemo5(
26128
25843
  () => getConnectionMeta(
26129
25844
  connectionStatus,
26130
25845
  reconnectAttempt,
@@ -26144,7 +25859,8 @@ function SkillStatusBar({
26144
25859
  text: skillStoreConnected ? `\u5DF2\u5B89\u88C5 ${skillStats.installed_skill_count} \u4E2A\u6280\u80FD` : "\u5C1A\u672A\u767B\u5F55\u6280\u80FD\u5546\u5E97"
26145
25860
  }
26146
25861
  ].filter((item) => item.key !== "total" || skillStats.remote_configured);
26147
- const tokenSummary = useMemo6(() => {
25862
+ const tokenSummary = useMemo5(() => {
25863
+ if (mode !== "developer") return null;
26148
25864
  if (contextStatsLoading || contextStatsError || !contextStats) {
26149
25865
  return {
26150
25866
  detail: /* @__PURE__ */ jsx14("div", { className: "pt-1 text-[hsl(var(--muted-foreground))]", children: "\u4E0A\u4E0B\u6587\u7EDF\u8BA1\u4E0D\u53EF\u7528" }),
@@ -26170,7 +25886,7 @@ function SkillStatusBar({
26170
25886
  label: contextStats.context_window > 0 ? `${formatTokensK(contextStats.tokens_used)} / ${formatTokensK(contextStats.context_window)} \u4F1A\u8BDD\u6D88\u606F\u4F30\u7B97` : `${formatTokensK(contextStats.tokens_used)} \u4F1A\u8BDD\u6D88\u606F\u4F30\u7B97`,
26171
25887
  warn: tokenPressure.level === "critical"
26172
25888
  };
26173
- }, [contextStats, contextStatsError, contextStatsLoading, tokenPressure.level]);
25889
+ }, [mode, contextStats, contextStatsError, contextStatsLoading, tokenPressure.level]);
26174
25890
  const containerClass = vertical ? "text-[11px] text-[hsl(var(--muted-foreground))]" : "bg-[hsl(var(--background))] px-5 pt-2";
26175
25891
  const innerClass = vertical ? "" : "mx-auto max-w-3xl";
26176
25892
  const listClass = vertical ? "flex flex-col items-stretch gap-1.5 text-[11px] text-[hsl(var(--muted-foreground))]" : "flex flex-wrap items-center gap-2 text-[10px] text-[hsl(var(--muted-foreground))]";
@@ -26213,20 +25929,16 @@ function SkillStatusBar({
26213
25929
  /* @__PURE__ */ jsx14("span", { className: "mt-1.5 inline-block h-2 w-2 shrink-0 rounded-full border border-[hsl(var(--swf-success))] bg-transparent" }),
26214
25930
  /* @__PURE__ */ jsx14("span", { className: "break-words", children: skillDisplayName(skill) })
26215
25931
  ] }, skill.skill_id)) }) : null }) : null
26216
- ] }) : (
26217
- // 「已安装」是可点的导航:用户看到数字会想去看是哪些技能。
26218
- // 改的是「已加载」那一行就会变成另一个功能,所以只动这一条。
26219
- onOpenSkills ? /* @__PURE__ */ jsx14(
26220
- "button",
26221
- {
26222
- type: "button",
26223
- onClick: onOpenSkills,
26224
- title: "\u67E5\u770B\u5DF2\u5B89\u88C5\u7684\u6280\u80FD",
26225
- className: "cursor-pointer font-mono underline decoration-dotted underline-offset-2 transition-colors hover:text-[hsl(var(--foreground))]",
26226
- children: item.text
26227
- }
26228
- ) : /* @__PURE__ */ jsx14("span", { className: "font-mono", children: item.text })
26229
- )
25932
+ ] }) : onOpenSkills ? /* @__PURE__ */ jsx14(
25933
+ "button",
25934
+ {
25935
+ type: "button",
25936
+ onClick: onOpenSkills,
25937
+ title: "\u67E5\u770B\u5DF2\u5B89\u88C5\u7684\u6280\u80FD",
25938
+ className: "cursor-pointer font-mono underline decoration-dotted underline-offset-2 transition-colors hover:text-[hsl(var(--foreground))]",
25939
+ children: item.text
25940
+ }
25941
+ ) : /* @__PURE__ */ jsx14("span", { className: "font-mono", children: item.text })
26230
25942
  ]
26231
25943
  },
26232
25944
  item.key
@@ -26234,11 +25946,72 @@ function SkillStatusBar({
26234
25946
  ] }) }) });
26235
25947
  }
26236
25948
 
25949
+ // src/rich-input/InputActionSubmenu.tsx
25950
+ import { useSyncExternalStore as useSyncExternalStore4 } from "react";
25951
+ import { jsx as jsx15, jsxs as jsxs6 } from "react/jsx-runtime";
25952
+ var narrowQuery = "(max-width: 639px)";
25953
+ function subscribeToViewport(onChange) {
25954
+ const media = window.matchMedia(narrowQuery);
25955
+ media.addEventListener("change", onChange);
25956
+ return () => media.removeEventListener("change", onChange);
25957
+ }
25958
+ var isNarrowViewport = () => window.matchMedia(narrowQuery).matches;
25959
+ function InputActionSubmenu({ label, icon, open, onOpenChange, children, disabled = false }) {
25960
+ const narrow = useSyncExternalStore4(subscribeToViewport, isNarrowViewport, () => false);
25961
+ return /* @__PURE__ */ jsxs6(dist_exports.Root, { open, onOpenChange, children: [
25962
+ /* @__PURE__ */ jsx15(dist_exports.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs6(
25963
+ "button",
25964
+ {
25965
+ type: "button",
25966
+ disabled,
25967
+ onClick: (event) => {
25968
+ event.preventDefault();
25969
+ onOpenChange(true);
25970
+ },
25971
+ onPointerEnter: (event) => {
25972
+ if (event.pointerType === "mouse" && !disabled) onOpenChange(true);
25973
+ },
25974
+ onKeyDown: (event) => {
25975
+ if (event.key === "ArrowRight") {
25976
+ event.preventDefault();
25977
+ onOpenChange(true);
25978
+ }
25979
+ },
25980
+ className: "flex w-full items-center gap-2 rounded-lg px-3 py-2.5 text-left text-sm text-[hsl(var(--popover-foreground))] outline-none hover:bg-[hsl(var(--accent))] focus-visible:bg-[hsl(var(--accent))] disabled:opacity-50 data-[state=open]:bg-[hsl(var(--accent))]",
25981
+ children: [
25982
+ icon,
25983
+ /* @__PURE__ */ jsx15("span", { children: label }),
25984
+ /* @__PURE__ */ jsx15(ChevronRight, { size: 14, className: "ml-auto", "aria-hidden": "true" })
25985
+ ]
25986
+ }
25987
+ ) }),
25988
+ /* @__PURE__ */ jsx15(dist_exports.Portal, { children: /* @__PURE__ */ jsx15(
25989
+ dist_exports.Content,
25990
+ {
25991
+ side: narrow ? "bottom" : "right",
25992
+ align: "start",
25993
+ sideOffset: 8,
25994
+ collisionPadding: 12,
25995
+ "aria-label": label,
25996
+ onEscapeKeyDown: (event) => event.stopPropagation(),
25997
+ onKeyDown: (event) => {
25998
+ if (event.key === "ArrowLeft" && !(event.target instanceof HTMLInputElement || event.target instanceof HTMLSelectElement)) {
25999
+ event.preventDefault();
26000
+ onOpenChange(false);
26001
+ }
26002
+ },
26003
+ className: "z-50 max-h-[min(70vh,var(--radix-popover-content-available-height))] w-[min(320px,calc(100vw-2rem))] overflow-y-auto rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-1 text-xs text-[hsl(var(--popover-foreground))] shadow-[var(--swf-shadow-overlay)] outline-none",
26004
+ children
26005
+ }
26006
+ ) })
26007
+ ] });
26008
+ }
26009
+
26237
26010
  // src/rich-input/ConnectButton.tsx
26238
26011
  import { useState as useState6 } from "react";
26239
26012
 
26240
26013
  // src/rich-input/lib/skill-suggestions.ts
26241
- var sessionPath2 = (sessionId, rest) => `/api/sessions/${encodeURIComponent(sessionId)}/${rest}`;
26014
+ var sessionPath = (sessionId, rest) => `/api/sessions/${encodeURIComponent(sessionId)}/${rest}`;
26242
26015
  function toItem(skill) {
26243
26016
  return {
26244
26017
  type: "skill",
@@ -26246,9 +26019,8 @@ function toItem(skill) {
26246
26019
  displayName: skill.display_name,
26247
26020
  description: skill.description,
26248
26021
  local: skill.local,
26249
- // 本地技能天然可用。搜索结果带后端算好的安装状态,列表接口没有这个字段
26250
- // 时按 local 推断。
26251
- installed: "installed" in skill ? skill.installed : skill.local
26022
+ installed: "installed" in skill ? skill.installed : skill.local,
26023
+ hasFlow: skill.has_flow === true
26252
26024
  };
26253
26025
  }
26254
26026
  var CACHE_TTL_MS = 15e3;
@@ -26256,19 +26028,12 @@ var cachesByClient = /* @__PURE__ */ new WeakMap();
26256
26028
  function cachesFor(client) {
26257
26029
  const existing = cachesByClient.get(client);
26258
26030
  if (existing) return existing;
26259
- const caches2 = {
26260
- requests: /* @__PURE__ */ new Map(),
26261
- workflows: /* @__PURE__ */ new Map(),
26262
- workflowsRefreshedAt: /* @__PURE__ */ new Map(),
26263
- workflowsAbort: null,
26264
- searchSeq: 0
26265
- };
26266
- cachesByClient.set(client, caches2);
26031
+ const caches = { requests: /* @__PURE__ */ new Map(), searchSeq: 0 };
26032
+ cachesByClient.set(client, caches);
26267
26033
  onInputCachesReset(client, () => {
26268
- caches2.workflowsAbort?.abort();
26269
- if (cachesByClient.get(client) === caches2) cachesByClient.delete(client);
26034
+ if (cachesByClient.get(client) === caches) cachesByClient.delete(client);
26270
26035
  });
26271
- return caches2;
26036
+ return caches;
26272
26037
  }
26273
26038
  function cached(client, key, load) {
26274
26039
  const { requests } = cachesFor(client);
@@ -26282,9 +26047,7 @@ function cached(client, key, load) {
26282
26047
  return request;
26283
26048
  }
26284
26049
  function invalidateSlashSuggestions(client, sessionId) {
26285
- const caches2 = cachesFor(client);
26286
- caches2.requests.delete(`session-skills:${sessionId ?? ""}`);
26287
- caches2.workflows.delete(sessionId ?? "__home__");
26050
+ cachesFor(client).requests.delete(`session-skills:${sessionId ?? ""}`);
26288
26051
  }
26289
26052
  async function loadSessionSkills({ client, sessionId, renderMode }) {
26290
26053
  if (!sessionId) return [];
@@ -26292,79 +26055,50 @@ async function loadSessionSkills({ client, sessionId, renderMode }) {
26292
26055
  const skills = await cached(
26293
26056
  client,
26294
26057
  `session-skills:${sessionId}`,
26295
- () => client.json("GET", sessionPath2(sessionId, "skills"))
26058
+ () => client.json("GET", sessionPath(sessionId, "skills"))
26296
26059
  );
26297
26060
  return visibleSkills(skills, renderMode);
26298
26061
  } catch {
26299
26062
  return [];
26300
26063
  }
26301
26064
  }
26065
+ var HUB_WAIT_MS = 600;
26302
26066
  var DEFAULT_SUGGESTION_LIMIT = 50;
26303
26067
  async function getDefaultSuggestions(options) {
26304
26068
  if (options.sessionId) {
26305
26069
  return (await loadSessionSkills(options)).map(toItem);
26306
26070
  }
26071
+ const { client, renderMode } = options;
26072
+ const installedRequest = cached(
26073
+ client,
26074
+ "installed-skills",
26075
+ () => client.json("GET", "/api/skills/installed").catch(() => [])
26076
+ );
26307
26077
  try {
26308
- const skills = await cached(options.client, "skills", () => options.client.json("GET", "/api/skills"));
26309
- return visibleSkills(skills, options.renderMode).slice(0, DEFAULT_SUGGESTION_LIMIT).map(toItem);
26078
+ const local = await cached(client, "skills", () => client.json("GET", "/api/skills"));
26079
+ const installed = await Promise.race([
26080
+ installedRequest,
26081
+ new Promise((resolve) => setTimeout(() => resolve([]), HUB_WAIT_MS))
26082
+ ]);
26083
+ const seen = new Set(local.map((skill) => skill.skill_id));
26084
+ const hub = (Array.isArray(installed) ? installed : []).filter((skill) => skill.id && !seen.has(skill.id)).map((skill) => ({
26085
+ skill_id: skill.id,
26086
+ display_name: skill.display_name ?? "",
26087
+ description: skill.description ?? "",
26088
+ local: false,
26089
+ installed: true,
26090
+ has_flow: skill.has_flow
26091
+ }));
26092
+ return [
26093
+ ...visibleSkills(local, renderMode).slice(0, DEFAULT_SUGGESTION_LIMIT),
26094
+ ...visibleSkills(hub, renderMode).slice(0, DEFAULT_SUGGESTION_LIMIT)
26095
+ ].map(toItem);
26310
26096
  } catch {
26311
26097
  return [];
26312
26098
  }
26313
26099
  }
26314
- async function loadWorkflows(client, sessionId) {
26315
- const caches2 = cachesFor(client);
26316
- caches2.workflowsAbort?.abort();
26317
- const ac = new AbortController();
26318
- caches2.workflowsAbort = ac;
26319
- let timedOut = false;
26320
- const timer = setTimeout(() => {
26321
- timedOut = true;
26322
- ac.abort();
26323
- }, 1500);
26324
- try {
26325
- const res = await client.jsonFromInit(
26326
- sessionId ? sessionPath2(sessionId, "workflows") : "/api/workflows",
26327
- { signal: ac.signal }
26328
- );
26329
- const items = res.workflows.map((w) => ({
26330
- type: "workflow",
26331
- name: w.name,
26332
- displayName: w.display_name || w.name,
26333
- description: w.description || "",
26334
- inputs: w.inputs ?? []
26335
- }));
26336
- caches2.workflows.set(sessionId ?? "__home__", items);
26337
- caches2.workflowsRefreshedAt.set(sessionId ?? "__home__", Date.now());
26338
- return items;
26339
- } catch (err) {
26340
- if (timedOut || err?.name !== "AbortError") {
26341
- caches2.workflows.set(sessionId ?? "__home__", []);
26342
- }
26343
- return caches2.workflows.get(sessionId ?? "__home__") ?? [];
26344
- } finally {
26345
- clearTimeout(timer);
26346
- if (caches2.workflowsAbort === ac) caches2.workflowsAbort = null;
26347
- }
26348
- }
26349
26100
  async function getSlashSuggestions(query, options) {
26350
- const q = query.trim().toLowerCase();
26351
- const cacheKey = options.sessionId ?? "__home__";
26352
- const caches2 = cachesFor(options.client);
26353
- const cachedWorkflows = caches2.workflows.get(cacheKey);
26354
- let workflowsP;
26355
- if (cachedWorkflows) {
26356
- if (Date.now() - (caches2.workflowsRefreshedAt.get(cacheKey) ?? 0) >= CACHE_TTL_MS) {
26357
- void loadWorkflows(options.client, options.sessionId);
26358
- }
26359
- workflowsP = Promise.resolve(cachedWorkflows);
26360
- } else {
26361
- workflowsP = loadWorkflows(options.client, options.sessionId);
26362
- }
26363
- const [workflows, skills] = await Promise.all([workflowsP, getSkillSuggestions(query, options)]);
26364
- const matched = workflows.filter(
26365
- (w) => !q || w.name.toLowerCase().includes(q) || w.displayName.toLowerCase().includes(q) || w.description.toLowerCase().includes(q)
26366
- );
26367
- return [...matched, ...skills];
26101
+ return getSkillSuggestions(query, options);
26368
26102
  }
26369
26103
  var SEARCH_DEBOUNCE_MS = 150;
26370
26104
  async function getSkillSuggestions(query, options) {
@@ -26372,14 +26106,14 @@ async function getSkillSuggestions(query, options) {
26372
26106
  if (!trimmed) {
26373
26107
  return getDefaultSuggestions(options);
26374
26108
  }
26375
- const caches2 = cachesFor(options.client);
26376
- const seq = ++caches2.searchSeq;
26109
+ const caches = cachesFor(options.client);
26110
+ const seq = ++caches.searchSeq;
26377
26111
  const q = trimmed.toLowerCase();
26378
26112
  const sessionMatches = (await loadSessionSkills(options)).filter(
26379
26113
  (skill) => skill.skill_id.toLowerCase().includes(q) || skill.description.toLowerCase().includes(q)
26380
26114
  ).map(toItem);
26381
26115
  await new Promise((resolve) => setTimeout(resolve, SEARCH_DEBOUNCE_MS));
26382
- if (seq !== caches2.searchSeq) return sessionMatches;
26116
+ if (seq !== caches.searchSeq) return sessionMatches;
26383
26117
  try {
26384
26118
  const seen = new Set(sessionMatches.map((item) => item.skillId));
26385
26119
  const { client, renderMode } = options;
@@ -26396,7 +26130,7 @@ async function getSkillSuggestions(query, options) {
26396
26130
  }
26397
26131
 
26398
26132
  // src/rich-input/ConnectButton.tsx
26399
- import { jsx as jsx15, jsxs as jsxs6 } from "react/jsx-runtime";
26133
+ import { jsx as jsx16, jsxs as jsxs7 } from "react/jsx-runtime";
26400
26134
  function ConnectButton({
26401
26135
  sessionId,
26402
26136
  open,
@@ -26404,12 +26138,15 @@ function ConnectButton({
26404
26138
  pendingPlugins,
26405
26139
  onPendingPluginsChange,
26406
26140
  pendingPluginsDisabledReason,
26407
- pendingComputers,
26408
- onPendingComputersChange,
26409
- onPluginsChanged
26141
+ excludedComputers,
26142
+ onExcludedComputersChange,
26143
+ pendingPhones,
26144
+ onPendingPhonesChange,
26145
+ onPluginsChanged,
26146
+ variant = "icon"
26410
26147
  }) {
26411
26148
  const client = useBladeClient();
26412
- const { ConnectorComputerSection, ConnectorAccountsSection } = useRichInputServices();
26149
+ const { ConnectorComputerSection, ConnectorPhoneSection, ConnectorAccountsSection } = useRichInputServices();
26413
26150
  const invalidation = useSessionDataInvalidation();
26414
26151
  const [uncontrolledOpen, setUncontrolledOpen] = useState6(false);
26415
26152
  const isOpen = open ?? uncontrolledOpen;
@@ -26422,60 +26159,83 @@ function ConnectButton({
26422
26159
  const summary = triggerSummary(triggerItems);
26423
26160
  const triggerCls = summary.total === 0 ? "w-9 p-0 text-[hsl(var(--muted-foreground))]" : summary.total === 1 ? "w-9 p-0" : "px-1";
26424
26161
  const selectedLabels = sessionId === null ? (pendingPlugins ?? []).map((item) => item.displayName?.trim() || item.name) : selectedItems.map((item) => item.display_name?.trim() || item.name);
26425
- return /* @__PURE__ */ jsxs6(dist_exports.Root, { open: isOpen, onOpenChange: setOpen, children: [
26426
- /* @__PURE__ */ jsx15(dist_exports.Trigger, { asChild: true, children: /* @__PURE__ */ jsx15(
26162
+ const panel = /* @__PURE__ */ jsx16(
26163
+ ConnectorPanel,
26164
+ {
26165
+ client,
26166
+ sessionId,
26167
+ pendingPlugins,
26168
+ onPendingPluginsChange,
26169
+ pendingDisabledReason: pendingPluginsDisabledReason,
26170
+ onPluginsChanged: () => {
26171
+ if (sessionId) {
26172
+ invalidateSlashSuggestions(client, sessionId);
26173
+ invalidation.pluginsChanged(sessionId);
26174
+ }
26175
+ onPluginsChanged?.();
26176
+ },
26177
+ onSelectedChange: setSelectedItems,
26178
+ renderComputerSection: ConnectorComputerSection ? (query) => /* @__PURE__ */ jsx16(
26179
+ ConnectorComputerSection,
26180
+ {
26181
+ sessionId,
26182
+ query,
26183
+ excludedSelection: excludedComputers,
26184
+ onExcludedSelectionChange: onExcludedComputersChange,
26185
+ closePanel: () => setOpen(false)
26186
+ }
26187
+ ) : void 0,
26188
+ renderPhoneSection: ConnectorPhoneSection ? (query) => /* @__PURE__ */ jsx16(
26189
+ ConnectorPhoneSection,
26190
+ {
26191
+ sessionId,
26192
+ query,
26193
+ pendingSelection: pendingPhones,
26194
+ onPendingSelectionChange: onPendingPhonesChange,
26195
+ closePanel: () => setOpen(false)
26196
+ }
26197
+ ) : void 0,
26198
+ renderExternalAccounts: ConnectorAccountsSection ? (query) => /* @__PURE__ */ jsx16(ConnectorAccountsSection, { query, closePanel: () => setOpen(false) }) : void 0
26199
+ }
26200
+ );
26201
+ if (variant === "submenu") {
26202
+ return /* @__PURE__ */ jsx16(
26203
+ InputActionSubmenu,
26204
+ {
26205
+ label: summary.total ? `\u8FDE\u63A5\u5668 \xB7 \u5DF2\u9009 ${summary.total}` : "\u8FDE\u63A5\u5668",
26206
+ icon: /* @__PURE__ */ jsx16(Plug, { size: 16, "aria-hidden": "true" }),
26207
+ open: isOpen,
26208
+ onOpenChange: setOpen,
26209
+ children: panel
26210
+ }
26211
+ );
26212
+ }
26213
+ return /* @__PURE__ */ jsxs7(dist_exports.Root, { open: isOpen, onOpenChange: setOpen, children: [
26214
+ /* @__PURE__ */ jsx16(dist_exports.Trigger, { asChild: true, children: /* @__PURE__ */ jsx16(
26427
26215
  "button",
26428
26216
  {
26429
26217
  type: "button",
26430
26218
  "aria-label": summary.total > 0 ? `\u8FDE\u63A5\u5668\uFF1A\u5DF2\u9009 ${summary.total} \u4E2A\u63D2\u4EF6` : "\u8FDE\u63A5\u5668",
26431
26219
  title: selectedLabels.length > 0 ? `\u8FDE\u63A5\u5668\uFF1A${selectedLabels.join("\u3001")}` : "\u8FDE\u63A5\u5668",
26432
26220
  className: `flex h-9 shrink-0 cursor-pointer items-center justify-center rounded-full border border-[hsl(var(--border))] transition-colors hover:border-[hsl(var(--ring))] hover:text-[hsl(var(--foreground))] ${triggerCls}`,
26433
- children: summary.total === 0 ? /* @__PURE__ */ jsx15(Plug, { size: 14, "aria-hidden": "true" }) : /* @__PURE__ */ jsx15(PluginTriggerStack, { client, sessionId, summary })
26221
+ children: summary.total === 0 ? /* @__PURE__ */ jsx16(Plug, { size: 14, "aria-hidden": "true" }) : /* @__PURE__ */ jsx16(PluginTriggerStack, { client, sessionId, summary })
26434
26222
  }
26435
26223
  ) }),
26436
- /* @__PURE__ */ jsx15(dist_exports.Portal, { children: /* @__PURE__ */ jsx15(
26224
+ /* @__PURE__ */ jsx16(dist_exports.Portal, { children: /* @__PURE__ */ jsx16(
26437
26225
  dist_exports.Content,
26438
26226
  {
26439
26227
  side: "top",
26440
26228
  align: "start",
26441
26229
  sideOffset: 8,
26442
26230
  className: "z-50 w-[min(320px,calc(100vw-2rem))] origin-(--radix-popover-content-transform-origin) overflow-hidden rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--popover))] text-[11px] text-[hsl(var(--popover-foreground))] shadow-[var(--swf-shadow-overlay)] outline-none data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
26443
- children: /* @__PURE__ */ jsx15("div", { className: "max-h-[min(70vh,32rem)] overflow-y-auto", children: /* @__PURE__ */ jsx15(
26444
- ConnectorPanel,
26445
- {
26446
- client,
26447
- sessionId,
26448
- pendingPlugins,
26449
- onPendingPluginsChange,
26450
- pendingDisabledReason: pendingPluginsDisabledReason,
26451
- onPluginsChanged: () => {
26452
- if (sessionId) {
26453
- invalidateSlashSuggestions(client, sessionId);
26454
- invalidation.pluginsChanged(sessionId);
26455
- }
26456
- onPluginsChanged?.();
26457
- },
26458
- onSelectedChange: setSelectedItems,
26459
- renderComputerSection: ConnectorComputerSection ? (query) => /* @__PURE__ */ jsx15(
26460
- ConnectorComputerSection,
26461
- {
26462
- sessionId,
26463
- query,
26464
- pendingSelection: pendingComputers,
26465
- onPendingSelectionChange: onPendingComputersChange,
26466
- closePanel: () => setOpen(false)
26467
- }
26468
- ) : void 0,
26469
- renderExternalAccounts: ConnectorAccountsSection ? (query) => /* @__PURE__ */ jsx15(ConnectorAccountsSection, { query, closePanel: () => setOpen(false) }) : void 0
26470
- }
26471
- ) })
26231
+ children: /* @__PURE__ */ jsx16("div", { className: "max-h-[min(70vh,32rem)] overflow-y-auto", children: panel })
26472
26232
  }
26473
26233
  ) })
26474
26234
  ] });
26475
26235
  }
26476
26236
 
26477
26237
  // src/rich-input/voice/use-voice-input.ts
26478
- import { useCallback as useCallback3, useEffect as useEffect7, useRef as useRef7, useState as useState7 } from "react";
26238
+ import { useCallback as useCallback2, useEffect as useEffect6, useRef as useRef5, useState as useState7 } from "react";
26479
26239
 
26480
26240
  // src/rich-input/voice/voice-input-support.ts
26481
26241
  function isIpHost(hostname) {
@@ -26523,25 +26283,25 @@ function matchesRequest(data, requestId) {
26523
26283
  }
26524
26284
  function useVoiceInput(options) {
26525
26285
  const client = useBladeClient();
26526
- const clientRef = useRef7(client);
26286
+ const clientRef = useRef5(client);
26527
26287
  clientRef.current = client;
26528
- const getSocket = useCallback3(() => clientRef.current.socket(), []);
26288
+ const getSocket = useCallback2(() => clientRef.current.socket(), []);
26529
26289
  const [status, setStatus] = useState7("idle");
26530
26290
  const [error, setError] = useState7(null);
26531
26291
  const [level, setLevel] = useState7(0);
26532
- const sessionRef = useRef7(null);
26533
- const stoppingRef = useRef7(false);
26534
- const startAbortRef = useRef7(null);
26535
- const optionsRef = useRef7(options);
26292
+ const sessionRef = useRef5(null);
26293
+ const stoppingRef = useRef5(false);
26294
+ const startAbortRef = useRef5(null);
26295
+ const optionsRef = useRef5(options);
26536
26296
  optionsRef.current = options;
26537
- const reportError = useCallback3((err) => {
26297
+ const reportError = useCallback2((err) => {
26538
26298
  const payload = typeof err === "string" ? { title: err } : err;
26539
26299
  setError(payload.title);
26540
26300
  setStatus("error");
26541
26301
  setLevel(0);
26542
26302
  optionsRef.current.onError?.(payload);
26543
26303
  }, []);
26544
- const disposeSession = useCallback3((s) => {
26304
+ const disposeSession = useCallback2((s) => {
26545
26305
  if (s.disposed) return;
26546
26306
  s.disposed = true;
26547
26307
  const socket = getSocket();
@@ -26566,7 +26326,7 @@ function useVoiceInput(options) {
26566
26326
  } catch {
26567
26327
  }
26568
26328
  }, [getSocket]);
26569
- const stop = useCallback3(async () => {
26329
+ const stop = useCallback2(async () => {
26570
26330
  startAbortRef.current?.abort();
26571
26331
  const s = sessionRef.current;
26572
26332
  if (!s || stoppingRef.current) {
@@ -26613,7 +26373,7 @@ function useVoiceInput(options) {
26613
26373
  setLevel(0);
26614
26374
  setStatus((prev) => prev === "error" ? "error" : "idle");
26615
26375
  }, [disposeSession, getSocket]);
26616
- const start = useCallback3(async () => {
26376
+ const start = useCallback2(async () => {
26617
26377
  if (sessionRef.current || startAbortRef.current && !startAbortRef.current.signal.aborted || stoppingRef.current) {
26618
26378
  return;
26619
26379
  }
@@ -26787,7 +26547,7 @@ function useVoiceInput(options) {
26787
26547
  if (startAbortRef.current === abort) startAbortRef.current = null;
26788
26548
  }
26789
26549
  }, [reportError, disposeSession, getSocket]);
26790
- useEffect7(() => {
26550
+ useEffect6(() => {
26791
26551
  return () => {
26792
26552
  startAbortRef.current?.abort();
26793
26553
  const s = sessionRef.current;
@@ -26805,7 +26565,7 @@ function useVoiceInput(options) {
26805
26565
  }
26806
26566
 
26807
26567
  // src/rich-input/use-reference-candidates.ts
26808
- import { useLayoutEffect as useLayoutEffect2, useRef as useRef8 } from "react";
26568
+ import { useLayoutEffect as useLayoutEffect2, useRef as useRef6 } from "react";
26809
26569
 
26810
26570
  // src/rich-input/lib/reference-candidates.ts
26811
26571
  function createReferenceCandidateController(getScope, sources, timeoutMs = 300) {
@@ -26880,7 +26640,6 @@ function createReferenceCandidateController(getScope, sources, timeoutMs = 300)
26880
26640
  }
26881
26641
  return result;
26882
26642
  },
26883
- /** Bind by result identity, never by label/query: closing and reopening @ is a new request. */
26884
26643
  observe(items, listener) {
26885
26644
  const request = requests.get(items);
26886
26645
  if (!request || !isCurrent(request)) {
@@ -26904,7 +26663,7 @@ function useReferenceCandidates(getScope, sources) {
26904
26663
  const plugins = useEffectEvent((query) => sources.plugins?.(query) ?? Promise.resolve([]));
26905
26664
  const topics = useEffectEvent(sources.topics);
26906
26665
  const files = useEffectEvent(sources.files);
26907
- const ref = useRef8(null);
26666
+ const ref = useRef6(null);
26908
26667
  if (!ref.current) ref.current = createReferenceCandidateController(readScope, { plugins, topics, files });
26909
26668
  const controller = ref.current;
26910
26669
  const [client, identity, session, topic] = getScope();
@@ -26914,7 +26673,7 @@ function useReferenceCandidates(getScope, sources) {
26914
26673
  }
26915
26674
 
26916
26675
  // src/rich-input/use-input-history.ts
26917
- import { useCallback as useCallback4, useEffect as useEffect8, useMemo as useMemo7, useState as useState8 } from "react";
26676
+ import { useCallback as useCallback3, useEffect as useEffect7, useMemo as useMemo6, useState as useState8 } from "react";
26918
26677
 
26919
26678
  // src/rich-input/lib/input-history-document.ts
26920
26679
  import { normalizeTopicAssetRefs as normalizeTopicAssetRefs3 } from "@blade-hq/agent-client";
@@ -26923,8 +26682,7 @@ function copyEditorDocument(value) {
26923
26682
  pluginMention: { provider: "string", plugin: "string", server: "string", id: "string", label: "string" },
26924
26683
  fileMention: { path: "string", name: "string" },
26925
26684
  topicAssetMention: { topic_id: "string", path: "string" },
26926
- skillMention: { skillId: "string", displayName: "string", description: "string", local: "boolean", installed: "boolean" },
26927
- workflowMention: { name: "string" }
26685
+ skillMention: { skillId: "string", displayName: "string", description: "string", local: "boolean", installed: "boolean" }
26928
26686
  };
26929
26687
  const copy2 = (input, parent) => {
26930
26688
  if (!input || typeof input !== "object" || Array.isArray(input)) return null;
@@ -27005,17 +26763,17 @@ function readEntries(storageKey) {
27005
26763
  }
27006
26764
  function useInputHistory(sessionId, client) {
27007
26765
  const [generation, setGeneration] = useState8(getInputHistoryGeneration);
27008
- const storageKey = useMemo7(() => getStorageKey(sessionId), [sessionId]);
26766
+ const storageKey = useMemo6(() => getStorageKey(sessionId), [sessionId]);
27009
26767
  const [entries, setEntries] = useState8([]);
27010
26768
  const [cursor, setCursor] = useState8(null);
27011
26769
  const [draft, setDraft] = useState8(emptyEntry);
27012
- useEffect8(() => {
26770
+ useEffect7(() => {
27013
26771
  setGeneration(getInputHistoryGeneration());
27014
26772
  setEntries(readEntries(storageKey));
27015
26773
  setCursor(null);
27016
26774
  setDraft(emptyEntry());
27017
26775
  }, [storageKey, client]);
27018
- useEffect8(() => {
26776
+ useEffect7(() => {
27019
26777
  if (!client) return;
27020
26778
  return onInputCachesReset(client, () => {
27021
26779
  setGeneration(getInputHistoryGeneration());
@@ -27024,7 +26782,7 @@ function useInputHistory(sessionId, client) {
27024
26782
  setDraft(emptyEntry());
27025
26783
  });
27026
26784
  }, [client]);
27027
- const persistEntries = useCallback4(
26785
+ const persistEntries = useCallback3(
27028
26786
  (nextEntries) => {
27029
26787
  if (generation !== getInputHistoryGeneration() || typeof window === "undefined" || !storageKey) {
27030
26788
  return;
@@ -27036,7 +26794,7 @@ function useInputHistory(sessionId, client) {
27036
26794
  },
27037
26795
  [storageKey, generation]
27038
26796
  );
27039
- const addEntry = useCallback4(
26797
+ const addEntry = useCallback3(
27040
26798
  (value) => {
27041
26799
  if (generation !== getInputHistoryGeneration()) return;
27042
26800
  const document2 = copyEditorDocument(value);
@@ -27052,7 +26810,7 @@ function useInputHistory(sessionId, client) {
27052
26810
  },
27053
26811
  [persistEntries, generation]
27054
26812
  );
27055
- const navigateUp = useCallback4(
26813
+ const navigateUp = useCallback3(
27056
26814
  (currentDraft = emptyEntry().document) => {
27057
26815
  if (generation !== getInputHistoryGeneration() || entries.length === 0) {
27058
26816
  return null;
@@ -27066,7 +26824,7 @@ function useInputHistory(sessionId, client) {
27066
26824
  },
27067
26825
  [cursor, entries, generation]
27068
26826
  );
27069
- const navigateDown = useCallback4(() => {
26827
+ const navigateDown = useCallback3(() => {
27070
26828
  if (generation !== getInputHistoryGeneration() || cursor == null) {
27071
26829
  return null;
27072
26830
  }
@@ -27117,8 +26875,7 @@ function splitFilesBySize(files, limitBytes = ATTACHMENT_SIZE_LIMIT_BYTES) {
27117
26875
 
27118
26876
  // src/rich-input/ChatInput.tsx
27119
26877
  import {
27120
- buildMessageContent,
27121
- transformSlashCommand
26878
+ buildMessageContent
27122
26879
  } from "@blade-hq/agent-client/internal";
27123
26880
 
27124
26881
  // src/rich-input/lib/upload-results.ts
@@ -27149,47 +26906,20 @@ function getUnsupportedImageFiles(files, supportsImage) {
27149
26906
  }
27150
26907
 
27151
26908
  // src/rich-input/FileCompletionMenu.tsx
27152
- import { forwardRef as forwardRef2, useCallback as useCallback5, useImperativeHandle, useMemo as useMemo8, useState as useState9 } from "react";
26909
+ import { forwardRef as forwardRef2, useCallback as useCallback4, useImperativeHandle, useMemo as useMemo7, useState as useState9 } from "react";
27153
26910
 
27154
26911
  // src/rich-input/lib/user-home.ts
27155
- var SANDBOX_HOME_ROOT = "/root";
27156
- var SANDBOX_RUNTIME = { homePath: SANDBOX_HOME_ROOT, separator: "/" };
27157
26912
  var CACHE_TTL_MS2 = 15e3;
27158
26913
  var cachesByClient2 = /* @__PURE__ */ new WeakMap();
27159
- var lastResolvedRuntime = SANDBOX_RUNTIME;
27160
26914
  function cachesFor2(client) {
27161
26915
  const existing = cachesByClient2.get(client);
27162
26916
  if (existing) return existing;
27163
- const caches2 = { runtime: null, dirs: /* @__PURE__ */ new Map() };
27164
- cachesByClient2.set(client, caches2);
26917
+ const caches = { dirs: /* @__PURE__ */ new Map() };
26918
+ cachesByClient2.set(client, caches);
27165
26919
  onInputCachesReset(client, () => {
27166
- if (cachesByClient2.get(client) === caches2) cachesByClient2.delete(client);
27167
- lastResolvedRuntime = SANDBOX_RUNTIME;
27168
- });
27169
- return caches2;
27170
- }
27171
- function getUserHomeRuntime(client) {
27172
- const caches2 = cachesFor2(client);
27173
- if (caches2.runtime && Date.now() - caches2.runtime.at < CACHE_TTL_MS2) {
27174
- return caches2.runtime.request;
27175
- }
27176
- const request = client.json("GET", "/api/agent-board/workspace-runtime").then((runtime) => {
27177
- const homePath = (runtime.home_path ?? "").trim() || SANDBOX_HOME_ROOT;
27178
- const resolved = {
27179
- homePath,
27180
- separator: (runtime.os ?? "").toLowerCase().startsWith("windows") ? "\\" : "/"
27181
- };
27182
- lastResolvedRuntime = resolved;
27183
- return resolved;
27184
- }).catch(() => {
27185
- if (caches2.runtime?.request === request) caches2.runtime = null;
27186
- return SANDBOX_RUNTIME;
26920
+ if (cachesByClient2.get(client) === caches) cachesByClient2.delete(client);
27187
26921
  });
27188
- caches2.runtime = { at: Date.now(), request };
27189
- return request;
27190
- }
27191
- function getLastUserHomeRuntime() {
27192
- return lastResolvedRuntime;
26922
+ return caches;
27193
26923
  }
27194
26924
  function listUserHomeDir(client, dirPath) {
27195
26925
  const { dirs } = cachesFor2(client);
@@ -27204,7 +26934,7 @@ function listUserHomeDir(client, dirPath) {
27204
26934
  }
27205
26935
 
27206
26936
  // src/rich-input/FileCompletionMenu.tsx
27207
- import { Fragment as Fragment4, jsx as jsx16, jsxs as jsxs7 } from "react/jsx-runtime";
26937
+ import { Fragment as Fragment4, jsx as jsx17, jsxs as jsxs8 } from "react/jsx-runtime";
27208
26938
  var ROOT_DIR = ".";
27209
26939
  function installSuggestionOutsideDismiss(container, onDismiss) {
27210
26940
  const onPointerDown = (event) => {
@@ -27301,7 +27031,9 @@ async function getFileSuggestionItems(client, sessionId, query) {
27301
27031
  const entries = await listDirectory(client, sessionId, dirPath);
27302
27032
  return filterEntries(entries, filterQuery);
27303
27033
  }
27304
- function parseUserHomeQuery(query, { homePath, separator }) {
27034
+ function parseUserHomeQuery(query) {
27035
+ const homePath = "/root";
27036
+ const separator = "/";
27305
27037
  if (!query.startsWith(homePath)) {
27306
27038
  return { dirPath: homePath, filterQuery: query };
27307
27039
  }
@@ -27315,8 +27047,7 @@ function parseUserHomeQuery(query, { homePath, separator }) {
27315
27047
  };
27316
27048
  }
27317
27049
  async function getUserHomeSuggestionItems(client, query) {
27318
- const runtime = await getUserHomeRuntime(client);
27319
- const { dirPath, filterQuery } = parseUserHomeQuery(query, runtime);
27050
+ const { dirPath, filterQuery } = parseUserHomeQuery(query);
27320
27051
  let entries;
27321
27052
  try {
27322
27053
  entries = (await listUserHomeDir(client, dirPath)).map((entry) => ({
@@ -27331,11 +27062,11 @@ async function getUserHomeSuggestionItems(client, query) {
27331
27062
  var FileCompletionMenu = forwardRef2(
27332
27063
  function FileCompletionMenu2({ command: command2, editor, items, onExit, query, range, scope = "session", sessionId: sessionIdProp }, ref) {
27333
27064
  const sessionId = sessionIdProp ?? null;
27334
- const { dirPath, filterQuery } = useMemo8(
27065
+ const { dirPath, filterQuery } = useMemo7(
27335
27066
  () => scope === "userHome" ? { dirPath: query, filterQuery: "" } : parseSuggestionQuery(query),
27336
27067
  [query, scope]
27337
27068
  );
27338
- const { pluginItems, pluginError, fileItems, topicItems, topicError } = useMemo8(() => {
27069
+ const { pluginItems, pluginError, fileItems, topicItems, topicError } = useMemo7(() => {
27339
27070
  let pluginError2;
27340
27071
  const pluginItems2 = [];
27341
27072
  const files = [];
@@ -27350,7 +27081,7 @@ var FileCompletionMenu = forwardRef2(
27350
27081
  }
27351
27082
  return { pluginItems: pluginItems2, pluginError: pluginError2, fileItems: files, topicItems: topicItems2, topicError: topicError2 };
27352
27083
  }, [items]);
27353
- return /* @__PURE__ */ jsx16(
27084
+ return /* @__PURE__ */ jsx17(
27354
27085
  FileCompletionMenuContent,
27355
27086
  {
27356
27087
  ref,
@@ -27373,21 +27104,20 @@ var FileCompletionMenu = forwardRef2(
27373
27104
  );
27374
27105
  var FileCompletionMenuContent = forwardRef2(function FileCompletionMenuContent2({ command: command2, editor, filterQuery, items, pluginItems, pluginError, topicItems, topicError, onExit, range, scope, sessionId }, ref) {
27375
27106
  const [rawSelectedIndex, setRawSelectedIndex] = useState9(0);
27376
- const filteredEntries = useMemo8(() => filterEntries(items, filterQuery), [filterQuery, items]);
27377
- const navigableItems = useMemo8(
27107
+ const filteredEntries = useMemo7(() => filterEntries(items, filterQuery), [filterQuery, items]);
27108
+ const navigableItems = useMemo7(
27378
27109
  () => [...pluginItems, ...topicItems, ...filteredEntries],
27379
27110
  [filteredEntries, pluginItems, topicItems]
27380
27111
  );
27381
27112
  const selectedIndex = navigableItems.length === 0 ? 0 : Math.min(rawSelectedIndex, navigableItems.length - 1);
27382
- const handleSelect = useCallback5(
27113
+ const handleSelect = useCallback4(
27383
27114
  (entry) => {
27384
27115
  if (isPluginSuggestionItem(entry) || isTopicAssetSuggestionItem(entry)) {
27385
27116
  command2(entry);
27386
27117
  return;
27387
27118
  }
27388
27119
  if (entry.is_dir) {
27389
- const separator = scope === "userHome" ? getLastUserHomeRuntime().separator : "/";
27390
- const nextValue = entry.path === ROOT_DIR ? "@" : `@${entry.path}${separator}`;
27120
+ const nextValue = entry.path === ROOT_DIR ? "@" : `@${entry.path}/`;
27391
27121
  editor.chain().focus().insertContentAt(range, nextValue).run();
27392
27122
  return;
27393
27123
  }
@@ -27397,7 +27127,7 @@ var FileCompletionMenuContent = forwardRef2(function FileCompletionMenuContent2(
27397
27127
  path: entry.path
27398
27128
  });
27399
27129
  },
27400
- [command2, editor, range, scope]
27130
+ [command2, editor, range]
27401
27131
  );
27402
27132
  useImperativeHandle(
27403
27133
  ref,
@@ -27445,9 +27175,9 @@ var FileCompletionMenuContent = forwardRef2(function FileCompletionMenuContent2(
27445
27175
  };
27446
27176
  const showGroupLabels = pluginItems.length > 0 || topicItems.length > 0 || Boolean(topicError);
27447
27177
  const fileEmptyLabel = scope === "session" && !sessionId ? "\u6682\u65E0\u4F1A\u8BDD" : filteredEntries.length === 0 ? "\u6CA1\u6709\u6587\u4EF6" : null;
27448
- return /* @__PURE__ */ jsxs7("div", { className: "max-h-64 overflow-y-auto rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--popover))] py-1 shadow-[var(--swf-shadow-overlay)]", children: [
27449
- pluginError ? /* @__PURE__ */ jsx16("output", { className: "block px-3 py-2 text-xs text-muted-foreground", children: pluginError }) : null,
27450
- pluginItems.map((item, index) => /* @__PURE__ */ jsxs7(
27178
+ return /* @__PURE__ */ jsxs8("div", { className: "max-h-64 overflow-y-auto rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--popover))] py-1 shadow-[var(--swf-shadow-overlay)]", children: [
27179
+ pluginError ? /* @__PURE__ */ jsx17("output", { className: "block px-3 py-2 text-xs text-muted-foreground", children: pluginError }) : null,
27180
+ pluginItems.map((item, index) => /* @__PURE__ */ jsxs8(
27451
27181
  "button",
27452
27182
  {
27453
27183
  ref: selectedRef(index),
@@ -27458,31 +27188,31 @@ var FileCompletionMenuContent = forwardRef2(function FileCompletionMenuContent2(
27458
27188
  handleSelect(item);
27459
27189
  },
27460
27190
  children: [
27461
- item.icon ? /* @__PURE__ */ jsx16("img", { src: item.icon, alt: "", width: 16, height: 16, className: "shrink-0" }) : /* @__PURE__ */ jsx16(BookOpen, { size: 14 }),
27462
- /* @__PURE__ */ jsx16("span", { className: "truncate", children: item.label }),
27463
- /* @__PURE__ */ jsx16("span", { className: "ml-auto truncate text-xs text-muted-foreground", children: item.display_name })
27191
+ item.icon ? /* @__PURE__ */ jsx17("img", { src: item.icon, alt: "", width: 16, height: 16, className: "shrink-0" }) : /* @__PURE__ */ jsx17(BookOpen, { size: 14 }),
27192
+ /* @__PURE__ */ jsx17("span", { className: "truncate", children: item.label }),
27193
+ /* @__PURE__ */ jsx17("span", { className: "ml-auto truncate text-xs text-muted-foreground", children: item.display_name })
27464
27194
  ]
27465
27195
  },
27466
27196
  `${item.plugin}:${item.server}:${item.id}`
27467
27197
  )),
27468
- topicItems.length > 0 || topicError ? /* @__PURE__ */ jsxs7(Fragment4, { children: [
27469
- /* @__PURE__ */ jsx16("div", { className: "px-3 pt-1 pb-0.5 text-xs font-medium text-muted-foreground", children: "\u4E3B\u9898\u8D44\u4EA7" }),
27470
- topicError ? /* @__PURE__ */ jsx16("output", { className: "block px-3 py-2 text-xs text-muted-foreground", children: topicError }) : null,
27198
+ topicItems.length > 0 || topicError ? /* @__PURE__ */ jsxs8(Fragment4, { children: [
27199
+ /* @__PURE__ */ jsx17("div", { className: "px-3 pt-1 pb-0.5 text-xs font-medium text-muted-foreground", children: "\u5DE5\u4F5C\u7A7A\u95F4\u8D44\u4EA7" }),
27200
+ topicError ? /* @__PURE__ */ jsx17("output", { className: "block px-3 py-2 text-xs text-muted-foreground", children: topicError }) : null,
27471
27201
  topicItems.map((item, topicIndex) => {
27472
27202
  const index = pluginItems.length + topicIndex;
27473
- return /* @__PURE__ */ jsxs7("button", { ref: selectedRef(index), type: "button", title: item.path, className: rowClassName(index), onMouseDown: (event) => {
27203
+ return /* @__PURE__ */ jsxs8("button", { ref: selectedRef(index), type: "button", title: item.path, className: rowClassName(index), onMouseDown: (event) => {
27474
27204
  event.preventDefault();
27475
27205
  handleSelect(item);
27476
27206
  }, children: [
27477
- /* @__PURE__ */ jsx16(File, { size: 14, className: "shrink-0 text-muted-foreground" }),
27478
- /* @__PURE__ */ jsx16("span", { className: "truncate", children: item.path })
27207
+ /* @__PURE__ */ jsx17(File, { size: 14, className: "shrink-0 text-muted-foreground" }),
27208
+ /* @__PURE__ */ jsx17("span", { className: "truncate", children: item.path })
27479
27209
  ] }, `${item.topic_id}:${item.path}`);
27480
27210
  })
27481
27211
  ] }) : null,
27482
- showGroupLabels ? /* @__PURE__ */ jsx16("div", { className: "px-3 pt-1 pb-0.5 text-[10px] font-medium uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u6587\u4EF6" }) : null,
27483
- fileEmptyLabel ? /* @__PURE__ */ jsx16("div", { className: "px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]", children: fileEmptyLabel }) : filteredEntries.map((entry, fileIndex) => {
27212
+ showGroupLabels ? /* @__PURE__ */ jsx17("div", { className: "px-3 pt-1 pb-0.5 text-[10px] font-medium uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u6587\u4EF6" }) : null,
27213
+ fileEmptyLabel ? /* @__PURE__ */ jsx17("div", { className: "px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]", children: fileEmptyLabel }) : filteredEntries.map((entry, fileIndex) => {
27484
27214
  const index = pluginItems.length + topicItems.length + fileIndex;
27485
- return /* @__PURE__ */ jsxs7(
27215
+ return /* @__PURE__ */ jsxs8(
27486
27216
  "button",
27487
27217
  {
27488
27218
  ref: selectedRef(index),
@@ -27493,9 +27223,9 @@ var FileCompletionMenuContent = forwardRef2(function FileCompletionMenuContent2(
27493
27223
  },
27494
27224
  className: rowClassName(index),
27495
27225
  children: [
27496
- entry.is_dir ? /* @__PURE__ */ jsx16(Folder, { size: 14, className: "shrink-0 text-[hsl(var(--primary))]" }) : /* @__PURE__ */ jsx16(File, { size: 14, className: "shrink-0 text-[hsl(var(--muted-foreground))]" }),
27497
- /* @__PURE__ */ jsx16("span", { className: "truncate", children: entry.name }),
27498
- entry.is_dir && /* @__PURE__ */ jsx16(ChevronRight, { size: 12, className: "ml-auto shrink-0 opacity-40" })
27226
+ entry.is_dir ? /* @__PURE__ */ jsx17(Folder, { size: 14, className: "shrink-0 text-[hsl(var(--primary))]" }) : /* @__PURE__ */ jsx17(File, { size: 14, className: "shrink-0 text-[hsl(var(--muted-foreground))]" }),
27227
+ /* @__PURE__ */ jsx17("span", { className: "truncate", children: entry.name }),
27228
+ entry.is_dir && /* @__PURE__ */ jsx17(ChevronRight, { size: 12, className: "ml-auto shrink-0 opacity-40" })
27499
27229
  ]
27500
27230
  },
27501
27231
  entry.path
@@ -27505,13 +27235,13 @@ var FileCompletionMenuContent = forwardRef2(function FileCompletionMenuContent2(
27505
27235
  });
27506
27236
 
27507
27237
  // src/rich-input/SkillCompletionMenu.tsx
27508
- import { forwardRef as forwardRef3, useCallback as useCallback6, useImperativeHandle as useImperativeHandle2, useState as useState10 } from "react";
27509
- import { jsx as jsx17, jsxs as jsxs8 } from "react/jsx-runtime";
27238
+ import { forwardRef as forwardRef3, useCallback as useCallback5, useImperativeHandle as useImperativeHandle2, useState as useState10 } from "react";
27239
+ import { jsx as jsx18, jsxs as jsxs9 } from "react/jsx-runtime";
27510
27240
  var SkillCompletionMenu = forwardRef3(
27511
27241
  function SkillCompletionMenu2({ command: command2, items }, ref) {
27512
27242
  const [rawSelectedIndex, setRawSelectedIndex] = useState10(0);
27513
27243
  const selectedIndex = items.length === 0 ? 0 : Math.min(rawSelectedIndex, items.length - 1);
27514
- const handleSelect = useCallback6(
27244
+ const handleSelect = useCallback5(
27515
27245
  (item) => {
27516
27246
  command2(item);
27517
27247
  },
@@ -27552,12 +27282,11 @@ var SkillCompletionMenu = forwardRef3(
27552
27282
  [handleSelect, items, selectedIndex]
27553
27283
  );
27554
27284
  const commandItems = items.filter((item) => item.type === "command");
27555
- const workflowItems = items.filter((item) => item.type === "workflow");
27556
27285
  const skillItems = items.filter((item) => item.type === "skill");
27557
- return /* @__PURE__ */ jsx17("div", { className: "max-h-64 overflow-y-auto rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--popover))] py-1 shadow-[var(--swf-shadow-overlay)]", children: items.length === 0 ? /* @__PURE__ */ jsx17("div", { className: "px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]", children: "\u6CA1\u6709\u5339\u914D\u7684\u547D\u4EE4\u6216\u6280\u80FD" }) : /* @__PURE__ */ jsxs8("div", { children: [
27558
- commandItems.length > 0 ? /* @__PURE__ */ jsxs8("div", { className: "px-2 pb-1 pt-1", children: [
27559
- /* @__PURE__ */ jsx17("div", { className: "px-1 pb-1 text-[10px] font-semibold uppercase tracking-[0.08em] text-[hsl(var(--muted-foreground))]", children: "\u547D\u4EE4" }),
27560
- commandItems.map((item, index) => /* @__PURE__ */ jsxs8(
27286
+ return /* @__PURE__ */ jsx18("div", { className: "max-h-64 overflow-y-auto rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--popover))] py-1 shadow-[var(--swf-shadow-overlay)]", children: items.length === 0 ? /* @__PURE__ */ jsx18("div", { className: "px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]", children: "\u6CA1\u6709\u5339\u914D\u7684\u547D\u4EE4\u6216\u6280\u80FD" }) : /* @__PURE__ */ jsxs9("div", { children: [
27287
+ commandItems.length > 0 ? /* @__PURE__ */ jsxs9("div", { className: "px-2 pb-1 pt-1", children: [
27288
+ /* @__PURE__ */ jsx18("div", { className: "px-1 pb-1 text-[10px] font-semibold uppercase tracking-[0.08em] text-[hsl(var(--muted-foreground))]", children: "\u547D\u4EE4" }),
27289
+ commandItems.map((item, index) => /* @__PURE__ */ jsxs9(
27561
27290
  "button",
27562
27291
  {
27563
27292
  ref: (element) => {
@@ -27572,51 +27301,21 @@ var SkillCompletionMenu = forwardRef3(
27572
27301
  },
27573
27302
  className: `flex w-full items-start gap-2 rounded-lg px-2 py-1.5 text-left transition-colors ${index === selectedIndex ? "bg-[hsl(var(--accent))] text-[hsl(var(--accent-foreground))]" : "text-[hsl(var(--popover-foreground))] hover:bg-[hsl(var(--accent))]"}`,
27574
27303
  children: [
27575
- /* @__PURE__ */ jsx17("span", { className: "pt-0.5 text-sm", children: "\u21BB" }),
27576
- /* @__PURE__ */ jsxs8("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
27577
- /* @__PURE__ */ jsx17("span", { className: "text-sm font-medium", children: item.label }),
27578
- /* @__PURE__ */ jsx17("span", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: item.description })
27304
+ /* @__PURE__ */ jsx18("span", { className: "pt-0.5 text-sm", children: "\u21BB" }),
27305
+ /* @__PURE__ */ jsxs9("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
27306
+ /* @__PURE__ */ jsx18("span", { className: "text-sm font-medium", children: item.label }),
27307
+ /* @__PURE__ */ jsx18("span", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: item.description })
27579
27308
  ] })
27580
27309
  ]
27581
27310
  },
27582
27311
  item.id
27583
27312
  ))
27584
27313
  ] }) : null,
27585
- workflowItems.length > 0 ? /* @__PURE__ */ jsxs8("div", { className: "px-2 pb-1 pt-1", children: [
27586
- /* @__PURE__ */ jsx17("div", { className: "px-1 pb-1 text-[10px] font-semibold uppercase tracking-[0.08em] text-[hsl(var(--muted-foreground))]", children: "\u5DE5\u4F5C\u6D41" }),
27587
- workflowItems.map((item, wfIndex) => {
27588
- const index = commandItems.length + wfIndex;
27589
- return /* @__PURE__ */ jsxs8(
27590
- "button",
27591
- {
27592
- ref: (element) => {
27593
- if (element && index === selectedIndex) {
27594
- element.scrollIntoView({ block: "nearest" });
27595
- }
27596
- },
27597
- type: "button",
27598
- onMouseDown: (event) => {
27599
- event.preventDefault();
27600
- handleSelect(item);
27601
- },
27602
- className: `flex w-full items-start gap-2 rounded-lg px-2 py-1.5 text-left transition-colors ${index === selectedIndex ? "bg-[hsl(var(--accent))] text-[hsl(var(--accent-foreground))]" : "text-[hsl(var(--popover-foreground))] hover:bg-[hsl(var(--accent))]"}`,
27603
- children: [
27604
- /* @__PURE__ */ jsx17("span", { className: "pt-0.5 text-sm", children: "\u2699" }),
27605
- /* @__PURE__ */ jsxs8("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
27606
- /* @__PURE__ */ jsx17("span", { className: "text-sm font-medium", children: item.displayName }),
27607
- /* @__PURE__ */ jsx17("span", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: item.description || "\u8FD0\u884C\u8FD9\u4E2A\u5DE5\u4F5C\u6D41" })
27608
- ] })
27609
- ]
27610
- },
27611
- `wf:${item.name}`
27612
- );
27613
- })
27614
- ] }) : null,
27615
- skillItems.length > 0 ? /* @__PURE__ */ jsxs8("div", { className: "px-2 pb-1 pt-1", children: [
27616
- /* @__PURE__ */ jsx17("div", { className: "px-1 pb-1 text-[10px] font-semibold uppercase tracking-[0.08em] text-[hsl(var(--muted-foreground))]", children: "\u6280\u80FD" }),
27314
+ skillItems.length > 0 ? /* @__PURE__ */ jsxs9("div", { className: "px-2 pb-1 pt-1", children: [
27315
+ /* @__PURE__ */ jsx18("div", { className: "px-1 pb-1 text-[10px] font-semibold uppercase tracking-[0.08em] text-[hsl(var(--muted-foreground))]", children: "\u6280\u80FD" }),
27617
27316
  skillItems.map((item, skillIndex) => {
27618
- const index = commandItems.length + workflowItems.length + skillIndex;
27619
- return /* @__PURE__ */ jsxs8(
27317
+ const index = commandItems.length + skillIndex;
27318
+ return /* @__PURE__ */ jsxs9(
27620
27319
  "button",
27621
27320
  {
27622
27321
  ref: (element) => {
@@ -27631,11 +27330,19 @@ var SkillCompletionMenu = forwardRef3(
27631
27330
  },
27632
27331
  className: `flex w-full flex-col gap-0.5 rounded-lg px-2 py-1.5 text-left transition-colors ${index === selectedIndex ? "bg-[hsl(var(--accent))] text-[hsl(var(--accent-foreground))]" : "text-[hsl(var(--popover-foreground))] hover:bg-[hsl(var(--accent))]"}`,
27633
27332
  children: [
27634
- /* @__PURE__ */ jsxs8("span", { className: "flex items-center gap-1.5", children: [
27635
- /* @__PURE__ */ jsx17("span", { className: "text-sm font-medium", children: skillDisplayName(item) }),
27636
- item.installed === false ? /* @__PURE__ */ jsx17("span", { className: "shrink-0 rounded-full bg-[hsl(var(--muted))] px-1.5 py-px text-[10px] text-[hsl(var(--muted-foreground))]", children: "\u672A\u5B89\u88C5" }) : null
27333
+ /* @__PURE__ */ jsxs9("span", { className: "flex items-center gap-1.5", children: [
27334
+ /* @__PURE__ */ jsx18("span", { className: "text-sm font-medium", children: skillDisplayName(item) }),
27335
+ item.hasFlow ? /* @__PURE__ */ jsx18(
27336
+ "span",
27337
+ {
27338
+ title: "\u8FD9\u4E2A\u6280\u80FD\u6309\u56FA\u5B9A\u6D41\u7A0B\u6267\u884C:\u6B65\u9AA4\u4E8B\u5148\u7F16\u6392\u597D,\u8FD0\u884C\u4E2D\u4E0D\u4F1A\u5373\u5174\u53D1\u6325,\u4E5F\u4E0D\u4F1A\u4E2D\u9014\u95EE\u4F60",
27339
+ className: "shrink-0 rounded-full bg-violet-500/10 px-1.5 py-px text-[10px] font-medium text-violet-600",
27340
+ children: "\u26A1 \u56FA\u5B9A\u6D41\u7A0B"
27341
+ }
27342
+ ) : null,
27343
+ item.installed === false ? /* @__PURE__ */ jsx18("span", { className: "shrink-0 rounded-full bg-[hsl(var(--muted))] px-1.5 py-px text-[10px] text-[hsl(var(--muted-foreground))]", children: "\u672A\u5B89\u88C5" }) : null
27637
27344
  ] }),
27638
- /* @__PURE__ */ jsx17("span", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: item.description })
27345
+ /* @__PURE__ */ jsx18("span", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: item.description })
27639
27346
  ]
27640
27347
  },
27641
27348
  item.skillId
@@ -27647,7 +27354,7 @@ var SkillCompletionMenu = forwardRef3(
27647
27354
  );
27648
27355
 
27649
27356
  // src/rich-input/FileSizeLimitDialog.tsx
27650
- import { jsx as jsx18, jsxs as jsxs9 } from "react/jsx-runtime";
27357
+ import { jsx as jsx19, jsxs as jsxs10 } from "react/jsx-runtime";
27651
27358
  function FileSizeLimitDialog({
27652
27359
  open,
27653
27360
  onOpenChange,
@@ -27658,37 +27365,37 @@ function FileSizeLimitDialog({
27658
27365
  return null;
27659
27366
  }
27660
27367
  const limitText = formatFileSize(limitBytes);
27661
- return /* @__PURE__ */ jsx18(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs9(DialogContent, { showCloseButton: false, className: "w-full max-w-lg gap-0 p-0", children: [
27662
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-4 py-3", children: [
27663
- /* @__PURE__ */ jsxs9("div", { children: [
27664
- /* @__PURE__ */ jsx18(DialogTitle, { className: "text-sm font-semibold text-[hsl(var(--foreground))]", children: "\u9644\u4EF6\u8D85\u8FC7\u5927\u5C0F\u9650\u5236" }),
27665
- /* @__PURE__ */ jsxs9("p", { className: "mt-1 text-xs text-[hsl(var(--muted-foreground))]", children: [
27368
+ return /* @__PURE__ */ jsx19(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs10(DialogContent, { showCloseButton: false, className: "w-full max-w-lg gap-0 p-0", children: [
27369
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-4 py-3", children: [
27370
+ /* @__PURE__ */ jsxs10("div", { children: [
27371
+ /* @__PURE__ */ jsx19(DialogTitle, { className: "text-sm font-semibold text-[hsl(var(--foreground))]", children: "\u9644\u4EF6\u8D85\u8FC7\u5927\u5C0F\u9650\u5236" }),
27372
+ /* @__PURE__ */ jsxs10("p", { className: "mt-1 text-xs text-[hsl(var(--muted-foreground))]", children: [
27666
27373
  "\u5355\u4E2A\u9644\u4EF6\u6700\u5927\u652F\u6301 ",
27667
27374
  limitText,
27668
27375
  "\u3002\u4EE5\u4E0B\u6587\u4EF6\u672A\u52A0\u5165\u9644\u4EF6\u5217\u8868\u3002"
27669
27376
  ] })
27670
27377
  ] }),
27671
- /* @__PURE__ */ jsx18(
27378
+ /* @__PURE__ */ jsx19(
27672
27379
  DialogClose,
27673
27380
  {
27674
27381
  title: "\u5173\u95ED",
27675
27382
  className: "flex h-7 w-7 items-center justify-center rounded-md text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
27676
- children: /* @__PURE__ */ jsx18(X, { size: 14 })
27383
+ children: /* @__PURE__ */ jsx19(X, { size: 14 })
27677
27384
  }
27678
27385
  )
27679
27386
  ] }),
27680
- /* @__PURE__ */ jsx18("div", { className: "max-h-[min(50vh,24rem)] overflow-auto px-4 py-3", children: /* @__PURE__ */ jsx18("div", { className: "flex flex-col gap-2", children: files.map((file) => /* @__PURE__ */ jsxs9(
27387
+ /* @__PURE__ */ jsx19("div", { className: "max-h-[min(50vh,24rem)] overflow-auto px-4 py-3", children: /* @__PURE__ */ jsx19("div", { className: "flex flex-col gap-2", children: files.map((file) => /* @__PURE__ */ jsxs10(
27681
27388
  "div",
27682
27389
  {
27683
27390
  className: "flex items-center justify-between gap-3 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--accent))] px-3 py-2",
27684
27391
  children: [
27685
- /* @__PURE__ */ jsx18("span", { className: "min-w-0 truncate text-sm text-[hsl(var(--foreground))]", children: file.name }),
27686
- /* @__PURE__ */ jsx18("span", { className: "shrink-0 text-xs text-[hsl(var(--muted-foreground))]", children: formatFileSize(file.size) })
27392
+ /* @__PURE__ */ jsx19("span", { className: "min-w-0 truncate text-sm text-[hsl(var(--foreground))]", children: file.name }),
27393
+ /* @__PURE__ */ jsx19("span", { className: "shrink-0 text-xs text-[hsl(var(--muted-foreground))]", children: formatFileSize(file.size) })
27687
27394
  ]
27688
27395
  },
27689
27396
  `${file.name}:${file.size}`
27690
27397
  )) }) }),
27691
- /* @__PURE__ */ jsx18("div", { className: "flex justify-end border-t border-[hsl(var(--border))] px-4 py-3", children: /* @__PURE__ */ jsx18(
27398
+ /* @__PURE__ */ jsx19("div", { className: "flex justify-end border-t border-[hsl(var(--border))] px-4 py-3", children: /* @__PURE__ */ jsx19(
27692
27399
  "button",
27693
27400
  {
27694
27401
  type: "button",
@@ -27751,41 +27458,6 @@ var FileMention = index_default.extend({
27751
27458
  }
27752
27459
  });
27753
27460
 
27754
- // src/rich-input/extensions/workflow-mention.ts
27755
- var WorkflowMention = Node3.create({
27756
- name: "workflowMention",
27757
- group: "inline",
27758
- inline: true,
27759
- atom: true,
27760
- selectable: false,
27761
- addAttributes() {
27762
- return {
27763
- name: {
27764
- default: "",
27765
- parseHTML: (element) => element.getAttribute("data-workflow") || "",
27766
- renderHTML: (attributes) => ({ "data-workflow": attributes.name })
27767
- }
27768
- };
27769
- },
27770
- parseHTML() {
27771
- return [{ tag: "span[data-workflow]" }];
27772
- },
27773
- renderHTML({ node, HTMLAttributes }) {
27774
- return [
27775
- "span",
27776
- mergeAttributes(HTMLAttributes, {
27777
- // 复用技能胶囊的现成样式(两个输入框的容器 class 都已带它的规则)
27778
- class: "skill-mention-pill",
27779
- "data-workflow": node.attrs.name
27780
- }),
27781
- `\u8FD0\u884C\u5DE5\u4F5C\u6D41 ${node.attrs.name}`
27782
- ];
27783
- },
27784
- renderText({ node }) {
27785
- return `\u8FD0\u884C\u5DE5\u4F5C\u6D41 ${node.attrs.name}`;
27786
- }
27787
- });
27788
-
27789
27461
  // src/rich-input/lib/reasoning-levels.ts
27790
27462
  var REASONING_LEVEL_LABELS = {
27791
27463
  off: "\u5173",
@@ -27801,7 +27473,7 @@ function reasoningLevelLabel(level) {
27801
27473
  }
27802
27474
 
27803
27475
  // src/rich-input/ReasoningModeSelect.tsx
27804
- import { jsx as jsx19, jsxs as jsxs10 } from "react/jsx-runtime";
27476
+ import { jsx as jsx20, jsxs as jsxs11 } from "react/jsx-runtime";
27805
27477
  function ReasoningModeSelect({
27806
27478
  level,
27807
27479
  levels,
@@ -27809,11 +27481,11 @@ function ReasoningModeSelect({
27809
27481
  disabledReason,
27810
27482
  onChange
27811
27483
  }) {
27812
- return /* @__PURE__ */ jsxs10("label", { className: "flex w-full flex-col gap-1 px-3 py-2", children: [
27813
- /* @__PURE__ */ jsxs10("span", { className: "flex w-full items-center gap-2", children: [
27814
- /* @__PURE__ */ jsx19(Brain, { size: 14, className: `shrink-0 ${chatTone("reasoning").text}`, "aria-hidden": "true" }),
27815
- /* @__PURE__ */ jsx19("span", { className: "shrink-0", children: "\u601D\u8003\u6A21\u5F0F" }),
27816
- /* @__PURE__ */ jsx19(
27484
+ return /* @__PURE__ */ jsxs11("label", { className: "flex w-full flex-col gap-1 px-3 py-2", children: [
27485
+ /* @__PURE__ */ jsxs11("span", { className: "flex w-full items-center gap-2", children: [
27486
+ /* @__PURE__ */ jsx20(Brain, { size: 14, className: `shrink-0 ${chatTone("reasoning").text}`, "aria-hidden": "true" }),
27487
+ /* @__PURE__ */ jsx20("span", { className: "shrink-0", children: "\u601D\u8003\u6A21\u5F0F" }),
27488
+ /* @__PURE__ */ jsx20(
27817
27489
  "select",
27818
27490
  {
27819
27491
  value: level,
@@ -27822,18 +27494,18 @@ function ReasoningModeSelect({
27822
27494
  "aria-label": "\u601D\u8003\u6A21\u5F0F",
27823
27495
  title: "\u9009\u62E9\u601D\u8003\u6863\u4F4D\u3002\u6863\u4F4D\u8D8A\u9AD8\uFF0C\u6A21\u578B\u601D\u8003\u8D8A\u6DF1\u5165\uFF0C\u4F46\u54CD\u5E94\u53EF\u80FD\u66F4\u6162",
27824
27496
  className: "ml-auto h-6 min-w-20 rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--background))] px-1.5 disabled:cursor-not-allowed disabled:opacity-50",
27825
- children: levels.map((item) => /* @__PURE__ */ jsx19("option", { value: item, children: reasoningLevelLabel(item) }, item))
27497
+ children: levels.map((item) => /* @__PURE__ */ jsx20("option", { value: item, children: reasoningLevelLabel(item) }, item))
27826
27498
  }
27827
27499
  )
27828
27500
  ] }),
27829
- disabled && disabledReason ? /* @__PURE__ */ jsx19("span", { className: "pl-[22px] text-xs text-[hsl(var(--muted-foreground))]", children: disabledReason }) : null
27501
+ disabled && disabledReason ? /* @__PURE__ */ jsx20("span", { className: "pl-[22px] text-xs text-[hsl(var(--muted-foreground))]", children: disabledReason }) : null
27830
27502
  ] });
27831
27503
  }
27832
27504
 
27833
27505
  // src/rich-input/PlanningToggle.tsx
27834
- import { jsx as jsx20, jsxs as jsxs11 } from "react/jsx-runtime";
27506
+ import { jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
27835
27507
  function PlanningToggle({ enabled, onChange, disabled }) {
27836
- return /* @__PURE__ */ jsxs11(
27508
+ return /* @__PURE__ */ jsxs12(
27837
27509
  "button",
27838
27510
  {
27839
27511
  type: "button",
@@ -27845,18 +27517,18 @@ function PlanningToggle({ enabled, onChange, disabled }) {
27845
27517
  disabled,
27846
27518
  className: "flex w-full items-center justify-between gap-3 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))] disabled:cursor-not-allowed disabled:opacity-50",
27847
27519
  children: [
27848
- /* @__PURE__ */ jsxs11("span", { className: "flex items-center gap-2", children: [
27849
- /* @__PURE__ */ jsx20(Lightbulb, { size: 14, className: "text-[#F97316]", "aria-hidden": "true" }),
27520
+ /* @__PURE__ */ jsxs12("span", { className: "flex items-center gap-2", children: [
27521
+ /* @__PURE__ */ jsx21(Lightbulb, { size: 14, className: "text-[#F97316]", "aria-hidden": "true" }),
27850
27522
  "\u89C4\u5212\u6A21\u5F0F"
27851
27523
  ] }),
27852
- /* @__PURE__ */ jsxs11("span", { className: "flex items-center gap-2", children: [
27853
- /* @__PURE__ */ jsx20("span", { className: "text-[hsl(var(--muted-foreground))]", children: enabled ? "\u5F00" : "\u5173" }),
27854
- /* @__PURE__ */ jsx20(
27524
+ /* @__PURE__ */ jsxs12("span", { className: "flex items-center gap-2", children: [
27525
+ /* @__PURE__ */ jsx21("span", { className: "text-[hsl(var(--muted-foreground))]", children: enabled ? "\u5F00" : "\u5173" }),
27526
+ /* @__PURE__ */ jsx21(
27855
27527
  "span",
27856
27528
  {
27857
27529
  className: `flex h-4 w-7 items-center rounded-full p-0.5 transition-colors ${enabled ? "justify-end bg-[hsl(var(--primary))]" : "justify-start bg-[hsl(var(--muted))]"}`,
27858
27530
  "aria-hidden": "true",
27859
- children: /* @__PURE__ */ jsx20("span", { className: "h-3 w-3 rounded-full bg-[hsl(var(--background))]" })
27531
+ children: /* @__PURE__ */ jsx21("span", { className: "h-3 w-3 rounded-full bg-[hsl(var(--background))]" })
27860
27532
  }
27861
27533
  )
27862
27534
  ] })
@@ -27877,12 +27549,12 @@ function shouldHandleHistoryKey(event, menuOpen) {
27877
27549
  }
27878
27550
 
27879
27551
  // src/rich-input/ComposerAttachmentViewport.tsx
27880
- import { jsx as jsx21 } from "react/jsx-runtime";
27552
+ import { jsx as jsx23 } from "react/jsx-runtime";
27881
27553
  function ComposerAttachmentViewport({
27882
27554
  className,
27883
27555
  ...props
27884
27556
  }) {
27885
- return /* @__PURE__ */ jsx21(
27557
+ return /* @__PURE__ */ jsx23(
27886
27558
  "div",
27887
27559
  {
27888
27560
  className: cn("min-h-0 max-h-40 overflow-y-auto overscroll-contain", className),
@@ -27892,7 +27564,7 @@ function ComposerAttachmentViewport({
27892
27564
  }
27893
27565
 
27894
27566
  // src/rich-input/ChatInput.tsx
27895
- import { Fragment as Fragment5, jsx as jsx23, jsxs as jsxs12 } from "react/jsx-runtime";
27567
+ import { Fragment as Fragment5, jsx as jsx24, jsxs as jsxs13 } from "react/jsx-runtime";
27896
27568
  var RECENT_SESSION_LIMIT = 50;
27897
27569
  var DOUBLE_ESCAPE_MS = 450;
27898
27570
  function getEditorText(editor) {
@@ -28063,31 +27735,31 @@ function ComposerFilePill({
28063
27735
  const isFailed = isFile && attachment.status === "failed";
28064
27736
  const isUploading = isFile && attachment.status === "uploading";
28065
27737
  const uploadPercent = isUploading && typeof attachment.uploadProgress === "number" ? Math.max(0, Math.min(100, Math.round(attachment.uploadProgress * 100))) : null;
28066
- return /* @__PURE__ */ jsxs12(
27738
+ return /* @__PURE__ */ jsxs13(
28067
27739
  "div",
28068
27740
  {
28069
27741
  className: `relative flex shrink-0 items-center gap-1.5 overflow-hidden rounded-full border px-2.5 py-1 text-[11px] ${isFailed ? "border-[hsl(var(--swf-danger)/0.3)] bg-[hsl(var(--swf-danger-soft))] text-[hsl(var(--swf-danger))]" : "border-[hsl(var(--border))] bg-[hsl(var(--card))] text-[hsl(var(--foreground))]"}`,
28070
27742
  children: [
28071
- uploadPercent !== null ? /* @__PURE__ */ jsx23(
27743
+ uploadPercent !== null ? /* @__PURE__ */ jsx24(
28072
27744
  "span",
28073
27745
  {
28074
27746
  className: "absolute inset-y-0 left-0 bg-[hsl(var(--primary))]/10 transition-[width]",
28075
27747
  style: { width: `${uploadPercent}%` }
28076
27748
  }
28077
27749
  ) : null,
28078
- isUploading ? /* @__PURE__ */ jsx23(
27750
+ isUploading ? /* @__PURE__ */ jsx24(
28079
27751
  LoaderCircle,
28080
27752
  {
28081
27753
  size: 12,
28082
27754
  className: "relative z-10 shrink-0 animate-spin text-[hsl(var(--muted-foreground))]"
28083
27755
  }
28084
- ) : /* @__PURE__ */ jsx23(Icon, { size: 12, className: "relative z-10 shrink-0 text-[hsl(var(--muted-foreground))]" }),
28085
- /* @__PURE__ */ jsx23("span", { className: "relative z-10 max-w-32 truncate", children: attachment.name }),
28086
- uploadPercent !== null ? /* @__PURE__ */ jsxs12("span", { className: "relative z-10 font-mono text-[10px] tabular-nums text-[hsl(var(--muted-foreground))]", children: [
27756
+ ) : /* @__PURE__ */ jsx24(Icon, { size: 12, className: "relative z-10 shrink-0 text-[hsl(var(--muted-foreground))]" }),
27757
+ /* @__PURE__ */ jsx24("span", { className: "relative z-10 max-w-32 truncate", children: attachment.name }),
27758
+ uploadPercent !== null ? /* @__PURE__ */ jsxs13("span", { className: "relative z-10 font-mono text-[10px] tabular-nums text-[hsl(var(--muted-foreground))]", children: [
28087
27759
  uploadPercent,
28088
27760
  "%"
28089
27761
  ] }) : null,
28090
- /* @__PURE__ */ jsx23(
27762
+ /* @__PURE__ */ jsx24(
28091
27763
  "button",
28092
27764
  {
28093
27765
  type: "button",
@@ -28095,7 +27767,7 @@ function ComposerFilePill({
28095
27767
  "aria-label": `\u79FB\u9664 ${attachment.name}`,
28096
27768
  title: "\u79FB\u9664",
28097
27769
  className: "relative z-10 ml-0.5 inline-flex shrink-0 items-center justify-center rounded-full text-[hsl(var(--muted-foreground))] transition hover:text-[hsl(var(--swf-danger))]",
28098
- children: /* @__PURE__ */ jsx23(X, { size: 10 })
27770
+ children: /* @__PURE__ */ jsx24(X, { size: 10 })
28099
27771
  }
28100
27772
  )
28101
27773
  ]
@@ -28218,7 +27890,7 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
28218
27890
  setImportingId(null);
28219
27891
  }
28220
27892
  };
28221
- return /* @__PURE__ */ jsx23(
27893
+ return /* @__PURE__ */ jsx24(
28222
27894
  "div",
28223
27895
  {
28224
27896
  className: "fixed inset-0 z-[60] flex items-center justify-center bg-black/55 p-4",
@@ -28226,44 +27898,44 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
28226
27898
  onKeyDown: (e) => {
28227
27899
  if (e.key === "Escape") onClose();
28228
27900
  },
28229
- children: /* @__PURE__ */ jsxs12(
27901
+ children: /* @__PURE__ */ jsxs13(
28230
27902
  "div",
28231
27903
  {
28232
27904
  className: "w-full max-w-lg flex flex-col rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] shadow-[var(--swf-shadow-overlay)]",
28233
27905
  onClick: (e) => e.stopPropagation(),
28234
27906
  onKeyDown: (e) => e.stopPropagation(),
28235
27907
  children: [
28236
- /* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-5 py-3", children: [
28237
- /* @__PURE__ */ jsx23("h4", { className: "text-sm font-semibold text-[hsl(var(--foreground))]", children: "\u6DFB\u52A0\u4E0A\u4E0B\u6587" }),
28238
- /* @__PURE__ */ jsx23(
27908
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-5 py-3", children: [
27909
+ /* @__PURE__ */ jsx24("h4", { className: "text-sm font-semibold text-[hsl(var(--foreground))]", children: "\u6DFB\u52A0\u4E0A\u4E0B\u6587" }),
27910
+ /* @__PURE__ */ jsx24(
28239
27911
  "button",
28240
27912
  {
28241
27913
  type: "button",
28242
27914
  onClick: onClose,
28243
27915
  className: "rounded-md p-1 text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
28244
- children: /* @__PURE__ */ jsx23(X, { size: 14 })
27916
+ children: /* @__PURE__ */ jsx24(X, { size: 14 })
28245
27917
  }
28246
27918
  )
28247
27919
  ] }),
28248
- /* @__PURE__ */ jsxs12("div", { className: "px-5 py-4 space-y-3", children: [
28249
- /* @__PURE__ */ jsxs12("div", { className: "relative", children: [
28250
- /* @__PURE__ */ jsxs12(
27920
+ /* @__PURE__ */ jsxs13("div", { className: "px-5 py-4 space-y-3", children: [
27921
+ /* @__PURE__ */ jsxs13("div", { className: "relative", children: [
27922
+ /* @__PURE__ */ jsxs13(
28251
27923
  "button",
28252
27924
  {
28253
27925
  type: "button",
28254
27926
  onClick: handleLoadSessions,
28255
27927
  className: "inline-flex items-center gap-1.5 rounded-md border border-[hsl(var(--border))] px-2.5 py-1.5 text-xs text-[hsl(var(--foreground))] transition-colors hover:bg-[hsl(var(--accent))]",
28256
27928
  children: [
28257
- /* @__PURE__ */ jsx23(Import, { size: 12 }),
27929
+ /* @__PURE__ */ jsx24(Import, { size: 12 }),
28258
27930
  "\u4ECE\u5176\u4ED6\u4F1A\u8BDD\u5BFC\u5165",
28259
- /* @__PURE__ */ jsx23(ChevronDown, { size: 10, className: `transition-transform ${showSessionPicker ? "rotate-180" : ""}` })
27931
+ /* @__PURE__ */ jsx24(ChevronDown, { size: 10, className: `transition-transform ${showSessionPicker ? "rotate-180" : ""}` })
28260
27932
  ]
28261
27933
  }
28262
27934
  ),
28263
- showSessionPicker && /* @__PURE__ */ jsx23("div", { className: "absolute left-0 top-full z-10 mt-1 max-h-48 w-full overflow-y-auto rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--card))] shadow-[var(--swf-shadow-overlay)]", children: loadingSessions ? /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2 px-3 py-2.5 text-xs text-[hsl(var(--muted-foreground))]", children: [
28264
- /* @__PURE__ */ jsx23(LoaderCircle, { size: 12, className: "animate-spin" }),
27935
+ showSessionPicker && /* @__PURE__ */ jsx24("div", { className: "absolute left-0 top-full z-10 mt-1 max-h-48 w-full overflow-y-auto rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--card))] shadow-[var(--swf-shadow-overlay)]", children: loadingSessions ? /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 px-3 py-2.5 text-xs text-[hsl(var(--muted-foreground))]", children: [
27936
+ /* @__PURE__ */ jsx24(LoaderCircle, { size: 12, className: "animate-spin" }),
28265
27937
  "\u52A0\u8F7D\u4F1A\u8BDD\u5217\u8868\u2026"
28266
- ] }) : sessions.length === 0 ? /* @__PURE__ */ jsx23("div", { className: "px-3 py-2.5 text-xs text-[hsl(var(--muted-foreground))]", children: "\u6682\u65E0\u5176\u4ED6\u4F1A\u8BDD" }) : sessions.map((s) => /* @__PURE__ */ jsxs12(
27938
+ ] }) : sessions.length === 0 ? /* @__PURE__ */ jsx24("div", { className: "px-3 py-2.5 text-xs text-[hsl(var(--muted-foreground))]", children: "\u6682\u65E0\u5176\u4ED6\u4F1A\u8BDD" }) : sessions.map((s) => /* @__PURE__ */ jsxs13(
28267
27939
  "button",
28268
27940
  {
28269
27941
  type: "button",
@@ -28271,16 +27943,16 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
28271
27943
  onClick: () => handleImportSession(s.id),
28272
27944
  className: "flex w-full items-center gap-2 px-3 py-2 text-left text-xs text-[hsl(var(--foreground))] transition-colors hover:bg-[hsl(var(--accent))] disabled:opacity-50",
28273
27945
  children: [
28274
- importingId === s.id && /* @__PURE__ */ jsx23(LoaderCircle, { size: 10, className: "shrink-0 animate-spin" }),
28275
- /* @__PURE__ */ jsx23("span", { className: "truncate", children: s.intent })
27946
+ importingId === s.id && /* @__PURE__ */ jsx24(LoaderCircle, { size: 10, className: "shrink-0 animate-spin" }),
27947
+ /* @__PURE__ */ jsx24("span", { className: "truncate", children: s.intent })
28276
27948
  ]
28277
27949
  },
28278
27950
  s.id
28279
27951
  )) })
28280
27952
  ] }),
28281
- /* @__PURE__ */ jsxs12("div", { children: [
28282
- /* @__PURE__ */ jsx23("label", { htmlFor: "ctx-label", className: "block text-xs font-medium text-[hsl(var(--foreground))] mb-1", children: "\u6807\u7B7E" }),
28283
- /* @__PURE__ */ jsx23(
27953
+ /* @__PURE__ */ jsxs13("div", { children: [
27954
+ /* @__PURE__ */ jsx24("label", { htmlFor: "ctx-label", className: "block text-xs font-medium text-[hsl(var(--foreground))] mb-1", children: "\u6807\u7B7E" }),
27955
+ /* @__PURE__ */ jsx24(
28284
27956
  "input",
28285
27957
  {
28286
27958
  id: "ctx-label",
@@ -28291,13 +27963,13 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
28291
27963
  }
28292
27964
  )
28293
27965
  ] }),
28294
- /* @__PURE__ */ jsxs12("div", { children: [
28295
- /* @__PURE__ */ jsx23("label", { htmlFor: "ctx-content", className: "block text-xs font-medium text-[hsl(var(--foreground))] mb-1", children: "\u5185\u5BB9" }),
28296
- isImportProcessing && /* @__PURE__ */ jsxs12("div", { className: "mb-1.5 flex items-center gap-1.5 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
28297
- /* @__PURE__ */ jsx23(LoaderCircle, { size: 12, className: "animate-spin" }),
27966
+ /* @__PURE__ */ jsxs13("div", { children: [
27967
+ /* @__PURE__ */ jsx24("label", { htmlFor: "ctx-content", className: "block text-xs font-medium text-[hsl(var(--foreground))] mb-1", children: "\u5185\u5BB9" }),
27968
+ isImportProcessing && /* @__PURE__ */ jsxs13("div", { className: "mb-1.5 flex items-center gap-1.5 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
27969
+ /* @__PURE__ */ jsx24(LoaderCircle, { size: 12, className: "animate-spin" }),
28298
27970
  "\u6B63\u5728\u5904\u7406\u5BFC\u5165\u5185\u5BB9\u5E76\u5199\u5165 workspace/context\uFF0C\u5B8C\u6210\u540E\u53EF\u70B9\u51FB\u201C\u786E\u5B9A\u201D"
28299
27971
  ] }),
28300
- /* @__PURE__ */ jsx23(
27972
+ /* @__PURE__ */ jsx24(
28301
27973
  "textarea",
28302
27974
  {
28303
27975
  id: "ctx-content",
@@ -28310,8 +27982,8 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
28310
27982
  )
28311
27983
  ] })
28312
27984
  ] }),
28313
- /* @__PURE__ */ jsxs12("div", { className: "flex justify-end gap-2 border-t border-[hsl(var(--border))] px-5 py-3", children: [
28314
- /* @__PURE__ */ jsx23(
27985
+ /* @__PURE__ */ jsxs13("div", { className: "flex justify-end gap-2 border-t border-[hsl(var(--border))] px-5 py-3", children: [
27986
+ /* @__PURE__ */ jsx24(
28315
27987
  "button",
28316
27988
  {
28317
27989
  type: "button",
@@ -28320,7 +27992,7 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
28320
27992
  children: "\u53D6\u6D88"
28321
27993
  }
28322
27994
  ),
28323
- /* @__PURE__ */ jsx23(
27995
+ /* @__PURE__ */ jsx24(
28324
27996
  "button",
28325
27997
  {
28326
27998
  type: "button",
@@ -28351,19 +28023,19 @@ function ComposerContextPill({
28351
28023
  }) {
28352
28024
  const [showDetail, setShowDetail] = useState11(false);
28353
28025
  const tokenK = formatTokenK(content);
28354
- return /* @__PURE__ */ jsxs12(Fragment5, { children: [
28355
- /* @__PURE__ */ jsxs12("div", { className: "flex shrink-0 items-center gap-1.5 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--accent))] px-2.5 py-1 text-[11px] text-[hsl(var(--foreground))]", children: [
28356
- imageUrl ? /* @__PURE__ */ jsx23(
28026
+ return /* @__PURE__ */ jsxs13(Fragment5, { children: [
28027
+ /* @__PURE__ */ jsxs13("div", { className: "flex shrink-0 items-center gap-1.5 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--accent))] px-2.5 py-1 text-[11px] text-[hsl(var(--foreground))]", children: [
28028
+ imageUrl ? /* @__PURE__ */ jsx24(
28357
28029
  "button",
28358
28030
  {
28359
28031
  type: "button",
28360
28032
  onClick: () => setShowDetail(true),
28361
28033
  className: "h-6 w-6 overflow-hidden rounded-md border border-[hsl(var(--border))] bg-white",
28362
28034
  title: "\u67E5\u770B\u9009\u4E2D\u533A\u57DF\u622A\u56FE",
28363
- children: /* @__PURE__ */ jsx23("img", { src: imageUrl, alt: "\u9009\u4E2D\u533A\u57DF\u622A\u56FE", className: "h-full w-full object-cover" })
28035
+ children: /* @__PURE__ */ jsx24("img", { src: imageUrl, alt: "\u9009\u4E2D\u533A\u57DF\u622A\u56FE", className: "h-full w-full object-cover" })
28364
28036
  }
28365
28037
  ) : null,
28366
- /* @__PURE__ */ jsx23(
28038
+ /* @__PURE__ */ jsx24(
28367
28039
  "button",
28368
28040
  {
28369
28041
  type: "button",
@@ -28373,7 +28045,7 @@ function ComposerContextPill({
28373
28045
  children: label
28374
28046
  }
28375
28047
  ),
28376
- /* @__PURE__ */ jsx23(
28048
+ /* @__PURE__ */ jsx24(
28377
28049
  "span",
28378
28050
  {
28379
28051
  className: "shrink-0 rounded bg-[hsl(var(--background))] px-1.5 py-0.5 text-[10px] text-[hsl(var(--muted-foreground))]",
@@ -28381,7 +28053,7 @@ function ComposerContextPill({
28381
28053
  children: tokenK
28382
28054
  }
28383
28055
  ),
28384
- /* @__PURE__ */ jsx23(
28056
+ /* @__PURE__ */ jsx24(
28385
28057
  "button",
28386
28058
  {
28387
28059
  type: "button",
@@ -28389,11 +28061,11 @@ function ComposerContextPill({
28389
28061
  "aria-label": `\u79FB\u9664\u4E0A\u4E0B\u6587 ${label}`,
28390
28062
  title: "\u79FB\u9664",
28391
28063
  className: "ml-0.5 inline-flex shrink-0 items-center justify-center rounded-full text-[hsl(var(--muted-foreground))] transition hover:text-[hsl(var(--swf-danger))]",
28392
- children: /* @__PURE__ */ jsx23(X, { size: 10 })
28064
+ children: /* @__PURE__ */ jsx24(X, { size: 10 })
28393
28065
  }
28394
28066
  )
28395
28067
  ] }),
28396
- showDetail && /* @__PURE__ */ jsx23(
28068
+ showDetail && /* @__PURE__ */ jsx24(
28397
28069
  "div",
28398
28070
  {
28399
28071
  className: "fixed inset-0 z-[60] flex items-center justify-center bg-black/55 p-6",
@@ -28401,31 +28073,31 @@ function ComposerContextPill({
28401
28073
  onKeyDown: (e) => {
28402
28074
  if (e.key === "Escape") setShowDetail(false);
28403
28075
  },
28404
- children: /* @__PURE__ */ jsxs12(
28076
+ children: /* @__PURE__ */ jsxs13(
28405
28077
  "div",
28406
28078
  {
28407
28079
  className: "w-full max-w-4xl max-h-[85vh] flex flex-col rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] shadow-[var(--swf-shadow-overlay)]",
28408
28080
  onClick: (e) => e.stopPropagation(),
28409
28081
  onKeyDown: (e) => e.stopPropagation(),
28410
28082
  children: [
28411
- /* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-6 py-3", children: [
28412
- /* @__PURE__ */ jsxs12("div", { className: "min-w-0", children: [
28413
- /* @__PURE__ */ jsx23("h4", { className: "truncate text-xs font-semibold text-[hsl(var(--foreground))]", children: label }),
28414
- imageUrl ? /* @__PURE__ */ jsx23("p", { className: "mt-0.5 text-[11px] text-[hsl(var(--muted-foreground))]", children: "\u5DF2\u9644\u52A0\u9009\u4E2D\u533A\u57DF\u622A\u56FE\uFF0C\u975E\u591A\u6A21\u6001\u6A21\u578B\u4F1A\u81EA\u52A8\u5FFD\u7565\u56FE\u7247\u3002" }) : null
28083
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-6 py-3", children: [
28084
+ /* @__PURE__ */ jsxs13("div", { className: "min-w-0", children: [
28085
+ /* @__PURE__ */ jsx24("h4", { className: "truncate text-xs font-semibold text-[hsl(var(--foreground))]", children: label }),
28086
+ imageUrl ? /* @__PURE__ */ jsx24("p", { className: "mt-0.5 text-[11px] text-[hsl(var(--muted-foreground))]", children: "\u5DF2\u9644\u52A0\u9009\u4E2D\u533A\u57DF\u622A\u56FE\uFF0C\u975E\u591A\u6A21\u6001\u6A21\u578B\u4F1A\u81EA\u52A8\u5FFD\u7565\u56FE\u7247\u3002" }) : null
28415
28087
  ] }),
28416
- /* @__PURE__ */ jsx23(
28088
+ /* @__PURE__ */ jsx24(
28417
28089
  "button",
28418
28090
  {
28419
28091
  type: "button",
28420
28092
  onClick: () => setShowDetail(false),
28421
28093
  className: "rounded-md p-1 text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
28422
- children: /* @__PURE__ */ jsx23(X, { size: 14 })
28094
+ children: /* @__PURE__ */ jsx24(X, { size: 14 })
28423
28095
  }
28424
28096
  )
28425
28097
  ] }),
28426
- /* @__PURE__ */ jsxs12("div", { className: "min-h-0 flex-1 overflow-y-auto px-6 py-4", children: [
28427
- imageUrl ? /* @__PURE__ */ jsx23("div", { className: "mb-4 rounded-xl border border-[hsl(var(--border))] bg-white p-2", children: /* @__PURE__ */ jsx23("img", { src: imageUrl, alt: "\u9009\u4E2D\u533A\u57DF\u622A\u56FE", className: "max-h-72 max-w-full rounded-lg object-contain" }) }) : null,
28428
- /* @__PURE__ */ jsx23("pre", { className: "whitespace-pre-wrap break-words font-mono text-[11px] leading-[1.6] text-[hsl(var(--foreground)/0.85)]", children: content })
28098
+ /* @__PURE__ */ jsxs13("div", { className: "min-h-0 flex-1 overflow-y-auto px-6 py-4", children: [
28099
+ imageUrl ? /* @__PURE__ */ jsx24("div", { className: "mb-4 rounded-xl border border-[hsl(var(--border))] bg-white p-2", children: /* @__PURE__ */ jsx24("img", { src: imageUrl, alt: "\u9009\u4E2D\u533A\u57DF\u622A\u56FE", className: "max-h-72 max-w-full rounded-lg object-contain" }) }) : null,
28100
+ /* @__PURE__ */ jsx24("pre", { className: "whitespace-pre-wrap break-words font-mono text-[11px] leading-[1.6] text-[hsl(var(--foreground)/0.85)]", children: content })
28429
28101
  ] })
28430
28102
  ]
28431
28103
  }
@@ -28498,6 +28170,7 @@ function ChatInput({
28498
28170
  lite = false,
28499
28171
  canCreateBoardTask = false
28500
28172
  }) {
28173
+ const developer = useChatRenderMode() === "developer";
28501
28174
  const isBusy = isStreaming || isCompacting;
28502
28175
  const resolvedInputLabel = inputLabel?.trim() || "\u8F93\u5165\u6D88\u606F";
28503
28176
  const initialInput = externalDraft?.value ?? initialDraft ?? "";
@@ -28507,10 +28180,11 @@ function ChatInput({
28507
28180
  externalDraft?.setValue(value);
28508
28181
  });
28509
28182
  const externalDraftValue = externalDraft?.value;
28510
- const inputRef = useRef9(input);
28183
+ const inputRef = useRef7(input);
28511
28184
  inputRef.current = input;
28512
- const appliedInitialDraftKeyRef = useRef9(null);
28513
- useEffect9(() => {
28185
+ const appliedInitialDraftKeyRef = useRef7(null);
28186
+ const appliedInitialDraftRef = useRef7(null);
28187
+ useEffect8(() => {
28514
28188
  if (externalDraftValue == null) return;
28515
28189
  if (inputRef.current === externalDraftValue) return;
28516
28190
  if (editorRef.current) {
@@ -28518,16 +28192,18 @@ function ChatInput({
28518
28192
  }
28519
28193
  setInputInternal(externalDraftValue);
28520
28194
  }, [externalDraftValue]);
28521
- useEffect9(() => {
28195
+ useEffect8(() => {
28522
28196
  const key = initialDraftKey ?? initialDraft ?? "";
28523
28197
  if (!initialDraft || !key || appliedInitialDraftKeyRef.current === key) return;
28524
- if (inputRef.current.trim()) {
28198
+ if (inputRef.current === initialDraft) appliedInitialDraftRef.current = initialDraft;
28199
+ if (inputRef.current.trim() && inputRef.current !== appliedInitialDraftRef.current) {
28525
28200
  appliedInitialDraftKeyRef.current = key;
28526
28201
  return;
28527
28202
  }
28528
28203
  replaceEditorText(editorRef.current, initialDraft);
28529
28204
  setInput(initialDraft);
28530
28205
  appliedInitialDraftKeyRef.current = key;
28206
+ appliedInitialDraftRef.current = initialDraft;
28531
28207
  }, [initialDraft, initialDraftKey, setInput]);
28532
28208
  const [composerAttachments, setComposerAttachmentsInternal] = useState11(
28533
28209
  externalAttachments?.value ?? []
@@ -28542,9 +28218,9 @@ function ChatInput({
28542
28218
  }
28543
28219
  );
28544
28220
  const externalAttachmentsValue = externalAttachments?.value;
28545
- const composerAttachmentsRef = useRef9(composerAttachments);
28221
+ const composerAttachmentsRef = useRef7(composerAttachments);
28546
28222
  composerAttachmentsRef.current = composerAttachments;
28547
- useEffect9(() => {
28223
+ useEffect8(() => {
28548
28224
  if (externalAttachmentsValue == null) return;
28549
28225
  if (composerAttachmentsRef.current === externalAttachmentsValue) return;
28550
28226
  setComposerAttachmentsInternal(externalAttachmentsValue);
@@ -28558,16 +28234,16 @@ function ChatInput({
28558
28234
  const invalidation = useSessionDataInvalidation();
28559
28235
  const SkillStatusBarComponent = SkillStatusBarOverride ?? SkillStatusBar;
28560
28236
  const [actionMenuOpen, setActionMenuOpen] = useState11(false);
28561
- const actionMenuOpenRef = useRef9(false);
28562
- useEffect9(() => {
28237
+ const actionMenuOpenRef = useRef7(false);
28238
+ useEffect8(() => {
28563
28239
  actionMenuOpenRef.current = actionMenuOpen;
28564
28240
  }, [actionMenuOpen]);
28565
28241
  const [connectMenuOpen, setConnectMenuOpen] = useState11(false);
28566
- const fileInputRef = useRef9(null);
28567
- const folderInputRef = useRef9(null);
28568
- const editorRef = useRef9(null);
28569
- const lastEscapeAtRef = useRef9(0);
28570
- const localImageUrlsRef = useRef9(/* @__PURE__ */ new Map());
28242
+ const fileInputRef = useRef7(null);
28243
+ const folderInputRef = useRef7(null);
28244
+ const editorRef = useRef7(null);
28245
+ const lastEscapeAtRef = useRef7(0);
28246
+ const localImageUrlsRef = useRef7(/* @__PURE__ */ new Map());
28571
28247
  const currentChatSessionId = useCurrentChatSessionId();
28572
28248
  const activeSessionId = sessionIdProp ?? currentChatSessionId;
28573
28249
  const currentSession = useChatSessionDetail(activeSessionId);
@@ -28600,9 +28276,9 @@ function ChatInput({
28600
28276
  if (!activeSessionId) return [];
28601
28277
  try {
28602
28278
  const detail = await client.sessions.getSession(activeSessionId);
28603
- return detail.runtime_type === "sandbox" ? getTopicAssetSuggestionItems(client, detail.chat_group_id, query) : [];
28279
+ return getTopicAssetSuggestionItems(client, detail.chat_group_id, query);
28604
28280
  } catch {
28605
- return [{ kind: "topicAssetError", message: "\u4E3B\u9898\u8D44\u4EA7\u6682\u65F6\u65E0\u6CD5\u52A0\u8F7D\uFF0C\u8BF7\u91CD\u65B0\u8F93\u5165 @ \u91CD\u8BD5" }];
28281
+ return [{ kind: "topicAssetError", message: "\u5DE5\u4F5C\u7A7A\u95F4\u8D44\u4EA7\u6682\u65F6\u65E0\u6CD5\u52A0\u8F7D\uFF0C\u8BF7\u91CD\u65B0\u8F93\u5165 @ \u91CD\u8BD5" }];
28606
28282
  }
28607
28283
  });
28608
28284
  const getSessionId = useEffectEvent(() => activeSessionId);
@@ -28655,7 +28331,7 @@ function ChatInput({
28655
28331
  }
28656
28332
  };
28657
28333
  const stableAppendFiles = useEffectEvent((files) => appendFiles(files));
28658
- const stableHandleSubmit = useEffectEvent(() => handleSubmit());
28334
+ const stableHandleSubmit = useEffectEvent((queueWhenRunning = false) => handleSubmit(queueWhenRunning));
28659
28335
  const getEditorState = useEffectEvent(() => ({
28660
28336
  input,
28661
28337
  connectionStatus,
@@ -28686,7 +28362,6 @@ function ChatInput({
28686
28362
  gapcursor: false,
28687
28363
  heading: false,
28688
28364
  horizontalRule: false,
28689
- // 输入框是纯文本输入区,关掉自动识别链接,避免点击输入的网址直接跳转
28690
28365
  link: false,
28691
28366
  orderedList: false
28692
28367
  }),
@@ -28720,7 +28395,7 @@ function ChatInput({
28720
28395
  if (!container || !root) return;
28721
28396
  updateSuggestionPosition(container, props.clientRect);
28722
28397
  root.render(
28723
- /* @__PURE__ */ jsx23(
28398
+ /* @__PURE__ */ jsx24(
28724
28399
  FileCompletionMenu,
28725
28400
  {
28726
28401
  ref: (instance) => {
@@ -28774,7 +28449,6 @@ function ChatInput({
28774
28449
  }
28775
28450
  }
28776
28451
  }),
28777
- WorkflowMention,
28778
28452
  PluginMention,
28779
28453
  TopicAssetMention,
28780
28454
  SkillMention.configure({
@@ -28789,13 +28463,6 @@ function ChatInput({
28789
28463
  void handleSlashCommand(item.id);
28790
28464
  return;
28791
28465
  }
28792
- if (item.type === "workflow") {
28793
- suggestionEditor.chain().focus().insertContentAt(range, [
28794
- { type: "workflowMention", attrs: { name: item.name } },
28795
- { type: "text", text: workflowParamsTail(item) }
28796
- ]).run();
28797
- return;
28798
- }
28799
28466
  suggestionEditor.chain().focus().insertContentAt(range, [
28800
28467
  {
28801
28468
  type: "skillMention",
@@ -28821,7 +28488,7 @@ function ChatInput({
28821
28488
  if (!container || !root) return;
28822
28489
  updateSuggestionPosition(container, props.clientRect);
28823
28490
  root.render(
28824
- /* @__PURE__ */ jsx23(
28491
+ /* @__PURE__ */ jsx24(
28825
28492
  SkillCompletionMenu,
28826
28493
  {
28827
28494
  ref: (instance) => {
@@ -28939,7 +28606,7 @@ function ChatInput({
28939
28606
  if (state3.connectionStatus !== "connected") {
28940
28607
  return true;
28941
28608
  }
28942
- void state3.handleSubmit();
28609
+ void state3.handleSubmit(isQueueShortcut(event));
28943
28610
  return true;
28944
28611
  }
28945
28612
  return false;
@@ -28956,13 +28623,13 @@ function ChatInput({
28956
28623
  }
28957
28624
  });
28958
28625
  useDismissSkillSuggestionsOnModeChange(editor);
28959
- useEffect9(() => {
28626
+ useEffect8(() => {
28960
28627
  const dom = editor?.view.dom;
28961
28628
  if (!dom) return;
28962
28629
  dom.setAttribute("aria-label", resolvedInputLabel);
28963
28630
  dom.setAttribute("data-blade-input-label", resolvedInputLabel);
28964
28631
  }, [editor, resolvedInputLabel]);
28965
- useEffect9(() => {
28632
+ useEffect8(() => {
28966
28633
  if (!editor || !activeSessionId || rewindDraft == null) {
28967
28634
  return;
28968
28635
  }
@@ -28973,9 +28640,9 @@ function ChatInput({
28973
28640
  editor.commands.focus("end");
28974
28641
  composerChannels.setRewindDraft(activeSessionId, null);
28975
28642
  }, [activeSessionId, editor, rewindDraft]);
28976
- const submittingRef = useRef9(false);
28643
+ const submittingRef = useRef7(false);
28977
28644
  const [isSubmitting, setIsSubmitting] = useState11(false);
28978
- useEffect9(() => {
28645
+ useEffect8(() => {
28979
28646
  let changed = false;
28980
28647
  const nextLocalIds = /* @__PURE__ */ new Set();
28981
28648
  for (const attachment of composerAttachments) {
@@ -29000,7 +28667,7 @@ function ChatInput({
29000
28667
  setLocalImageUrls(Object.fromEntries(localImageUrlsRef.current));
29001
28668
  }
29002
28669
  }, [composerAttachments]);
29003
- useEffect9(() => {
28670
+ useEffect8(() => {
29004
28671
  return () => {
29005
28672
  for (const url of localImageUrlsRef.current.values()) {
29006
28673
  URL.revokeObjectURL(url);
@@ -29009,8 +28676,8 @@ function ChatInput({
29009
28676
  };
29010
28677
  }, []);
29011
28678
  const sessionHandle = useSessionHandle(activeSessionId);
29012
- const restoredPluginSelection = useRef9(null);
29013
- useEffect9(() => {
28679
+ const restoredPluginSelection = useRef7(null);
28680
+ useEffect8(() => {
29014
28681
  if (!sessionHandle || !activeSessionId || !editor) return;
29015
28682
  const restore = () => {
29016
28683
  if (restoredPluginSelection.current === activeSessionId) return;
@@ -29019,13 +28686,13 @@ function ChatInput({
29019
28686
  if (!latest || latest.turn_id.startsWith("local-user-")) return;
29020
28687
  restoredPluginSelection.current = activeSessionId;
29021
28688
  if (!getEditorText(editor).trim() && latest.refs?.length) {
29022
- editor.commands.setContent({ type: "doc", content: [{ type: "paragraph", content: latest.refs.flatMap((ref) => [{ type: "pluginMention", attrs: { ...ref } }, { type: "text", text: " " }]) }] });
28689
+ editor.commands.setContent(buildPluginSelectionDocument(latest.refs));
29023
28690
  }
29024
28691
  };
29025
28692
  restore();
29026
28693
  return sessionHandle.subscribe(restore);
29027
28694
  }, [sessionHandle, activeSessionId, editor]);
29028
- useEffect9(() => {
28695
+ useEffect8(() => {
29029
28696
  if (!sessionHandle || !activeSessionId) return;
29030
28697
  const offInsert = sessionHandle.on("insertTextRequested", ({ text }) => {
29031
28698
  const separate = /^\n/.test(text);
@@ -29060,7 +28727,7 @@ ${append2.text}` : append2.text;
29060
28727
  editor.chain().focus("end").insertContent(text).run();
29061
28728
  });
29062
28729
  const editorReady = editor != null;
29063
- useEffect9(() => {
28730
+ useEffect8(() => {
29064
28731
  if (!editorReady || !draftAppends?.length) {
29065
28732
  return;
29066
28733
  }
@@ -29076,7 +28743,7 @@ ${append2.text}` : append2.text;
29076
28743
  }
29077
28744
  void stableHandleSubmit();
29078
28745
  });
29079
- useEffect9(() => {
28746
+ useEffect8(() => {
29080
28747
  if (!sendRequests?.length) {
29081
28748
  return;
29082
28749
  }
@@ -29091,10 +28758,10 @@ ${append2.text}` : append2.text;
29091
28758
  });
29092
28759
  const { isRecording, level: voiceLevel } = voice;
29093
28760
  const isVoiceStarting = voice.status === "starting";
29094
- const voiceStopRef = useRef9(voice.stop);
28761
+ const voiceStopRef = useRef7(voice.stop);
29095
28762
  voiceStopRef.current = voice.stop;
29096
- const prevSessionIdRef = useRef9(activeSessionId);
29097
- useEffect9(() => {
28763
+ const prevSessionIdRef = useRef7(activeSessionId);
28764
+ useEffect8(() => {
29098
28765
  if (prevSessionIdRef.current !== activeSessionId) {
29099
28766
  prevSessionIdRef.current = activeSessionId;
29100
28767
  if (isRecording) {
@@ -29102,12 +28769,16 @@ ${append2.text}` : append2.text;
29102
28769
  }
29103
28770
  }
29104
28771
  }, [activeSessionId, isRecording]);
29105
- const handleSubmit = async () => {
28772
+ const hasRunningSendBlockers = () => {
28773
+ const json = editor?.getJSON();
28774
+ return composerAttachments.length > 0 || collectMessageMentions(json).length > 0 || collectTopicAssetMentions(json).length > 0;
28775
+ };
28776
+ const handleSubmit = async (queueWhenRunning = false) => {
29106
28777
  if (connectionStatus !== "connected") {
29107
28778
  return;
29108
28779
  }
29109
28780
  if (isCompacting) {
29110
- notifyChat(environment, "info", "\u5BF9\u8BDD\u6B63\u5728\u6574\u7406\u4E2D\uFF0C\u8BF7\u7A0D\u540E\u518D\u53D1\u9001");
28781
+ notifyChat(environment, "info", developer ? "\u5BF9\u8BDD\u6B63\u5728\u6574\u7406\u4E2D\uFF0C\u8BF7\u7A0D\u540E\u518D\u53D1\u9001" : "\u6B63\u5728\u5904\u7406\uFF0C\u8BF7\u7A0D\u540E\u518D\u53D1\u9001");
29111
28782
  return;
29112
28783
  }
29113
28784
  if (isStopping) {
@@ -29117,12 +28788,9 @@ ${append2.text}` : append2.text;
29117
28788
  notifyChat(environment, "info", "\u5F53\u524D\u56DE\u590D\u5C1A\u672A\u7ED3\u675F\uFF0C\u8BF7\u7B49\u5F85\u672C\u8F6E\u7ED3\u675F\u540E\u518D\u53D1\u9001");
29118
28789
  return;
29119
28790
  }
29120
- if (isStreaming) {
29121
- const json = editor?.getJSON();
29122
- if (composerAttachments.length > 0 || collectPluginMentions(json).length > 0 || collectTopicAssetMentions(json).length > 0) {
29123
- notifyChat(environment, "info", "\u5F53\u524D\u56DE\u590D\u5C1A\u672A\u7ED3\u675F\uFF0C\u5E26\u9644\u4EF6\u6216\u5F15\u7528\u7684\u6D88\u606F\u8BF7\u7B49\u5F85\u672C\u8F6E\u7ED3\u675F\u540E\u518D\u53D1\u9001");
29124
- return;
29125
- }
28791
+ if (isStreaming && hasRunningSendBlockers()) {
28792
+ notifyChat(environment, "info", "\u5F53\u524D\u56DE\u590D\u5C1A\u672A\u7ED3\u675F\uFF0C\u5E26\u9644\u4EF6\u6216\u5F15\u7528\u7684\u6D88\u606F\u8BF7\u7B49\u5F85\u672C\u8F6E\u7ED3\u675F\u540E\u518D\u53D1\u9001");
28793
+ return;
29126
28794
  }
29127
28795
  if (!isStreaming) {
29128
28796
  const modelGate = gateSendWhileModelLoading(isModelLoading, hasComposerContent);
@@ -29151,21 +28819,17 @@ ${append2.text}` : append2.text;
29151
28819
  const rawText = serializeEditorContent(json);
29152
28820
  let submittedSessionId = activeSessionId;
29153
28821
  const submittedAttachmentIds = composerAttachments.map((attachment) => attachment.id);
29154
- const skill = findLeadingSkillMention(json);
29155
- const refs = collectPluginMentions(json);
28822
+ const refs = collectMessageMentions(json);
29156
28823
  if (refs.length > 20) {
29157
- notifyChat(environment, "error", "\u6BCF\u6761\u6D88\u606F\u6700\u591A\u9009\u62E9 20 \u4E2A\u63D2\u4EF6\u6761\u76EE");
28824
+ notifyChat(environment, "error", "\u6BCF\u6761\u6D88\u606F\u6700\u591A\u9009\u62E9 20 \u4E2A\u5F15\u7528");
29158
28825
  return;
29159
28826
  }
29160
28827
  const topicAssetRefs = collectTopicAssetMentions(json);
29161
28828
  if (topicAssetRefs.length > 20) {
29162
- notifyChat(environment, "error", "\u6BCF\u6761\u6D88\u606F\u6700\u591A\u5F15\u7528 20 \u4E2A\u4E3B\u9898\u8D44\u4EA7");
28829
+ notifyChat(environment, "error", "\u6BCF\u6761\u6D88\u606F\u6700\u591A\u5F15\u7528 20 \u4E2A\u5DE5\u4F5C\u7A7A\u95F4\u8D44\u4EA7");
29163
28830
  return;
29164
28831
  }
29165
- const text = skill ? transformSlashCommand(skill.skillId, rawText, {
29166
- local: skill.local,
29167
- installed: skill.installed
29168
- }) : rawText;
28832
+ const text = rawText;
29169
28833
  const pendingFiles = composerAttachments.filter(
29170
28834
  (a) => a.kind === "file" && a.status === "pending" && !!a.file
29171
28835
  );
@@ -29297,10 +28961,10 @@ ${append2.text}` : append2.text;
29297
28961
  try {
29298
28962
  accepted = await onSend(nextPayload, {
29299
28963
  targetSessionId: uploadTargetSessionId,
28964
+ queueWhenRunning,
29300
28965
  model: submitModels.sendModel,
29301
28966
  thinkingOverride: thinkingAvailable && selectedReasoningLevel ? true : void 0,
29302
28967
  reasoningLevel: thinkingAvailable ? selectedReasoningLevel || void 0 : void 0,
29303
- // 只有用户显式 @ 知识库才传选择;纯文本不附加知识库指令。
29304
28968
  refs: pluginRefsForSend(refs, sessionHandle?.getState().turns),
29305
28969
  topicAssetRefs: topicAssetRefs.length > 0 ? topicAssetRefs : void 0
29306
28970
  });
@@ -29318,7 +28982,7 @@ ${append2.text}` : append2.text;
29318
28982
  return;
29319
28983
  }
29320
28984
  if (refs.length && editor && !getEditorText(editor).trim()) {
29321
- editor.commands.setContent({ type: "doc", content: [{ type: "paragraph", content: refs.flatMap((ref) => [{ type: "pluginMention", attrs: { ...ref } }, { type: "text", text: " " }]) }] });
28985
+ editor.commands.setContent(buildPluginSelectionDocument(refs));
29322
28986
  }
29323
28987
  if (activeSessionId && activePendingContexts.length > 0) {
29324
28988
  composerChannels.consumePendingContexts(activeSessionId);
@@ -29331,7 +28995,7 @@ ${append2.text}` : append2.text;
29331
28995
  setIsSubmitting(false);
29332
28996
  }
29333
28997
  };
29334
- useEffect9(() => {
28998
+ useEffect8(() => {
29335
28999
  if (!editor || !activeSessionId || !queuedTopicRefs?.length) return;
29336
29000
  const existing = collectTopicAssetMentions(editor.getJSON());
29337
29001
  const refs = composerChannels.consumeTopicAssetReferences(activeSessionId).filter((ref) => !existing.some((item) => item.topic_id === ref.topic_id && item.path === ref.path));
@@ -29351,9 +29015,9 @@ ${append2.text}` : append2.text;
29351
29015
  const reduceMotion = typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
29352
29016
  return reduceMotion ? fullPlaceholder : "";
29353
29017
  });
29354
- const typewriterPlayedRef = useRef9(false);
29355
- const isTypingRef = useRef9(false);
29356
- useEffect9(() => {
29018
+ const typewriterPlayedRef = useRef7(false);
29019
+ const isTypingRef = useRef7(false);
29020
+ useEffect8(() => {
29357
29021
  if (!typewriterPlaceholder || typewriterPlayedRef.current) return;
29358
29022
  typewriterPlayedRef.current = true;
29359
29023
  const reduceMotion = typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
@@ -29374,7 +29038,7 @@ ${append2.text}` : append2.text;
29374
29038
  isTypingRef.current = false;
29375
29039
  };
29376
29040
  }, [typewriterPlaceholder]);
29377
- useEffect9(() => {
29041
+ useEffect8(() => {
29378
29042
  if (isTypingRef.current) return;
29379
29043
  setTypedPlaceholder(fullPlaceholder);
29380
29044
  }, [fullPlaceholder]);
@@ -29382,7 +29046,7 @@ ${append2.text}` : append2.text;
29382
29046
  const attachments = renderAttachments?.() ?? null;
29383
29047
  const hasRenderedAttachments = attachments !== null;
29384
29048
  const hasPendingContexts = (pendingContexts?.length ?? 0) > 0;
29385
- const isSkillEditor = currentSession?.solution_id === "skill_editor" || currentSession?.template_id === "skill_editor";
29049
+ const isSkillEditor = currentSession?.solution_id === "skill_editor";
29386
29050
  const imageAttachments = composerAttachments.filter(isImageAttachment);
29387
29051
  const fileAttachments = composerAttachments.filter(
29388
29052
  (attachment) => !isImageAttachment(attachment)
@@ -29394,11 +29058,12 @@ ${append2.text}` : append2.text;
29394
29058
  const submitWhileRunning = isStreaming && !isStopping && queueWhileRunning;
29395
29059
  const hasComposerContent = Boolean(input.trim()) || hasValidAttachments || hasRenderedAttachments || hasPendingContexts;
29396
29060
  const isSendDisabled = connectionStatus !== "connected" || isCompacting || !submitWhileRunning && isModelLoading || !submitWhileRunning && !hasAvailableModel || isSubmitting || hasUploadingFiles || !input.trim() && !hasValidAttachments && !hasRenderedAttachments && !hasPendingContexts;
29397
- return /* @__PURE__ */ jsxs12(Fragment5, { children: [
29398
- /* @__PURE__ */ jsx23("div", { className: `px-5 pb-3 pt-0 ${className ?? ""}`, children: /* @__PURE__ */ jsxs12("div", { className: `mx-auto ${maxWidthClassName} ${innerClassName ?? ""}`, children: [
29399
- statusBarAddon ? /* @__PURE__ */ jsx23("div", { className: "mb-2 flex flex-wrap items-center gap-2", children: statusBarAddon }) : null,
29400
- !isModelLoading && !hasAvailableModel ? /* @__PURE__ */ jsx23("div", { className: "mb-2 rounded-lg border border-[hsl(var(--destructive))]/30 bg-[hsl(var(--destructive))]/8 px-3 py-2 text-xs text-[hsl(var(--destructive))]", children: modelAvailabilityMessage }) : null,
29401
- /* @__PURE__ */ jsx23(
29061
+ const showQueueShortcut = Boolean(input.trim()) && !isSendDisabled && !isStopping && !isRecording && (!isStreaming || queueWhileRunning && !hasRunningSendBlockers());
29062
+ return /* @__PURE__ */ jsxs13(Fragment5, { children: [
29063
+ /* @__PURE__ */ jsx24("div", { className: `px-5 pb-3 pt-0 ${className ?? ""}`, children: /* @__PURE__ */ jsxs13("div", { className: `mx-auto ${maxWidthClassName} ${innerClassName ?? ""}`, children: [
29064
+ statusBarAddon ? /* @__PURE__ */ jsx24("div", { className: "mb-2 flex flex-wrap items-center gap-2", children: statusBarAddon }) : null,
29065
+ !isModelLoading && !hasAvailableModel ? /* @__PURE__ */ jsx24("div", { className: "mb-2 rounded-lg border border-[hsl(var(--destructive))]/30 bg-[hsl(var(--destructive))]/8 px-3 py-2 text-xs text-[hsl(var(--destructive))]", children: modelAvailabilityMessage }) : null,
29066
+ /* @__PURE__ */ jsx24(
29402
29067
  "div",
29403
29068
  {
29404
29069
  className: "relative",
@@ -29432,22 +29097,20 @@ ${append2.text}` : append2.text;
29432
29097
  if (files.length > 0) void stableAppendFiles(files);
29433
29098
  });
29434
29099
  },
29435
- children: /* @__PURE__ */ jsxs12(
29100
+ children: /* @__PURE__ */ jsxs13(
29436
29101
  "div",
29437
29102
  {
29438
- className: `overflow-visible border bg-[hsl(var(--card))] transition-[box-shadow,border-color] duration-300 ${// 上方贴着队列面板时上两角改直角:面板比输入框窄一圈,上角留着
29439
- // 22px 圆弧的话,这两段弧会从面板两侧露出来,就是截图里的尖角。
29440
- mergesWithPanelAbove ? "rounded-b-[22px]" : "rounded-[22px]"} ${isRecording ? "border-[hsl(var(--swf-success))]!" : isPlanning ? dragging || isEditorFocused ? "border-[hsl(var(--swf-warning)/0.6)]" : "border-[hsl(var(--swf-warning)/0.3)]" : dragging || isEditorFocused ? "border-[hsl(213_94%_60%/0.55)] shadow-[0_0_0_3px_hsl(213_94%_60%/0.16),0_8px_24px_-6px_hsl(213_94%_60%/0.3)]" : "border-[hsl(213_94%_60%/0.28)] shadow-[0_0_0_2px_hsl(213_94%_60%/0.08),0_4px_14px_-6px_hsl(213_94%_60%/0.16)]"}`,
29103
+ className: `overflow-visible border bg-[hsl(var(--card))] transition-[box-shadow,border-color] duration-300 ${mergesWithPanelAbove ? "rounded-b-[22px]" : "rounded-[22px]"} ${isRecording ? "border-[hsl(var(--swf-success))]!" : isPlanning ? dragging || isEditorFocused ? "border-[hsl(var(--swf-warning)/0.6)]" : "border-[hsl(var(--swf-warning)/0.3)]" : dragging || isEditorFocused ? "border-[hsl(213_94%_60%/0.55)] shadow-[0_0_0_3px_hsl(213_94%_60%/0.16),0_8px_24px_-6px_hsl(213_94%_60%/0.3)]" : "border-[hsl(213_94%_60%/0.28)] shadow-[0_0_0_2px_hsl(213_94%_60%/0.08),0_4px_14px_-6px_hsl(213_94%_60%/0.16)]"}`,
29441
29104
  children: [
29442
- dragging && /* @__PURE__ */ jsx23("div", { className: `pointer-events-none absolute inset-0 z-10 flex items-center justify-center bg-[hsl(var(--primary)/0.06)] ${mergesWithPanelAbove ? "rounded-b-[22px]" : "rounded-2xl"}`, children: /* @__PURE__ */ jsx23("span", { className: "rounded-full bg-[hsl(var(--primary)/0.12)] px-4 py-2 text-sm font-medium text-[hsl(var(--primary))]", children: "\u677E\u624B\u5F15\u7528\u6587\u4EF6" }) }),
29105
+ dragging && /* @__PURE__ */ jsx24("div", { className: `pointer-events-none absolute inset-0 z-10 flex items-center justify-center bg-[hsl(var(--primary)/0.06)] ${mergesWithPanelAbove ? "rounded-b-[22px]" : "rounded-2xl"}`, children: /* @__PURE__ */ jsx24("span", { className: "rounded-full bg-[hsl(var(--primary)/0.12)] px-4 py-2 text-sm font-medium text-[hsl(var(--primary))]", children: "\u677E\u624B\u5F15\u7528\u6587\u4EF6" }) }),
29443
29106
  planPanel,
29444
- composerAttachments.length > 0 && /* @__PURE__ */ jsxs12(ComposerAttachmentViewport, { className: "flex flex-col gap-2 border-b border-[hsl(var(--border))] px-4 py-2", children: [
29445
- imageAttachments.length > 0 && /* @__PURE__ */ jsx23("div", { className: "grid grid-cols-3 gap-2", children: imageAttachments.map((attachment) => /* @__PURE__ */ jsxs12(
29107
+ composerAttachments.length > 0 && /* @__PURE__ */ jsxs13(ComposerAttachmentViewport, { className: "flex flex-col gap-2 border-b border-[hsl(var(--border))] px-4 py-2", children: [
29108
+ imageAttachments.length > 0 && /* @__PURE__ */ jsx24("div", { className: "grid grid-cols-3 gap-2", children: imageAttachments.map((attachment) => /* @__PURE__ */ jsxs13(
29446
29109
  "div",
29447
29110
  {
29448
29111
  className: "relative overflow-hidden rounded-xl border border-[hsl(var(--border))]",
29449
29112
  children: [
29450
- /* @__PURE__ */ jsx23(
29113
+ /* @__PURE__ */ jsx24(
29451
29114
  "img",
29452
29115
  {
29453
29116
  src: getImagePreviewUrl(client, attachment, activeSessionId, localImageUrls),
@@ -29455,7 +29118,7 @@ ${append2.text}` : append2.text;
29455
29118
  className: "h-24 w-full object-cover"
29456
29119
  }
29457
29120
  ),
29458
- /* @__PURE__ */ jsx23(
29121
+ /* @__PURE__ */ jsx24(
29459
29122
  "button",
29460
29123
  {
29461
29124
  type: "button",
@@ -29463,14 +29126,14 @@ ${append2.text}` : append2.text;
29463
29126
  "aria-label": `\u79FB\u9664 ${attachment.name || "\u56FE\u7247"}`,
29464
29127
  title: "\u79FB\u9664",
29465
29128
  className: "absolute right-1.5 top-1.5 flex h-6 w-6 items-center justify-center rounded-full bg-[hsl(var(--background)/0.85)] text-[hsl(var(--foreground))]",
29466
- children: /* @__PURE__ */ jsx23(X, { size: 12 })
29129
+ children: /* @__PURE__ */ jsx24(X, { size: 12 })
29467
29130
  }
29468
29131
  )
29469
29132
  ]
29470
29133
  },
29471
29134
  attachment.id
29472
29135
  )) }),
29473
- fileAttachments.length > 0 && /* @__PURE__ */ jsx23("div", { className: "flex flex-wrap gap-1.5", children: fileAttachments.map((attachment) => /* @__PURE__ */ jsx23(
29136
+ fileAttachments.length > 0 && /* @__PURE__ */ jsx24("div", { className: "flex flex-wrap gap-1.5", children: fileAttachments.map((attachment) => /* @__PURE__ */ jsx24(
29474
29137
  ComposerFilePill,
29475
29138
  {
29476
29139
  attachment,
@@ -29479,8 +29142,8 @@ ${append2.text}` : append2.text;
29479
29142
  attachment.id
29480
29143
  )) })
29481
29144
  ] }),
29482
- hasPendingContexts || isSkillEditor ? /* @__PURE__ */ jsxs12("div", { className: "flex flex-wrap items-center gap-1.5 border-b border-[hsl(var(--border))] px-4 py-2", children: [
29483
- pendingContexts?.map((context) => /* @__PURE__ */ jsx23(
29145
+ hasPendingContexts || isSkillEditor ? /* @__PURE__ */ jsxs13("div", { className: "flex flex-wrap items-center gap-1.5 border-b border-[hsl(var(--border))] px-4 py-2", children: [
29146
+ pendingContexts?.map((context) => /* @__PURE__ */ jsx24(
29484
29147
  ComposerContextPill,
29485
29148
  {
29486
29149
  id: context.id,
@@ -29496,18 +29159,18 @@ ${append2.text}` : append2.text;
29496
29159
  },
29497
29160
  context.id
29498
29161
  )),
29499
- isSkillEditor && /* @__PURE__ */ jsx23(
29162
+ isSkillEditor && /* @__PURE__ */ jsx24(
29500
29163
  "button",
29501
29164
  {
29502
29165
  type: "button",
29503
29166
  onClick: () => setShowAddContext(true),
29504
29167
  title: "\u6DFB\u52A0\u4E0A\u4E0B\u6587",
29505
29168
  className: "inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full border border-dashed border-[hsl(var(--border))] text-[hsl(var(--muted-foreground))] transition-colors hover:border-[hsl(var(--ring))] hover:text-[hsl(var(--foreground))]",
29506
- children: /* @__PURE__ */ jsx23(Plus, { size: 12 })
29169
+ children: /* @__PURE__ */ jsx24(Plus, { size: 12 })
29507
29170
  }
29508
29171
  )
29509
29172
  ] }) : null,
29510
- showAddContext && activeSessionId && /* @__PURE__ */ jsx23(
29173
+ showAddContext && activeSessionId && /* @__PURE__ */ jsx24(
29511
29174
  AddContextDialog,
29512
29175
  {
29513
29176
  sessionId: activeSessionId,
@@ -29519,15 +29182,15 @@ ${append2.text}` : append2.text;
29519
29182
  }
29520
29183
  }
29521
29184
  ),
29522
- attachments ? /* @__PURE__ */ jsx23("div", { className: "border-b border-[hsl(var(--border))] px-4 py-3", children: attachments }) : null,
29523
- slotAboveTextarea ? /* @__PURE__ */ jsx23("div", { className: "border-b border-[hsl(var(--border))] px-4 py-2", children: slotAboveTextarea }) : null,
29524
- /* @__PURE__ */ jsxs12("div", { className: "relative", children: [
29525
- input.length === 0 && /* @__PURE__ */ jsx23("div", { className: "pointer-events-none absolute left-5 top-3 text-sm leading-relaxed text-[hsl(var(--muted-foreground)/0.6)]", children: placeholder }),
29526
- /* @__PURE__ */ jsx23(EditorContent, { editor })
29185
+ attachments ? /* @__PURE__ */ jsx24("div", { className: "border-b border-[hsl(var(--border))] px-4 py-3", children: attachments }) : null,
29186
+ slotAboveTextarea ? /* @__PURE__ */ jsx24("div", { className: "border-b border-[hsl(var(--border))] px-4 py-2", children: slotAboveTextarea }) : null,
29187
+ /* @__PURE__ */ jsxs13("div", { className: "relative", children: [
29188
+ input.length === 0 && /* @__PURE__ */ jsx24("div", { className: "pointer-events-none absolute left-5 top-3 text-sm leading-relaxed text-[hsl(var(--muted-foreground)/0.6)]", children: placeholder }),
29189
+ /* @__PURE__ */ jsx24(EditorContent, { editor })
29527
29190
  ] }),
29528
- /* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-between px-4 pb-3 pt-1", children: [
29529
- /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
29530
- /* @__PURE__ */ jsx23(
29191
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center justify-between px-4 pb-3 pt-1", children: [
29192
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
29193
+ /* @__PURE__ */ jsx24(
29531
29194
  "input",
29532
29195
  {
29533
29196
  ref: fileInputRef,
@@ -29543,7 +29206,7 @@ ${append2.text}` : append2.text;
29543
29206
  className: "hidden"
29544
29207
  }
29545
29208
  ),
29546
- /* @__PURE__ */ jsx23(
29209
+ /* @__PURE__ */ jsx24(
29547
29210
  "input",
29548
29211
  {
29549
29212
  ref: folderInputRef,
@@ -29559,7 +29222,7 @@ ${append2.text}` : append2.text;
29559
29222
  ...{ webkitdirectory: "" }
29560
29223
  }
29561
29224
  ),
29562
- /* @__PURE__ */ jsxs12(
29225
+ /* @__PURE__ */ jsxs13(
29563
29226
  dist_exports.Root,
29564
29227
  {
29565
29228
  open: actionMenuOpen,
@@ -29568,17 +29231,17 @@ ${append2.text}` : append2.text;
29568
29231
  if (open) setConnectMenuOpen(false);
29569
29232
  },
29570
29233
  children: [
29571
- /* @__PURE__ */ jsx23(dist_exports.Trigger, { asChild: true, children: /* @__PURE__ */ jsx23(
29234
+ /* @__PURE__ */ jsx24(dist_exports.Trigger, { asChild: true, children: /* @__PURE__ */ jsx24(
29572
29235
  "button",
29573
29236
  {
29574
29237
  type: "button",
29575
29238
  "aria-label": "\u6DFB\u52A0\u5185\u5BB9",
29576
29239
  title: "\u6DFB\u52A0\u5185\u5BB9",
29577
29240
  className: "flex h-9 w-9 shrink-0 cursor-pointer items-center justify-center rounded-full border border-[hsl(var(--border))] text-[hsl(var(--muted-foreground))] transition-colors hover:border-[hsl(var(--ring))] hover:text-[hsl(var(--foreground))]",
29578
- children: /* @__PURE__ */ jsx23(Plus, { size: 14 })
29241
+ children: /* @__PURE__ */ jsx24(Plus, { size: 14 })
29579
29242
  }
29580
29243
  ) }),
29581
- /* @__PURE__ */ jsx23(dist_exports.Portal, { children: /* @__PURE__ */ jsxs12(
29244
+ /* @__PURE__ */ jsx24(dist_exports.Portal, { children: /* @__PURE__ */ jsxs13(
29582
29245
  dist_exports.Content,
29583
29246
  {
29584
29247
  side: "top",
@@ -29586,7 +29249,7 @@ ${append2.text}` : append2.text;
29586
29249
  sideOffset: 8,
29587
29250
  className: "z-30 w-[min(380px,calc(100vw-2rem))] origin-(--radix-popover-content-transform-origin) overflow-visible rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--popover))] py-1 text-[11px] text-[hsl(var(--popover-foreground))] shadow-[var(--swf-shadow-overlay)] outline-none data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
29588
29251
  children: [
29589
- /* @__PURE__ */ jsxs12(
29252
+ /* @__PURE__ */ jsxs13(
29590
29253
  "button",
29591
29254
  {
29592
29255
  type: "button",
@@ -29596,12 +29259,12 @@ ${append2.text}` : append2.text;
29596
29259
  },
29597
29260
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
29598
29261
  children: [
29599
- /* @__PURE__ */ jsx23(Paperclip, { size: 14 }),
29262
+ /* @__PURE__ */ jsx24(Paperclip, { size: 14 }),
29600
29263
  "\u4E0A\u4F20\u6587\u4EF6"
29601
29264
  ]
29602
29265
  }
29603
29266
  ),
29604
- /* @__PURE__ */ jsxs12(
29267
+ /* @__PURE__ */ jsxs13(
29605
29268
  "button",
29606
29269
  {
29607
29270
  type: "button",
@@ -29611,12 +29274,12 @@ ${append2.text}` : append2.text;
29611
29274
  },
29612
29275
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
29613
29276
  children: [
29614
- /* @__PURE__ */ jsx23(FolderUp, { size: 14 }),
29277
+ /* @__PURE__ */ jsx24(FolderUp, { size: 14 }),
29615
29278
  "\u4E0A\u4F20\u6587\u4EF6\u5939"
29616
29279
  ]
29617
29280
  }
29618
29281
  ),
29619
- onCommand && canCreateBoardTask && !lite ? /* @__PURE__ */ jsxs12(
29282
+ onCommand && canCreateBoardTask && !lite ? /* @__PURE__ */ jsxs13(
29620
29283
  "button",
29621
29284
  {
29622
29285
  type: "button",
@@ -29626,12 +29289,12 @@ ${append2.text}` : append2.text;
29626
29289
  },
29627
29290
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
29628
29291
  children: [
29629
- /* @__PURE__ */ jsx23(ListPlus, { size: 14 }),
29292
+ /* @__PURE__ */ jsx24(ListPlus, { size: 14 }),
29630
29293
  "\u521B\u5EFA\u540E\u53F0\u4EFB\u52A1"
29631
29294
  ]
29632
29295
  }
29633
29296
  ) : null,
29634
- onDoubleEscape ? /* @__PURE__ */ jsxs12(
29297
+ onDoubleEscape ? /* @__PURE__ */ jsxs13(
29635
29298
  "button",
29636
29299
  {
29637
29300
  type: "button",
@@ -29643,13 +29306,13 @@ ${append2.text}` : append2.text;
29643
29306
  },
29644
29307
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
29645
29308
  children: [
29646
- /* @__PURE__ */ jsx23(RotateCcw, { size: 14 }),
29309
+ /* @__PURE__ */ jsx24(RotateCcw, { size: 14 }),
29647
29310
  "\u56DE\u5230\u4E4B\u524D\u7684\u67D0\u4E00\u6B65"
29648
29311
  ]
29649
29312
  }
29650
29313
  ) : null,
29651
- onCommand && !lite ? /* @__PURE__ */ jsxs12(Fragment5, { children: [
29652
- /* @__PURE__ */ jsxs12(
29314
+ onCommand && !lite ? /* @__PURE__ */ jsxs13(Fragment5, { children: [
29315
+ developer ? /* @__PURE__ */ jsxs13(
29653
29316
  "button",
29654
29317
  {
29655
29318
  type: "button",
@@ -29660,12 +29323,12 @@ ${append2.text}` : append2.text;
29660
29323
  disabled: isBusy,
29661
29324
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))] disabled:cursor-not-allowed disabled:opacity-50",
29662
29325
  children: [
29663
- isCompacting ? /* @__PURE__ */ jsx23(LoaderCircle, { size: 14, className: "animate-spin" }) : /* @__PURE__ */ jsx23(Scissors, { size: 14 }),
29326
+ isCompacting ? /* @__PURE__ */ jsx24(LoaderCircle, { size: 14, className: "animate-spin" }) : /* @__PURE__ */ jsx24(Scissors, { size: 14 }),
29664
29327
  "\u6574\u7406\u5BF9\u8BDD"
29665
29328
  ]
29666
29329
  }
29667
- ),
29668
- /* @__PURE__ */ jsxs12(
29330
+ ) : null,
29331
+ /* @__PURE__ */ jsxs13(
29669
29332
  "button",
29670
29333
  {
29671
29334
  type: "button",
@@ -29675,12 +29338,12 @@ ${append2.text}` : append2.text;
29675
29338
  },
29676
29339
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
29677
29340
  children: [
29678
- /* @__PURE__ */ jsx23(Download, { size: 14 }),
29341
+ /* @__PURE__ */ jsx24(Download, { size: 14 }),
29679
29342
  "\u5BFC\u51FA\u4F1A\u8BDD"
29680
29343
  ]
29681
29344
  }
29682
29345
  ),
29683
- /* @__PURE__ */ jsxs12(
29346
+ /* @__PURE__ */ jsxs13(
29684
29347
  "button",
29685
29348
  {
29686
29349
  type: "button",
@@ -29690,12 +29353,12 @@ ${append2.text}` : append2.text;
29690
29353
  },
29691
29354
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
29692
29355
  children: [
29693
- /* @__PURE__ */ jsx23(Play, { size: 14 }),
29356
+ /* @__PURE__ */ jsx24(Play, { size: 14 }),
29694
29357
  "\u56DE\u653E\u8FD9\u4E2A\u5BF9\u8BDD"
29695
29358
  ]
29696
29359
  }
29697
29360
  ),
29698
- canShareSession ? /* @__PURE__ */ jsxs12(
29361
+ canShareSession ? /* @__PURE__ */ jsxs13(
29699
29362
  "button",
29700
29363
  {
29701
29364
  type: "button",
@@ -29705,12 +29368,12 @@ ${append2.text}` : append2.text;
29705
29368
  },
29706
29369
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
29707
29370
  children: [
29708
- /* @__PURE__ */ jsx23(Share2, { size: 14 }),
29371
+ /* @__PURE__ */ jsx24(Share2, { size: 14 }),
29709
29372
  "\u5206\u4EAB\u4F1A\u8BDD"
29710
29373
  ]
29711
29374
  }
29712
29375
  ) : null,
29713
- /* @__PURE__ */ jsxs12(
29376
+ /* @__PURE__ */ jsxs13(
29714
29377
  "button",
29715
29378
  {
29716
29379
  type: "button",
@@ -29720,12 +29383,12 @@ ${append2.text}` : append2.text;
29720
29383
  },
29721
29384
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
29722
29385
  children: [
29723
- /* @__PURE__ */ jsx23(FlaskConical, { size: 14 }),
29386
+ /* @__PURE__ */ jsx24(FlaskConical, { size: 14 }),
29724
29387
  "\u63D0\u53D6\u6280\u80FD"
29725
29388
  ]
29726
29389
  }
29727
29390
  ),
29728
- /* @__PURE__ */ jsxs12(
29391
+ /* @__PURE__ */ jsxs13(
29729
29392
  "button",
29730
29393
  {
29731
29394
  type: "button",
@@ -29735,13 +29398,13 @@ ${append2.text}` : append2.text;
29735
29398
  },
29736
29399
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
29737
29400
  children: [
29738
- /* @__PURE__ */ jsx23(Rocket, { size: 14 }),
29401
+ /* @__PURE__ */ jsx24(Rocket, { size: 14 }),
29739
29402
  "\u751F\u6210\u5E94\u7528"
29740
29403
  ]
29741
29404
  }
29742
29405
  )
29743
29406
  ] }) : null,
29744
- onToggleMode && !lite ? /* @__PURE__ */ jsx23(
29407
+ onToggleMode && !lite ? /* @__PURE__ */ jsx24(
29745
29408
  PlanningToggle,
29746
29409
  {
29747
29410
  enabled: isPlanning,
@@ -29752,22 +29415,23 @@ ${append2.text}` : append2.text;
29752
29415
  disabled: isBusy
29753
29416
  }
29754
29417
  ) : null,
29755
- !lite && thinkingAvailable && reasoningLevels.length > 0 ? /* @__PURE__ */ jsx23(
29418
+ !lite && thinkingAvailable && reasoningLevels.length > 0 ? /* @__PURE__ */ jsx24(
29756
29419
  ReasoningModeSelect,
29757
29420
  {
29758
29421
  level: selectedReasoningLevel,
29759
29422
  levels: reasoningLevels,
29760
29423
  disabled: isCompacting,
29761
- disabledReason: "\u5BF9\u8BDD\u6574\u7406\u5B8C\u6210\u540E\u53EF\u8C03\u6574",
29424
+ disabledReason: developer ? "\u5BF9\u8BDD\u6574\u7406\u5B8C\u6210\u540E\u53EF\u8C03\u6574" : "\u5904\u7406\u5B8C\u6210\u540E\u53EF\u8C03\u6574",
29762
29425
  onChange: model.setReasoningLevel
29763
29426
  }
29764
29427
  ) : null,
29765
- !lite ? /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2 px-3 py-2", children: [
29766
- /* @__PURE__ */ jsx23(Sparkles, { size: 14, className: "shrink-0", "aria-hidden": "true" }),
29767
- /* @__PURE__ */ jsx23("span", { className: "shrink-0", children: "\u6A21\u578B" }),
29768
- /* @__PURE__ */ jsx23(
29428
+ !lite ? /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 px-3 py-2", children: [
29429
+ /* @__PURE__ */ jsx24(Sparkles, { size: 14, className: "shrink-0", "aria-hidden": "true" }),
29430
+ /* @__PURE__ */ jsx24("span", { className: "shrink-0", children: "\u6A21\u578B" }),
29431
+ /* @__PURE__ */ jsx24(
29769
29432
  ModelSelector,
29770
29433
  {
29434
+ disabled: isModelLoading,
29771
29435
  value: selectedModel,
29772
29436
  onValueChange: model.selectModel,
29773
29437
  compact: true,
@@ -29775,8 +29439,8 @@ ${append2.text}` : append2.text;
29775
29439
  }
29776
29440
  )
29777
29441
  ] }) : null,
29778
- !lite && activeSessionId && actionMenuOpen ? /* @__PURE__ */ jsxs12("div", { className: "border-t border-[hsl(var(--border))] px-3 py-2.5", children: [
29779
- /* @__PURE__ */ jsx23(
29442
+ !lite && activeSessionId && actionMenuOpen ? /* @__PURE__ */ jsxs13("div", { className: "border-t border-[hsl(var(--border))] px-3 py-2.5", children: [
29443
+ /* @__PURE__ */ jsx24(
29780
29444
  SkillStatusBarComponent,
29781
29445
  {
29782
29446
  sessionId: activeSessionId,
@@ -29786,7 +29450,7 @@ ${append2.text}` : append2.text;
29786
29450
  innerClassName: skillStatusBarInnerClassName
29787
29451
  }
29788
29452
  ),
29789
- composerHint ? /* @__PURE__ */ jsx23("div", { className: "mt-2 border-t border-[hsl(var(--border))] pt-2 text-[hsl(var(--muted-foreground))]", children: composerHint }) : null
29453
+ composerHint ? /* @__PURE__ */ jsx24("div", { className: "mt-2 border-t border-[hsl(var(--border))] pt-2 text-[hsl(var(--muted-foreground))]", children: composerHint }) : null
29790
29454
  ] }) : null
29791
29455
  ]
29792
29456
  }
@@ -29794,7 +29458,7 @@ ${append2.text}` : append2.text;
29794
29458
  ]
29795
29459
  }
29796
29460
  ),
29797
- /* @__PURE__ */ jsx23(
29461
+ /* @__PURE__ */ jsx24(
29798
29462
  ConnectButton,
29799
29463
  {
29800
29464
  sessionId: activeSessionId,
@@ -29807,11 +29471,15 @@ ${append2.text}` : append2.text;
29807
29471
  }
29808
29472
  }
29809
29473
  ),
29810
- !lite && activeSessionId ? /* @__PURE__ */ jsx23(BackgroundTasksPill, { sessionId: activeSessionId }) : null
29474
+ !lite && activeSessionId ? /* @__PURE__ */ jsx24(BackgroundTasksPill, { sessionId: activeSessionId }) : null
29811
29475
  ] }),
29812
- /* @__PURE__ */ jsxs12("div", { className: "flex min-h-10 items-center gap-1.5", children: [
29476
+ /* @__PURE__ */ jsxs13("div", { className: "flex min-h-10 items-center gap-1.5", children: [
29477
+ showQueueShortcut && /* @__PURE__ */ jsxs13("span", { className: "mr-1 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
29478
+ queueShortcutLabel(),
29479
+ " \xB7 \u6392\u961F\u6D88\u606F"
29480
+ ] }),
29813
29481
  slotBeforeSend,
29814
- !isStreaming && !isCompacting && asrEnabled && (isRecording || isVoiceStarting || !hasComposerContent) ? /* @__PURE__ */ jsx23(
29482
+ !isStreaming && !isCompacting && asrEnabled && (isRecording || isVoiceStarting || !hasComposerContent) ? /* @__PURE__ */ jsx24(
29815
29483
  "button",
29816
29484
  {
29817
29485
  type: "button",
@@ -29819,23 +29487,23 @@ ${append2.text}` : append2.text;
29819
29487
  "aria-label": isRecording || isVoiceStarting ? "\u505C\u6B62\u8BED\u97F3\u8F93\u5165" : "\u5F00\u59CB\u8BED\u97F3\u8F93\u5165",
29820
29488
  title: isVoiceStarting ? "\u6B63\u5728\u8FDE\u63A5\u8BED\u97F3\u8F93\u5165\uFF0C\u70B9\u51FB\u53D6\u6D88" : isRecording ? "\u505C\u6B62\u8BED\u97F3\u8F93\u5165" : "\u8BED\u97F3\u8F93\u5165",
29821
29489
  className: `flex items-center justify-center rounded-full transition-[width,height,background-color,color,box-shadow] duration-300 disabled:opacity-40 ${isRecording ? "h-10 w-10 bg-[hsl(var(--swf-success-soft))] text-[hsl(var(--swf-success))]" : "h-10 w-10 bg-[hsl(213_94%_60%/0.10)] text-[hsl(213_94%_45%)] hover:bg-[hsl(213_94%_60%/0.18)]"}`,
29822
- children: isVoiceStarting ? /* @__PURE__ */ jsx23(LoaderCircle, { size: 20, className: "animate-spin" }) : isRecording ? /* @__PURE__ */ jsx23(VoiceWaveform, { level: voiceLevel, size: 20 }) : /* @__PURE__ */ jsx23(Mic, { size: 20 })
29490
+ children: isVoiceStarting ? /* @__PURE__ */ jsx24(LoaderCircle, { size: 20, className: "animate-spin" }) : isRecording ? /* @__PURE__ */ jsx24(VoiceWaveform, { level: voiceLevel, size: 20 }) : /* @__PURE__ */ jsx24(Mic, { size: 20 })
29823
29491
  }
29824
29492
  ) : null,
29825
- isStreaming ? /* @__PURE__ */ jsxs12(Fragment5, { children: [
29826
- submitWhileRunning ? /* @__PURE__ */ jsx23(
29493
+ isStreaming ? /* @__PURE__ */ jsxs13(Fragment5, { children: [
29494
+ submitWhileRunning ? /* @__PURE__ */ jsx24(
29827
29495
  "button",
29828
29496
  {
29829
29497
  type: "button",
29830
- onClick: handleSubmit,
29498
+ onClick: () => void handleSubmit(),
29831
29499
  disabled: isSendDisabled || isRecording,
29832
- "aria-label": "\u52A0\u5165\u6392\u961F",
29833
- title: "\u52A0\u5165\u6392\u961F",
29500
+ "aria-label": "\u53D1\u9001\u5F15\u5BFC\u6D88\u606F",
29501
+ title: "\u53D1\u9001\u5F15\u5BFC\u6D88\u606F",
29834
29502
  className: "flex h-10 w-10 items-center justify-center rounded-full bg-[hsl(213_94%_55%)] text-white disabled:opacity-25",
29835
- children: isSubmitting ? /* @__PURE__ */ jsx23(LoaderCircle, { size: 16, className: "animate-spin" }) : /* @__PURE__ */ jsx23(Send, { size: 16 })
29503
+ children: isSubmitting ? /* @__PURE__ */ jsx24(LoaderCircle, { size: 16, className: "animate-spin" }) : /* @__PURE__ */ jsx24(Send, { size: 16 })
29836
29504
  }
29837
29505
  ) : null,
29838
- /* @__PURE__ */ jsx23(
29506
+ /* @__PURE__ */ jsx24(
29839
29507
  "button",
29840
29508
  {
29841
29509
  type: "button",
@@ -29844,41 +29512,41 @@ ${append2.text}` : append2.text;
29844
29512
  "aria-label": isStopping ? "\u6B63\u5728\u505C\u6B62" : "\u505C\u6B62\u751F\u6210",
29845
29513
  title: isStopping ? "\u6B63\u5728\u505C\u6B62" : "\u505C\u6B62\u751F\u6210",
29846
29514
  className: "flex h-10 w-10 items-center justify-center rounded-full bg-[hsl(var(--destructive))] text-[hsl(var(--destructive-foreground))] transition-opacity hover:opacity-80 disabled:cursor-wait disabled:opacity-70",
29847
- children: isStopping ? /* @__PURE__ */ jsx23(LoaderCircle, { size: 16, className: "animate-spin" }) : /* @__PURE__ */ jsx23(Square, { size: 16 })
29515
+ children: isStopping ? /* @__PURE__ */ jsx24(LoaderCircle, { size: 16, className: "animate-spin" }) : /* @__PURE__ */ jsx24(Square, { size: 16 })
29848
29516
  }
29849
29517
  )
29850
- ] }) : isCompacting ? /* @__PURE__ */ jsx23(
29518
+ ] }) : isCompacting ? /* @__PURE__ */ jsx24(
29851
29519
  "button",
29852
29520
  {
29853
29521
  type: "button",
29854
29522
  disabled: true,
29855
- "aria-label": "\u6B63\u5728\u6574\u7406\u5BF9\u8BDD",
29856
- title: "\u6B63\u5728\u6574\u7406\u5BF9\u8BDD",
29523
+ "aria-label": developer ? "\u6B63\u5728\u6574\u7406\u5BF9\u8BDD" : "\u6B63\u5728\u5904\u7406",
29524
+ title: developer ? "\u6B63\u5728\u6574\u7406\u5BF9\u8BDD" : "\u6B63\u5728\u5904\u7406",
29857
29525
  className: "flex h-10 w-10 items-center justify-center rounded-full bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))] opacity-50",
29858
- children: /* @__PURE__ */ jsx23(LoaderCircle, { size: 16, className: "animate-spin" })
29526
+ children: /* @__PURE__ */ jsx24(LoaderCircle, { size: 16, className: "animate-spin" })
29859
29527
  }
29860
- ) : !isRecording && hasComposerContent ? /* @__PURE__ */ jsx23(
29528
+ ) : !isRecording && hasComposerContent ? /* @__PURE__ */ jsx24(
29861
29529
  "button",
29862
29530
  {
29863
29531
  type: "button",
29864
- onClick: handleSubmit,
29532
+ onClick: () => void handleSubmit(),
29865
29533
  disabled: isSendDisabled,
29866
- "aria-label": "\u53D1\u9001\u6D88\u606F",
29867
- title: isModelLoading ? "\u6B63\u5728\u52A0\u8F7D\u6A21\u578B\u914D\u7F6E" : !hasAvailableModel ? modelAvailabilityMessage : "\u53D1\u9001\u6D88\u606F",
29534
+ "aria-label": "\u53D1\u9001\u5F15\u5BFC\u6D88\u606F",
29535
+ title: isModelLoading ? "\u6B63\u5728\u52A0\u8F7D\u6A21\u578B\u914D\u7F6E" : !hasAvailableModel ? modelAvailabilityMessage : "\u53D1\u9001\u5F15\u5BFC\u6D88\u606F",
29868
29536
  className: "flex h-10 w-10 items-center justify-center rounded-full bg-[hsl(213_94%_55%)] text-white transition-colors duration-[120ms] ease-out hover:bg-[hsl(213_94%_48%)] disabled:opacity-25",
29869
- children: isSubmitting ? /* @__PURE__ */ jsx23(LoaderCircle, { size: 16, className: "animate-spin" }) : /* @__PURE__ */ jsx23(Send, { size: 16 })
29537
+ children: isSubmitting ? /* @__PURE__ */ jsx24(LoaderCircle, { size: 16, className: "animate-spin" }) : /* @__PURE__ */ jsx24(Send, { size: 16 })
29870
29538
  }
29871
29539
  ) : null
29872
29540
  ] })
29873
29541
  ] }),
29874
- slotBelowActions ? /* @__PURE__ */ jsx23("div", { className: "border-t border-[hsl(var(--border))] px-4 py-1.5", children: slotBelowActions }) : null
29542
+ slotBelowActions ? /* @__PURE__ */ jsx24("div", { className: "border-t border-[hsl(var(--border))] px-4 py-1.5", children: slotBelowActions }) : null
29875
29543
  ]
29876
29544
  }
29877
29545
  )
29878
29546
  }
29879
29547
  )
29880
29548
  ] }) }),
29881
- /* @__PURE__ */ jsx23(
29549
+ /* @__PURE__ */ jsx24(
29882
29550
  FileSizeLimitDialog,
29883
29551
  {
29884
29552
  open: oversizedFiles.length > 0,
@@ -29893,6 +29561,42 @@ ${append2.text}` : append2.text;
29893
29561
  )
29894
29562
  ] });
29895
29563
  }
29564
+
29565
+ // src/rich-input/SkillActionMenu.tsx
29566
+ import { useEffect as useEffect9, useState as useState12 } from "react";
29567
+ import { Fragment as Fragment6, jsx as jsx25, jsxs as jsxs14 } from "react/jsx-runtime";
29568
+ function SkillActionMenu({ open, onOpenChange, renderMode, onSelect, onManage, disabled }) {
29569
+ return /* @__PURE__ */ jsx25(InputActionSubmenu, { label: "\u6280\u80FD", icon: /* @__PURE__ */ jsx25(Sparkles, { size: 16, "aria-hidden": "true" }), open, onOpenChange, disabled, children: /* @__PURE__ */ jsx25(SkillPicker, { renderMode, onSelect, onManage }) });
29570
+ }
29571
+ function SkillPicker({ renderMode, onSelect, onManage }) {
29572
+ const client = useBladeClient();
29573
+ const [query, setQuery] = useState12("");
29574
+ const [skills, setSkills] = useState12(null);
29575
+ useEffect9(() => {
29576
+ let active = true;
29577
+ setSkills(null);
29578
+ getSlashSuggestions(query, { client, sessionId: null, renderMode }).then((items) => {
29579
+ if (active) setSkills(items);
29580
+ }).catch(() => {
29581
+ if (active) setSkills([]);
29582
+ });
29583
+ return () => {
29584
+ active = false;
29585
+ };
29586
+ }, [client, renderMode, query]);
29587
+ return /* @__PURE__ */ jsxs14(Fragment6, { children: [
29588
+ /* @__PURE__ */ jsxs14("label", { className: "m-1 flex items-center gap-2 rounded-lg bg-[hsl(var(--muted))] px-3 py-2", children: [
29589
+ /* @__PURE__ */ jsx25(Search, { size: 14, "aria-hidden": "true" }),
29590
+ /* @__PURE__ */ jsx25("input", { "aria-label": "\u641C\u7D22\u6280\u80FD", placeholder: "\u641C\u7D22\u6280\u80FD", value: query, onChange: (event) => setQuery(event.target.value), className: "min-w-0 flex-1 bg-transparent outline-none" })
29591
+ ] }),
29592
+ /* @__PURE__ */ jsx25("div", { className: "max-h-60 overflow-y-auto", children: skills === null ? /* @__PURE__ */ jsx25("p", { className: "px-3 py-2 text-[hsl(var(--muted-foreground))]", children: "\u52A0\u8F7D\u6280\u80FD\u4E2D\u2026" }) : skills.length ? skills.map((skill) => skill.type === "skill" ? /* @__PURE__ */ jsxs14("button", { type: "button", onClick: () => onSelect(skill), className: "flex w-full flex-col gap-1 rounded-lg px-3 py-2 text-left hover:bg-[hsl(var(--accent))] focus-visible:bg-[hsl(var(--accent))]", children: [
29593
+ /* @__PURE__ */ jsx25("span", { children: skillDisplayName(skill) }),
29594
+ /* @__PURE__ */ jsx25("span", { className: "line-clamp-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: skill.description })
29595
+ ] }, skill.skillId) : null) : /* @__PURE__ */ jsx25("p", { className: "px-3 py-2 text-[hsl(var(--muted-foreground))]", children: "\u6CA1\u6709\u5339\u914D\u7684\u6280\u80FD" }) }),
29596
+ /* @__PURE__ */ jsx25("div", { className: "my-1 border-t border-[hsl(var(--border))]" }),
29597
+ /* @__PURE__ */ jsx25("button", { type: "button", onClick: onManage, className: "w-full rounded-lg px-3 py-2 text-left hover:bg-[hsl(var(--accent))]", children: "\u7BA1\u7406\u6280\u80FD \u2192" })
29598
+ ] });
29599
+ }
29896
29600
  export {
29897
29601
  ATTACHMENT_SIZE_LIMIT_BYTES,
29898
29602
  ATTENTION_STATUSES,
@@ -29904,6 +29608,7 @@ export {
29904
29608
  FileMention,
29905
29609
  FileSizeLimitDialog,
29906
29610
  IMAGE_INPUT_UNSUPPORTED_MESSAGE,
29611
+ InputActionSubmenu,
29907
29612
  LIVE_STATUSES,
29908
29613
  MODEL_LOADING_SEND_HINT,
29909
29614
  MODEL_REASONING_LEVELS_KEY,
@@ -29916,16 +29621,18 @@ export {
29916
29621
  RichInputServicesProvider,
29917
29622
  STATUS_LABELS,
29918
29623
  STOPPABLE_STATUSES,
29624
+ SkillActionMenu,
29919
29625
  SkillCompletionMenu,
29920
29626
  SkillMention,
29921
29627
  SkillStatusBar,
29922
29628
  TopicAssetMention,
29923
29629
  VoiceWaveform,
29924
- WorkflowMention,
29925
29630
  buildEditorDocument,
29926
29631
  buildEditorDocumentWithMentions,
29632
+ buildPluginSelectionDocument,
29927
29633
  buildSubmitPayload,
29928
29634
  buildVoiceInputUnavailableError,
29635
+ collectMessageMentions,
29929
29636
  collectPluginMentions,
29930
29637
  collectTopicAssetMentions,
29931
29638
  entryLabel,
@@ -29938,13 +29645,11 @@ export {
29938
29645
  gateSendWhileModelLoading,
29939
29646
  getFileSuggestionItems,
29940
29647
  getInputModalities,
29941
- getLastUserHomeRuntime,
29942
29648
  getPluginSuggestionItems,
29943
29649
  getSkillSuggestions,
29944
29650
  getSlashSuggestions,
29945
29651
  getTopicAssetSuggestionItems,
29946
29652
  getUnsupportedImageFiles,
29947
- getUserHomeRuntime,
29948
29653
  getUserHomeSuggestionItems,
29949
29654
  installSuggestionOutsideDismiss,
29950
29655
  invalidateSlashSuggestions,
@@ -30001,9 +29706,7 @@ export {
30001
29706
  useSessionSkills,
30002
29707
  useSkillStats,
30003
29708
  useTiptapVoiceInput,
30004
- useVoiceInput,
30005
- workflowParamsTail,
30006
- workflowRunText
29709
+ useVoiceInput
30007
29710
  };
30008
29711
  /*! Bundled license information:
30009
29712