@blade-hq/agent-react 2612.0.0-beta.6 → 2612.0.0-beta.60

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 (112) hide show
  1. package/README.md +30 -1
  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 -4
  22. package/dist/chat/lib/citations.d.ts +2 -23
  23. package/dist/chat/markdown/ExternalAnchor.d.ts +2 -2
  24. package/dist/chat/markdown/MarkdownContent.d.ts +3 -0
  25. package/dist/chat/message-list-blocks.d.ts +0 -1
  26. package/dist/chat/runtime/actions.d.ts +2 -3
  27. package/dist/chat/runtime/background-task-dismissals.d.ts +0 -1
  28. package/dist/chat/runtime/composer-channels.d.ts +0 -3
  29. package/dist/chat/runtime/input-cache-reset.d.ts +0 -5
  30. package/dist/chat/runtime/input-services.d.ts +10 -6
  31. package/dist/chat/runtime/session-source.d.ts +0 -5
  32. package/dist/chat/runtime/use-chat-actions.d.ts +0 -4
  33. package/dist/{chat-OCLOVB3H.css → chat-IHPRU35X.css} +5 -18
  34. package/dist/chat.css +5 -18
  35. package/dist/chunk-2E6DQCXM.js +602 -0
  36. package/dist/chunk-2E6DQCXM.js.map +1 -0
  37. package/dist/chunk-ARX4JV5T.js +1988 -0
  38. package/dist/chunk-ARX4JV5T.js.map +1 -0
  39. package/dist/chunk-HBMFIJG2.js +13622 -0
  40. package/dist/chunk-HBMFIJG2.js.map +1 -0
  41. package/dist/chunk-HS5G33FO.js +6894 -0
  42. package/dist/chunk-HS5G33FO.js.map +1 -0
  43. package/dist/{chunk-UKQFSXGC.js → chunk-MAFNMG2O.js} +2419 -13726
  44. package/dist/chunk-MAFNMG2O.js.map +1 -0
  45. package/dist/{chunk-XJLFFRQP.js → chunk-UC7SY3G5.js} +3744 -25994
  46. package/dist/chunk-UC7SY3G5.js.map +1 -0
  47. package/dist/chunk-VSIUEXGV.js +4981 -0
  48. package/dist/chunk-VSIUEXGV.js.map +1 -0
  49. package/dist/chunk-XV6AO37F.js +9480 -0
  50. package/dist/chunk-XV6AO37F.js.map +1 -0
  51. package/dist/components/AccountConnectors.d.ts +13 -0
  52. package/dist/components/BrowserConnectionDialog.d.ts +7 -0
  53. package/dist/components/ChatInput.d.ts +1 -15
  54. package/dist/components/ConnectorAuthorizationProgress.d.ts +6 -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/PlanUpdateBlock.d.ts +0 -1
  62. package/dist/components/SessionPluginConfigForm.d.ts +3 -1
  63. package/dist/components/plugin-connector.d.ts +1 -0
  64. package/dist/connectors.d.ts +1 -0
  65. package/dist/connectors.js +9 -0
  66. package/dist/connectors.js.map +1 -0
  67. package/dist/embed/blade-chat-element.d.ts +0 -8
  68. package/dist/embed/entry.d.ts +8 -19
  69. package/dist/hooks/use-message-pin.d.ts +1 -1
  70. package/dist/host.d.ts +0 -4
  71. package/dist/index.d.ts +1 -0
  72. package/dist/index.js +12 -3
  73. package/dist/internal.d.ts +4 -2
  74. package/dist/internal.js +45 -70
  75. package/dist/internal.js.map +1 -1
  76. package/dist/lib/message-shortcuts.d.ts +5 -0
  77. package/dist/questions.d.ts +7 -0
  78. package/dist/questions.js +909 -0
  79. package/dist/questions.js.map +1 -0
  80. package/dist/rich-input/ConnectButton.d.ts +7 -5
  81. package/dist/rich-input/FileCompletionMenu.d.ts +5 -11
  82. package/dist/rich-input/InputActionSubmenu.d.ts +10 -0
  83. package/dist/rich-input/SkillActionMenu.d.ts +10 -0
  84. package/dist/rich-input/SkillStatusBar.d.ts +0 -6
  85. package/dist/rich-input/extensions/skill-mention.d.ts +3 -20
  86. package/dist/rich-input/index.d.ts +3 -4
  87. package/dist/rich-input/lib/composer-content.d.ts +7 -22
  88. package/dist/rich-input/lib/plugin-suggestions.d.ts +5 -5
  89. package/dist/rich-input/lib/reference-candidates.d.ts +0 -4
  90. package/dist/rich-input/lib/skill-suggestions.d.ts +1 -1
  91. package/dist/rich-input/lib/user-home.d.ts +0 -17
  92. package/dist/rich-input/services.d.ts +2 -3
  93. package/dist/rich-input/voice/VoiceWaveform.d.ts +0 -3
  94. package/dist/rich-input.js +786 -1300
  95. package/dist/rich-input.js.map +1 -1
  96. package/dist/style.css +16 -55
  97. package/dist/style.full.css +23 -77
  98. package/dist/tool-details.d.ts +8 -0
  99. package/dist/tool-details.js +24 -0
  100. package/dist/tool-details.js.map +1 -0
  101. package/package.json +15 -3
  102. package/public-api.md +10 -5
  103. package/dist/chat/tool-renderers/KbSearchRenderer.d.ts +0 -2
  104. package/dist/chat/tool-renderers/kb-search-result.d.ts +0 -19
  105. package/dist/chunk-IRBOKMF5.js +0 -258
  106. package/dist/chunk-IRBOKMF5.js.map +0 -1
  107. package/dist/chunk-UKQFSXGC.js.map +0 -1
  108. package/dist/chunk-XJLFFRQP.js.map +0 -1
  109. package/dist/lib/agent-computer-command.d.ts +0 -32
  110. package/dist/rich-input/extensions/kb-mention.d.ts +0 -18
  111. package/dist/rich-input/extensions/workflow-mention.d.ts +0 -10
  112. package/dist/rich-input/lib/kb-suggestions.d.ts +0 -37
@@ -3,7 +3,45 @@ import {
3
3
  PluginTriggerStack,
4
4
  selectionFromItem,
5
5
  triggerSummary
6
- } from "./chunk-IRBOKMF5.js";
6
+ } from "./chunk-2E6DQCXM.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-MAFNMG2O.js";
44
+ import "./chunk-ARX4JV5T.js";
7
45
  import {
8
46
  Archive,
9
47
  BookOpen,
@@ -37,32 +75,28 @@ import {
37
75
  Rocket,
38
76
  RotateCcw,
39
77
  Scissors,
78
+ Search,
40
79
  Send,
41
80
  Share2,
42
81
  Sparkles,
43
82
  Square,
44
83
  Terminal,
45
84
  X,
46
- chatTone,
47
85
  cn,
48
- cn2,
49
- dist_exports2 as dist_exports,
50
- getInputHistoryGeneration,
51
- getPluginSuggestionItems,
52
86
  notifyChat,
53
- onInputCachesReset,
54
- pluginRefsForSend,
55
- sendToSession,
56
87
  useBladeClient,
57
88
  useChatEnvironment,
58
89
  useChatRenderMode,
59
90
  useChatSessionDetail,
60
91
  useCurrentChatSessionId,
61
- useEffectEvent,
62
- usePortalContainer,
63
92
  useSessionHandle,
64
- useSessionState
65
- } from "./chunk-UKQFSXGC.js";
93
+ useSessionSource
94
+ } from "./chunk-VSIUEXGV.js";
95
+ import {
96
+ cn as cn2,
97
+ dist_exports4 as dist_exports,
98
+ usePortalContainer
99
+ } from "./chunk-HS5G33FO.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,345 +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/client-query.ts
295
- import { useCallback, useEffect, useSyncExternalStore as useSyncExternalStore2 } from "react";
296
- var EMPTY = { data: void 0, error: null, isLoading: false, isFetching: false };
297
- var caches = /* @__PURE__ */ new WeakMap();
298
- function entryFor(client, key) {
299
- let cache = caches.get(client);
300
- if (!cache) {
301
- const created = /* @__PURE__ */ new Map();
302
- cache = created;
303
- caches.set(client, created);
304
- onInputCachesReset(client, () => {
305
- for (const [key2, entry2] of created) {
306
- entry2.request = null;
307
- entry2.fetchedAt = 0;
308
- update(entry2, EMPTY);
309
- const load = loadersFor(client).get(key2);
310
- if (load && entry2.listeners.size > 0) void fetchClientQuery(client, key2, load, { force: true }).catch(() => {
311
- });
312
- }
313
- });
314
- }
315
- let entry = cache.get(key);
316
- if (!entry) {
317
- entry = { snapshot: EMPTY, fetchedAt: 0, request: null, listeners: /* @__PURE__ */ new Set() };
318
- cache.set(key, entry);
319
- }
320
- return entry;
321
- }
322
- function update(entry, patch) {
323
- entry.snapshot = { ...entry.snapshot, ...patch };
324
- for (const listener of [...entry.listeners]) listener();
325
- }
326
- function fetchClientQuery(client, key, load, { staleMs = 3e4, force = false } = {}) {
327
- const entry = entryFor(client, key);
328
- if (entry.request) return entry.request;
329
- if (!force && entry.snapshot.data !== void 0 && Date.now() - entry.fetchedAt < staleMs) {
330
- return Promise.resolve(entry.snapshot.data);
331
- }
332
- const request = Promise.resolve().then(() => load(client));
333
- entry.request = request;
334
- update(entry, { isFetching: true, isLoading: entry.snapshot.data === void 0 });
335
- request.then(
336
- (data) => {
337
- if (entry.request !== request) return;
338
- entry.request = null;
339
- entry.fetchedAt = Date.now();
340
- update(entry, { data, error: null, isFetching: false, isLoading: false });
341
- },
342
- (error) => {
343
- if (entry.request !== request) return;
344
- entry.request = null;
345
- update(entry, { error, isFetching: false, isLoading: false });
346
- }
347
- );
348
- return request;
349
- }
350
- function setClientQueryData(client, key, updater) {
351
- const entry = entryFor(client, key);
352
- if (entry.snapshot.data === void 0) return;
353
- update(entry, { data: updater(entry.snapshot.data) });
354
- }
355
- function useClientQuery(key, load, { staleMs = 3e4 } = {}) {
356
- const client = useBladeClient();
357
- const subscribe = useCallback(
358
- (listener) => {
359
- if (!key) return () => {
360
- };
361
- const entry = entryFor(client, key);
362
- entry.listeners.add(listener);
363
- return () => {
364
- entry.listeners.delete(listener);
365
- };
366
- },
367
- [client, key]
368
- );
369
- const snapshot = useSyncExternalStore2(
370
- subscribe,
371
- () => key ? entryFor(client, key).snapshot : EMPTY,
372
- () => key ? entryFor(client, key).snapshot : EMPTY
373
- );
374
- if (key) loadersFor(client).set(key, load);
375
- useEffect(() => {
376
- if (!key) return;
377
- const registered = loadersFor(client).get(key);
378
- if (registered) void fetchClientQuery(client, key, registered, { staleMs }).catch(() => {
379
- });
380
- }, [client, key, staleMs]);
381
- const refetch = useCallback(async () => {
382
- if (!key) return void 0;
383
- const registered = loadersFor(client).get(key);
384
- if (!registered) return void 0;
385
- return fetchClientQuery(client, key, registered, { force: true }).catch(() => void 0);
386
- }, [client, key]);
387
- return { ...snapshot, refetch };
388
- }
389
- var loaderRegistry = /* @__PURE__ */ new WeakMap();
390
- function loadersFor(client) {
391
- let loaders = loaderRegistry.get(client);
392
- if (!loaders) {
393
- loaders = /* @__PURE__ */ new Map();
394
- loaderRegistry.set(client, loaders);
395
- }
396
- return loaders;
397
- }
398
- function refreshClientQuery(client, key) {
399
- const entry = caches.get(client)?.get(key);
400
- if (!entry) return;
401
- entry.fetchedAt = 0;
402
- const load = loadersFor(client).get(key);
403
- if (load && entry.listeners.size > 0) void fetchClientQuery(client, key, load, { force: true }).catch(() => {
404
- });
405
- }
406
-
407
- // src/rich-input/lib/session-data.ts
408
- import { useEffect as useEffect2, useRef } from "react";
409
- var sessionPath = (sessionId, rest) => `/api/sessions/${encodeURIComponent(sessionId)}/${rest}`;
410
- function useRefreshWhenRunEnds(sessionId, keys3) {
411
- const client = useBladeClient();
412
- const streaming = useSessionState(sessionId, (state3) => state3.isStreaming);
413
- const wasStreaming = useRef(streaming);
414
- useEffect2(() => {
415
- if (wasStreaming.current && !streaming) {
416
- for (const key of keys3) refreshClientQuery(client, key);
417
- }
418
- wasStreaming.current = streaming;
419
- });
420
- }
421
- function useClientSessionSkills(sessionId) {
422
- const key = sessionId ? `session-skills:${sessionId}` : null;
423
- const query = useClientQuery(
424
- key,
425
- (client) => client.json("GET", sessionPath(sessionId ?? "", "skills"))
426
- );
427
- useRefreshWhenRunEnds(sessionId, key ? [key] : []);
428
- return { data: query.data, loading: query.isLoading, error: query.error };
429
- }
430
- function useClientSkillStats(sessionId) {
431
- const key = sessionId ? `skill-stats:${sessionId}` : null;
432
- const query = useClientQuery(key, (client) => client.json("GET", sessionPath(sessionId ?? "", "skill-stats")), {
433
- staleMs: 3e5
434
- });
435
- useRefreshWhenRunEnds(sessionId, key ? [key] : []);
436
- return { data: query.data, loading: query.isLoading, error: query.error };
437
- }
438
- function useClientContextStats(sessionId) {
439
- const key = sessionId ? `context-stats:${sessionId}` : null;
440
- const query = useClientQuery(
441
- key,
442
- (client) => client.json("GET", sessionPath(sessionId ?? "", "context-stats"))
443
- );
444
- useRefreshWhenRunEnds(sessionId, key ? [key] : []);
445
- return { data: query.data, loading: query.isLoading, error: query.error };
446
- }
447
- function useClientBackgroundTasks(sessionId) {
448
- const client = useBladeClient();
449
- const key = sessionId ? `background-tasks:${sessionId}` : null;
450
- const query = useClientQuery(key, (c) => c.sessions.listBackgroundTasks(sessionId ?? ""));
451
- const session = useSessionHandle(sessionId);
452
- useEffect2(() => {
453
- if (!session || !key) return;
454
- return session.on("backgroundTask", () => refreshClientQuery(client, key));
455
- }, [client, key, session]);
456
- return { data: query.data, loading: query.isLoading, error: query.error };
457
- }
458
- function refreshClientSessionSkills(client, sessionId) {
459
- refreshClientQuery(client, `session-skills:${sessionId}`);
460
- refreshClientQuery(client, `skill-stats:${sessionId}`);
461
- }
462
- function useClientSessionModel(sessionId) {
463
- const key = sessionId ? `session-detail:${sessionId}` : null;
464
- const query = useClientQuery(key, (client) => client.sessions.getSession(sessionId ?? ""));
465
- useRefreshWhenRunEnds(sessionId, key ? [key] : []);
466
- return query.data?.model ?? null;
467
- }
468
-
469
- // src/rich-input/model/model-data.ts
470
- var EMPTY_MODELS = [];
471
- var EMPTY_IDS = [];
472
- var CATALOG_KEY = "model-catalog";
473
- function useClientModelCatalog() {
474
- const { data, isLoading, isFetching, refetch } = useClientQuery(
475
- CATALOG_KEY,
476
- (client) => client.json("GET", "/api/config/models"),
477
- // 模型服务在设置里随时可改:打开选择器时总是重新拉一次(见 ModelSelector)
478
- { staleMs: 0 }
479
- );
480
- return {
481
- models: data?.models ?? EMPTY_MODELS,
482
- defaultModel: data?.default ?? "",
483
- thinkingAvailable: data?.thinkingAvailable ?? false,
484
- unavailableProviderIds: data?.unavailableProviderIds ?? EMPTY_IDS,
485
- unavailableModelIds: data?.unavailableModelIds ?? EMPTY_IDS,
486
- isLoading,
487
- isFetching,
488
- refresh: async () => {
489
- await refetch();
490
- }
491
- };
492
- }
493
- var PREFERRED_MODEL_KEY = "preferred_model";
494
- var MODEL_REASONING_LEVELS_KEY = "llm.model_thinking_preferences";
495
- var PREFERENCES_KEY = "model-preferences";
496
- function loadPreferences(client) {
497
- const query = new URLSearchParams();
498
- query.append("key", PREFERRED_MODEL_KEY);
499
- query.append("key", MODEL_REASONING_LEVELS_KEY);
500
- return client.json("GET", `/api/user/preferences?${query.toString()}`).then((response) => response.values ?? {});
501
- }
502
- async function writePreference(client, key, value) {
503
- const previous = await fetchClientQuery(client, PREFERENCES_KEY, loadPreferences, { staleMs: 6e4 }).catch(
504
- () => ({})
505
- );
506
- setClientQueryData(client, PREFERENCES_KEY, (current) => ({ ...current, [key]: value }));
507
- try {
508
- await client.json("PUT", `/api/user/preferences/${encodeURIComponent(key)}`, { value });
509
- } catch {
510
- setClientQueryData(client, PREFERENCES_KEY, (current) => ({ ...current, [key]: previous[key] ?? null }));
511
- }
512
- }
513
- var EMPTY_LEVELS = {};
514
- function useClientModelPreferences() {
515
- const client = useBladeClient();
516
- const { data } = useClientQuery(PREFERENCES_KEY, loadPreferences, { staleMs: 6e4 });
517
- const rawLevels = data?.[MODEL_REASONING_LEVELS_KEY] ?? null;
518
- const reasoningLevels = rawLevels ? parseModelReasoningLevels(rawLevels) : EMPTY_LEVELS;
519
- return {
520
- preferredModel: data?.[PREFERRED_MODEL_KEY] ?? null,
521
- setPreferredModel: (modelId) => void writePreference(client, PREFERRED_MODEL_KEY, modelId),
522
- reasoningLevels,
523
- setReasoningLevel: (modelId, level) => {
524
- if (!modelId) return;
525
- void writePreference(
526
- client,
527
- MODEL_REASONING_LEVELS_KEY,
528
- JSON.stringify({ ...reasoningLevels, [modelId]: level })
529
- );
530
- }
531
- };
532
- }
533
-
534
- // src/rich-input/services.tsx
535
- function useModelCatalog() {
536
- const use = useRichInputServices().useModelCatalog ?? useClientModelCatalog;
537
- return use();
538
- }
539
- function useModelPreferences() {
540
- const use = useRichInputServices().useModelPreferences ?? useClientModelPreferences;
541
- return use();
542
- }
543
- function loadKnowledgeBases(client) {
544
- return client.json("GET", "/api/registry/kb").then(
545
- (response) => (Array.isArray(response) ? response : response?.items ?? []).filter((item) => typeof item?.id === "number")
546
- );
547
- }
548
- function useClientKnowledgeBaseLoader() {
549
- const client = useBladeClient();
550
- return useMemo(
551
- () => () => fetchClientQuery(client, "knowledge-bases", loadKnowledgeBases, { staleMs: 6e4 }),
552
- [client]
553
- );
554
- }
555
- function useKnowledgeBaseLoader() {
556
- const use = useRichInputServices().useKnowledgeBaseLoader ?? useClientKnowledgeBaseLoader;
557
- return use();
558
- }
559
- function useSessionConnection(sessionId) {
560
- const connection = useSessionState(sessionId, (state3) => state3.connection);
561
- const status = sessionId ? connection : "connected";
562
- const everConnected = useRef2(false);
563
- if (status === "connected") everConnected.current = true;
564
- return { status, reconnectAttempt: 0, hasEverConnected: everConnected.current };
565
- }
566
- function useComposerConnectionInfo(sessionId) {
567
- const use = useRichInputServices().useConnection ?? useSessionConnection;
568
- return use(sessionId);
569
- }
570
- function useComposerConnection(sessionId) {
571
- return useComposerConnectionInfo(sessionId).status;
572
- }
573
- function useSessionSkills(sessionId) {
574
- const use = useRichInputServices().useSessionSkills ?? useClientSessionSkills;
575
- return use(sessionId);
576
- }
577
- function useSkillStats(sessionId) {
578
- const use = useRichInputServices().useSkillStats ?? useClientSkillStats;
579
- return use(sessionId);
580
- }
581
- function useContextStats(sessionId) {
582
- const use = useRichInputServices().useContextStats ?? useClientContextStats;
583
- return use(sessionId);
584
- }
585
- function useBackgroundTaskList(sessionId) {
586
- const use = useRichInputServices().useBackgroundTasks ?? useClientBackgroundTasks;
587
- return use(sessionId);
588
- }
589
- function useClientSessionDataInvalidation() {
590
- const client = useBladeClient();
591
- return useMemo(
592
- () => ({
593
- filesUploaded: (_sessionId) => {
594
- },
595
- pluginsChanged: (sessionId) => refreshClientSessionSkills(client, sessionId)
596
- }),
597
- [client]
598
- );
599
- }
600
- function useSessionDataInvalidation() {
601
- const use = useRichInputServices().useSessionDataInvalidation ?? useClientSessionDataInvalidation;
602
- return use();
603
- }
604
-
605
299
  // src/rich-input/lib/background-tasks-view.ts
606
300
  var LIVE_STATUSES = /* @__PURE__ */ new Set(["starting", "running", "cancelling"]);
607
301
  var ATTENTION_STATUSES = /* @__PURE__ */ new Set(["failed", "lost"]);
@@ -613,7 +307,6 @@ var STATUS_LABELS = {
613
307
  succeeded: "\u5DF2\u5B8C\u6210",
614
308
  cancelled: "\u5DF2\u505C\u6B62",
615
309
  failed: "\u5931\u8D25",
616
- // 不是失败:平台只是不再能追踪这个进程,它可能还在跑。
617
310
  lost: "\u72B6\u6001\u672A\u77E5"
618
311
  };
619
312
  function statusLabel(status) {
@@ -662,7 +355,7 @@ function formatStartedAt(value, now = /* @__PURE__ */ new Date()) {
662
355
  }
663
356
 
664
357
  // src/rich-input/BackgroundTasksPill.tsx
665
- import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
358
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
666
359
  var NO_TASKS = [];
667
360
  function TaskCard({
668
361
  task,
@@ -672,8 +365,8 @@ function TaskCard({
672
365
  }) {
673
366
  return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-[hsl(var(--border))] p-2", children: [
674
367
  /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2", children: [
675
- /* @__PURE__ */ jsx2("div", { className: "min-w-0 break-words text-[hsl(var(--foreground))]", children: task.description || task.command }),
676
- /* @__PURE__ */ jsx2(
368
+ /* @__PURE__ */ jsx("div", { className: "min-w-0 break-words text-[hsl(var(--foreground))]", children: task.description || task.command }),
369
+ /* @__PURE__ */ jsx(
677
370
  "span",
678
371
  {
679
372
  className: cn(
@@ -684,10 +377,10 @@ function TaskCard({
684
377
  }
685
378
  )
686
379
  ] }),
687
- 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,
688
381
  /* @__PURE__ */ jsxs("div", { className: "mt-1 flex items-center gap-1.5 text-[10px] text-[hsl(var(--muted-foreground))]/60", children: [
689
- /* @__PURE__ */ jsx2("span", { children: formatStartedAt(task.started_at) }),
690
- /* @__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 })
691
384
  ] }),
692
385
  /* @__PURE__ */ jsxs("div", { className: "mt-2 flex items-center gap-1.5", children: [
693
386
  /* @__PURE__ */ jsxs(
@@ -697,7 +390,7 @@ function TaskCard({
697
390
  onClick: onOpenLog,
698
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))]",
699
392
  children: [
700
- /* @__PURE__ */ jsx2(FileText, { size: 12 }),
393
+ /* @__PURE__ */ jsx(FileText, { size: 12 }),
701
394
  "\u65E5\u5FD7"
702
395
  ]
703
396
  }
@@ -709,7 +402,7 @@ function TaskCard({
709
402
  onClick: onStop,
710
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))]",
711
404
  children: [
712
- /* @__PURE__ */ jsx2(Square, { size: 10 }),
405
+ /* @__PURE__ */ jsx(Square, { size: 10 }),
713
406
  "\u505C\u6B62"
714
407
  ]
715
408
  }
@@ -721,7 +414,7 @@ function TaskCard({
721
414
  onClick: onDismiss,
722
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))]",
723
416
  children: [
724
- /* @__PURE__ */ jsx2(EyeOff, { size: 12 }),
417
+ /* @__PURE__ */ jsx(EyeOff, { size: 12 }),
725
418
  "\u9690\u85CF"
726
419
  ]
727
420
  }
@@ -738,7 +431,7 @@ function BackgroundTasksPill({ sessionId }) {
738
431
  const [historyOverride, setHistoryOverride] = useState(null);
739
432
  const [logTask, setLogTask] = useState(null);
740
433
  const [logDialogOpen, setLogDialogOpen] = useState(false);
741
- const { activeTasks, historyTasks, runningCount, attentionCount } = useMemo2(
434
+ const { activeTasks, historyTasks, runningCount, attentionCount } = useMemo(
742
435
  () => splitTasks(tasks, dismissed),
743
436
  [tasks, dismissed]
744
437
  );
@@ -772,7 +465,6 @@ function BackgroundTasksPill({ sessionId }) {
772
465
  title,
773
466
  output: "",
774
467
  loading: false,
775
- // 跟丢或过期的任务,控制目录可能已经被回收,报错串对用户没有意义。
776
468
  error: "\u65E5\u5FD7\u5DF2\u65E0\u6CD5\u8BFB\u53D6\uFF0C\u53EF\u80FD\u5DF2\u88AB\u6E05\u7406"
777
469
  });
778
470
  }
@@ -785,7 +477,7 @@ function BackgroundTasksPill({ sessionId }) {
785
477
  closePanel();
786
478
  };
787
479
  return /* @__PURE__ */ jsxs(Fragment, { children: [
788
- /* @__PURE__ */ jsx2(
480
+ /* @__PURE__ */ jsx(
789
481
  Dialog,
790
482
  {
791
483
  open: logDialogOpen,
@@ -800,10 +492,10 @@ function BackgroundTasksPill({ sessionId }) {
800
492
  children: [
801
493
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 border-b border-[hsl(var(--border))] px-4 py-3", children: [
802
494
  /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
803
- /* @__PURE__ */ jsx2(DialogTitle, { className: "truncate text-sm font-medium text-[hsl(var(--foreground))]", children: logTask?.title }),
804
- /* @__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" })
805
497
  ] }),
806
- /* @__PURE__ */ jsx2(
498
+ /* @__PURE__ */ jsx(
807
499
  "button",
808
500
  {
809
501
  type: "button",
@@ -813,7 +505,7 @@ function BackgroundTasksPill({ sessionId }) {
813
505
  }
814
506
  )
815
507
  ] }),
816
- /* @__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 })
817
509
  ]
818
510
  }
819
511
  )
@@ -835,8 +527,8 @@ function BackgroundTasksPill({ sessionId }) {
835
527
  title: summary,
836
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))]",
837
529
  children: [
838
- /* @__PURE__ */ jsx2(Terminal, { size: 16 }),
839
- 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(
840
532
  "span",
841
533
  {
842
534
  "data-attention-dot": "true",
@@ -846,64 +538,59 @@ function BackgroundTasksPill({ sessionId }) {
846
538
  ]
847
539
  }
848
540
  ),
849
- open ? (
850
- // before 那层透明桥接盖住浮层和按钮之间 mb-2 的空隙:没有它,鼠标从按钮
851
- // 移向浮层会先穿过一段"两者都不在"的空白,onMouseLeave 立刻收起浮层,
852
- // 里面的日志/停止按钮根本点不到。
853
- /* @__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: [
854
- activeTasks.map((task) => /* @__PURE__ */ jsx2(
855
- TaskCard,
856
- {
857
- task,
858
- onOpenLog: () => void openTaskLog(task),
859
- onStop: () => requestStopTask(task),
860
- onDismiss: ATTENTION_STATUSES.has(task.status) ? () => hideTask(task.id) : null
861
- },
862
- task.id
863
- )),
864
- historyTasks.length > 0 ? /* @__PURE__ */ jsxs(
865
- "div",
866
- {
867
- className: cn(
868
- 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
+ }
869
579
  ),
870
- children: [
871
- /* @__PURE__ */ jsxs(
872
- "button",
873
- {
874
- type: "button",
875
- onClick: () => setHistoryOverride(!historyOpen),
876
- "aria-expanded": historyOpen,
877
- 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))]",
878
- children: [
879
- /* @__PURE__ */ jsx2(
880
- ChevronDown,
881
- {
882
- size: 12,
883
- className: cn("transition-transform", historyOpen ? "" : "-rotate-90")
884
- }
885
- ),
886
- "\u5386\u53F2\u540E\u53F0\u4EFB\u52A1\uFF08",
887
- historyTasks.length,
888
- "\uFF09"
889
- ]
890
- }
891
- ),
892
- historyOpen ? /* @__PURE__ */ jsx2("div", { className: "mt-2 space-y-2", children: historyTasks.map((task) => /* @__PURE__ */ jsx2(
893
- TaskCard,
894
- {
895
- task,
896
- onOpenLog: () => void openTaskLog(task),
897
- onStop: () => requestStopTask(task),
898
- onDismiss: null
899
- },
900
- task.id
901
- )) }) : null
902
- ]
903
- }
904
- ) : null
905
- ] }) })
906
- ) : 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
907
594
  ]
908
595
  }
909
596
  )
@@ -12268,7 +11955,7 @@ function resolveSelection(view, doc3, parsedSel) {
12268
11955
  }
12269
11956
  function isMarkChange(cur, prev) {
12270
11957
  let curMarks = cur.firstChild.marks, prevMarks = prev.firstChild.marks;
12271
- let added = curMarks, removed = prevMarks, type, mark, update2;
11958
+ let added = curMarks, removed = prevMarks, type, mark, update;
12272
11959
  for (let i = 0; i < prevMarks.length; i++)
12273
11960
  added = prevMarks[i].removeFromSet(added);
12274
11961
  for (let i = 0; i < curMarks.length; i++)
@@ -12276,17 +11963,17 @@ function isMarkChange(cur, prev) {
12276
11963
  if (added.length == 1 && removed.length == 0) {
12277
11964
  mark = added[0];
12278
11965
  type = "add";
12279
- update2 = (node) => node.mark(mark.addToSet(node.marks));
11966
+ update = (node) => node.mark(mark.addToSet(node.marks));
12280
11967
  } else if (added.length == 0 && removed.length == 1) {
12281
11968
  mark = removed[0];
12282
11969
  type = "remove";
12283
- update2 = (node) => node.mark(mark.removeFromSet(node.marks));
11970
+ update = (node) => node.mark(mark.removeFromSet(node.marks));
12284
11971
  } else {
12285
11972
  return null;
12286
11973
  }
12287
11974
  let updated = [];
12288
11975
  for (let i = 0; i < prev.childCount; i++)
12289
- updated.push(update2(prev.child(i)));
11976
+ updated.push(update(prev.child(i)));
12290
11977
  if (Fragment2.from(updated).eq(cur))
12291
11978
  return { mark, type };
12292
11979
  }
@@ -18962,7 +18649,7 @@ var PluginMention = index_default.extend({
18962
18649
  });
18963
18650
 
18964
18651
  // src/rich-input/lib/composer-content.ts
18965
- import { normalizePluginRefs, normalizeTopicAssetRefs } from "@blade-hq/agent-client";
18652
+ import { normalizePluginRefs, normalizeMessageRefs, normalizeTopicAssetRefs } from "@blade-hq/agent-client";
18966
18653
  function serializeEditorContent(node) {
18967
18654
  if (!node) return "";
18968
18655
  if (node.type === "text") {
@@ -18977,21 +18664,13 @@ function serializeEditorContent(node) {
18977
18664
  }
18978
18665
  if (node.type === "skillMention") {
18979
18666
  const skillId = typeof node.attrs?.skillId === "string" ? node.attrs.skillId : "";
18980
- return skillId ? `<skill>${skillId}</skill>` : "";
18981
- }
18982
- if (node.type === "workflowMention") {
18983
- const name = typeof node.attrs?.name === "string" ? node.attrs.name : "";
18984
- return name ? `\u8FD0\u884C\u5DE5\u4F5C\u6D41 ${name}` : "";
18667
+ return skillId ? `@${node.attrs?.displayName || skillId}` : "";
18985
18668
  }
18986
18669
  if (node.type === "pluginMention") return `@${node.attrs?.label ?? ""}`;
18987
18670
  if (node.type === "topicAssetMention") {
18988
18671
  const path = typeof node.attrs?.path === "string" ? node.attrs.path : "";
18989
18672
  return path ? `@${path}` : "";
18990
18673
  }
18991
- if (node.type === "kbMention") {
18992
- const name = kbMentionName(node);
18993
- return name ? `@${name}` : "";
18994
- }
18995
18674
  const children = (node.content ?? []).map((child) => serializeEditorContent(child));
18996
18675
  if (node.type === "doc") {
18997
18676
  return children.join("\n");
@@ -19005,14 +18684,11 @@ function scanLeadingSkillMention(node, seenContent) {
19005
18684
  if (node.type === "text") {
19006
18685
  return { skill: null, seenContent: seenContent || /\S/.test(node.text ?? "") };
19007
18686
  }
19008
- if (node.type === "hardBreak" || node.type === "fileMention" || node.type === "workflowMention") {
18687
+ if (node.type === "hardBreak" || node.type === "fileMention") {
19009
18688
  return { skill: null, seenContent: true };
19010
18689
  }
19011
18690
  if (node.type === "pluginMention") return { skill: null, seenContent };
19012
18691
  if (node.type === "topicAssetMention") return { skill: null, seenContent };
19013
- if (node.type === "kbMention") {
19014
- return { skill: null, seenContent };
19015
- }
19016
18692
  if (node.type === "skillMention") {
19017
18693
  const skillId = typeof node.attrs?.skillId === "string" ? node.attrs.skillId : null;
19018
18694
  return {
@@ -19037,70 +18713,6 @@ function scanLeadingSkillMention(node, seenContent) {
19037
18713
  function findLeadingSkillMention(node) {
19038
18714
  return scanLeadingSkillMention(node, false).skill;
19039
18715
  }
19040
- function kbMentionName(node) {
19041
- const name = typeof node.attrs?.name === "string" ? node.attrs.name.trim() : "";
19042
- if (name) return name;
19043
- const kbId = node.attrs?.kbId;
19044
- return typeof kbId === "number" && kbId > 0 ? `\u77E5\u8BC6\u5E93 #${kbId}` : "";
19045
- }
19046
- function collectKbMentions(node) {
19047
- const result = [];
19048
- const seen = /* @__PURE__ */ new Set();
19049
- const visit = (current) => {
19050
- if (!current) return;
19051
- if (current.type === "kbMention") {
19052
- const kbId = current.attrs?.kbId;
19053
- if (typeof kbId === "number" && Number.isInteger(kbId) && kbId > 0 && !seen.has(kbId)) {
19054
- seen.add(kbId);
19055
- result.push({ kbId, name: kbMentionName(current) });
19056
- }
19057
- return;
19058
- }
19059
- for (const child of current.content ?? []) visit(child);
19060
- };
19061
- visit(node);
19062
- return result;
19063
- }
19064
- function buildEditorDocumentWithKbMentions(text, kbMentions) {
19065
- return {
19066
- type: "doc",
19067
- content: text.split("\n").map((line) => ({
19068
- type: "paragraph",
19069
- content: line ? buildLineContentWithKbMentions(line, kbMentions) : []
19070
- }))
19071
- };
19072
- }
19073
- function buildLineContentWithKbMentions(line, kbMentions) {
19074
- if (kbMentions.length === 0) {
19075
- return [{ type: "text", text: line }];
19076
- }
19077
- const matches2 = [];
19078
- for (const mention of kbMentions) {
19079
- if (!mention.name) continue;
19080
- const marker = `@${mention.name}`;
19081
- const index = line.indexOf(marker);
19082
- if (index === -1) continue;
19083
- if (matches2.some((m) => index < m.end && index + marker.length > m.start)) continue;
19084
- matches2.push({ start: index, end: index + marker.length, kbId: mention.kbId, name: mention.name });
19085
- }
19086
- if (matches2.length === 0) {
19087
- return [{ type: "text", text: line }];
19088
- }
19089
- matches2.sort((a, b) => a.start - b.start);
19090
- const content = [];
19091
- let cursor = 0;
19092
- for (const match of matches2) {
19093
- if (match.start > cursor) {
19094
- content.push({ type: "text", text: line.slice(cursor, match.start) });
19095
- }
19096
- content.push({ type: "kbMention", attrs: { kbId: match.kbId, name: match.name } });
19097
- cursor = match.end;
19098
- }
19099
- if (cursor < line.length) {
19100
- content.push({ type: "text", text: line.slice(cursor) });
19101
- }
19102
- return content;
19103
- }
19104
18716
  function collectTopicAssetMentions(node) {
19105
18717
  const refs = [];
19106
18718
  const visit = (current) => {
@@ -19111,8 +18723,8 @@ function collectTopicAssetMentions(node) {
19111
18723
  visit(node);
19112
18724
  return normalizeTopicAssetRefs(refs);
19113
18725
  }
19114
- function buildEditorDocumentWithMentions(text, kbMentions = [], topicAssetRefs = []) {
19115
- const doc3 = buildEditorDocumentWithKbMentions(text, kbMentions);
18726
+ function buildEditorDocumentWithMentions(text, topicAssetRefs = []) {
18727
+ const doc3 = buildEditorDocument(text);
19116
18728
  const replace2 = (node) => {
19117
18729
  if (node.type !== "text") return [{ ...node, ...node.content ? { content: node.content.flatMap(replace2) } : {} }];
19118
18730
  let nodes = [node];
@@ -19151,6 +18763,30 @@ function collectPluginMentions(node) {
19151
18763
  visit(node);
19152
18764
  return normalizePluginRefs(refs);
19153
18765
  }
18766
+ function buildEditorDocument(text) {
18767
+ return { type: "doc", content: text.split("\n").map((line) => ({ type: "paragraph", content: line ? [{ type: "text", text: line }] : [] })) };
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
+ }
19154
18790
 
19155
18791
  // src/rich-input/extensions/topic-asset-mention.ts
19156
18792
  function isTopicAssetSuggestionItem(value) {
@@ -19174,7 +18810,7 @@ var TopicAssetMention = index_default.extend({
19174
18810
  class: "file-mention-pill topic-asset-mention-pill",
19175
18811
  "data-topic-id": node.attrs.topic_id,
19176
18812
  "data-path": node.attrs.path,
19177
- title: `\u4E3B\u9898\u8D44\u4EA7\uFF1A${node.attrs.path}`
18813
+ title: `\u5DE5\u4F5C\u7A7A\u95F4\u8D44\u4EA7\uFF1A${node.attrs.path}`
19178
18814
  }, `@${node.attrs.path}`]
19179
18815
  };
19180
18816
  },
@@ -19191,7 +18827,7 @@ var TopicAssetMention = index_default.extend({
19191
18827
 
19192
18828
  // src/chat/runtime/composer-channels.ts
19193
18829
  import { normalizeTopicAssetRefs as normalizeTopicAssetRefs2 } from "@blade-hq/agent-client";
19194
- import { useSyncExternalStore as useSyncExternalStore3 } from "react";
18830
+ import { useSyncExternalStore as useSyncExternalStore2 } from "react";
19195
18831
  function buildSignalId() {
19196
18832
  if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
19197
18833
  return crypto.randomUUID();
@@ -19213,8 +18849,8 @@ var state2 = {
19213
18849
  rewindDrafts: {}
19214
18850
  };
19215
18851
  var listeners2 = /* @__PURE__ */ new Set();
19216
- function setState(update2) {
19217
- const next = update2(state2);
18852
+ function setState(update) {
18853
+ const next = update(state2);
19218
18854
  if (next === state2) return;
19219
18855
  state2 = next;
19220
18856
  for (const listener of [...listeners2]) listener();
@@ -19299,13 +18935,11 @@ var composerChannels = {
19299
18935
  clearModelDraft(sessionId) {
19300
18936
  setState((current) => ({ ...current, modelDrafts: withoutKey(current.modelDrafts, sessionId) }));
19301
18937
  },
19302
- /** 回退到某一步后,把那一步的用户原话放回输入框(null 清除)。 */
19303
18938
  setRewindDraft(sessionId, text) {
19304
18939
  setState(
19305
18940
  (current) => text === null ? { ...current, rewindDrafts: withoutKey(current.rewindDrafts, sessionId) } : { ...current, rewindDrafts: { ...current.rewindDrafts, [sessionId]: text } }
19306
18941
  );
19307
18942
  },
19308
- /** 会话被关闭 / 删除:清掉它还没被取走的信号。 */
19309
18943
  clearSession(sessionId) {
19310
18944
  setState((current) => ({
19311
18945
  ...current,
@@ -19315,13 +18949,12 @@ var composerChannels = {
19315
18949
  sendRequests: withoutKey(current.sendRequests, sessionId)
19316
18950
  }));
19317
18951
  },
19318
- /** 换身份:清空全部通道。 */
19319
18952
  reset() {
19320
18953
  setState(() => ({ topicAssetReferences: {}, pendingContexts: {}, draftAppends: {}, sendRequests: {}, modelDrafts: {}, rewindDrafts: {} }));
19321
18954
  }
19322
18955
  };
19323
18956
  function useComposerChannels(selector) {
19324
- return useSyncExternalStore3(
18957
+ return useSyncExternalStore2(
19325
18958
  composerChannels.subscribe,
19326
18959
  () => selector(state2),
19327
18960
  () => selector(state2)
@@ -19335,7 +18968,7 @@ async function getTopicAssetSuggestionItems(client, topicId, query) {
19335
18968
  const result = await client.chatGroups.listAssets(topicId);
19336
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 }));
19337
18970
  } catch {
19338
- 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" }];
19339
18972
  }
19340
18973
  }
19341
18974
  function queueTopicAssetReference(sessionId, ref) {
@@ -19343,22 +18976,9 @@ function queueTopicAssetReference(sessionId, ref) {
19343
18976
  }
19344
18977
 
19345
18978
  // src/rich-input/use-dismiss-skill-suggestions-on-mode-change.ts
19346
- import { useEffect as useEffect3, useRef as useRef3 } from "react";
18979
+ import { useEffect, useRef } from "react";
19347
18980
 
19348
18981
  // src/rich-input/extensions/skill-mention.ts
19349
- function workflowParamsTail(item) {
19350
- const params = (item.inputs ?? []).filter((p) => p.name);
19351
- if (params.length === 0) return " ";
19352
- const filled = params.map((p) => {
19353
- const hasDefault = p.default !== void 0 && p.default !== null;
19354
- const value = hasDefault ? typeof p.default === "string" ? p.default : JSON.stringify(p.default) : `<${p.description || "\u586B\u503C"}>`;
19355
- return `${p.name}=${value}`;
19356
- }).join(" ");
19357
- return ` ${filled} `;
19358
- }
19359
- function workflowRunText(item) {
19360
- return `\u8FD0\u884C\u5DE5\u4F5C\u6D41 ${item.name}${workflowParamsTail(item)}`.trimEnd();
19361
- }
19362
18982
  var skillMentionSuggestionKey = new PluginKey("skillMentionSuggestion");
19363
18983
  function getSkillMentionName(attrs) {
19364
18984
  return attrs.displayName || attrs.skillId || "";
@@ -19440,8 +19060,8 @@ var SkillMention = index_default.extend({
19440
19060
  // src/rich-input/use-dismiss-skill-suggestions-on-mode-change.ts
19441
19061
  function useDismissSkillSuggestionsOnModeChange(editor) {
19442
19062
  const renderMode = useChatRenderMode();
19443
- const previousRef = useRef3(renderMode);
19444
- useEffect3(() => {
19063
+ const previousRef = useRef(renderMode);
19064
+ useEffect(() => {
19445
19065
  if (previousRef.current === renderMode) return;
19446
19066
  previousRef.current = renderMode;
19447
19067
  if (editor && !editor.isDestroyed && skillMentionSuggestionKey.getState(editor.state)?.active) {
@@ -19452,12 +19072,12 @@ function useDismissSkillSuggestionsOnModeChange(editor) {
19452
19072
 
19453
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
19454
19074
  var import_shim = __toESM(require_shim(), 1);
19455
- import { createContext as createContext2, useContext as useContext2, useMemo as useMemo3 } from "react";
19075
+ import { createContext, useContext, useMemo as useMemo2 } from "react";
19456
19076
  import React, { forwardRef } from "react";
19457
19077
  import ReactDOM from "react-dom";
19458
- 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";
19459
19079
  var import_shim2 = __toESM(require_shim(), 1);
19460
- 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";
19461
19081
 
19462
19082
  // ../../node_modules/.pnpm/fast-equals@5.4.0/node_modules/fast-equals/dist/es/index.mjs
19463
19083
  var { getOwnPropertyNames, getOwnPropertySymbols } = Object;
@@ -19899,10 +19519,10 @@ function createCustomEqual(options = {}) {
19899
19519
 
19900
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
19901
19521
  var import_with_selector = __toESM(require_with_selector(), 1);
19902
- import { useDebugValue, useEffect as useEffect4, useLayoutEffect, useState as useState3 } from "react";
19522
+ import { useDebugValue, useEffect as useEffect3, useLayoutEffect, useState as useState3 } from "react";
19903
19523
  import { jsx as jsx22, jsxs as jsxs22 } from "react/jsx-runtime";
19904
- import { createContext as createContext22, createElement, useContext as useContext22 } from "react";
19905
- 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";
19906
19526
  import React3 from "react";
19907
19527
  import { jsx as jsx4 } from "react/jsx-runtime";
19908
19528
  import React4 from "react";
@@ -19932,7 +19552,7 @@ var Portals = ({ contentComponent }) => {
19932
19552
  contentComponent.getSnapshot,
19933
19553
  contentComponent.getServerSnapshot
19934
19554
  );
19935
- return /* @__PURE__ */ jsx3(Fragment3, { children: Object.values(renderers) });
19555
+ return /* @__PURE__ */ jsx2(Fragment3, { children: Object.values(renderers) });
19936
19556
  };
19937
19557
  function getInstance() {
19938
19558
  const subscribers = /* @__PURE__ */ new Set();
@@ -20053,8 +19673,8 @@ var PureEditorContent = class extends React.Component {
20053
19673
  render() {
20054
19674
  const { editor, innerRef, ...rest } = this.props;
20055
19675
  return /* @__PURE__ */ jsxs2(Fragment3, { children: [
20056
- /* @__PURE__ */ jsx3("div", { ref: mergeRefs(innerRef, this.editorContentRef), ...rest }),
20057
- (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 })
20058
19678
  ] });
20059
19679
  }
20060
19680
  };
@@ -20071,7 +19691,7 @@ var EditorContentWithKey = forwardRef(
20071
19691
  }
20072
19692
  );
20073
19693
  var EditorContent = React.memo(EditorContentWithKey);
20074
- var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect4;
19694
+ var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect3;
20075
19695
  var EditorStateManager = class {
20076
19696
  constructor(initialEditor) {
20077
19697
  this.transactionNumber = 0;
@@ -20379,7 +19999,7 @@ var EditorInstanceManager = class _EditorInstanceManager {
20379
19999
  }
20380
20000
  };
20381
20001
  function useEditor(options = {}, deps = []) {
20382
- const mostRecentOptions = useRef4(options);
20002
+ const mostRecentOptions = useRef2(options);
20383
20003
  mostRecentOptions.current = options;
20384
20004
  const [instanceManager] = useState2(() => new EditorInstanceManager(mostRecentOptions));
20385
20005
  const editor = (0, import_shim2.useSyncExternalStore)(
@@ -20388,7 +20008,7 @@ function useEditor(options = {}, deps = []) {
20388
20008
  instanceManager.getServerSnapshot
20389
20009
  );
20390
20010
  useDebugValue2(editor);
20391
- useEffect22(instanceManager.onRender(deps));
20011
+ useEffect2(instanceManager.onRender(deps));
20392
20012
  useEditorState({
20393
20013
  editor,
20394
20014
  selector: ({ transactionNumber }) => {
@@ -20403,18 +20023,18 @@ function useEditor(options = {}, deps = []) {
20403
20023
  });
20404
20024
  return editor;
20405
20025
  }
20406
- var EditorContext = createContext2({
20026
+ var EditorContext = createContext({
20407
20027
  editor: null
20408
20028
  });
20409
20029
  var EditorConsumer = EditorContext.Consumer;
20410
- var ReactNodeViewContext = createContext22({
20030
+ var ReactNodeViewContext = createContext2({
20411
20031
  onDragStart: () => {
20412
20032
  },
20413
20033
  nodeViewContentChildren: void 0,
20414
20034
  nodeViewContentRef: () => {
20415
20035
  }
20416
20036
  });
20417
- var useReactNodeView = () => useContext22(ReactNodeViewContext);
20037
+ var useReactNodeView = () => useContext2(ReactNodeViewContext);
20418
20038
  var NodeViewWrapper = React3.forwardRef((props, ref) => {
20419
20039
  const { onDragStart } = useReactNodeView();
20420
20040
  const Tag = props.as || "div";
@@ -25477,8 +25097,8 @@ var index_default2 = StarterKit;
25477
25097
 
25478
25098
  // src/rich-input/ChatInput.tsx
25479
25099
  import {
25480
- useEffect as useEffect9,
25481
- useRef as useRef9,
25100
+ useEffect as useEffect8,
25101
+ useRef as useRef7,
25482
25102
  useState as useState11
25483
25103
  } from "react";
25484
25104
  import { createRoot } from "react-dom/client";
@@ -25493,7 +25113,7 @@ function skillDisplayName(skill) {
25493
25113
  }
25494
25114
 
25495
25115
  // src/rich-input/voice/use-tiptap-voice-input.ts
25496
- import { useCallback as useCallback2, useEffect as useEffect5, useRef as useRef5 } from "react";
25116
+ import { useCallback, useEffect as useEffect4, useRef as useRef3 } from "react";
25497
25117
  var IDLE_VOICE = {
25498
25118
  status: "idle",
25499
25119
  error: null,
@@ -25509,8 +25129,8 @@ function useNoVoiceInput() {
25509
25129
  function useTiptapVoiceInput(options) {
25510
25130
  const { editorRef, workletUrl, onError } = options;
25511
25131
  const useVoiceInput2 = options.useVoiceInput ?? useNoVoiceInput;
25512
- const partialRangeRef = useRef5(null);
25513
- const lastPartialLenRef = useRef5(0);
25132
+ const partialRangeRef = useRef3(null);
25133
+ const lastPartialLenRef = useRef3(0);
25514
25134
  const handlePartial = useEffectEvent((text) => {
25515
25135
  const ed = editorRef.current;
25516
25136
  if (!ed) return;
@@ -25560,18 +25180,18 @@ function useTiptapVoiceInput(options) {
25560
25180
  onError: handleError
25561
25181
  });
25562
25182
  const isRecording = voice.status === "recording";
25563
- useEffect5(() => {
25183
+ useEffect4(() => {
25564
25184
  const ed = editorRef.current;
25565
25185
  if (!ed) return;
25566
25186
  ed.setEditable(!isRecording);
25567
25187
  }, [isRecording, editorRef]);
25568
- useEffect5(() => {
25188
+ useEffect4(() => {
25569
25189
  if (voice.status === "idle" || voice.status === "error") {
25570
25190
  partialRangeRef.current = null;
25571
25191
  lastPartialLenRef.current = 0;
25572
25192
  }
25573
25193
  }, [voice.status]);
25574
- const toggle = useCallback2(() => {
25194
+ const toggle = useCallback(() => {
25575
25195
  if (voice.status === "recording" || voice.status === "starting") {
25576
25196
  void voice.stop();
25577
25197
  } else {
@@ -25628,7 +25248,7 @@ function VoiceWaveform({ level, color = "currentColor", size = 16 }) {
25628
25248
  }
25629
25249
 
25630
25250
  // src/rich-input/model/resolve-model.ts
25631
- import { useMemo as useMemo4 } from "react";
25251
+ import { useMemo as useMemo3 } from "react";
25632
25252
  var MODEL_LOADING_SEND_HINT = "\u6B63\u5728\u52A0\u8F7D\u6A21\u578B\u914D\u7F6E\uFF0C\u8BF7\u7A0D\u540E\u518D\u53D1\u9001";
25633
25253
  function gateSendWhileModelLoading(isModelLoading, hasContent) {
25634
25254
  if (!isModelLoading) return { blocked: false };
@@ -25697,7 +25317,7 @@ function resolveModelChoice({
25697
25317
  function useResolvedModel(activeSessionModel) {
25698
25318
  const { models, defaultModel, thinkingAvailable, isLoading, unavailableProviderIds, unavailableModelIds } = useModelCatalog();
25699
25319
  const { preferredModel } = useModelPreferences();
25700
- const resolved = useMemo4(() => {
25320
+ const resolved = useMemo3(() => {
25701
25321
  return resolveModelChoice({
25702
25322
  activeSessionModel,
25703
25323
  preferredModel,
@@ -25717,9 +25337,6 @@ function useResolvedModel(activeSessionModel) {
25717
25337
  reasoningLevels: selectedModel?.reasoningLevels ?? [],
25718
25338
  defaultReasoningLevel: selectedModel?.defaultReasoningLevel ?? "",
25719
25339
  modelAvailabilityMessage,
25720
- // Undefined means the catalog is still loading or the model does not
25721
- // publish this optional capability. In either case keep existing upload
25722
- // behavior until the server has explicitly said images are unsupported.
25723
25340
  supportsImage: selectedModel?.supportsImage ?? selectedModel?.inputModalities?.includes("image")
25724
25341
  };
25725
25342
  }
@@ -25734,17 +25351,21 @@ function useReasoningLevelPreference(modelId) {
25734
25351
  }
25735
25352
 
25736
25353
  // src/rich-input/model/use-composer-model.ts
25737
- 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";
25738
25355
  function useInjectedSessionModel(sessionId) {
25739
25356
  return useChatSessionDetail(sessionId)?.model ?? null;
25740
25357
  }
25741
25358
  function useComposerModel(activeSessionId) {
25742
25359
  const [newSessionModelSelection, setNewSessionModelSelection] = useState4(null);
25743
- const newSessionModelSelectionRef = useRef6(null);
25360
+ const newSessionModelSelectionRef = useRef4(null);
25744
25361
  const { setPreferredModel } = useModelPreferences();
25745
25362
  const { models: modelCatalog } = useModelCatalog();
25746
25363
  const useSessionModel = useChatEnvironment().useSessionDetail ? useInjectedSessionModel : useClientSessionModel;
25747
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);
25748
25369
  const sharedModelDraft = useComposerChannels(
25749
25370
  (state3) => activeSessionId ? state3.modelDrafts[activeSessionId] : void 0
25750
25371
  );
@@ -25759,18 +25380,18 @@ function useComposerModel(activeSessionId) {
25759
25380
  isLoading
25760
25381
  } = useResolvedModel(resolveComposerModel(activeSessionId, activeSessionModel, explicitModelSelection));
25761
25382
  const { reasoningLevelPreference, setReasoningLevelPreference } = useReasoningLevelPreference(selectedModel);
25762
- useEffect6(() => {
25383
+ useEffect5(() => {
25763
25384
  if (!activeSessionId || !newSessionModelSelectionRef.current) return;
25764
25385
  newSessionModelSelectionRef.current = null;
25765
25386
  setNewSessionModelSelection(null);
25766
25387
  }, [activeSessionId]);
25767
- useEffect6(() => {
25388
+ useEffect5(() => {
25768
25389
  if (!activeSessionId || !sharedModelDraft || isLoading || modelCatalog.length === 0) return;
25769
25390
  if (!modelCatalog.some((model) => model.id === sharedModelDraft)) {
25770
25391
  composerChannels.clearModelDraft(activeSessionId);
25771
25392
  }
25772
25393
  }, [activeSessionId, sharedModelDraft, isLoading, modelCatalog]);
25773
- useEffect6(() => {
25394
+ useEffect5(() => {
25774
25395
  if (!activeSessionId || sharedModelDraft !== activeSessionModel) return;
25775
25396
  composerChannels.clearModelDraft(activeSessionId);
25776
25397
  }, [activeSessionId, activeSessionModel, sharedModelDraft]);
@@ -25778,7 +25399,7 @@ function useComposerModel(activeSessionId) {
25778
25399
  return {
25779
25400
  selectedModel,
25780
25401
  hasAvailableModel,
25781
- isLoading,
25402
+ isLoading: isLoading || !!activeSessionId && (selectingSession === activeSessionId || !session),
25782
25403
  availabilityMessage: modelAvailabilityMessage,
25783
25404
  thinkingAvailable,
25784
25405
  reasoningLevels,
@@ -25786,7 +25407,22 @@ function useComposerModel(activeSessionId) {
25786
25407
  setReasoningLevel: setReasoningLevelPreference,
25787
25408
  selectModel(model) {
25788
25409
  if (activeSessionId) {
25410
+ if (selectingRef.current === activeSessionId) return;
25411
+ selectingRef.current = activeSessionId;
25412
+ setSelectingSession(activeSessionId);
25789
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
+ });
25790
25426
  } else {
25791
25427
  const selection = { sessionId: activeSessionId, model };
25792
25428
  newSessionModelSelectionRef.current = selection;
@@ -25850,7 +25486,7 @@ function PopoverContent({
25850
25486
  }
25851
25487
 
25852
25488
  // src/rich-input/ModelSelector.tsx
25853
- import { useMemo as useMemo5, useState as useState5 } from "react";
25489
+ import { useMemo as useMemo4, useState as useState5 } from "react";
25854
25490
  import { jsx as jsx12, jsxs as jsxs3 } from "react/jsx-runtime";
25855
25491
  var inputModalityLabels = {
25856
25492
  text: "\u6587\u672C",
@@ -25892,7 +25528,7 @@ function ModelSelector({
25892
25528
  }
25893
25529
  void refresh();
25894
25530
  }
25895
- const filteredModels = useMemo5(() => {
25531
+ const filteredModels = useMemo4(() => {
25896
25532
  const normalized = query.trim().toLowerCase();
25897
25533
  if (!normalized) return models;
25898
25534
  return models.filter(
@@ -25919,10 +25555,7 @@ function ModelSelector({
25919
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"}`,
25920
25556
  title: selectorTitle,
25921
25557
  children: [
25922
- isLoading ? /* @__PURE__ */ jsx12(LoaderCircle, { size: 14, className: "animate-spin", "aria-hidden": "true" }) : compact ? null : (
25923
- // compact 用于「+」菜单的「模型」行,行首已有图标,触发器内不再重复。
25924
- /* @__PURE__ */ jsx12(Sparkles, { size: 14, "aria-hidden": "true" })
25925
- ),
25558
+ isLoading ? /* @__PURE__ */ jsx12(LoaderCircle, { size: 14, className: "animate-spin", "aria-hidden": "true" }) : compact ? null : /* @__PURE__ */ jsx12(Sparkles, { size: 14, "aria-hidden": "true" }),
25926
25559
  /* @__PURE__ */ jsx12(
25927
25560
  "span",
25928
25561
  {
@@ -26028,7 +25661,7 @@ function ModelSelector({
26028
25661
  }
26029
25662
 
26030
25663
  // src/rich-input/SkillStatusBar.tsx
26031
- import { useMemo as useMemo6 } from "react";
25664
+ import { useMemo as useMemo5 } from "react";
26032
25665
 
26033
25666
  // src/chat/lib/skill-visibility.ts
26034
25667
  function visibleSkills(skills, mode) {
@@ -26206,7 +25839,7 @@ function SkillStatusBar({
26206
25839
  const { status: connectionStatus, reconnectAttempt, hasEverConnected } = useComposerConnectionInfo(sessionId);
26207
25840
  const statsReady = !loading && !error;
26208
25841
  const skillStoreConnected = statsReady && skillStats.remote_connected;
26209
- const connectionMeta = useMemo6(
25842
+ const connectionMeta = useMemo5(
26210
25843
  () => getConnectionMeta(
26211
25844
  connectionStatus,
26212
25845
  reconnectAttempt,
@@ -26226,7 +25859,8 @@ function SkillStatusBar({
26226
25859
  text: skillStoreConnected ? `\u5DF2\u5B89\u88C5 ${skillStats.installed_skill_count} \u4E2A\u6280\u80FD` : "\u5C1A\u672A\u767B\u5F55\u6280\u80FD\u5546\u5E97"
26227
25860
  }
26228
25861
  ].filter((item) => item.key !== "total" || skillStats.remote_configured);
26229
- const tokenSummary = useMemo6(() => {
25862
+ const tokenSummary = useMemo5(() => {
25863
+ if (mode !== "developer") return null;
26230
25864
  if (contextStatsLoading || contextStatsError || !contextStats) {
26231
25865
  return {
26232
25866
  detail: /* @__PURE__ */ jsx14("div", { className: "pt-1 text-[hsl(var(--muted-foreground))]", children: "\u4E0A\u4E0B\u6587\u7EDF\u8BA1\u4E0D\u53EF\u7528" }),
@@ -26252,7 +25886,7 @@ function SkillStatusBar({
26252
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`,
26253
25887
  warn: tokenPressure.level === "critical"
26254
25888
  };
26255
- }, [contextStats, contextStatsError, contextStatsLoading, tokenPressure.level]);
25889
+ }, [mode, contextStats, contextStatsError, contextStatsLoading, tokenPressure.level]);
26256
25890
  const containerClass = vertical ? "text-[11px] text-[hsl(var(--muted-foreground))]" : "bg-[hsl(var(--background))] px-5 pt-2";
26257
25891
  const innerClass = vertical ? "" : "mx-auto max-w-3xl";
26258
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))]";
@@ -26295,20 +25929,16 @@ function SkillStatusBar({
26295
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" }),
26296
25930
  /* @__PURE__ */ jsx14("span", { className: "break-words", children: skillDisplayName(skill) })
26297
25931
  ] }, skill.skill_id)) }) : null }) : null
26298
- ] }) : (
26299
- // 「已安装」是可点的导航:用户看到数字会想去看是哪些技能。
26300
- // 改的是「已加载」那一行就会变成另一个功能,所以只动这一条。
26301
- onOpenSkills ? /* @__PURE__ */ jsx14(
26302
- "button",
26303
- {
26304
- type: "button",
26305
- onClick: onOpenSkills,
26306
- title: "\u67E5\u770B\u5DF2\u5B89\u88C5\u7684\u6280\u80FD",
26307
- className: "cursor-pointer font-mono underline decoration-dotted underline-offset-2 transition-colors hover:text-[hsl(var(--foreground))]",
26308
- children: item.text
26309
- }
26310
- ) : /* @__PURE__ */ jsx14("span", { className: "font-mono", children: item.text })
26311
- )
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 })
26312
25942
  ]
26313
25943
  },
26314
25944
  item.key
@@ -26316,11 +25946,72 @@ function SkillStatusBar({
26316
25946
  ] }) }) });
26317
25947
  }
26318
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
+
26319
26010
  // src/rich-input/ConnectButton.tsx
26320
26011
  import { useState as useState6 } from "react";
26321
26012
 
26322
26013
  // src/rich-input/lib/skill-suggestions.ts
26323
- var sessionPath2 = (sessionId, rest) => `/api/sessions/${encodeURIComponent(sessionId)}/${rest}`;
26014
+ var sessionPath = (sessionId, rest) => `/api/sessions/${encodeURIComponent(sessionId)}/${rest}`;
26324
26015
  function toItem(skill) {
26325
26016
  return {
26326
26017
  type: "skill",
@@ -26328,9 +26019,8 @@ function toItem(skill) {
26328
26019
  displayName: skill.display_name,
26329
26020
  description: skill.description,
26330
26021
  local: skill.local,
26331
- // 本地技能天然可用。搜索结果带后端算好的安装状态,列表接口没有这个字段
26332
- // 时按 local 推断。
26333
- installed: "installed" in skill ? skill.installed : skill.local
26022
+ installed: "installed" in skill ? skill.installed : skill.local,
26023
+ hasFlow: skill.has_flow === true
26334
26024
  };
26335
26025
  }
26336
26026
  var CACHE_TTL_MS = 15e3;
@@ -26338,19 +26028,12 @@ var cachesByClient = /* @__PURE__ */ new WeakMap();
26338
26028
  function cachesFor(client) {
26339
26029
  const existing = cachesByClient.get(client);
26340
26030
  if (existing) return existing;
26341
- const caches2 = {
26342
- requests: /* @__PURE__ */ new Map(),
26343
- workflows: /* @__PURE__ */ new Map(),
26344
- workflowsRefreshedAt: /* @__PURE__ */ new Map(),
26345
- workflowsAbort: null,
26346
- searchSeq: 0
26347
- };
26348
- cachesByClient.set(client, caches2);
26031
+ const caches = { requests: /* @__PURE__ */ new Map(), searchSeq: 0 };
26032
+ cachesByClient.set(client, caches);
26349
26033
  onInputCachesReset(client, () => {
26350
- caches2.workflowsAbort?.abort();
26351
- if (cachesByClient.get(client) === caches2) cachesByClient.delete(client);
26034
+ if (cachesByClient.get(client) === caches) cachesByClient.delete(client);
26352
26035
  });
26353
- return caches2;
26036
+ return caches;
26354
26037
  }
26355
26038
  function cached(client, key, load) {
26356
26039
  const { requests } = cachesFor(client);
@@ -26364,9 +26047,7 @@ function cached(client, key, load) {
26364
26047
  return request;
26365
26048
  }
26366
26049
  function invalidateSlashSuggestions(client, sessionId) {
26367
- const caches2 = cachesFor(client);
26368
- caches2.requests.delete(`session-skills:${sessionId ?? ""}`);
26369
- caches2.workflows.delete(sessionId ?? "__home__");
26050
+ cachesFor(client).requests.delete(`session-skills:${sessionId ?? ""}`);
26370
26051
  }
26371
26052
  async function loadSessionSkills({ client, sessionId, renderMode }) {
26372
26053
  if (!sessionId) return [];
@@ -26374,79 +26055,50 @@ async function loadSessionSkills({ client, sessionId, renderMode }) {
26374
26055
  const skills = await cached(
26375
26056
  client,
26376
26057
  `session-skills:${sessionId}`,
26377
- () => client.json("GET", sessionPath2(sessionId, "skills"))
26058
+ () => client.json("GET", sessionPath(sessionId, "skills"))
26378
26059
  );
26379
26060
  return visibleSkills(skills, renderMode);
26380
26061
  } catch {
26381
26062
  return [];
26382
26063
  }
26383
26064
  }
26065
+ var HUB_WAIT_MS = 600;
26384
26066
  var DEFAULT_SUGGESTION_LIMIT = 50;
26385
26067
  async function getDefaultSuggestions(options) {
26386
26068
  if (options.sessionId) {
26387
26069
  return (await loadSessionSkills(options)).map(toItem);
26388
26070
  }
26071
+ const { client, renderMode } = options;
26072
+ const installedRequest = cached(
26073
+ client,
26074
+ "installed-skills",
26075
+ () => client.json("GET", "/api/skills/installed").catch(() => [])
26076
+ );
26389
26077
  try {
26390
- const skills = await cached(options.client, "skills", () => options.client.json("GET", "/api/skills"));
26391
- 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);
26392
26096
  } catch {
26393
26097
  return [];
26394
26098
  }
26395
26099
  }
26396
- async function loadWorkflows(client, sessionId) {
26397
- const caches2 = cachesFor(client);
26398
- caches2.workflowsAbort?.abort();
26399
- const ac = new AbortController();
26400
- caches2.workflowsAbort = ac;
26401
- let timedOut = false;
26402
- const timer = setTimeout(() => {
26403
- timedOut = true;
26404
- ac.abort();
26405
- }, 1500);
26406
- try {
26407
- const res = await client.jsonFromInit(
26408
- sessionId ? sessionPath2(sessionId, "workflows") : "/api/workflows",
26409
- { signal: ac.signal }
26410
- );
26411
- const items = res.workflows.map((w) => ({
26412
- type: "workflow",
26413
- name: w.name,
26414
- displayName: w.display_name || w.name,
26415
- description: w.description || "",
26416
- inputs: w.inputs ?? []
26417
- }));
26418
- caches2.workflows.set(sessionId ?? "__home__", items);
26419
- caches2.workflowsRefreshedAt.set(sessionId ?? "__home__", Date.now());
26420
- return items;
26421
- } catch (err) {
26422
- if (timedOut || err?.name !== "AbortError") {
26423
- caches2.workflows.set(sessionId ?? "__home__", []);
26424
- }
26425
- return caches2.workflows.get(sessionId ?? "__home__") ?? [];
26426
- } finally {
26427
- clearTimeout(timer);
26428
- if (caches2.workflowsAbort === ac) caches2.workflowsAbort = null;
26429
- }
26430
- }
26431
26100
  async function getSlashSuggestions(query, options) {
26432
- const q = query.trim().toLowerCase();
26433
- const cacheKey = options.sessionId ?? "__home__";
26434
- const caches2 = cachesFor(options.client);
26435
- const cachedWorkflows = caches2.workflows.get(cacheKey);
26436
- let workflowsP;
26437
- if (cachedWorkflows) {
26438
- if (Date.now() - (caches2.workflowsRefreshedAt.get(cacheKey) ?? 0) >= CACHE_TTL_MS) {
26439
- void loadWorkflows(options.client, options.sessionId);
26440
- }
26441
- workflowsP = Promise.resolve(cachedWorkflows);
26442
- } else {
26443
- workflowsP = loadWorkflows(options.client, options.sessionId);
26444
- }
26445
- const [workflows, skills] = await Promise.all([workflowsP, getSkillSuggestions(query, options)]);
26446
- const matched = workflows.filter(
26447
- (w) => !q || w.name.toLowerCase().includes(q) || w.displayName.toLowerCase().includes(q) || w.description.toLowerCase().includes(q)
26448
- );
26449
- return [...matched, ...skills];
26101
+ return getSkillSuggestions(query, options);
26450
26102
  }
26451
26103
  var SEARCH_DEBOUNCE_MS = 150;
26452
26104
  async function getSkillSuggestions(query, options) {
@@ -26454,14 +26106,14 @@ async function getSkillSuggestions(query, options) {
26454
26106
  if (!trimmed) {
26455
26107
  return getDefaultSuggestions(options);
26456
26108
  }
26457
- const caches2 = cachesFor(options.client);
26458
- const seq = ++caches2.searchSeq;
26109
+ const caches = cachesFor(options.client);
26110
+ const seq = ++caches.searchSeq;
26459
26111
  const q = trimmed.toLowerCase();
26460
26112
  const sessionMatches = (await loadSessionSkills(options)).filter(
26461
26113
  (skill) => skill.skill_id.toLowerCase().includes(q) || skill.description.toLowerCase().includes(q)
26462
26114
  ).map(toItem);
26463
26115
  await new Promise((resolve) => setTimeout(resolve, SEARCH_DEBOUNCE_MS));
26464
- if (seq !== caches2.searchSeq) return sessionMatches;
26116
+ if (seq !== caches.searchSeq) return sessionMatches;
26465
26117
  try {
26466
26118
  const seen = new Set(sessionMatches.map((item) => item.skillId));
26467
26119
  const { client, renderMode } = options;
@@ -26478,7 +26130,7 @@ async function getSkillSuggestions(query, options) {
26478
26130
  }
26479
26131
 
26480
26132
  // src/rich-input/ConnectButton.tsx
26481
- import { jsx as jsx15, jsxs as jsxs6 } from "react/jsx-runtime";
26133
+ import { jsx as jsx16, jsxs as jsxs7 } from "react/jsx-runtime";
26482
26134
  function ConnectButton({
26483
26135
  sessionId,
26484
26136
  open,
@@ -26486,12 +26138,15 @@ function ConnectButton({
26486
26138
  pendingPlugins,
26487
26139
  onPendingPluginsChange,
26488
26140
  pendingPluginsDisabledReason,
26489
- pendingComputers,
26490
- onPendingComputersChange,
26491
- onPluginsChanged
26141
+ excludedComputers,
26142
+ onExcludedComputersChange,
26143
+ pendingPhones,
26144
+ onPendingPhonesChange,
26145
+ onPluginsChanged,
26146
+ variant = "icon"
26492
26147
  }) {
26493
26148
  const client = useBladeClient();
26494
- const { ConnectorComputerSection, ConnectorAccountsSection } = useRichInputServices();
26149
+ const { ConnectorComputerSection, ConnectorPhoneSection, ConnectorAccountsSection } = useRichInputServices();
26495
26150
  const invalidation = useSessionDataInvalidation();
26496
26151
  const [uncontrolledOpen, setUncontrolledOpen] = useState6(false);
26497
26152
  const isOpen = open ?? uncontrolledOpen;
@@ -26504,93 +26159,83 @@ function ConnectButton({
26504
26159
  const summary = triggerSummary(triggerItems);
26505
26160
  const triggerCls = summary.total === 0 ? "w-9 p-0 text-[hsl(var(--muted-foreground))]" : summary.total === 1 ? "w-9 p-0" : "px-1";
26506
26161
  const selectedLabels = sessionId === null ? (pendingPlugins ?? []).map((item) => item.displayName?.trim() || item.name) : selectedItems.map((item) => item.display_name?.trim() || item.name);
26507
- return /* @__PURE__ */ jsxs6(dist_exports.Root, { open: isOpen, onOpenChange: setOpen, children: [
26508
- /* @__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(
26509
26215
  "button",
26510
26216
  {
26511
26217
  type: "button",
26512
26218
  "aria-label": summary.total > 0 ? `\u8FDE\u63A5\u5668\uFF1A\u5DF2\u9009 ${summary.total} \u4E2A\u63D2\u4EF6` : "\u8FDE\u63A5\u5668",
26513
26219
  title: selectedLabels.length > 0 ? `\u8FDE\u63A5\u5668\uFF1A${selectedLabels.join("\u3001")}` : "\u8FDE\u63A5\u5668",
26514
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}`,
26515
- 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 })
26516
26222
  }
26517
26223
  ) }),
26518
- /* @__PURE__ */ jsx15(dist_exports.Portal, { children: /* @__PURE__ */ jsx15(
26224
+ /* @__PURE__ */ jsx16(dist_exports.Portal, { children: /* @__PURE__ */ jsx16(
26519
26225
  dist_exports.Content,
26520
26226
  {
26521
26227
  side: "top",
26522
26228
  align: "start",
26523
26229
  sideOffset: 8,
26524
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",
26525
- children: /* @__PURE__ */ jsx15("div", { className: "max-h-[min(70vh,32rem)] overflow-y-auto", children: /* @__PURE__ */ jsx15(
26526
- ConnectorPanel,
26527
- {
26528
- client,
26529
- sessionId,
26530
- pendingPlugins,
26531
- onPendingPluginsChange,
26532
- pendingDisabledReason: pendingPluginsDisabledReason,
26533
- onPluginsChanged: () => {
26534
- if (sessionId) {
26535
- invalidateSlashSuggestions(client, sessionId);
26536
- invalidation.pluginsChanged(sessionId);
26537
- }
26538
- onPluginsChanged?.();
26539
- },
26540
- onSelectedChange: setSelectedItems,
26541
- renderComputerSection: ConnectorComputerSection ? (query) => /* @__PURE__ */ jsx15(
26542
- ConnectorComputerSection,
26543
- {
26544
- sessionId,
26545
- query,
26546
- pendingSelection: pendingComputers,
26547
- onPendingSelectionChange: onPendingComputersChange,
26548
- closePanel: () => setOpen(false)
26549
- }
26550
- ) : void 0,
26551
- renderExternalAccounts: ConnectorAccountsSection ? (query) => /* @__PURE__ */ jsx15(ConnectorAccountsSection, { query, closePanel: () => setOpen(false) }) : void 0
26552
- }
26553
- ) })
26231
+ children: /* @__PURE__ */ jsx16("div", { className: "max-h-[min(70vh,32rem)] overflow-y-auto", children: panel })
26554
26232
  }
26555
26233
  ) })
26556
26234
  ] });
26557
26235
  }
26558
26236
 
26559
- // src/rich-input/lib/kb-suggestions.ts
26560
- function toKbSuggestionItems(knowledgeBases) {
26561
- return knowledgeBases.map((kb) => ({
26562
- kind: "kb",
26563
- kbId: kb.id,
26564
- name: kb.name,
26565
- description: kb.description ?? ""
26566
- }));
26567
- }
26568
- var KB_SUGGESTION_TIMEOUT_MS = 300;
26569
- function withKbSuggestionTimeout(promise, timeoutMs = KB_SUGGESTION_TIMEOUT_MS) {
26570
- return Promise.race([
26571
- promise,
26572
- new Promise((resolve) => {
26573
- setTimeout(() => resolve([]), timeoutMs);
26574
- })
26575
- ]);
26576
- }
26577
- function notifyWhenKbSuggestionsArriveLate(kbPromise, raced, onLate) {
26578
- if (raced.length > 0) return;
26579
- void kbPromise.then((lateItems) => {
26580
- if (lateItems.length > 0) onLate(lateItems);
26581
- });
26582
- }
26583
- function filterKbSuggestions(items, query) {
26584
- if (query.includes("/") || query.includes("\\")) return [];
26585
- const normalized = query.trim().toLowerCase();
26586
- if (!normalized) return [...items];
26587
- return items.filter(
26588
- (item) => item.name.toLowerCase().includes(normalized) || item.description.toLowerCase().includes(normalized)
26589
- );
26590
- }
26591
-
26592
26237
  // src/rich-input/voice/use-voice-input.ts
26593
- 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";
26594
26239
 
26595
26240
  // src/rich-input/voice/voice-input-support.ts
26596
26241
  function isIpHost(hostname) {
@@ -26638,25 +26283,25 @@ function matchesRequest(data, requestId) {
26638
26283
  }
26639
26284
  function useVoiceInput(options) {
26640
26285
  const client = useBladeClient();
26641
- const clientRef = useRef7(client);
26286
+ const clientRef = useRef5(client);
26642
26287
  clientRef.current = client;
26643
- const getSocket = useCallback3(() => clientRef.current.socket(), []);
26288
+ const getSocket = useCallback2(() => clientRef.current.socket(), []);
26644
26289
  const [status, setStatus] = useState7("idle");
26645
26290
  const [error, setError] = useState7(null);
26646
26291
  const [level, setLevel] = useState7(0);
26647
- const sessionRef = useRef7(null);
26648
- const stoppingRef = useRef7(false);
26649
- const startAbortRef = useRef7(null);
26650
- const optionsRef = useRef7(options);
26292
+ const sessionRef = useRef5(null);
26293
+ const stoppingRef = useRef5(false);
26294
+ const startAbortRef = useRef5(null);
26295
+ const optionsRef = useRef5(options);
26651
26296
  optionsRef.current = options;
26652
- const reportError = useCallback3((err) => {
26297
+ const reportError = useCallback2((err) => {
26653
26298
  const payload = typeof err === "string" ? { title: err } : err;
26654
26299
  setError(payload.title);
26655
26300
  setStatus("error");
26656
26301
  setLevel(0);
26657
26302
  optionsRef.current.onError?.(payload);
26658
26303
  }, []);
26659
- const disposeSession = useCallback3((s) => {
26304
+ const disposeSession = useCallback2((s) => {
26660
26305
  if (s.disposed) return;
26661
26306
  s.disposed = true;
26662
26307
  const socket = getSocket();
@@ -26681,7 +26326,7 @@ function useVoiceInput(options) {
26681
26326
  } catch {
26682
26327
  }
26683
26328
  }, [getSocket]);
26684
- const stop = useCallback3(async () => {
26329
+ const stop = useCallback2(async () => {
26685
26330
  startAbortRef.current?.abort();
26686
26331
  const s = sessionRef.current;
26687
26332
  if (!s || stoppingRef.current) {
@@ -26728,7 +26373,7 @@ function useVoiceInput(options) {
26728
26373
  setLevel(0);
26729
26374
  setStatus((prev) => prev === "error" ? "error" : "idle");
26730
26375
  }, [disposeSession, getSocket]);
26731
- const start = useCallback3(async () => {
26376
+ const start = useCallback2(async () => {
26732
26377
  if (sessionRef.current || startAbortRef.current && !startAbortRef.current.signal.aborted || stoppingRef.current) {
26733
26378
  return;
26734
26379
  }
@@ -26902,7 +26547,7 @@ function useVoiceInput(options) {
26902
26547
  if (startAbortRef.current === abort) startAbortRef.current = null;
26903
26548
  }
26904
26549
  }, [reportError, disposeSession, getSocket]);
26905
- useEffect7(() => {
26550
+ useEffect6(() => {
26906
26551
  return () => {
26907
26552
  startAbortRef.current?.abort();
26908
26553
  const s = sessionRef.current;
@@ -26920,10 +26565,10 @@ function useVoiceInput(options) {
26920
26565
  }
26921
26566
 
26922
26567
  // src/rich-input/use-reference-candidates.ts
26923
- import { useLayoutEffect as useLayoutEffect2, useRef as useRef8 } from "react";
26568
+ import { useLayoutEffect as useLayoutEffect2, useRef as useRef6 } from "react";
26924
26569
 
26925
26570
  // src/rich-input/lib/reference-candidates.ts
26926
- function createReferenceCandidateController(getScope, sources, timeoutMs = KB_SUGGESTION_TIMEOUT_MS) {
26571
+ function createReferenceCandidateController(getScope, sources, timeoutMs = 300) {
26927
26572
  const requests = /* @__PURE__ */ new WeakMap();
26928
26573
  let current;
26929
26574
  const isCurrent = (request) => {
@@ -26935,9 +26580,9 @@ function createReferenceCandidateController(getScope, sources, timeoutMs = KB_SU
26935
26580
  current = void 0;
26936
26581
  previous?.finish();
26937
26582
  previous?.listener?.({
26938
- groups: { plugins: [], kbs: [], topics: [], files: [] },
26583
+ groups: { plugins: [], topics: [], files: [] },
26939
26584
  items: [],
26940
- loading: { plugins: false, kbs: false, topics: false, files: false },
26585
+ loading: { plugins: false, topics: false, files: false },
26941
26586
  errors: {}
26942
26587
  });
26943
26588
  if (previous) previous.listener = void 0;
@@ -26947,9 +26592,9 @@ function createReferenceCandidateController(getScope, sources, timeoutMs = KB_SU
26947
26592
  query(query) {
26948
26593
  cancel();
26949
26594
  const snapshot = {
26950
- groups: { plugins: [], kbs: [], topics: [], files: [] },
26595
+ groups: { plugins: [], topics: [], files: [] },
26951
26596
  items: [],
26952
- loading: { plugins: Boolean(sources.plugins), kbs: true, topics: true, files: true },
26597
+ loading: { plugins: Boolean(sources.plugins), topics: true, files: true },
26953
26598
  errors: {}
26954
26599
  };
26955
26600
  let resolve;
@@ -26973,11 +26618,11 @@ function createReferenceCandidateController(getScope, sources, timeoutMs = KB_SU
26973
26618
  const timer = setTimeout(request.finish, timeoutMs);
26974
26619
  const publish = () => {
26975
26620
  if (!isCurrent(request)) return;
26976
- snapshot.items = [...snapshot.groups.plugins, ...snapshot.groups.kbs, ...snapshot.groups.topics, ...snapshot.groups.files];
26621
+ snapshot.items = [...snapshot.groups.plugins, ...snapshot.groups.topics, ...snapshot.groups.files];
26977
26622
  request.listener?.(snapshot);
26978
26623
  if (!Object.values(snapshot.loading).some(Boolean)) request.finish();
26979
26624
  };
26980
- for (const key of ["plugins", "kbs", "topics", "files"]) {
26625
+ for (const key of ["plugins", "topics", "files"]) {
26981
26626
  void Promise.resolve().then(async () => {
26982
26627
  if (key === "plugins") await new Promise((done) => setTimeout(done, 150));
26983
26628
  return isCurrent(request) ? sources[key]?.(query) ?? [] : [];
@@ -26995,14 +26640,13 @@ function createReferenceCandidateController(getScope, sources, timeoutMs = KB_SU
26995
26640
  }
26996
26641
  return result;
26997
26642
  },
26998
- /** Bind by result identity, never by label/query: closing and reopening @ is a new request. */
26999
26643
  observe(items, listener) {
27000
26644
  const request = requests.get(items);
27001
26645
  if (!request || !isCurrent(request)) {
27002
26646
  listener({
27003
- groups: { plugins: [], kbs: [], topics: [], files: [] },
26647
+ groups: { plugins: [], topics: [], files: [] },
27004
26648
  items: [],
27005
- loading: { plugins: false, kbs: false, topics: false, files: false },
26649
+ loading: { plugins: false, topics: false, files: false },
27006
26650
  errors: {}
27007
26651
  });
27008
26652
  return;
@@ -27017,11 +26661,10 @@ function createReferenceCandidateController(getScope, sources, timeoutMs = KB_SU
27017
26661
  function useReferenceCandidates(getScope, sources) {
27018
26662
  const readScope = useEffectEvent(getScope);
27019
26663
  const plugins = useEffectEvent((query) => sources.plugins?.(query) ?? Promise.resolve([]));
27020
- const kbs = useEffectEvent(sources.kbs);
27021
26664
  const topics = useEffectEvent(sources.topics);
27022
26665
  const files = useEffectEvent(sources.files);
27023
- const ref = useRef8(null);
27024
- if (!ref.current) ref.current = createReferenceCandidateController(readScope, { plugins, kbs, topics, files });
26666
+ const ref = useRef6(null);
26667
+ if (!ref.current) ref.current = createReferenceCandidateController(readScope, { plugins, topics, files });
27025
26668
  const controller = ref.current;
27026
26669
  const [client, identity, session, topic] = getScope();
27027
26670
  useLayoutEffect2(() => onInputCachesReset(client, controller.cancel), [client, controller]);
@@ -27030,7 +26673,7 @@ function useReferenceCandidates(getScope, sources) {
27030
26673
  }
27031
26674
 
27032
26675
  // src/rich-input/use-input-history.ts
27033
- 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";
27034
26677
 
27035
26678
  // src/rich-input/lib/input-history-document.ts
27036
26679
  import { normalizeTopicAssetRefs as normalizeTopicAssetRefs3 } from "@blade-hq/agent-client";
@@ -27038,10 +26681,8 @@ function copyEditorDocument(value) {
27038
26681
  const attributes = {
27039
26682
  pluginMention: { provider: "string", plugin: "string", server: "string", id: "string", label: "string" },
27040
26683
  fileMention: { path: "string", name: "string" },
27041
- kbMention: { kbId: "number", name: "string" },
27042
26684
  topicAssetMention: { topic_id: "string", path: "string" },
27043
- skillMention: { skillId: "string", displayName: "string", description: "string", local: "boolean", installed: "boolean" },
27044
- workflowMention: { name: "string" }
26685
+ skillMention: { skillId: "string", displayName: "string", description: "string", local: "boolean", installed: "boolean" }
27045
26686
  };
27046
26687
  const copy2 = (input, parent) => {
27047
26688
  if (!input || typeof input !== "object" || Array.isArray(input)) return null;
@@ -27073,7 +26714,6 @@ function copyEditorDocument(value) {
27073
26714
  if (expected === "string" && typeof attr !== "string" || expected === "number" && typeof attr !== "number" || expected === "boolean" && typeof attr !== "boolean") return null;
27074
26715
  attrs[key] = attr;
27075
26716
  }
27076
- if (type === "kbMention" && !(Number.isInteger(attrs.kbId) && attrs.kbId > 0)) return null;
27077
26717
  if (type === "topicAssetMention" && normalizeTopicAssetRefs3([attrs]).length !== 1) return null;
27078
26718
  return { type, attrs };
27079
26719
  };
@@ -27123,17 +26763,17 @@ function readEntries(storageKey) {
27123
26763
  }
27124
26764
  function useInputHistory(sessionId, client) {
27125
26765
  const [generation, setGeneration] = useState8(getInputHistoryGeneration);
27126
- const storageKey = useMemo7(() => getStorageKey(sessionId), [sessionId]);
26766
+ const storageKey = useMemo6(() => getStorageKey(sessionId), [sessionId]);
27127
26767
  const [entries, setEntries] = useState8([]);
27128
26768
  const [cursor, setCursor] = useState8(null);
27129
26769
  const [draft, setDraft] = useState8(emptyEntry);
27130
- useEffect8(() => {
26770
+ useEffect7(() => {
27131
26771
  setGeneration(getInputHistoryGeneration());
27132
26772
  setEntries(readEntries(storageKey));
27133
26773
  setCursor(null);
27134
26774
  setDraft(emptyEntry());
27135
26775
  }, [storageKey, client]);
27136
- useEffect8(() => {
26776
+ useEffect7(() => {
27137
26777
  if (!client) return;
27138
26778
  return onInputCachesReset(client, () => {
27139
26779
  setGeneration(getInputHistoryGeneration());
@@ -27142,7 +26782,7 @@ function useInputHistory(sessionId, client) {
27142
26782
  setDraft(emptyEntry());
27143
26783
  });
27144
26784
  }, [client]);
27145
- const persistEntries = useCallback4(
26785
+ const persistEntries = useCallback3(
27146
26786
  (nextEntries) => {
27147
26787
  if (generation !== getInputHistoryGeneration() || typeof window === "undefined" || !storageKey) {
27148
26788
  return;
@@ -27154,7 +26794,7 @@ function useInputHistory(sessionId, client) {
27154
26794
  },
27155
26795
  [storageKey, generation]
27156
26796
  );
27157
- const addEntry = useCallback4(
26797
+ const addEntry = useCallback3(
27158
26798
  (value) => {
27159
26799
  if (generation !== getInputHistoryGeneration()) return;
27160
26800
  const document2 = copyEditorDocument(value);
@@ -27170,7 +26810,7 @@ function useInputHistory(sessionId, client) {
27170
26810
  },
27171
26811
  [persistEntries, generation]
27172
26812
  );
27173
- const navigateUp = useCallback4(
26813
+ const navigateUp = useCallback3(
27174
26814
  (currentDraft = emptyEntry().document) => {
27175
26815
  if (generation !== getInputHistoryGeneration() || entries.length === 0) {
27176
26816
  return null;
@@ -27184,7 +26824,7 @@ function useInputHistory(sessionId, client) {
27184
26824
  },
27185
26825
  [cursor, entries, generation]
27186
26826
  );
27187
- const navigateDown = useCallback4(() => {
26827
+ const navigateDown = useCallback3(() => {
27188
26828
  if (generation !== getInputHistoryGeneration() || cursor == null) {
27189
26829
  return null;
27190
26830
  }
@@ -27235,8 +26875,7 @@ function splitFilesBySize(files, limitBytes = ATTACHMENT_SIZE_LIMIT_BYTES) {
27235
26875
 
27236
26876
  // src/rich-input/ChatInput.tsx
27237
26877
  import {
27238
- buildMessageContent,
27239
- transformSlashCommand
26878
+ buildMessageContent
27240
26879
  } from "@blade-hq/agent-client/internal";
27241
26880
 
27242
26881
  // src/rich-input/lib/upload-results.ts
@@ -27267,47 +26906,20 @@ function getUnsupportedImageFiles(files, supportsImage) {
27267
26906
  }
27268
26907
 
27269
26908
  // src/rich-input/FileCompletionMenu.tsx
27270
- 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";
27271
26910
 
27272
26911
  // src/rich-input/lib/user-home.ts
27273
- var SANDBOX_HOME_ROOT = "/root";
27274
- var SANDBOX_RUNTIME = { homePath: SANDBOX_HOME_ROOT, separator: "/" };
27275
26912
  var CACHE_TTL_MS2 = 15e3;
27276
26913
  var cachesByClient2 = /* @__PURE__ */ new WeakMap();
27277
- var lastResolvedRuntime = SANDBOX_RUNTIME;
27278
26914
  function cachesFor2(client) {
27279
26915
  const existing = cachesByClient2.get(client);
27280
26916
  if (existing) return existing;
27281
- const caches2 = { runtime: null, dirs: /* @__PURE__ */ new Map() };
27282
- cachesByClient2.set(client, caches2);
26917
+ const caches = { dirs: /* @__PURE__ */ new Map() };
26918
+ cachesByClient2.set(client, caches);
27283
26919
  onInputCachesReset(client, () => {
27284
- if (cachesByClient2.get(client) === caches2) cachesByClient2.delete(client);
27285
- lastResolvedRuntime = SANDBOX_RUNTIME;
27286
- });
27287
- return caches2;
27288
- }
27289
- function getUserHomeRuntime(client) {
27290
- const caches2 = cachesFor2(client);
27291
- if (caches2.runtime && Date.now() - caches2.runtime.at < CACHE_TTL_MS2) {
27292
- return caches2.runtime.request;
27293
- }
27294
- const request = client.json("GET", "/api/agent-board/workspace-runtime").then((runtime) => {
27295
- const homePath = (runtime.home_path ?? "").trim() || SANDBOX_HOME_ROOT;
27296
- const resolved = {
27297
- homePath,
27298
- separator: (runtime.os ?? "").toLowerCase().startsWith("windows") ? "\\" : "/"
27299
- };
27300
- lastResolvedRuntime = resolved;
27301
- return resolved;
27302
- }).catch(() => {
27303
- if (caches2.runtime?.request === request) caches2.runtime = null;
27304
- return SANDBOX_RUNTIME;
26920
+ if (cachesByClient2.get(client) === caches) cachesByClient2.delete(client);
27305
26921
  });
27306
- caches2.runtime = { at: Date.now(), request };
27307
- return request;
27308
- }
27309
- function getLastUserHomeRuntime() {
27310
- return lastResolvedRuntime;
26922
+ return caches;
27311
26923
  }
27312
26924
  function listUserHomeDir(client, dirPath) {
27313
26925
  const { dirs } = cachesFor2(client);
@@ -27321,61 +26933,8 @@ function listUserHomeDir(client, dirPath) {
27321
26933
  return entries;
27322
26934
  }
27323
26935
 
27324
- // src/rich-input/extensions/kb-mention.ts
27325
- function isKbSuggestionItem(value) {
27326
- return typeof value === "object" && value !== null && value.kind === "kb" && typeof value.kbId === "number";
27327
- }
27328
- function getKbMentionName(attrs) {
27329
- return attrs.name || (attrs.kbId != null ? `\u77E5\u8BC6\u5E93 #${attrs.kbId}` : "");
27330
- }
27331
- var KbMention = index_default.extend({
27332
- name: "kbMention",
27333
- addOptions() {
27334
- const parentOptions = this.parent?.();
27335
- return {
27336
- ...parentOptions,
27337
- HTMLAttributes: {
27338
- ...parentOptions?.HTMLAttributes ?? {},
27339
- class: "kb-mention-pill"
27340
- },
27341
- deleteTriggerWithBackspace: true,
27342
- // 只为满足 Mention 的选项类型;下面 addProseMirrorPlugins 返回空,不会真的装上。
27343
- suggestion: { ...parentOptions?.suggestion ?? {}, char: "@" },
27344
- suggestions: parentOptions?.suggestions ?? [],
27345
- renderText: ({ node }) => `@${getKbMentionName(node.attrs)}`,
27346
- renderHTML: ({ options, node }) => [
27347
- "span",
27348
- {
27349
- ...options.HTMLAttributes ?? {},
27350
- class: "kb-mention-pill",
27351
- "data-kb-id": String(node.attrs.kbId ?? ""),
27352
- "data-name": node.attrs.name
27353
- },
27354
- `@${getKbMentionName(node.attrs)}`
27355
- ]
27356
- };
27357
- },
27358
- addAttributes() {
27359
- return {
27360
- kbId: {
27361
- default: 0,
27362
- parseHTML: (element) => Number(element.getAttribute("data-kb-id") || 0),
27363
- renderHTML: (attributes) => ({ "data-kb-id": String(attributes.kbId) })
27364
- },
27365
- name: {
27366
- default: "",
27367
- parseHTML: (element) => element.getAttribute("data-name") || "",
27368
- renderHTML: (attributes) => ({ "data-name": attributes.name })
27369
- }
27370
- };
27371
- },
27372
- addProseMirrorPlugins() {
27373
- return [];
27374
- }
27375
- });
27376
-
27377
26936
  // src/rich-input/FileCompletionMenu.tsx
27378
- 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";
27379
26938
  var ROOT_DIR = ".";
27380
26939
  function installSuggestionOutsideDismiss(container, onDismiss) {
27381
26940
  const onPointerDown = (event) => {
@@ -27472,7 +27031,9 @@ async function getFileSuggestionItems(client, sessionId, query) {
27472
27031
  const entries = await listDirectory(client, sessionId, dirPath);
27473
27032
  return filterEntries(entries, filterQuery);
27474
27033
  }
27475
- function parseUserHomeQuery(query, { homePath, separator }) {
27034
+ function parseUserHomeQuery(query) {
27035
+ const homePath = "/root";
27036
+ const separator = "/";
27476
27037
  if (!query.startsWith(homePath)) {
27477
27038
  return { dirPath: homePath, filterQuery: query };
27478
27039
  }
@@ -27486,8 +27047,7 @@ function parseUserHomeQuery(query, { homePath, separator }) {
27486
27047
  };
27487
27048
  }
27488
27049
  async function getUserHomeSuggestionItems(client, query) {
27489
- const runtime = await getUserHomeRuntime(client);
27490
- const { dirPath, filterQuery } = parseUserHomeQuery(query, runtime);
27050
+ const { dirPath, filterQuery } = parseUserHomeQuery(query);
27491
27051
  let entries;
27492
27052
  try {
27493
27053
  entries = (await listUserHomeDir(client, dirPath)).map((entry) => ({
@@ -27502,14 +27062,13 @@ async function getUserHomeSuggestionItems(client, query) {
27502
27062
  var FileCompletionMenu = forwardRef2(
27503
27063
  function FileCompletionMenu2({ command: command2, editor, items, onExit, query, range, scope = "session", sessionId: sessionIdProp }, ref) {
27504
27064
  const sessionId = sessionIdProp ?? null;
27505
- const { dirPath, filterQuery } = useMemo8(
27065
+ const { dirPath, filterQuery } = useMemo7(
27506
27066
  () => scope === "userHome" ? { dirPath: query, filterQuery: "" } : parseSuggestionQuery(query),
27507
27067
  [query, scope]
27508
27068
  );
27509
- const { pluginItems, pluginError, kbItems, fileItems, topicItems, topicError } = useMemo8(() => {
27069
+ const { pluginItems, pluginError, fileItems, topicItems, topicError } = useMemo7(() => {
27510
27070
  let pluginError2;
27511
27071
  const pluginItems2 = [];
27512
- const kbs = [];
27513
27072
  const files = [];
27514
27073
  const topicItems2 = [];
27515
27074
  let topicError2;
@@ -27518,12 +27077,11 @@ var FileCompletionMenu = forwardRef2(
27518
27077
  else if (isPluginSuggestionItem(item)) pluginItems2.push(item);
27519
27078
  else if (isTopicAssetSuggestionItem(item)) topicItems2.push(item);
27520
27079
  else if (isTopicAssetSuggestionError(item)) topicError2 = item.message;
27521
- else if (isKbSuggestionItem(item)) kbs.push(item);
27522
27080
  else files.push(item);
27523
27081
  }
27524
- return { pluginItems: pluginItems2, pluginError: pluginError2, kbItems: filterKbSuggestions(kbs, query), fileItems: files, topicItems: topicItems2, topicError: topicError2 };
27525
- }, [items, query]);
27526
- return /* @__PURE__ */ jsx16(
27082
+ return { pluginItems: pluginItems2, pluginError: pluginError2, fileItems: files, topicItems: topicItems2, topicError: topicError2 };
27083
+ }, [items]);
27084
+ return /* @__PURE__ */ jsx17(
27527
27085
  FileCompletionMenuContent,
27528
27086
  {
27529
27087
  ref,
@@ -27533,7 +27091,6 @@ var FileCompletionMenu = forwardRef2(
27533
27091
  items: fileItems,
27534
27092
  pluginError,
27535
27093
  pluginItems,
27536
- kbItems,
27537
27094
  topicItems,
27538
27095
  topicError,
27539
27096
  onExit,
@@ -27541,27 +27098,26 @@ var FileCompletionMenu = forwardRef2(
27541
27098
  scope,
27542
27099
  sessionId
27543
27100
  },
27544
- `${scope}:${sessionId ?? "none"}:${dirPath}:${filterQuery}:${kbItems.length}`
27101
+ `${scope}:${sessionId ?? "none"}:${dirPath}:${filterQuery}`
27545
27102
  );
27546
27103
  }
27547
27104
  );
27548
- var FileCompletionMenuContent = forwardRef2(function FileCompletionMenuContent2({ command: command2, editor, filterQuery, items, pluginItems, pluginError, kbItems, topicItems, topicError, onExit, range, scope, sessionId }, ref) {
27105
+ var FileCompletionMenuContent = forwardRef2(function FileCompletionMenuContent2({ command: command2, editor, filterQuery, items, pluginItems, pluginError, topicItems, topicError, onExit, range, scope, sessionId }, ref) {
27549
27106
  const [rawSelectedIndex, setRawSelectedIndex] = useState9(0);
27550
- const filteredEntries = useMemo8(() => filterEntries(items, filterQuery), [filterQuery, items]);
27551
- const navigableItems = useMemo8(
27552
- () => [...pluginItems, ...kbItems, ...topicItems, ...filteredEntries],
27553
- [filteredEntries, pluginItems, kbItems, topicItems]
27107
+ const filteredEntries = useMemo7(() => filterEntries(items, filterQuery), [filterQuery, items]);
27108
+ const navigableItems = useMemo7(
27109
+ () => [...pluginItems, ...topicItems, ...filteredEntries],
27110
+ [filteredEntries, pluginItems, topicItems]
27554
27111
  );
27555
27112
  const selectedIndex = navigableItems.length === 0 ? 0 : Math.min(rawSelectedIndex, navigableItems.length - 1);
27556
- const handleSelect = useCallback5(
27113
+ const handleSelect = useCallback4(
27557
27114
  (entry) => {
27558
- if (isPluginSuggestionItem(entry) || isKbSuggestionItem(entry) || isTopicAssetSuggestionItem(entry)) {
27115
+ if (isPluginSuggestionItem(entry) || isTopicAssetSuggestionItem(entry)) {
27559
27116
  command2(entry);
27560
27117
  return;
27561
27118
  }
27562
27119
  if (entry.is_dir) {
27563
- const separator = scope === "userHome" ? getLastUserHomeRuntime().separator : "/";
27564
- const nextValue = entry.path === ROOT_DIR ? "@" : `@${entry.path}${separator}`;
27120
+ const nextValue = entry.path === ROOT_DIR ? "@" : `@${entry.path}/`;
27565
27121
  editor.chain().focus().insertContentAt(range, nextValue).run();
27566
27122
  return;
27567
27123
  }
@@ -27571,7 +27127,7 @@ var FileCompletionMenuContent = forwardRef2(function FileCompletionMenuContent2(
27571
27127
  path: entry.path
27572
27128
  });
27573
27129
  },
27574
- [command2, editor, range, scope]
27130
+ [command2, editor, range]
27575
27131
  );
27576
27132
  useImperativeHandle(
27577
27133
  ref,
@@ -27617,11 +27173,11 @@ var FileCompletionMenuContent = forwardRef2(function FileCompletionMenuContent2(
27617
27173
  element.scrollIntoView({ block: "nearest" });
27618
27174
  }
27619
27175
  };
27620
- const showGroupLabels = pluginItems.length > 0 || kbItems.length > 0 || topicItems.length > 0 || Boolean(topicError);
27176
+ const showGroupLabels = pluginItems.length > 0 || topicItems.length > 0 || Boolean(topicError);
27621
27177
  const fileEmptyLabel = scope === "session" && !sessionId ? "\u6682\u65E0\u4F1A\u8BDD" : filteredEntries.length === 0 ? "\u6CA1\u6709\u6587\u4EF6" : null;
27622
- 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: [
27623
- pluginError ? /* @__PURE__ */ jsx16("output", { className: "block px-3 py-2 text-xs text-muted-foreground", children: pluginError }) : null,
27624
- 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(
27625
27181
  "button",
27626
27182
  {
27627
27183
  ref: selectedRef(index),
@@ -27632,52 +27188,31 @@ var FileCompletionMenuContent = forwardRef2(function FileCompletionMenuContent2(
27632
27188
  handleSelect(item);
27633
27189
  },
27634
27190
  children: [
27635
- item.icon ? /* @__PURE__ */ jsx16("img", { src: item.icon, alt: "", width: 16, height: 16, className: "shrink-0" }) : /* @__PURE__ */ jsx16(BookOpen, { size: 14 }),
27636
- /* @__PURE__ */ jsx16("span", { className: "truncate", children: item.label }),
27637
- /* @__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 })
27638
27194
  ]
27639
27195
  },
27640
27196
  `${item.plugin}:${item.server}:${item.id}`
27641
27197
  )),
27642
- kbItems.length > 0 ? /* @__PURE__ */ jsxs7(Fragment4, { children: [
27643
- /* @__PURE__ */ jsx16("div", { className: "px-3 pt-1 pb-0.5 text-[10px] font-medium uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u77E5\u8BC6\u5E93" }),
27644
- kbItems.map((item, index) => /* @__PURE__ */ jsxs7(
27645
- "button",
27646
- {
27647
- ref: selectedRef(pluginItems.length + index),
27648
- type: "button",
27649
- onMouseDown: (event) => {
27650
- event.preventDefault();
27651
- handleSelect(item);
27652
- },
27653
- className: rowClassName(pluginItems.length + index),
27654
- children: [
27655
- /* @__PURE__ */ jsx16(BookOpen, { size: 14, className: "shrink-0 text-[hsl(var(--primary))]" }),
27656
- /* @__PURE__ */ jsx16("span", { className: "truncate", children: item.name }),
27657
- item.description ? /* @__PURE__ */ jsx16("span", { className: "ml-auto max-w-[50%] truncate text-xs text-[hsl(var(--muted-foreground))]", children: item.description }) : null
27658
- ]
27659
- },
27660
- `kb-${item.kbId}`
27661
- ))
27662
- ] }) : null,
27663
- topicItems.length > 0 || topicError ? /* @__PURE__ */ jsxs7(Fragment4, { children: [
27664
- /* @__PURE__ */ jsx16("div", { className: "px-3 pt-1 pb-0.5 text-xs font-medium text-muted-foreground", children: "\u4E3B\u9898\u8D44\u4EA7" }),
27665
- 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,
27666
27201
  topicItems.map((item, topicIndex) => {
27667
- const index = pluginItems.length + kbItems.length + topicIndex;
27668
- return /* @__PURE__ */ jsxs7("button", { ref: selectedRef(index), type: "button", title: item.path, className: rowClassName(index), onMouseDown: (event) => {
27202
+ const index = pluginItems.length + topicIndex;
27203
+ return /* @__PURE__ */ jsxs8("button", { ref: selectedRef(index), type: "button", title: item.path, className: rowClassName(index), onMouseDown: (event) => {
27669
27204
  event.preventDefault();
27670
27205
  handleSelect(item);
27671
27206
  }, children: [
27672
- /* @__PURE__ */ jsx16(File, { size: 14, className: "shrink-0 text-muted-foreground" }),
27673
- /* @__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 })
27674
27209
  ] }, `${item.topic_id}:${item.path}`);
27675
27210
  })
27676
27211
  ] }) : null,
27677
- 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,
27678
- fileEmptyLabel ? /* @__PURE__ */ jsx16("div", { className: "px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]", children: fileEmptyLabel }) : filteredEntries.map((entry, fileIndex) => {
27679
- const index = pluginItems.length + kbItems.length + topicItems.length + fileIndex;
27680
- return /* @__PURE__ */ jsxs7(
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) => {
27214
+ const index = pluginItems.length + topicItems.length + fileIndex;
27215
+ return /* @__PURE__ */ jsxs8(
27681
27216
  "button",
27682
27217
  {
27683
27218
  ref: selectedRef(index),
@@ -27688,9 +27223,9 @@ var FileCompletionMenuContent = forwardRef2(function FileCompletionMenuContent2(
27688
27223
  },
27689
27224
  className: rowClassName(index),
27690
27225
  children: [
27691
- 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))]" }),
27692
- /* @__PURE__ */ jsx16("span", { className: "truncate", children: entry.name }),
27693
- 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" })
27694
27229
  ]
27695
27230
  },
27696
27231
  entry.path
@@ -27700,13 +27235,13 @@ var FileCompletionMenuContent = forwardRef2(function FileCompletionMenuContent2(
27700
27235
  });
27701
27236
 
27702
27237
  // src/rich-input/SkillCompletionMenu.tsx
27703
- import { forwardRef as forwardRef3, useCallback as useCallback6, useImperativeHandle as useImperativeHandle2, useState as useState10 } from "react";
27704
- 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";
27705
27240
  var SkillCompletionMenu = forwardRef3(
27706
27241
  function SkillCompletionMenu2({ command: command2, items }, ref) {
27707
27242
  const [rawSelectedIndex, setRawSelectedIndex] = useState10(0);
27708
27243
  const selectedIndex = items.length === 0 ? 0 : Math.min(rawSelectedIndex, items.length - 1);
27709
- const handleSelect = useCallback6(
27244
+ const handleSelect = useCallback5(
27710
27245
  (item) => {
27711
27246
  command2(item);
27712
27247
  },
@@ -27747,12 +27282,11 @@ var SkillCompletionMenu = forwardRef3(
27747
27282
  [handleSelect, items, selectedIndex]
27748
27283
  );
27749
27284
  const commandItems = items.filter((item) => item.type === "command");
27750
- const workflowItems = items.filter((item) => item.type === "workflow");
27751
27285
  const skillItems = items.filter((item) => item.type === "skill");
27752
- 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: [
27753
- commandItems.length > 0 ? /* @__PURE__ */ jsxs8("div", { className: "px-2 pb-1 pt-1", children: [
27754
- /* @__PURE__ */ jsx17("div", { className: "px-1 pb-1 text-[10px] font-semibold uppercase tracking-[0.08em] text-[hsl(var(--muted-foreground))]", children: "\u547D\u4EE4" }),
27755
- 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(
27756
27290
  "button",
27757
27291
  {
27758
27292
  ref: (element) => {
@@ -27767,51 +27301,21 @@ var SkillCompletionMenu = forwardRef3(
27767
27301
  },
27768
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))]"}`,
27769
27303
  children: [
27770
- /* @__PURE__ */ jsx17("span", { className: "pt-0.5 text-sm", children: "\u21BB" }),
27771
- /* @__PURE__ */ jsxs8("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
27772
- /* @__PURE__ */ jsx17("span", { className: "text-sm font-medium", children: item.label }),
27773
- /* @__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 })
27774
27308
  ] })
27775
27309
  ]
27776
27310
  },
27777
27311
  item.id
27778
27312
  ))
27779
27313
  ] }) : null,
27780
- workflowItems.length > 0 ? /* @__PURE__ */ jsxs8("div", { className: "px-2 pb-1 pt-1", children: [
27781
- /* @__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" }),
27782
- workflowItems.map((item, wfIndex) => {
27783
- const index = commandItems.length + wfIndex;
27784
- return /* @__PURE__ */ jsxs8(
27785
- "button",
27786
- {
27787
- ref: (element) => {
27788
- if (element && index === selectedIndex) {
27789
- element.scrollIntoView({ block: "nearest" });
27790
- }
27791
- },
27792
- type: "button",
27793
- onMouseDown: (event) => {
27794
- event.preventDefault();
27795
- handleSelect(item);
27796
- },
27797
- 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))]"}`,
27798
- children: [
27799
- /* @__PURE__ */ jsx17("span", { className: "pt-0.5 text-sm", children: "\u2699" }),
27800
- /* @__PURE__ */ jsxs8("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
27801
- /* @__PURE__ */ jsx17("span", { className: "text-sm font-medium", children: item.displayName }),
27802
- /* @__PURE__ */ jsx17("span", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: item.description || "\u8FD0\u884C\u8FD9\u4E2A\u5DE5\u4F5C\u6D41" })
27803
- ] })
27804
- ]
27805
- },
27806
- `wf:${item.name}`
27807
- );
27808
- })
27809
- ] }) : null,
27810
- skillItems.length > 0 ? /* @__PURE__ */ jsxs8("div", { className: "px-2 pb-1 pt-1", children: [
27811
- /* @__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" }),
27812
27316
  skillItems.map((item, skillIndex) => {
27813
- const index = commandItems.length + workflowItems.length + skillIndex;
27814
- return /* @__PURE__ */ jsxs8(
27317
+ const index = commandItems.length + skillIndex;
27318
+ return /* @__PURE__ */ jsxs9(
27815
27319
  "button",
27816
27320
  {
27817
27321
  ref: (element) => {
@@ -27826,11 +27330,19 @@ var SkillCompletionMenu = forwardRef3(
27826
27330
  },
27827
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))]"}`,
27828
27332
  children: [
27829
- /* @__PURE__ */ jsxs8("span", { className: "flex items-center gap-1.5", children: [
27830
- /* @__PURE__ */ jsx17("span", { className: "text-sm font-medium", children: skillDisplayName(item) }),
27831
- 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
27832
27344
  ] }),
27833
- /* @__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 })
27834
27346
  ]
27835
27347
  },
27836
27348
  item.skillId
@@ -27842,7 +27354,7 @@ var SkillCompletionMenu = forwardRef3(
27842
27354
  );
27843
27355
 
27844
27356
  // src/rich-input/FileSizeLimitDialog.tsx
27845
- import { jsx as jsx18, jsxs as jsxs9 } from "react/jsx-runtime";
27357
+ import { jsx as jsx19, jsxs as jsxs10 } from "react/jsx-runtime";
27846
27358
  function FileSizeLimitDialog({
27847
27359
  open,
27848
27360
  onOpenChange,
@@ -27853,37 +27365,37 @@ function FileSizeLimitDialog({
27853
27365
  return null;
27854
27366
  }
27855
27367
  const limitText = formatFileSize(limitBytes);
27856
- return /* @__PURE__ */ jsx18(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs9(DialogContent, { showCloseButton: false, className: "w-full max-w-lg gap-0 p-0", children: [
27857
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-4 py-3", children: [
27858
- /* @__PURE__ */ jsxs9("div", { children: [
27859
- /* @__PURE__ */ jsx18(DialogTitle, { className: "text-sm font-semibold text-[hsl(var(--foreground))]", children: "\u9644\u4EF6\u8D85\u8FC7\u5927\u5C0F\u9650\u5236" }),
27860
- /* @__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: [
27861
27373
  "\u5355\u4E2A\u9644\u4EF6\u6700\u5927\u652F\u6301 ",
27862
27374
  limitText,
27863
27375
  "\u3002\u4EE5\u4E0B\u6587\u4EF6\u672A\u52A0\u5165\u9644\u4EF6\u5217\u8868\u3002"
27864
27376
  ] })
27865
27377
  ] }),
27866
- /* @__PURE__ */ jsx18(
27378
+ /* @__PURE__ */ jsx19(
27867
27379
  DialogClose,
27868
27380
  {
27869
27381
  title: "\u5173\u95ED",
27870
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))]",
27871
- children: /* @__PURE__ */ jsx18(X, { size: 14 })
27383
+ children: /* @__PURE__ */ jsx19(X, { size: 14 })
27872
27384
  }
27873
27385
  )
27874
27386
  ] }),
27875
- /* @__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(
27876
27388
  "div",
27877
27389
  {
27878
27390
  className: "flex items-center justify-between gap-3 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--accent))] px-3 py-2",
27879
27391
  children: [
27880
- /* @__PURE__ */ jsx18("span", { className: "min-w-0 truncate text-sm text-[hsl(var(--foreground))]", children: file.name }),
27881
- /* @__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) })
27882
27394
  ]
27883
27395
  },
27884
27396
  `${file.name}:${file.size}`
27885
27397
  )) }) }),
27886
- /* @__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(
27887
27399
  "button",
27888
27400
  {
27889
27401
  type: "button",
@@ -27946,41 +27458,6 @@ var FileMention = index_default.extend({
27946
27458
  }
27947
27459
  });
27948
27460
 
27949
- // src/rich-input/extensions/workflow-mention.ts
27950
- var WorkflowMention = Node3.create({
27951
- name: "workflowMention",
27952
- group: "inline",
27953
- inline: true,
27954
- atom: true,
27955
- selectable: false,
27956
- addAttributes() {
27957
- return {
27958
- name: {
27959
- default: "",
27960
- parseHTML: (element) => element.getAttribute("data-workflow") || "",
27961
- renderHTML: (attributes) => ({ "data-workflow": attributes.name })
27962
- }
27963
- };
27964
- },
27965
- parseHTML() {
27966
- return [{ tag: "span[data-workflow]" }];
27967
- },
27968
- renderHTML({ node, HTMLAttributes }) {
27969
- return [
27970
- "span",
27971
- mergeAttributes(HTMLAttributes, {
27972
- // 复用技能胶囊的现成样式(两个输入框的容器 class 都已带它的规则)
27973
- class: "skill-mention-pill",
27974
- "data-workflow": node.attrs.name
27975
- }),
27976
- `\u8FD0\u884C\u5DE5\u4F5C\u6D41 ${node.attrs.name}`
27977
- ];
27978
- },
27979
- renderText({ node }) {
27980
- return `\u8FD0\u884C\u5DE5\u4F5C\u6D41 ${node.attrs.name}`;
27981
- }
27982
- });
27983
-
27984
27461
  // src/rich-input/lib/reasoning-levels.ts
27985
27462
  var REASONING_LEVEL_LABELS = {
27986
27463
  off: "\u5173",
@@ -27996,7 +27473,7 @@ function reasoningLevelLabel(level) {
27996
27473
  }
27997
27474
 
27998
27475
  // src/rich-input/ReasoningModeSelect.tsx
27999
- import { jsx as jsx19, jsxs as jsxs10 } from "react/jsx-runtime";
27476
+ import { jsx as jsx20, jsxs as jsxs11 } from "react/jsx-runtime";
28000
27477
  function ReasoningModeSelect({
28001
27478
  level,
28002
27479
  levels,
@@ -28004,11 +27481,11 @@ function ReasoningModeSelect({
28004
27481
  disabledReason,
28005
27482
  onChange
28006
27483
  }) {
28007
- return /* @__PURE__ */ jsxs10("label", { className: "flex w-full flex-col gap-1 px-3 py-2", children: [
28008
- /* @__PURE__ */ jsxs10("span", { className: "flex w-full items-center gap-2", children: [
28009
- /* @__PURE__ */ jsx19(Brain, { size: 14, className: `shrink-0 ${chatTone("reasoning").text}`, "aria-hidden": "true" }),
28010
- /* @__PURE__ */ jsx19("span", { className: "shrink-0", children: "\u601D\u8003\u6A21\u5F0F" }),
28011
- /* @__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(
28012
27489
  "select",
28013
27490
  {
28014
27491
  value: level,
@@ -28017,18 +27494,18 @@ function ReasoningModeSelect({
28017
27494
  "aria-label": "\u601D\u8003\u6A21\u5F0F",
28018
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",
28019
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",
28020
- 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))
28021
27498
  }
28022
27499
  )
28023
27500
  ] }),
28024
- 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
28025
27502
  ] });
28026
27503
  }
28027
27504
 
28028
27505
  // src/rich-input/PlanningToggle.tsx
28029
- import { jsx as jsx20, jsxs as jsxs11 } from "react/jsx-runtime";
27506
+ import { jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
28030
27507
  function PlanningToggle({ enabled, onChange, disabled }) {
28031
- return /* @__PURE__ */ jsxs11(
27508
+ return /* @__PURE__ */ jsxs12(
28032
27509
  "button",
28033
27510
  {
28034
27511
  type: "button",
@@ -28040,18 +27517,18 @@ function PlanningToggle({ enabled, onChange, disabled }) {
28040
27517
  disabled,
28041
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",
28042
27519
  children: [
28043
- /* @__PURE__ */ jsxs11("span", { className: "flex items-center gap-2", children: [
28044
- /* @__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" }),
28045
27522
  "\u89C4\u5212\u6A21\u5F0F"
28046
27523
  ] }),
28047
- /* @__PURE__ */ jsxs11("span", { className: "flex items-center gap-2", children: [
28048
- /* @__PURE__ */ jsx20("span", { className: "text-[hsl(var(--muted-foreground))]", children: enabled ? "\u5F00" : "\u5173" }),
28049
- /* @__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(
28050
27527
  "span",
28051
27528
  {
28052
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))]"}`,
28053
27530
  "aria-hidden": "true",
28054
- 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))]" })
28055
27532
  }
28056
27533
  )
28057
27534
  ] })
@@ -28072,12 +27549,12 @@ function shouldHandleHistoryKey(event, menuOpen) {
28072
27549
  }
28073
27550
 
28074
27551
  // src/rich-input/ComposerAttachmentViewport.tsx
28075
- import { jsx as jsx21 } from "react/jsx-runtime";
27552
+ import { jsx as jsx23 } from "react/jsx-runtime";
28076
27553
  function ComposerAttachmentViewport({
28077
27554
  className,
28078
27555
  ...props
28079
27556
  }) {
28080
- return /* @__PURE__ */ jsx21(
27557
+ return /* @__PURE__ */ jsx23(
28081
27558
  "div",
28082
27559
  {
28083
27560
  className: cn("min-h-0 max-h-40 overflow-y-auto overscroll-contain", className),
@@ -28087,7 +27564,7 @@ function ComposerAttachmentViewport({
28087
27564
  }
28088
27565
 
28089
27566
  // src/rich-input/ChatInput.tsx
28090
- 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";
28091
27568
  var RECENT_SESSION_LIMIT = 50;
28092
27569
  var DOUBLE_ESCAPE_MS = 450;
28093
27570
  function getEditorText(editor) {
@@ -28102,7 +27579,7 @@ function replaceEditorText(editor, text) {
28102
27579
  editor.commands.focus("end");
28103
27580
  return;
28104
27581
  }
28105
- editor.commands.setContent(buildEditorDocumentWithKbMentions(text, []));
27582
+ editor.commands.setContent(buildEditorDocument(text));
28106
27583
  editor.commands.focus("end");
28107
27584
  }
28108
27585
  function getFileCardIcon(attachment) {
@@ -28258,31 +27735,31 @@ function ComposerFilePill({
28258
27735
  const isFailed = isFile && attachment.status === "failed";
28259
27736
  const isUploading = isFile && attachment.status === "uploading";
28260
27737
  const uploadPercent = isUploading && typeof attachment.uploadProgress === "number" ? Math.max(0, Math.min(100, Math.round(attachment.uploadProgress * 100))) : null;
28261
- return /* @__PURE__ */ jsxs12(
27738
+ return /* @__PURE__ */ jsxs13(
28262
27739
  "div",
28263
27740
  {
28264
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))]"}`,
28265
27742
  children: [
28266
- uploadPercent !== null ? /* @__PURE__ */ jsx23(
27743
+ uploadPercent !== null ? /* @__PURE__ */ jsx24(
28267
27744
  "span",
28268
27745
  {
28269
27746
  className: "absolute inset-y-0 left-0 bg-[hsl(var(--primary))]/10 transition-[width]",
28270
27747
  style: { width: `${uploadPercent}%` }
28271
27748
  }
28272
27749
  ) : null,
28273
- isUploading ? /* @__PURE__ */ jsx23(
27750
+ isUploading ? /* @__PURE__ */ jsx24(
28274
27751
  LoaderCircle,
28275
27752
  {
28276
27753
  size: 12,
28277
27754
  className: "relative z-10 shrink-0 animate-spin text-[hsl(var(--muted-foreground))]"
28278
27755
  }
28279
- ) : /* @__PURE__ */ jsx23(Icon, { size: 12, className: "relative z-10 shrink-0 text-[hsl(var(--muted-foreground))]" }),
28280
- /* @__PURE__ */ jsx23("span", { className: "relative z-10 max-w-32 truncate", children: attachment.name }),
28281
- 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: [
28282
27759
  uploadPercent,
28283
27760
  "%"
28284
27761
  ] }) : null,
28285
- /* @__PURE__ */ jsx23(
27762
+ /* @__PURE__ */ jsx24(
28286
27763
  "button",
28287
27764
  {
28288
27765
  type: "button",
@@ -28290,7 +27767,7 @@ function ComposerFilePill({
28290
27767
  "aria-label": `\u79FB\u9664 ${attachment.name}`,
28291
27768
  title: "\u79FB\u9664",
28292
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))]",
28293
- children: /* @__PURE__ */ jsx23(X, { size: 10 })
27770
+ children: /* @__PURE__ */ jsx24(X, { size: 10 })
28294
27771
  }
28295
27772
  )
28296
27773
  ]
@@ -28413,7 +27890,7 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
28413
27890
  setImportingId(null);
28414
27891
  }
28415
27892
  };
28416
- return /* @__PURE__ */ jsx23(
27893
+ return /* @__PURE__ */ jsx24(
28417
27894
  "div",
28418
27895
  {
28419
27896
  className: "fixed inset-0 z-[60] flex items-center justify-center bg-black/55 p-4",
@@ -28421,44 +27898,44 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
28421
27898
  onKeyDown: (e) => {
28422
27899
  if (e.key === "Escape") onClose();
28423
27900
  },
28424
- children: /* @__PURE__ */ jsxs12(
27901
+ children: /* @__PURE__ */ jsxs13(
28425
27902
  "div",
28426
27903
  {
28427
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)]",
28428
27905
  onClick: (e) => e.stopPropagation(),
28429
27906
  onKeyDown: (e) => e.stopPropagation(),
28430
27907
  children: [
28431
- /* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-5 py-3", children: [
28432
- /* @__PURE__ */ jsx23("h4", { className: "text-sm font-semibold text-[hsl(var(--foreground))]", children: "\u6DFB\u52A0\u4E0A\u4E0B\u6587" }),
28433
- /* @__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(
28434
27911
  "button",
28435
27912
  {
28436
27913
  type: "button",
28437
27914
  onClick: onClose,
28438
27915
  className: "rounded-md p-1 text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
28439
- children: /* @__PURE__ */ jsx23(X, { size: 14 })
27916
+ children: /* @__PURE__ */ jsx24(X, { size: 14 })
28440
27917
  }
28441
27918
  )
28442
27919
  ] }),
28443
- /* @__PURE__ */ jsxs12("div", { className: "px-5 py-4 space-y-3", children: [
28444
- /* @__PURE__ */ jsxs12("div", { className: "relative", children: [
28445
- /* @__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(
28446
27923
  "button",
28447
27924
  {
28448
27925
  type: "button",
28449
27926
  onClick: handleLoadSessions,
28450
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))]",
28451
27928
  children: [
28452
- /* @__PURE__ */ jsx23(Import, { size: 12 }),
27929
+ /* @__PURE__ */ jsx24(Import, { size: 12 }),
28453
27930
  "\u4ECE\u5176\u4ED6\u4F1A\u8BDD\u5BFC\u5165",
28454
- /* @__PURE__ */ jsx23(ChevronDown, { size: 10, className: `transition-transform ${showSessionPicker ? "rotate-180" : ""}` })
27931
+ /* @__PURE__ */ jsx24(ChevronDown, { size: 10, className: `transition-transform ${showSessionPicker ? "rotate-180" : ""}` })
28455
27932
  ]
28456
27933
  }
28457
27934
  ),
28458
- 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: [
28459
- /* @__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" }),
28460
27937
  "\u52A0\u8F7D\u4F1A\u8BDD\u5217\u8868\u2026"
28461
- ] }) : 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(
28462
27939
  "button",
28463
27940
  {
28464
27941
  type: "button",
@@ -28466,16 +27943,16 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
28466
27943
  onClick: () => handleImportSession(s.id),
28467
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",
28468
27945
  children: [
28469
- importingId === s.id && /* @__PURE__ */ jsx23(LoaderCircle, { size: 10, className: "shrink-0 animate-spin" }),
28470
- /* @__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 })
28471
27948
  ]
28472
27949
  },
28473
27950
  s.id
28474
27951
  )) })
28475
27952
  ] }),
28476
- /* @__PURE__ */ jsxs12("div", { children: [
28477
- /* @__PURE__ */ jsx23("label", { htmlFor: "ctx-label", className: "block text-xs font-medium text-[hsl(var(--foreground))] mb-1", children: "\u6807\u7B7E" }),
28478
- /* @__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(
28479
27956
  "input",
28480
27957
  {
28481
27958
  id: "ctx-label",
@@ -28486,13 +27963,13 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
28486
27963
  }
28487
27964
  )
28488
27965
  ] }),
28489
- /* @__PURE__ */ jsxs12("div", { children: [
28490
- /* @__PURE__ */ jsx23("label", { htmlFor: "ctx-content", className: "block text-xs font-medium text-[hsl(var(--foreground))] mb-1", children: "\u5185\u5BB9" }),
28491
- isImportProcessing && /* @__PURE__ */ jsxs12("div", { className: "mb-1.5 flex items-center gap-1.5 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
28492
- /* @__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" }),
28493
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"
28494
27971
  ] }),
28495
- /* @__PURE__ */ jsx23(
27972
+ /* @__PURE__ */ jsx24(
28496
27973
  "textarea",
28497
27974
  {
28498
27975
  id: "ctx-content",
@@ -28505,8 +27982,8 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
28505
27982
  )
28506
27983
  ] })
28507
27984
  ] }),
28508
- /* @__PURE__ */ jsxs12("div", { className: "flex justify-end gap-2 border-t border-[hsl(var(--border))] px-5 py-3", children: [
28509
- /* @__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(
28510
27987
  "button",
28511
27988
  {
28512
27989
  type: "button",
@@ -28515,7 +27992,7 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
28515
27992
  children: "\u53D6\u6D88"
28516
27993
  }
28517
27994
  ),
28518
- /* @__PURE__ */ jsx23(
27995
+ /* @__PURE__ */ jsx24(
28519
27996
  "button",
28520
27997
  {
28521
27998
  type: "button",
@@ -28546,19 +28023,19 @@ function ComposerContextPill({
28546
28023
  }) {
28547
28024
  const [showDetail, setShowDetail] = useState11(false);
28548
28025
  const tokenK = formatTokenK(content);
28549
- return /* @__PURE__ */ jsxs12(Fragment5, { children: [
28550
- /* @__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: [
28551
- 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(
28552
28029
  "button",
28553
28030
  {
28554
28031
  type: "button",
28555
28032
  onClick: () => setShowDetail(true),
28556
28033
  className: "h-6 w-6 overflow-hidden rounded-md border border-[hsl(var(--border))] bg-white",
28557
28034
  title: "\u67E5\u770B\u9009\u4E2D\u533A\u57DF\u622A\u56FE",
28558
- 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" })
28559
28036
  }
28560
28037
  ) : null,
28561
- /* @__PURE__ */ jsx23(
28038
+ /* @__PURE__ */ jsx24(
28562
28039
  "button",
28563
28040
  {
28564
28041
  type: "button",
@@ -28568,7 +28045,7 @@ function ComposerContextPill({
28568
28045
  children: label
28569
28046
  }
28570
28047
  ),
28571
- /* @__PURE__ */ jsx23(
28048
+ /* @__PURE__ */ jsx24(
28572
28049
  "span",
28573
28050
  {
28574
28051
  className: "shrink-0 rounded bg-[hsl(var(--background))] px-1.5 py-0.5 text-[10px] text-[hsl(var(--muted-foreground))]",
@@ -28576,7 +28053,7 @@ function ComposerContextPill({
28576
28053
  children: tokenK
28577
28054
  }
28578
28055
  ),
28579
- /* @__PURE__ */ jsx23(
28056
+ /* @__PURE__ */ jsx24(
28580
28057
  "button",
28581
28058
  {
28582
28059
  type: "button",
@@ -28584,11 +28061,11 @@ function ComposerContextPill({
28584
28061
  "aria-label": `\u79FB\u9664\u4E0A\u4E0B\u6587 ${label}`,
28585
28062
  title: "\u79FB\u9664",
28586
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))]",
28587
- children: /* @__PURE__ */ jsx23(X, { size: 10 })
28064
+ children: /* @__PURE__ */ jsx24(X, { size: 10 })
28588
28065
  }
28589
28066
  )
28590
28067
  ] }),
28591
- showDetail && /* @__PURE__ */ jsx23(
28068
+ showDetail && /* @__PURE__ */ jsx24(
28592
28069
  "div",
28593
28070
  {
28594
28071
  className: "fixed inset-0 z-[60] flex items-center justify-center bg-black/55 p-6",
@@ -28596,31 +28073,31 @@ function ComposerContextPill({
28596
28073
  onKeyDown: (e) => {
28597
28074
  if (e.key === "Escape") setShowDetail(false);
28598
28075
  },
28599
- children: /* @__PURE__ */ jsxs12(
28076
+ children: /* @__PURE__ */ jsxs13(
28600
28077
  "div",
28601
28078
  {
28602
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)]",
28603
28080
  onClick: (e) => e.stopPropagation(),
28604
28081
  onKeyDown: (e) => e.stopPropagation(),
28605
28082
  children: [
28606
- /* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-6 py-3", children: [
28607
- /* @__PURE__ */ jsxs12("div", { className: "min-w-0", children: [
28608
- /* @__PURE__ */ jsx23("h4", { className: "truncate text-xs font-semibold text-[hsl(var(--foreground))]", children: label }),
28609
- 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
28610
28087
  ] }),
28611
- /* @__PURE__ */ jsx23(
28088
+ /* @__PURE__ */ jsx24(
28612
28089
  "button",
28613
28090
  {
28614
28091
  type: "button",
28615
28092
  onClick: () => setShowDetail(false),
28616
28093
  className: "rounded-md p-1 text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
28617
- children: /* @__PURE__ */ jsx23(X, { size: 14 })
28094
+ children: /* @__PURE__ */ jsx24(X, { size: 14 })
28618
28095
  }
28619
28096
  )
28620
28097
  ] }),
28621
- /* @__PURE__ */ jsxs12("div", { className: "min-h-0 flex-1 overflow-y-auto px-6 py-4", children: [
28622
- 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,
28623
- /* @__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 })
28624
28101
  ] })
28625
28102
  ]
28626
28103
  }
@@ -28693,6 +28170,7 @@ function ChatInput({
28693
28170
  lite = false,
28694
28171
  canCreateBoardTask = false
28695
28172
  }) {
28173
+ const developer = useChatRenderMode() === "developer";
28696
28174
  const isBusy = isStreaming || isCompacting;
28697
28175
  const resolvedInputLabel = inputLabel?.trim() || "\u8F93\u5165\u6D88\u606F";
28698
28176
  const initialInput = externalDraft?.value ?? initialDraft ?? "";
@@ -28702,10 +28180,11 @@ function ChatInput({
28702
28180
  externalDraft?.setValue(value);
28703
28181
  });
28704
28182
  const externalDraftValue = externalDraft?.value;
28705
- const inputRef = useRef9(input);
28183
+ const inputRef = useRef7(input);
28706
28184
  inputRef.current = input;
28707
- const appliedInitialDraftKeyRef = useRef9(null);
28708
- useEffect9(() => {
28185
+ const appliedInitialDraftKeyRef = useRef7(null);
28186
+ const appliedInitialDraftRef = useRef7(null);
28187
+ useEffect8(() => {
28709
28188
  if (externalDraftValue == null) return;
28710
28189
  if (inputRef.current === externalDraftValue) return;
28711
28190
  if (editorRef.current) {
@@ -28713,16 +28192,18 @@ function ChatInput({
28713
28192
  }
28714
28193
  setInputInternal(externalDraftValue);
28715
28194
  }, [externalDraftValue]);
28716
- useEffect9(() => {
28195
+ useEffect8(() => {
28717
28196
  const key = initialDraftKey ?? initialDraft ?? "";
28718
28197
  if (!initialDraft || !key || appliedInitialDraftKeyRef.current === key) return;
28719
- if (inputRef.current.trim()) {
28198
+ if (inputRef.current === initialDraft) appliedInitialDraftRef.current = initialDraft;
28199
+ if (inputRef.current.trim() && inputRef.current !== appliedInitialDraftRef.current) {
28720
28200
  appliedInitialDraftKeyRef.current = key;
28721
28201
  return;
28722
28202
  }
28723
28203
  replaceEditorText(editorRef.current, initialDraft);
28724
28204
  setInput(initialDraft);
28725
28205
  appliedInitialDraftKeyRef.current = key;
28206
+ appliedInitialDraftRef.current = initialDraft;
28726
28207
  }, [initialDraft, initialDraftKey, setInput]);
28727
28208
  const [composerAttachments, setComposerAttachmentsInternal] = useState11(
28728
28209
  externalAttachments?.value ?? []
@@ -28737,9 +28218,9 @@ function ChatInput({
28737
28218
  }
28738
28219
  );
28739
28220
  const externalAttachmentsValue = externalAttachments?.value;
28740
- const composerAttachmentsRef = useRef9(composerAttachments);
28221
+ const composerAttachmentsRef = useRef7(composerAttachments);
28741
28222
  composerAttachmentsRef.current = composerAttachments;
28742
- useEffect9(() => {
28223
+ useEffect8(() => {
28743
28224
  if (externalAttachmentsValue == null) return;
28744
28225
  if (composerAttachmentsRef.current === externalAttachmentsValue) return;
28745
28226
  setComposerAttachmentsInternal(externalAttachmentsValue);
@@ -28753,16 +28234,16 @@ function ChatInput({
28753
28234
  const invalidation = useSessionDataInvalidation();
28754
28235
  const SkillStatusBarComponent = SkillStatusBarOverride ?? SkillStatusBar;
28755
28236
  const [actionMenuOpen, setActionMenuOpen] = useState11(false);
28756
- const actionMenuOpenRef = useRef9(false);
28757
- useEffect9(() => {
28237
+ const actionMenuOpenRef = useRef7(false);
28238
+ useEffect8(() => {
28758
28239
  actionMenuOpenRef.current = actionMenuOpen;
28759
28240
  }, [actionMenuOpen]);
28760
28241
  const [connectMenuOpen, setConnectMenuOpen] = useState11(false);
28761
- const fileInputRef = useRef9(null);
28762
- const folderInputRef = useRef9(null);
28763
- const editorRef = useRef9(null);
28764
- const lastEscapeAtRef = useRef9(0);
28765
- 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());
28766
28247
  const currentChatSessionId = useCurrentChatSessionId();
28767
28248
  const activeSessionId = sessionIdProp ?? currentChatSessionId;
28768
28249
  const currentSession = useChatSessionDetail(activeSessionId);
@@ -28789,32 +28270,23 @@ function ChatInput({
28789
28270
  (state3) => activeSessionId ? state3.sendRequests[activeSessionId] : void 0
28790
28271
  );
28791
28272
  const connectionStatus = useComposerConnection(activeSessionId);
28792
- const loadKnowledgeBases2 = useKnowledgeBaseLoader();
28793
28273
  const inputHistory = useInputHistory(activeSessionId, client);
28794
28274
  const queuedTopicRefs = useComposerChannels((state3) => activeSessionId ? state3.topicAssetReferences[activeSessionId] : void 0);
28795
28275
  const getTopicSuggestions = useEffectEvent(async (query) => {
28796
28276
  if (!activeSessionId) return [];
28797
28277
  try {
28798
28278
  const detail = await client.sessions.getSession(activeSessionId);
28799
- return detail.runtime_type === "sandbox" ? getTopicAssetSuggestionItems(client, detail.chat_group_id, query) : [];
28279
+ return getTopicAssetSuggestionItems(client, detail.chat_group_id, query);
28800
28280
  } catch {
28801
- 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" }];
28802
28282
  }
28803
28283
  });
28804
28284
  const getSessionId = useEffectEvent(() => activeSessionId);
28805
28285
  const handleSlashCommand = useEffectEvent((commandId) => onCommand?.(commandId));
28806
- const getKbSuggestionItems = useEffectEvent(async () => {
28807
- try {
28808
- return toKbSuggestionItems(await loadKnowledgeBases2());
28809
- } catch {
28810
- return [];
28811
- }
28812
- });
28813
28286
  const referenceCandidates = useReferenceCandidates(
28814
28287
  () => [client, client.token, activeSessionId, currentSession?.chat_group_id],
28815
28288
  {
28816
28289
  plugins: (query) => getPluginSuggestionItems(client, getSessionId(), query),
28817
- kbs: getKbSuggestionItems,
28818
28290
  topics: getTopicSuggestions,
28819
28291
  files: (query) => getFileSuggestionItems(client, getSessionId(), query)
28820
28292
  }
@@ -28859,7 +28331,7 @@ function ChatInput({
28859
28331
  }
28860
28332
  };
28861
28333
  const stableAppendFiles = useEffectEvent((files) => appendFiles(files));
28862
- const stableHandleSubmit = useEffectEvent(() => handleSubmit());
28334
+ const stableHandleSubmit = useEffectEvent((queueWhenRunning = false) => handleSubmit(queueWhenRunning));
28863
28335
  const getEditorState = useEffectEvent(() => ({
28864
28336
  input,
28865
28337
  connectionStatus,
@@ -28890,7 +28362,6 @@ function ChatInput({
28890
28362
  gapcursor: false,
28891
28363
  heading: false,
28892
28364
  horizontalRule: false,
28893
- // 输入框是纯文本输入区,关掉自动识别链接,避免点击输入的网址直接跳转
28894
28365
  link: false,
28895
28366
  orderedList: false
28896
28367
  }),
@@ -28902,7 +28373,7 @@ function ChatInput({
28902
28373
  command: ({ editor: suggestionEditor, props, range }) => {
28903
28374
  const item = props;
28904
28375
  suggestionEditor.chain().focus().insertContentAt(range, [
28905
- isPluginSuggestionItem(item) ? { type: "pluginMention", attrs: { provider: item.provider, plugin: item.plugin, server: item.server, id: item.id, label: item.label } } : isTopicAssetSuggestionItem(item) ? { type: "topicAssetMention", attrs: { topic_id: item.topic_id, path: item.path } } : isKbSuggestionItem(item) ? { type: "kbMention", attrs: { kbId: item.kbId, name: item.name } } : { type: "fileMention", attrs: { name: item.name, path: item.path } },
28376
+ isPluginSuggestionItem(item) ? { type: "pluginMention", attrs: { provider: item.provider, plugin: item.plugin, server: item.server, id: item.id, label: item.label } } : isTopicAssetSuggestionItem(item) ? { type: "topicAssetMention", attrs: { topic_id: item.topic_id, path: item.path } } : { type: "fileMention", attrs: { name: item.name, path: item.path } },
28906
28377
  {
28907
28378
  type: "text",
28908
28379
  text: " "
@@ -28924,7 +28395,7 @@ function ChatInput({
28924
28395
  if (!container || !root) return;
28925
28396
  updateSuggestionPosition(container, props.clientRect);
28926
28397
  root.render(
28927
- /* @__PURE__ */ jsx23(
28398
+ /* @__PURE__ */ jsx24(
28928
28399
  FileCompletionMenu,
28929
28400
  {
28930
28401
  ref: (instance) => {
@@ -28978,8 +28449,6 @@ function ChatInput({
28978
28449
  }
28979
28450
  }
28980
28451
  }),
28981
- WorkflowMention,
28982
- KbMention,
28983
28452
  PluginMention,
28984
28453
  TopicAssetMention,
28985
28454
  SkillMention.configure({
@@ -28994,13 +28463,6 @@ function ChatInput({
28994
28463
  void handleSlashCommand(item.id);
28995
28464
  return;
28996
28465
  }
28997
- if (item.type === "workflow") {
28998
- suggestionEditor.chain().focus().insertContentAt(range, [
28999
- { type: "workflowMention", attrs: { name: item.name } },
29000
- { type: "text", text: workflowParamsTail(item) }
29001
- ]).run();
29002
- return;
29003
- }
29004
28466
  suggestionEditor.chain().focus().insertContentAt(range, [
29005
28467
  {
29006
28468
  type: "skillMention",
@@ -29026,7 +28488,7 @@ function ChatInput({
29026
28488
  if (!container || !root) return;
29027
28489
  updateSuggestionPosition(container, props.clientRect);
29028
28490
  root.render(
29029
- /* @__PURE__ */ jsx23(
28491
+ /* @__PURE__ */ jsx24(
29030
28492
  SkillCompletionMenu,
29031
28493
  {
29032
28494
  ref: (instance) => {
@@ -29068,7 +28530,7 @@ function ChatInput({
29068
28530
  }
29069
28531
  })
29070
28532
  ],
29071
- content: buildEditorDocumentWithKbMentions(initialInput, []),
28533
+ content: buildEditorDocument(initialInput),
29072
28534
  onCreate: ({ editor: editorInstance }) => {
29073
28535
  editorRef.current = editorInstance;
29074
28536
  syncEditorState(editorInstance);
@@ -29085,7 +28547,7 @@ function ChatInput({
29085
28547
  "aria-label": resolvedInputLabel,
29086
28548
  "data-testid": "chat-message-input",
29087
28549
  "data-blade-input-label": resolvedInputLabel,
29088
- class: "min-h-[34px] max-h-[240px] overflow-y-auto px-5 py-3 text-sm leading-relaxed text-[hsl(var(--foreground))] focus:outline-none [&_.file-mention-pill]:inline-flex [&_.file-mention-pill]:items-center [&_.file-mention-pill]:rounded-full [&_.file-mention-pill]:bg-[hsl(var(--accent))] [&_.file-mention-pill]:px-2 [&_.file-mention-pill]:py-0.5 [&_.file-mention-pill]:font-medium [&_.file-mention-pill]:text-[hsl(var(--primary))] [&_.file-mention-pill]:select-none [&_.file-mention-pill]:whitespace-nowrap [&_.skill-mention-pill]:inline-flex [&_.skill-mention-pill]:items-center [&_.skill-mention-pill]:rounded-full [&_.skill-mention-pill]:bg-[hsl(var(--primary)/0.15)] [&_.skill-mention-pill]:px-2 [&_.skill-mention-pill]:py-0.5 [&_.skill-mention-pill]:font-medium [&_.skill-mention-pill]:text-[hsl(var(--primary))] [&_.skill-mention-pill]:select-none [&_.skill-mention-pill]:whitespace-nowrap [&_.kb-mention-pill]:inline-flex [&_.kb-mention-pill]:items-center [&_.kb-mention-pill]:rounded-full [&_.kb-mention-pill]:bg-[hsl(var(--accent))] [&_.kb-mention-pill]:px-2 [&_.kb-mention-pill]:py-0.5 [&_.kb-mention-pill]:font-medium [&_.kb-mention-pill]:text-[hsl(var(--primary))] [&_.kb-mention-pill]:select-none [&_.kb-mention-pill]:whitespace-nowrap [&_p:first-child]:mt-0 [&_p:last-child]:mb-0"
28550
+ class: "min-h-[34px] max-h-[240px] overflow-y-auto px-5 py-3 text-sm leading-relaxed text-[hsl(var(--foreground))] focus:outline-none [&_.file-mention-pill]:inline-flex [&_.file-mention-pill]:items-center [&_.file-mention-pill]:rounded-full [&_.file-mention-pill]:bg-[hsl(var(--accent))] [&_.file-mention-pill]:px-2 [&_.file-mention-pill]:py-0.5 [&_.file-mention-pill]:font-medium [&_.file-mention-pill]:text-[hsl(var(--primary))] [&_.file-mention-pill]:select-none [&_.file-mention-pill]:whitespace-nowrap [&_.skill-mention-pill]:inline-flex [&_.skill-mention-pill]:items-center [&_.skill-mention-pill]:rounded-full [&_.skill-mention-pill]:bg-[hsl(var(--primary)/0.15)] [&_.skill-mention-pill]:px-2 [&_.skill-mention-pill]:py-0.5 [&_.skill-mention-pill]:font-medium [&_.skill-mention-pill]:text-[hsl(var(--primary))] [&_.skill-mention-pill]:select-none [&_.skill-mention-pill]:whitespace-nowrap [&_p:first-child]:mt-0 [&_p:last-child]:mb-0"
29089
28551
  },
29090
28552
  handleDOMEvents: {
29091
28553
  focus: () => {
@@ -29144,7 +28606,7 @@ function ChatInput({
29144
28606
  if (state3.connectionStatus !== "connected") {
29145
28607
  return true;
29146
28608
  }
29147
- void state3.handleSubmit();
28609
+ void state3.handleSubmit(isQueueShortcut(event));
29148
28610
  return true;
29149
28611
  }
29150
28612
  return false;
@@ -29161,13 +28623,13 @@ function ChatInput({
29161
28623
  }
29162
28624
  });
29163
28625
  useDismissSkillSuggestionsOnModeChange(editor);
29164
- useEffect9(() => {
28626
+ useEffect8(() => {
29165
28627
  const dom = editor?.view.dom;
29166
28628
  if (!dom) return;
29167
28629
  dom.setAttribute("aria-label", resolvedInputLabel);
29168
28630
  dom.setAttribute("data-blade-input-label", resolvedInputLabel);
29169
28631
  }, [editor, resolvedInputLabel]);
29170
- useEffect9(() => {
28632
+ useEffect8(() => {
29171
28633
  if (!editor || !activeSessionId || rewindDraft == null) {
29172
28634
  return;
29173
28635
  }
@@ -29178,9 +28640,9 @@ function ChatInput({
29178
28640
  editor.commands.focus("end");
29179
28641
  composerChannels.setRewindDraft(activeSessionId, null);
29180
28642
  }, [activeSessionId, editor, rewindDraft]);
29181
- const submittingRef = useRef9(false);
28643
+ const submittingRef = useRef7(false);
29182
28644
  const [isSubmitting, setIsSubmitting] = useState11(false);
29183
- useEffect9(() => {
28645
+ useEffect8(() => {
29184
28646
  let changed = false;
29185
28647
  const nextLocalIds = /* @__PURE__ */ new Set();
29186
28648
  for (const attachment of composerAttachments) {
@@ -29205,7 +28667,7 @@ function ChatInput({
29205
28667
  setLocalImageUrls(Object.fromEntries(localImageUrlsRef.current));
29206
28668
  }
29207
28669
  }, [composerAttachments]);
29208
- useEffect9(() => {
28670
+ useEffect8(() => {
29209
28671
  return () => {
29210
28672
  for (const url of localImageUrlsRef.current.values()) {
29211
28673
  URL.revokeObjectURL(url);
@@ -29214,8 +28676,8 @@ function ChatInput({
29214
28676
  };
29215
28677
  }, []);
29216
28678
  const sessionHandle = useSessionHandle(activeSessionId);
29217
- const restoredPluginSelection = useRef9(null);
29218
- useEffect9(() => {
28679
+ const restoredPluginSelection = useRef7(null);
28680
+ useEffect8(() => {
29219
28681
  if (!sessionHandle || !activeSessionId || !editor) return;
29220
28682
  const restore = () => {
29221
28683
  if (restoredPluginSelection.current === activeSessionId) return;
@@ -29224,13 +28686,13 @@ function ChatInput({
29224
28686
  if (!latest || latest.turn_id.startsWith("local-user-")) return;
29225
28687
  restoredPluginSelection.current = activeSessionId;
29226
28688
  if (!getEditorText(editor).trim() && latest.refs?.length) {
29227
- 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));
29228
28690
  }
29229
28691
  };
29230
28692
  restore();
29231
28693
  return sessionHandle.subscribe(restore);
29232
28694
  }, [sessionHandle, activeSessionId, editor]);
29233
- useEffect9(() => {
28695
+ useEffect8(() => {
29234
28696
  if (!sessionHandle || !activeSessionId) return;
29235
28697
  const offInsert = sessionHandle.on("insertTextRequested", ({ text }) => {
29236
28698
  const separate = /^\n/.test(text);
@@ -29265,7 +28727,7 @@ ${append2.text}` : append2.text;
29265
28727
  editor.chain().focus("end").insertContent(text).run();
29266
28728
  });
29267
28729
  const editorReady = editor != null;
29268
- useEffect9(() => {
28730
+ useEffect8(() => {
29269
28731
  if (!editorReady || !draftAppends?.length) {
29270
28732
  return;
29271
28733
  }
@@ -29281,7 +28743,7 @@ ${append2.text}` : append2.text;
29281
28743
  }
29282
28744
  void stableHandleSubmit();
29283
28745
  });
29284
- useEffect9(() => {
28746
+ useEffect8(() => {
29285
28747
  if (!sendRequests?.length) {
29286
28748
  return;
29287
28749
  }
@@ -29296,10 +28758,10 @@ ${append2.text}` : append2.text;
29296
28758
  });
29297
28759
  const { isRecording, level: voiceLevel } = voice;
29298
28760
  const isVoiceStarting = voice.status === "starting";
29299
- const voiceStopRef = useRef9(voice.stop);
28761
+ const voiceStopRef = useRef7(voice.stop);
29300
28762
  voiceStopRef.current = voice.stop;
29301
- const prevSessionIdRef = useRef9(activeSessionId);
29302
- useEffect9(() => {
28763
+ const prevSessionIdRef = useRef7(activeSessionId);
28764
+ useEffect8(() => {
29303
28765
  if (prevSessionIdRef.current !== activeSessionId) {
29304
28766
  prevSessionIdRef.current = activeSessionId;
29305
28767
  if (isRecording) {
@@ -29307,12 +28769,16 @@ ${append2.text}` : append2.text;
29307
28769
  }
29308
28770
  }
29309
28771
  }, [activeSessionId, isRecording]);
29310
- 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) => {
29311
28777
  if (connectionStatus !== "connected") {
29312
28778
  return;
29313
28779
  }
29314
28780
  if (isCompacting) {
29315
- 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");
29316
28782
  return;
29317
28783
  }
29318
28784
  if (isStopping) {
@@ -29322,12 +28788,9 @@ ${append2.text}` : append2.text;
29322
28788
  notifyChat(environment, "info", "\u5F53\u524D\u56DE\u590D\u5C1A\u672A\u7ED3\u675F\uFF0C\u8BF7\u7B49\u5F85\u672C\u8F6E\u7ED3\u675F\u540E\u518D\u53D1\u9001");
29323
28789
  return;
29324
28790
  }
29325
- if (isStreaming) {
29326
- const json = editor?.getJSON();
29327
- if (composerAttachments.length > 0 || collectPluginMentions(json).length > 0 || collectKbMentions(json).length > 0 || collectTopicAssetMentions(json).length > 0) {
29328
- 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");
29329
- return;
29330
- }
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;
29331
28794
  }
29332
28795
  if (!isStreaming) {
29333
28796
  const modelGate = gateSendWhileModelLoading(isModelLoading, hasComposerContent);
@@ -29356,23 +28819,17 @@ ${append2.text}` : append2.text;
29356
28819
  const rawText = serializeEditorContent(json);
29357
28820
  let submittedSessionId = activeSessionId;
29358
28821
  const submittedAttachmentIds = composerAttachments.map((attachment) => attachment.id);
29359
- const skill = findLeadingSkillMention(json);
29360
- const kbMentions = collectKbMentions(json);
29361
- const kbIds = kbMentions.map((item) => item.kbId);
29362
- const refs = collectPluginMentions(json);
28822
+ const refs = collectMessageMentions(json);
29363
28823
  if (refs.length > 20) {
29364
- 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");
29365
28825
  return;
29366
28826
  }
29367
28827
  const topicAssetRefs = collectTopicAssetMentions(json);
29368
28828
  if (topicAssetRefs.length > 20) {
29369
- 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");
29370
28830
  return;
29371
28831
  }
29372
- const text = skill ? transformSlashCommand(skill.skillId, rawText, {
29373
- local: skill.local,
29374
- installed: skill.installed
29375
- }) : rawText;
28832
+ const text = rawText;
29376
28833
  const pendingFiles = composerAttachments.filter(
29377
28834
  (a) => a.kind === "file" && a.status === "pending" && !!a.file
29378
28835
  );
@@ -29504,12 +28961,11 @@ ${append2.text}` : append2.text;
29504
28961
  try {
29505
28962
  accepted = await onSend(nextPayload, {
29506
28963
  targetSessionId: uploadTargetSessionId,
28964
+ queueWhenRunning,
29507
28965
  model: submitModels.sendModel,
29508
28966
  thinkingOverride: thinkingAvailable && selectedReasoningLevel ? true : void 0,
29509
28967
  reasoningLevel: thinkingAvailable ? selectedReasoningLevel || void 0 : void 0,
29510
- // 只有用户显式 @ 知识库才传选择;纯文本不附加知识库指令。
29511
28968
  refs: pluginRefsForSend(refs, sessionHandle?.getState().turns),
29512
- kbIds: kbIds.length > 0 ? kbIds : void 0,
29513
28969
  topicAssetRefs: topicAssetRefs.length > 0 ? topicAssetRefs : void 0
29514
28970
  });
29515
28971
  } catch (error) {
@@ -29526,7 +28982,7 @@ ${append2.text}` : append2.text;
29526
28982
  return;
29527
28983
  }
29528
28984
  if (refs.length && editor && !getEditorText(editor).trim()) {
29529
- 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));
29530
28986
  }
29531
28987
  if (activeSessionId && activePendingContexts.length > 0) {
29532
28988
  composerChannels.consumePendingContexts(activeSessionId);
@@ -29539,7 +28995,7 @@ ${append2.text}` : append2.text;
29539
28995
  setIsSubmitting(false);
29540
28996
  }
29541
28997
  };
29542
- useEffect9(() => {
28998
+ useEffect8(() => {
29543
28999
  if (!editor || !activeSessionId || !queuedTopicRefs?.length) return;
29544
29000
  const existing = collectTopicAssetMentions(editor.getJSON());
29545
29001
  const refs = composerChannels.consumeTopicAssetReferences(activeSessionId).filter((ref) => !existing.some((item) => item.topic_id === ref.topic_id && item.path === ref.path));
@@ -29559,9 +29015,9 @@ ${append2.text}` : append2.text;
29559
29015
  const reduceMotion = typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
29560
29016
  return reduceMotion ? fullPlaceholder : "";
29561
29017
  });
29562
- const typewriterPlayedRef = useRef9(false);
29563
- const isTypingRef = useRef9(false);
29564
- useEffect9(() => {
29018
+ const typewriterPlayedRef = useRef7(false);
29019
+ const isTypingRef = useRef7(false);
29020
+ useEffect8(() => {
29565
29021
  if (!typewriterPlaceholder || typewriterPlayedRef.current) return;
29566
29022
  typewriterPlayedRef.current = true;
29567
29023
  const reduceMotion = typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
@@ -29582,7 +29038,7 @@ ${append2.text}` : append2.text;
29582
29038
  isTypingRef.current = false;
29583
29039
  };
29584
29040
  }, [typewriterPlaceholder]);
29585
- useEffect9(() => {
29041
+ useEffect8(() => {
29586
29042
  if (isTypingRef.current) return;
29587
29043
  setTypedPlaceholder(fullPlaceholder);
29588
29044
  }, [fullPlaceholder]);
@@ -29590,7 +29046,7 @@ ${append2.text}` : append2.text;
29590
29046
  const attachments = renderAttachments?.() ?? null;
29591
29047
  const hasRenderedAttachments = attachments !== null;
29592
29048
  const hasPendingContexts = (pendingContexts?.length ?? 0) > 0;
29593
- const isSkillEditor = currentSession?.solution_id === "skill_editor" || currentSession?.template_id === "skill_editor";
29049
+ const isSkillEditor = currentSession?.solution_id === "skill_editor";
29594
29050
  const imageAttachments = composerAttachments.filter(isImageAttachment);
29595
29051
  const fileAttachments = composerAttachments.filter(
29596
29052
  (attachment) => !isImageAttachment(attachment)
@@ -29602,11 +29058,12 @@ ${append2.text}` : append2.text;
29602
29058
  const submitWhileRunning = isStreaming && !isStopping && queueWhileRunning;
29603
29059
  const hasComposerContent = Boolean(input.trim()) || hasValidAttachments || hasRenderedAttachments || hasPendingContexts;
29604
29060
  const isSendDisabled = connectionStatus !== "connected" || isCompacting || !submitWhileRunning && isModelLoading || !submitWhileRunning && !hasAvailableModel || isSubmitting || hasUploadingFiles || !input.trim() && !hasValidAttachments && !hasRenderedAttachments && !hasPendingContexts;
29605
- return /* @__PURE__ */ jsxs12(Fragment5, { children: [
29606
- /* @__PURE__ */ jsx23("div", { className: `px-5 pb-3 pt-0 ${className ?? ""}`, children: /* @__PURE__ */ jsxs12("div", { className: `mx-auto ${maxWidthClassName} ${innerClassName ?? ""}`, children: [
29607
- statusBarAddon ? /* @__PURE__ */ jsx23("div", { className: "mb-2 flex flex-wrap items-center gap-2", children: statusBarAddon }) : null,
29608
- !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,
29609
- /* @__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(
29610
29067
  "div",
29611
29068
  {
29612
29069
  className: "relative",
@@ -29640,22 +29097,20 @@ ${append2.text}` : append2.text;
29640
29097
  if (files.length > 0) void stableAppendFiles(files);
29641
29098
  });
29642
29099
  },
29643
- children: /* @__PURE__ */ jsxs12(
29100
+ children: /* @__PURE__ */ jsxs13(
29644
29101
  "div",
29645
29102
  {
29646
- className: `overflow-visible border bg-[hsl(var(--card))] transition-[box-shadow,border-color] duration-300 ${// 上方贴着队列面板时上两角改直角:面板比输入框窄一圈,上角留着
29647
- // 22px 圆弧的话,这两段弧会从面板两侧露出来,就是截图里的尖角。
29648
- 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)]"}`,
29649
29104
  children: [
29650
- 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" }) }),
29651
29106
  planPanel,
29652
- composerAttachments.length > 0 && /* @__PURE__ */ jsxs12(ComposerAttachmentViewport, { className: "flex flex-col gap-2 border-b border-[hsl(var(--border))] px-4 py-2", children: [
29653
- 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(
29654
29109
  "div",
29655
29110
  {
29656
29111
  className: "relative overflow-hidden rounded-xl border border-[hsl(var(--border))]",
29657
29112
  children: [
29658
- /* @__PURE__ */ jsx23(
29113
+ /* @__PURE__ */ jsx24(
29659
29114
  "img",
29660
29115
  {
29661
29116
  src: getImagePreviewUrl(client, attachment, activeSessionId, localImageUrls),
@@ -29663,7 +29118,7 @@ ${append2.text}` : append2.text;
29663
29118
  className: "h-24 w-full object-cover"
29664
29119
  }
29665
29120
  ),
29666
- /* @__PURE__ */ jsx23(
29121
+ /* @__PURE__ */ jsx24(
29667
29122
  "button",
29668
29123
  {
29669
29124
  type: "button",
@@ -29671,14 +29126,14 @@ ${append2.text}` : append2.text;
29671
29126
  "aria-label": `\u79FB\u9664 ${attachment.name || "\u56FE\u7247"}`,
29672
29127
  title: "\u79FB\u9664",
29673
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))]",
29674
- children: /* @__PURE__ */ jsx23(X, { size: 12 })
29129
+ children: /* @__PURE__ */ jsx24(X, { size: 12 })
29675
29130
  }
29676
29131
  )
29677
29132
  ]
29678
29133
  },
29679
29134
  attachment.id
29680
29135
  )) }),
29681
- 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(
29682
29137
  ComposerFilePill,
29683
29138
  {
29684
29139
  attachment,
@@ -29687,8 +29142,8 @@ ${append2.text}` : append2.text;
29687
29142
  attachment.id
29688
29143
  )) })
29689
29144
  ] }),
29690
- 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: [
29691
- 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(
29692
29147
  ComposerContextPill,
29693
29148
  {
29694
29149
  id: context.id,
@@ -29704,18 +29159,18 @@ ${append2.text}` : append2.text;
29704
29159
  },
29705
29160
  context.id
29706
29161
  )),
29707
- isSkillEditor && /* @__PURE__ */ jsx23(
29162
+ isSkillEditor && /* @__PURE__ */ jsx24(
29708
29163
  "button",
29709
29164
  {
29710
29165
  type: "button",
29711
29166
  onClick: () => setShowAddContext(true),
29712
29167
  title: "\u6DFB\u52A0\u4E0A\u4E0B\u6587",
29713
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))]",
29714
- children: /* @__PURE__ */ jsx23(Plus, { size: 12 })
29169
+ children: /* @__PURE__ */ jsx24(Plus, { size: 12 })
29715
29170
  }
29716
29171
  )
29717
29172
  ] }) : null,
29718
- showAddContext && activeSessionId && /* @__PURE__ */ jsx23(
29173
+ showAddContext && activeSessionId && /* @__PURE__ */ jsx24(
29719
29174
  AddContextDialog,
29720
29175
  {
29721
29176
  sessionId: activeSessionId,
@@ -29727,15 +29182,15 @@ ${append2.text}` : append2.text;
29727
29182
  }
29728
29183
  }
29729
29184
  ),
29730
- attachments ? /* @__PURE__ */ jsx23("div", { className: "border-b border-[hsl(var(--border))] px-4 py-3", children: attachments }) : null,
29731
- slotAboveTextarea ? /* @__PURE__ */ jsx23("div", { className: "border-b border-[hsl(var(--border))] px-4 py-2", children: slotAboveTextarea }) : null,
29732
- /* @__PURE__ */ jsxs12("div", { className: "relative", children: [
29733
- 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 }),
29734
- /* @__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 })
29735
29190
  ] }),
29736
- /* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-between px-4 pb-3 pt-1", children: [
29737
- /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
29738
- /* @__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(
29739
29194
  "input",
29740
29195
  {
29741
29196
  ref: fileInputRef,
@@ -29751,7 +29206,7 @@ ${append2.text}` : append2.text;
29751
29206
  className: "hidden"
29752
29207
  }
29753
29208
  ),
29754
- /* @__PURE__ */ jsx23(
29209
+ /* @__PURE__ */ jsx24(
29755
29210
  "input",
29756
29211
  {
29757
29212
  ref: folderInputRef,
@@ -29767,7 +29222,7 @@ ${append2.text}` : append2.text;
29767
29222
  ...{ webkitdirectory: "" }
29768
29223
  }
29769
29224
  ),
29770
- /* @__PURE__ */ jsxs12(
29225
+ /* @__PURE__ */ jsxs13(
29771
29226
  dist_exports.Root,
29772
29227
  {
29773
29228
  open: actionMenuOpen,
@@ -29776,17 +29231,17 @@ ${append2.text}` : append2.text;
29776
29231
  if (open) setConnectMenuOpen(false);
29777
29232
  },
29778
29233
  children: [
29779
- /* @__PURE__ */ jsx23(dist_exports.Trigger, { asChild: true, children: /* @__PURE__ */ jsx23(
29234
+ /* @__PURE__ */ jsx24(dist_exports.Trigger, { asChild: true, children: /* @__PURE__ */ jsx24(
29780
29235
  "button",
29781
29236
  {
29782
29237
  type: "button",
29783
29238
  "aria-label": "\u6DFB\u52A0\u5185\u5BB9",
29784
29239
  title: "\u6DFB\u52A0\u5185\u5BB9",
29785
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))]",
29786
- children: /* @__PURE__ */ jsx23(Plus, { size: 14 })
29241
+ children: /* @__PURE__ */ jsx24(Plus, { size: 14 })
29787
29242
  }
29788
29243
  ) }),
29789
- /* @__PURE__ */ jsx23(dist_exports.Portal, { children: /* @__PURE__ */ jsxs12(
29244
+ /* @__PURE__ */ jsx24(dist_exports.Portal, { children: /* @__PURE__ */ jsxs13(
29790
29245
  dist_exports.Content,
29791
29246
  {
29792
29247
  side: "top",
@@ -29794,7 +29249,7 @@ ${append2.text}` : append2.text;
29794
29249
  sideOffset: 8,
29795
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",
29796
29251
  children: [
29797
- /* @__PURE__ */ jsxs12(
29252
+ /* @__PURE__ */ jsxs13(
29798
29253
  "button",
29799
29254
  {
29800
29255
  type: "button",
@@ -29804,12 +29259,12 @@ ${append2.text}` : append2.text;
29804
29259
  },
29805
29260
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
29806
29261
  children: [
29807
- /* @__PURE__ */ jsx23(Paperclip, { size: 14 }),
29262
+ /* @__PURE__ */ jsx24(Paperclip, { size: 14 }),
29808
29263
  "\u4E0A\u4F20\u6587\u4EF6"
29809
29264
  ]
29810
29265
  }
29811
29266
  ),
29812
- /* @__PURE__ */ jsxs12(
29267
+ /* @__PURE__ */ jsxs13(
29813
29268
  "button",
29814
29269
  {
29815
29270
  type: "button",
@@ -29819,12 +29274,12 @@ ${append2.text}` : append2.text;
29819
29274
  },
29820
29275
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
29821
29276
  children: [
29822
- /* @__PURE__ */ jsx23(FolderUp, { size: 14 }),
29277
+ /* @__PURE__ */ jsx24(FolderUp, { size: 14 }),
29823
29278
  "\u4E0A\u4F20\u6587\u4EF6\u5939"
29824
29279
  ]
29825
29280
  }
29826
29281
  ),
29827
- onCommand && canCreateBoardTask && !lite ? /* @__PURE__ */ jsxs12(
29282
+ onCommand && canCreateBoardTask && !lite ? /* @__PURE__ */ jsxs13(
29828
29283
  "button",
29829
29284
  {
29830
29285
  type: "button",
@@ -29834,12 +29289,12 @@ ${append2.text}` : append2.text;
29834
29289
  },
29835
29290
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
29836
29291
  children: [
29837
- /* @__PURE__ */ jsx23(ListPlus, { size: 14 }),
29292
+ /* @__PURE__ */ jsx24(ListPlus, { size: 14 }),
29838
29293
  "\u521B\u5EFA\u540E\u53F0\u4EFB\u52A1"
29839
29294
  ]
29840
29295
  }
29841
29296
  ) : null,
29842
- onDoubleEscape ? /* @__PURE__ */ jsxs12(
29297
+ onDoubleEscape ? /* @__PURE__ */ jsxs13(
29843
29298
  "button",
29844
29299
  {
29845
29300
  type: "button",
@@ -29851,13 +29306,13 @@ ${append2.text}` : append2.text;
29851
29306
  },
29852
29307
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
29853
29308
  children: [
29854
- /* @__PURE__ */ jsx23(RotateCcw, { size: 14 }),
29309
+ /* @__PURE__ */ jsx24(RotateCcw, { size: 14 }),
29855
29310
  "\u56DE\u5230\u4E4B\u524D\u7684\u67D0\u4E00\u6B65"
29856
29311
  ]
29857
29312
  }
29858
29313
  ) : null,
29859
- onCommand && !lite ? /* @__PURE__ */ jsxs12(Fragment5, { children: [
29860
- /* @__PURE__ */ jsxs12(
29314
+ onCommand && !lite ? /* @__PURE__ */ jsxs13(Fragment5, { children: [
29315
+ developer ? /* @__PURE__ */ jsxs13(
29861
29316
  "button",
29862
29317
  {
29863
29318
  type: "button",
@@ -29868,12 +29323,12 @@ ${append2.text}` : append2.text;
29868
29323
  disabled: isBusy,
29869
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",
29870
29325
  children: [
29871
- 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 }),
29872
29327
  "\u6574\u7406\u5BF9\u8BDD"
29873
29328
  ]
29874
29329
  }
29875
- ),
29876
- /* @__PURE__ */ jsxs12(
29330
+ ) : null,
29331
+ /* @__PURE__ */ jsxs13(
29877
29332
  "button",
29878
29333
  {
29879
29334
  type: "button",
@@ -29883,12 +29338,12 @@ ${append2.text}` : append2.text;
29883
29338
  },
29884
29339
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
29885
29340
  children: [
29886
- /* @__PURE__ */ jsx23(Download, { size: 14 }),
29341
+ /* @__PURE__ */ jsx24(Download, { size: 14 }),
29887
29342
  "\u5BFC\u51FA\u4F1A\u8BDD"
29888
29343
  ]
29889
29344
  }
29890
29345
  ),
29891
- /* @__PURE__ */ jsxs12(
29346
+ /* @__PURE__ */ jsxs13(
29892
29347
  "button",
29893
29348
  {
29894
29349
  type: "button",
@@ -29898,12 +29353,12 @@ ${append2.text}` : append2.text;
29898
29353
  },
29899
29354
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
29900
29355
  children: [
29901
- /* @__PURE__ */ jsx23(Play, { size: 14 }),
29356
+ /* @__PURE__ */ jsx24(Play, { size: 14 }),
29902
29357
  "\u56DE\u653E\u8FD9\u4E2A\u5BF9\u8BDD"
29903
29358
  ]
29904
29359
  }
29905
29360
  ),
29906
- canShareSession ? /* @__PURE__ */ jsxs12(
29361
+ canShareSession ? /* @__PURE__ */ jsxs13(
29907
29362
  "button",
29908
29363
  {
29909
29364
  type: "button",
@@ -29913,12 +29368,12 @@ ${append2.text}` : append2.text;
29913
29368
  },
29914
29369
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
29915
29370
  children: [
29916
- /* @__PURE__ */ jsx23(Share2, { size: 14 }),
29371
+ /* @__PURE__ */ jsx24(Share2, { size: 14 }),
29917
29372
  "\u5206\u4EAB\u4F1A\u8BDD"
29918
29373
  ]
29919
29374
  }
29920
29375
  ) : null,
29921
- /* @__PURE__ */ jsxs12(
29376
+ /* @__PURE__ */ jsxs13(
29922
29377
  "button",
29923
29378
  {
29924
29379
  type: "button",
@@ -29928,12 +29383,12 @@ ${append2.text}` : append2.text;
29928
29383
  },
29929
29384
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
29930
29385
  children: [
29931
- /* @__PURE__ */ jsx23(FlaskConical, { size: 14 }),
29386
+ /* @__PURE__ */ jsx24(FlaskConical, { size: 14 }),
29932
29387
  "\u63D0\u53D6\u6280\u80FD"
29933
29388
  ]
29934
29389
  }
29935
29390
  ),
29936
- /* @__PURE__ */ jsxs12(
29391
+ /* @__PURE__ */ jsxs13(
29937
29392
  "button",
29938
29393
  {
29939
29394
  type: "button",
@@ -29943,13 +29398,13 @@ ${append2.text}` : append2.text;
29943
29398
  },
29944
29399
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
29945
29400
  children: [
29946
- /* @__PURE__ */ jsx23(Rocket, { size: 14 }),
29401
+ /* @__PURE__ */ jsx24(Rocket, { size: 14 }),
29947
29402
  "\u751F\u6210\u5E94\u7528"
29948
29403
  ]
29949
29404
  }
29950
29405
  )
29951
29406
  ] }) : null,
29952
- onToggleMode && !lite ? /* @__PURE__ */ jsx23(
29407
+ onToggleMode && !lite ? /* @__PURE__ */ jsx24(
29953
29408
  PlanningToggle,
29954
29409
  {
29955
29410
  enabled: isPlanning,
@@ -29960,22 +29415,23 @@ ${append2.text}` : append2.text;
29960
29415
  disabled: isBusy
29961
29416
  }
29962
29417
  ) : null,
29963
- !lite && thinkingAvailable && reasoningLevels.length > 0 ? /* @__PURE__ */ jsx23(
29418
+ !lite && thinkingAvailable && reasoningLevels.length > 0 ? /* @__PURE__ */ jsx24(
29964
29419
  ReasoningModeSelect,
29965
29420
  {
29966
29421
  level: selectedReasoningLevel,
29967
29422
  levels: reasoningLevels,
29968
29423
  disabled: isCompacting,
29969
- 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",
29970
29425
  onChange: model.setReasoningLevel
29971
29426
  }
29972
29427
  ) : null,
29973
- !lite ? /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2 px-3 py-2", children: [
29974
- /* @__PURE__ */ jsx23(Sparkles, { size: 14, className: "shrink-0", "aria-hidden": "true" }),
29975
- /* @__PURE__ */ jsx23("span", { className: "shrink-0", children: "\u6A21\u578B" }),
29976
- /* @__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(
29977
29432
  ModelSelector,
29978
29433
  {
29434
+ disabled: isModelLoading,
29979
29435
  value: selectedModel,
29980
29436
  onValueChange: model.selectModel,
29981
29437
  compact: true,
@@ -29983,8 +29439,8 @@ ${append2.text}` : append2.text;
29983
29439
  }
29984
29440
  )
29985
29441
  ] }) : null,
29986
- !lite && activeSessionId && actionMenuOpen ? /* @__PURE__ */ jsxs12("div", { className: "border-t border-[hsl(var(--border))] px-3 py-2.5", children: [
29987
- /* @__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(
29988
29444
  SkillStatusBarComponent,
29989
29445
  {
29990
29446
  sessionId: activeSessionId,
@@ -29994,7 +29450,7 @@ ${append2.text}` : append2.text;
29994
29450
  innerClassName: skillStatusBarInnerClassName
29995
29451
  }
29996
29452
  ),
29997
- 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
29998
29454
  ] }) : null
29999
29455
  ]
30000
29456
  }
@@ -30002,7 +29458,7 @@ ${append2.text}` : append2.text;
30002
29458
  ]
30003
29459
  }
30004
29460
  ),
30005
- /* @__PURE__ */ jsx23(
29461
+ /* @__PURE__ */ jsx24(
30006
29462
  ConnectButton,
30007
29463
  {
30008
29464
  sessionId: activeSessionId,
@@ -30015,11 +29471,15 @@ ${append2.text}` : append2.text;
30015
29471
  }
30016
29472
  }
30017
29473
  ),
30018
- !lite && activeSessionId ? /* @__PURE__ */ jsx23(BackgroundTasksPill, { sessionId: activeSessionId }) : null
29474
+ !lite && activeSessionId ? /* @__PURE__ */ jsx24(BackgroundTasksPill, { sessionId: activeSessionId }) : null
30019
29475
  ] }),
30020
- /* @__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
+ ] }),
30021
29481
  slotBeforeSend,
30022
- !isStreaming && !isCompacting && asrEnabled && (isRecording || isVoiceStarting || !hasComposerContent) ? /* @__PURE__ */ jsx23(
29482
+ !isStreaming && !isCompacting && asrEnabled && (isRecording || isVoiceStarting || !hasComposerContent) ? /* @__PURE__ */ jsx24(
30023
29483
  "button",
30024
29484
  {
30025
29485
  type: "button",
@@ -30027,23 +29487,23 @@ ${append2.text}` : append2.text;
30027
29487
  "aria-label": isRecording || isVoiceStarting ? "\u505C\u6B62\u8BED\u97F3\u8F93\u5165" : "\u5F00\u59CB\u8BED\u97F3\u8F93\u5165",
30028
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",
30029
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)]"}`,
30030
- 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 })
30031
29491
  }
30032
29492
  ) : null,
30033
- isStreaming ? /* @__PURE__ */ jsxs12(Fragment5, { children: [
30034
- submitWhileRunning ? /* @__PURE__ */ jsx23(
29493
+ isStreaming ? /* @__PURE__ */ jsxs13(Fragment5, { children: [
29494
+ submitWhileRunning ? /* @__PURE__ */ jsx24(
30035
29495
  "button",
30036
29496
  {
30037
29497
  type: "button",
30038
- onClick: handleSubmit,
29498
+ onClick: () => void handleSubmit(),
30039
29499
  disabled: isSendDisabled || isRecording,
30040
- "aria-label": "\u52A0\u5165\u6392\u961F",
30041
- title: "\u52A0\u5165\u6392\u961F",
29500
+ "aria-label": "\u53D1\u9001\u5F15\u5BFC\u6D88\u606F",
29501
+ title: "\u53D1\u9001\u5F15\u5BFC\u6D88\u606F",
30042
29502
  className: "flex h-10 w-10 items-center justify-center rounded-full bg-[hsl(213_94%_55%)] text-white disabled:opacity-25",
30043
- 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 })
30044
29504
  }
30045
29505
  ) : null,
30046
- /* @__PURE__ */ jsx23(
29506
+ /* @__PURE__ */ jsx24(
30047
29507
  "button",
30048
29508
  {
30049
29509
  type: "button",
@@ -30052,41 +29512,41 @@ ${append2.text}` : append2.text;
30052
29512
  "aria-label": isStopping ? "\u6B63\u5728\u505C\u6B62" : "\u505C\u6B62\u751F\u6210",
30053
29513
  title: isStopping ? "\u6B63\u5728\u505C\u6B62" : "\u505C\u6B62\u751F\u6210",
30054
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",
30055
- 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 })
30056
29516
  }
30057
29517
  )
30058
- ] }) : isCompacting ? /* @__PURE__ */ jsx23(
29518
+ ] }) : isCompacting ? /* @__PURE__ */ jsx24(
30059
29519
  "button",
30060
29520
  {
30061
29521
  type: "button",
30062
29522
  disabled: true,
30063
- "aria-label": "\u6B63\u5728\u6574\u7406\u5BF9\u8BDD",
30064
- 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",
30065
29525
  className: "flex h-10 w-10 items-center justify-center rounded-full bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))] opacity-50",
30066
- children: /* @__PURE__ */ jsx23(LoaderCircle, { size: 16, className: "animate-spin" })
29526
+ children: /* @__PURE__ */ jsx24(LoaderCircle, { size: 16, className: "animate-spin" })
30067
29527
  }
30068
- ) : !isRecording && hasComposerContent ? /* @__PURE__ */ jsx23(
29528
+ ) : !isRecording && hasComposerContent ? /* @__PURE__ */ jsx24(
30069
29529
  "button",
30070
29530
  {
30071
29531
  type: "button",
30072
- onClick: handleSubmit,
29532
+ onClick: () => void handleSubmit(),
30073
29533
  disabled: isSendDisabled,
30074
- "aria-label": "\u53D1\u9001\u6D88\u606F",
30075
- 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",
30076
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",
30077
- 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 })
30078
29538
  }
30079
29539
  ) : null
30080
29540
  ] })
30081
29541
  ] }),
30082
- 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
30083
29543
  ]
30084
29544
  }
30085
29545
  )
30086
29546
  }
30087
29547
  )
30088
29548
  ] }) }),
30089
- /* @__PURE__ */ jsx23(
29549
+ /* @__PURE__ */ jsx24(
30090
29550
  FileSizeLimitDialog,
30091
29551
  {
30092
29552
  open: oversizedFiles.length > 0,
@@ -30101,6 +29561,42 @@ ${append2.text}` : append2.text;
30101
29561
  )
30102
29562
  ] });
30103
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
+ }
30104
29600
  export {
30105
29601
  ATTACHMENT_SIZE_LIMIT_BYTES,
30106
29602
  ATTENTION_STATUSES,
@@ -30112,8 +29608,7 @@ export {
30112
29608
  FileMention,
30113
29609
  FileSizeLimitDialog,
30114
29610
  IMAGE_INPUT_UNSUPPORTED_MESSAGE,
30115
- KB_SUGGESTION_TIMEOUT_MS,
30116
- KbMention,
29611
+ InputActionSubmenu,
30117
29612
  LIVE_STATUSES,
30118
29613
  MODEL_LOADING_SEND_HINT,
30119
29614
  MODEL_REASONING_LEVELS_KEY,
@@ -30126,50 +29621,46 @@ export {
30126
29621
  RichInputServicesProvider,
30127
29622
  STATUS_LABELS,
30128
29623
  STOPPABLE_STATUSES,
29624
+ SkillActionMenu,
30129
29625
  SkillCompletionMenu,
30130
29626
  SkillMention,
30131
29627
  SkillStatusBar,
30132
29628
  TopicAssetMention,
30133
29629
  VoiceWaveform,
30134
- WorkflowMention,
30135
- buildEditorDocumentWithKbMentions,
29630
+ buildEditorDocument,
30136
29631
  buildEditorDocumentWithMentions,
29632
+ buildPluginSelectionDocument,
30137
29633
  buildSubmitPayload,
30138
29634
  buildVoiceInputUnavailableError,
30139
- collectKbMentions,
29635
+ collectMessageMentions,
30140
29636
  collectPluginMentions,
30141
29637
  collectTopicAssetMentions,
30142
29638
  entryLabel,
30143
29639
  estimateTokenCount,
30144
29640
  fetchClientQuery,
30145
29641
  fileMentionSuggestionKey,
30146
- filterKbSuggestions,
30147
29642
  findLeadingSkillMention,
30148
29643
  formatFileSize,
30149
29644
  formatStartedAt,
30150
29645
  gateSendWhileModelLoading,
30151
29646
  getFileSuggestionItems,
30152
29647
  getInputModalities,
30153
- getLastUserHomeRuntime,
30154
29648
  getPluginSuggestionItems,
30155
29649
  getSkillSuggestions,
30156
29650
  getSlashSuggestions,
30157
29651
  getTopicAssetSuggestionItems,
30158
29652
  getUnsupportedImageFiles,
30159
- getUserHomeRuntime,
30160
29653
  getUserHomeSuggestionItems,
30161
29654
  installSuggestionOutsideDismiss,
30162
29655
  invalidateSlashSuggestions,
30163
29656
  isImageFile,
30164
29657
  isImeCompositionKey,
30165
- isKbSuggestionItem,
30166
29658
  isPluginSuggestionItem,
30167
29659
  isSubmittedComposerStillCurrent,
30168
29660
  isTopicAssetSuggestionError,
30169
29661
  isTopicAssetSuggestionItem,
30170
29662
  listUserHomeDir,
30171
29663
  mergeSubmittedAttachmentUpdates,
30172
- notifyWhenKbSuggestionsArriveLate,
30173
29664
  parseUserHomeQuery,
30174
29665
  queueTopicAssetReference,
30175
29666
  reasoningLevelLabel,
@@ -30187,7 +29678,6 @@ export {
30187
29678
  splitTasks,
30188
29679
  statusClass,
30189
29680
  statusLabel,
30190
- toKbSuggestionItems,
30191
29681
  tokenPressureOf,
30192
29682
  uploadedPathsById,
30193
29683
  useBackgroundTaskList,
@@ -30205,7 +29695,6 @@ export {
30205
29695
  useContextStats,
30206
29696
  useDismissSkillSuggestionsOnModeChange,
30207
29697
  useInputHistory,
30208
- useKnowledgeBaseLoader,
30209
29698
  useModelCatalog,
30210
29699
  useModelPreferences,
30211
29700
  useReasoningLevelPreference,
@@ -30217,10 +29706,7 @@ export {
30217
29706
  useSessionSkills,
30218
29707
  useSkillStats,
30219
29708
  useTiptapVoiceInput,
30220
- useVoiceInput,
30221
- withKbSuggestionTimeout,
30222
- workflowParamsTail,
30223
- workflowRunText
29709
+ useVoiceInput
30224
29710
  };
30225
29711
  /*! Bundled license information:
30226
29712