@blade-hq/agent-kit 0.5.25 → 0.5.26

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 (34) hide show
  1. package/dist/{SkillStatusBar-BUisTEAL.d.ts → SkillStatusBar-qjGb3eKD.d.ts} +6 -3
  2. package/dist/{blade-client-KmBClau6.d.ts → blade-client-DA2h2P5I.d.ts} +13 -1
  3. package/dist/{chunk-UQWHEHG3.js → chunk-4FCXKLXT.js} +11 -5
  4. package/dist/chunk-4FCXKLXT.js.map +1 -0
  5. package/dist/{chunk-HAFDWDFG.js → chunk-6L6JFSR5.js} +2 -2
  6. package/dist/{chunk-SENUKC7C.js → chunk-QCDNRR74.js} +42 -12
  7. package/dist/chunk-QCDNRR74.js.map +1 -0
  8. package/dist/{chunk-FZXLII7S.js → chunk-UNO53NPU.js} +14 -2
  9. package/dist/{chunk-FZXLII7S.js.map → chunk-UNO53NPU.js.map} +1 -1
  10. package/dist/{chunk-PKQKLRFQ.js → chunk-Y7FRTBUT.js} +20 -4
  11. package/dist/chunk-Y7FRTBUT.js.map +1 -0
  12. package/dist/{chunk-7EVVRQ7G.js → chunk-ZWO6YBLA.js} +4 -3
  13. package/dist/chunk-ZWO6YBLA.js.map +1 -0
  14. package/dist/client/index.d.ts +63 -6
  15. package/dist/client/index.js +1 -1
  16. package/dist/react/api/vibe-coding.d.ts +2 -2
  17. package/dist/react/api/vibe-coding.js +2 -2
  18. package/dist/react/components/chat/index.d.ts +3 -3
  19. package/dist/react/components/chat/index.js +5 -5
  20. package/dist/react/components/plan/index.js +4 -4
  21. package/dist/react/components/session/index.js +3 -3
  22. package/dist/react/components/workspace/index.d.ts +2 -2
  23. package/dist/react/components/workspace/index.js +3 -3
  24. package/dist/react/index.d.ts +13 -6
  25. package/dist/react/index.js +9 -7
  26. package/dist/react/index.js.map +1 -1
  27. package/dist/{sessions-DfRYZZnH.d.ts → sessions-BZ3y17sP.d.ts} +1 -1
  28. package/dist/style.css +1 -1
  29. package/package.json +1 -1
  30. package/dist/chunk-7EVVRQ7G.js.map +0 -1
  31. package/dist/chunk-PKQKLRFQ.js.map +0 -1
  32. package/dist/chunk-SENUKC7C.js.map +0 -1
  33. package/dist/chunk-UQWHEHG3.js.map +0 -1
  34. /package/dist/{chunk-HAFDWDFG.js.map → chunk-6L6JFSR5.js.map} +0 -0
@@ -4,7 +4,7 @@ import { ComponentType, ReactNode } from 'react';
4
4
  import { C as ChatMessage, A as AskUserAnswerData, T as ToolCallInfo, M as MessageContent } from './AskUserQuestionBlock---kOTouk.js';
5
5
  import * as zustand from 'zustand';
6
6
  import { M as ModeId, a as SessionInfo, b as SessionStatus } from './session-B5v5KkVd.js';
7
- import { v as BladeClient } from './blade-client-KmBClau6.js';
7
+ import { v as BladeClient } from './blade-client-DA2h2P5I.js';
8
8
  import { C as ContentBlock } from './projection-BWYEFYNn.js';
9
9
 
10
10
  /**
@@ -172,8 +172,9 @@ interface ChatViewProps extends ChatViewCustomization {
172
172
  canShareSession?: boolean;
173
173
  onResyncSkills?: () => void;
174
174
  isResyncingSkills?: boolean;
175
+ inputLabel?: string;
175
176
  }
176
- declare function ChatView({ sessionId, renderAttachments, onBeforeSend, onCommand, canShareSession, onResyncSkills, isResyncingSkills, classNames, components, renderers, }: ChatViewProps): react_jsx_runtime.JSX.Element;
177
+ declare function ChatView({ sessionId, renderAttachments, onBeforeSend, onCommand, canShareSession, onResyncSkills, isResyncingSkills, inputLabel, classNames, components, renderers, }: ChatViewProps): react_jsx_runtime.JSX.Element;
177
178
 
178
179
  type SessionMode = ModeId;
179
180
  interface SessionState extends ClientAwareState {
@@ -218,6 +219,7 @@ declare const useSessionStore: zustand.UseBoundStore<zustand.StoreApi<SessionSta
218
219
 
219
220
  interface Props$2 {
220
221
  onSend: (message: MessageContent, targetSessionId?: string, model?: string | null) => void;
222
+ onAppend?: (message: string) => void;
221
223
  onStop: () => void | Promise<void>;
222
224
  isStreaming: boolean;
223
225
  isStopping?: boolean;
@@ -269,6 +271,7 @@ interface Props$2 {
269
271
  skillStatusBarInnerClassName?: string;
270
272
  onResyncSkills?: () => void;
271
273
  isResyncingSkills?: boolean;
274
+ inputLabel?: string;
272
275
  }
273
276
  type FileComposerAttachment = {
274
277
  id: string;
@@ -282,7 +285,7 @@ type FileComposerAttachment = {
282
285
  textContent?: string | null;
283
286
  uploadProgress?: number | null;
284
287
  };
285
- declare function ChatInput({ onSend, onStop, isStreaming, isStopping, mode, onToggleMode, renderAttachments, onBeforeSend, ensureSession, onCommand, canShareSession, slotAboveTextarea, externalDraft, externalAttachments, maxWidthClassName, className, innerClassName, SkillStatusBarComponent, skillStatusBarClassName, skillStatusBarInnerClassName, onResyncSkills, isResyncingSkills, }: Props$2): react_jsx_runtime.JSX.Element;
288
+ declare function ChatInput({ onSend, onAppend, onStop, isStreaming, isStopping, mode, onToggleMode, renderAttachments, onBeforeSend, ensureSession, onCommand, canShareSession, slotAboveTextarea, externalDraft, externalAttachments, maxWidthClassName, className, innerClassName, SkillStatusBarComponent, skillStatusBarClassName, skillStatusBarInnerClassName, onResyncSkills, isResyncingSkills, inputLabel, }: Props$2): react_jsx_runtime.JSX.Element;
286
289
 
287
290
  interface Props$1 {
288
291
  open: boolean;
@@ -313,7 +313,7 @@ declare class PublishedAppsResource {
313
313
  private client;
314
314
  constructor(client: BladeClient);
315
315
  listPublishedApps(): Promise<PublishedApp[]>;
316
- unpublishApp(sessionId: string): Promise<UnpublishAppResponse>;
316
+ unpublishApp(sessionId: string, appName?: string): Promise<UnpublishAppResponse>;
317
317
  }
318
318
 
319
319
  declare const AgentDriver: arktype_internal_variants_string_ts.StringType<"dify", {}>;
@@ -1235,6 +1235,16 @@ declare namespace ChatStopPayloadSchema {
1235
1235
  }
1236
1236
  }
1237
1237
  type ChatStopPayload = ChatStopPayloadSchema.ChatStopPayload;
1238
+ declare namespace ChatAppendPayloadSchema {
1239
+ type SessionId = string;
1240
+ type Message = string;
1241
+ interface ChatAppendPayload {
1242
+ session_id: SessionId;
1243
+ message: Message;
1244
+ [k: string]: unknown;
1245
+ }
1246
+ }
1247
+ type ChatAppendPayload = ChatAppendPayloadSchema.ChatAppendPayload;
1238
1248
  declare namespace ChatCompactPayloadSchema {
1239
1249
  type SessionId = string;
1240
1250
  interface ChatCompactPayload {
@@ -1594,6 +1604,7 @@ type ChatCompactAck = ChatCompactAckSchema.ChatCompactAck;
1594
1604
  interface ClientToServerEvents {
1595
1605
  "chat:send": (payload: ChatSendPayload) => void;
1596
1606
  "chat:stop": (payload: ChatStopPayload, ack: (response: ChatStopAck) => void) => void;
1607
+ "chat:append": (payload: ChatAppendPayload) => void;
1597
1608
  "chat:compact": (payload: ChatCompactPayload, ack: (response: ChatCompactAck) => void) => void;
1598
1609
  "session:subscribe": (payload: SessionSubscribePayload) => void;
1599
1610
  "session:unsubscribe": (payload: SessionUnsubscribePayload) => void;
@@ -1609,6 +1620,7 @@ interface ClientToServerEvents {
1609
1620
  interface ServerToClientEvents {
1610
1621
  "chat:start": (payload: ChatStartPayload) => void;
1611
1622
  "chat:end": (payload: ChatEndPayload) => void;
1623
+ "chat:append:ack": (payload: unknown) => void;
1612
1624
  "session:updated": (payload: SessionUpdatedPayload) => void;
1613
1625
  "workspace:files_changed": (payload: WorkspaceFilesChangedPayload) => void;
1614
1626
  "system:error": (payload: SystemErrorPayload) => void;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  apiFetchResponse,
3
3
  getAuthedUrl
4
- } from "./chunk-FZXLII7S.js";
4
+ } from "./chunk-UNO53NPU.js";
5
5
 
6
6
  // src/react/lib/session-file-preview.ts
7
7
  var IMAGE_EXTS = /* @__PURE__ */ new Set(["png", "jpg", "jpeg", "gif", "svg", "webp", "ico", "bmp"]);
@@ -54,6 +54,13 @@ function buildSessionBinaryPreviewTarget(sessionId, filePath, fileName) {
54
54
  }
55
55
  return null;
56
56
  }
57
+ function resolveTextPreviewType(fileName) {
58
+ const ext = getExt(fileName);
59
+ if (MARKDOWN_EXTS.has(ext)) return "markdown";
60
+ if (CSV_EXTS.has(ext)) return "csv";
61
+ if (HTML_EXTS.has(ext)) return "html";
62
+ return "file";
63
+ }
57
64
  async function resolveSessionFilePreviewTarget(sessionId, filePath, fileName) {
58
65
  const resolvedFileName = getDisplayFileName(filePath, fileName);
59
66
  const binaryTarget = buildSessionBinaryPreviewTarget(sessionId, filePath, resolvedFileName);
@@ -76,10 +83,8 @@ async function resolveSessionFilePreviewTarget(sessionId, filePath, fileName) {
76
83
  return { type: "download", content: downloadUrl, title: resolvedFileName, key: filePath };
77
84
  }
78
85
  const content = await res.text();
79
- const ext = getExt(resolvedFileName);
80
- const type = MARKDOWN_EXTS.has(ext) ? "markdown" : CSV_EXTS.has(ext) ? "csv" : HTML_EXTS.has(ext) ? "html" : "file";
81
86
  return {
82
- type,
87
+ type: resolveTextPreviewType(resolvedFileName),
83
88
  content,
84
89
  title: resolvedFileName,
85
90
  key: filePath
@@ -89,6 +94,7 @@ async function resolveSessionFilePreviewTarget(sessionId, filePath, fileName) {
89
94
  export {
90
95
  getSessionFilePath,
91
96
  buildSessionBinaryPreviewTarget,
97
+ resolveTextPreviewType,
92
98
  resolveSessionFilePreviewTarget
93
99
  };
94
- //# sourceMappingURL=chunk-UQWHEHG3.js.map
100
+ //# sourceMappingURL=chunk-4FCXKLXT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/react/lib/session-file-preview.ts"],"sourcesContent":["import { apiFetchResponse, getAuthedUrl } from \"../api/client\"\nimport type { PreviewTarget } from \"../stores/ui-store\"\n\nconst IMAGE_EXTS = new Set([\"png\", \"jpg\", \"jpeg\", \"gif\", \"svg\", \"webp\", \"ico\", \"bmp\"])\nconst DOCX_EXTS = new Set([\"docx\", \"doc\"])\nconst EXCEL_EXTS = new Set([\"xlsx\", \"xls\", \"xlsm\", \"xlsb\"])\nconst PPT_EXTS = new Set([\"pptx\", \"ppt\"])\nconst CSV_EXTS = new Set([\"csv\"])\nconst MARKDOWN_EXTS = new Set([\"md\", \"markdown\"])\nconst HTML_EXTS = new Set([\"html\", \"htm\"])\n\nfunction getExt(fileName: string): string {\n return fileName.split(\".\").pop()?.toLowerCase() ?? \"\"\n}\n\nfunction getDisplayFileName(filePath: string, fileName?: string): string {\n return fileName?.trim() || filePath.split(\"/\").pop() || filePath\n}\n\nexport function getSessionFilePath(sessionId: string, filePath: string): string {\n return `/api/sessions/${sessionId}/files/${encodeURIComponent(filePath)}`\n}\n\nfunction getSessionFileDownloadUrl(sessionId: string, filePath: string): string {\n return getAuthedUrl(getSessionFilePath(sessionId, filePath))\n}\n\n/**\n * 后端把可解码为 UTF-8 的文件返回为 text/plain,二进制文件返回各自的 MIME。\n * 只有文本类内容才能安全地整体读进内存渲染——其余一律不能读 body。\n */\nfunction isTextualContentType(contentType: string): boolean {\n return (\n contentType.startsWith(\"text/\") ||\n contentType.includes(\"json\") ||\n contentType.includes(\"xml\") ||\n contentType.includes(\"yaml\") ||\n contentType.includes(\"javascript\")\n )\n}\n\nexport function buildSessionBinaryPreviewTarget(\n sessionId: string,\n filePath: string,\n fileName?: string,\n): PreviewTarget | null {\n const resolvedFileName = getDisplayFileName(filePath, fileName)\n const ext = getExt(resolvedFileName)\n const filePathUrl = getSessionFilePath(sessionId, filePath)\n const downloadUrl = getSessionFileDownloadUrl(sessionId, filePath)\n\n if (IMAGE_EXTS.has(ext)) {\n return { type: \"image\", content: downloadUrl, title: resolvedFileName, key: filePath }\n }\n\n if (ext === \"pdf\") {\n return { type: \"pdf\", content: downloadUrl, title: resolvedFileName, key: filePath }\n }\n\n if (DOCX_EXTS.has(ext)) {\n return { type: \"docx\", content: downloadUrl, title: resolvedFileName, key: filePath }\n }\n\n if (EXCEL_EXTS.has(ext)) {\n return { type: \"excel\", content: downloadUrl, title: resolvedFileName, key: filePath }\n }\n\n if (PPT_EXTS.has(ext)) {\n return {\n type: \"ppt\",\n content: filePathUrl,\n sourceUrl: downloadUrl,\n title: resolvedFileName,\n key: filePath,\n }\n }\n\n return null\n}\n\nexport function resolveTextPreviewType(fileName: string): PreviewTarget[\"type\"] {\n const ext = getExt(fileName)\n if (MARKDOWN_EXTS.has(ext)) return \"markdown\"\n if (CSV_EXTS.has(ext)) return \"csv\"\n if (HTML_EXTS.has(ext)) return \"html\"\n return \"file\"\n}\n\nexport async function resolveSessionFilePreviewTarget(\n sessionId: string,\n filePath: string,\n fileName?: string,\n): Promise<PreviewTarget> {\n const resolvedFileName = getDisplayFileName(filePath, fileName)\n const binaryTarget = buildSessionBinaryPreviewTarget(sessionId, filePath, resolvedFileName)\n if (binaryTarget) {\n return binaryTarget\n }\n\n const downloadUrl = getSessionFileDownloadUrl(sessionId, filePath)\n\n // 其余文件按后端返回的 Content-Type 分派,而不是猜扩展名:\n // 视频/音频/压缩包等二进制文件绝不能读 body(整体读进内存会卡死页面),\n // 改为把下载 URL 交给原生 <video>/<audio> 流式播放,或回退为下载。\n const res = await apiFetchResponse(getSessionFilePath(sessionId, filePath))\n const contentType = (res.headers.get(\"content-type\") ?? \"\").toLowerCase()\n\n if (contentType.startsWith(\"video/\")) {\n void res.body?.cancel()\n return { type: \"video\", content: downloadUrl, title: resolvedFileName, key: filePath }\n }\n\n if (contentType.startsWith(\"audio/\")) {\n void res.body?.cancel()\n return { type: \"audio\", content: downloadUrl, title: resolvedFileName, key: filePath }\n }\n\n if (!isTextualContentType(contentType)) {\n void res.body?.cancel()\n return { type: \"download\", content: downloadUrl, title: resolvedFileName, key: filePath }\n }\n\n const content = await res.text()\n\n return {\n type: resolveTextPreviewType(resolvedFileName),\n content,\n title: resolvedFileName,\n key: filePath,\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  useSessionStore
3
- } from "./chunk-FZXLII7S.js";
3
+ } from "./chunk-UNO53NPU.js";
4
4
 
5
5
  // src/react/hooks/use-session.ts
6
6
  function useSession() {
@@ -27,4 +27,4 @@ function useSession() {
27
27
  export {
28
28
  useSession
29
29
  };
30
- //# sourceMappingURL=chunk-HAFDWDFG.js.map
30
+ //# sourceMappingURL=chunk-6L6JFSR5.js.map
@@ -8,7 +8,7 @@ import {
8
8
  getCodeLanguageFromFilename,
9
9
  parseAskUserQuestion,
10
10
  useHighlightedCodeHtml
11
- } from "./chunk-PKQKLRFQ.js";
11
+ } from "./chunk-Y7FRTBUT.js";
12
12
  import {
13
13
  Collapsible,
14
14
  CollapsibleContent,
@@ -16,7 +16,7 @@ import {
16
16
  } from "./chunk-H62LH2AG.js";
17
17
  import {
18
18
  resolveSessionFilePreviewTarget
19
- } from "./chunk-UQWHEHG3.js";
19
+ } from "./chunk-4FCXKLXT.js";
20
20
  import {
21
21
  apiFetchResponse,
22
22
  buildMessageContent,
@@ -60,7 +60,7 @@ import {
60
60
  useUiBridgeStore,
61
61
  useUiStore,
62
62
  writeFile
63
- } from "./chunk-FZXLII7S.js";
63
+ } from "./chunk-UNO53NPU.js";
64
64
  import {
65
65
  registerBridgeIframe,
66
66
  tapBridgeEvent
@@ -69,7 +69,7 @@ import {
69
69
  ModelOption,
70
70
  ModelsConfig,
71
71
  ModelsResource
72
- } from "./chunk-7EVVRQ7G.js";
72
+ } from "./chunk-ZWO6YBLA.js";
73
73
  import {
74
74
  cn,
75
75
  copyToClipboard
@@ -100,6 +100,12 @@ function useChat(sessionId) {
100
100
  },
101
101
  [sessionId]
102
102
  );
103
+ const append = useCallback(
104
+ (msg) => {
105
+ getSocket().append(sessionId, msg);
106
+ },
107
+ [sessionId]
108
+ );
103
109
  const stop = useCallback(async () => {
104
110
  if (isStopping) return;
105
111
  setIsStopping(true);
@@ -131,7 +137,7 @@ function useChat(sessionId) {
131
137
  setAnswerCallback(sessionId, answer);
132
138
  return () => setAnswerCallback(sessionId, void 0);
133
139
  }, [answer, sessionId, setAnswerCallback]);
134
- return { messages, isStreaming, isStopping, send, stop };
140
+ return { messages, isStreaming, isStopping, send, append, stop };
135
141
  }
136
142
  function buildPendingAskUserAnswer(sessionId, message) {
137
143
  const session = useSessionStore.getState().sessions.find((item) => item.id === sessionId);
@@ -2657,6 +2663,7 @@ function showVoiceInputErrorToast(error) {
2657
2663
  }
2658
2664
  function ChatInput({
2659
2665
  onSend,
2666
+ onAppend,
2660
2667
  onStop,
2661
2668
  isStreaming,
2662
2669
  isStopping = false,
@@ -2677,8 +2684,10 @@ function ChatInput({
2677
2684
  skillStatusBarClassName,
2678
2685
  skillStatusBarInnerClassName,
2679
2686
  onResyncSkills,
2680
- isResyncingSkills = false
2687
+ isResyncingSkills = false,
2688
+ inputLabel = "\u8F93\u5165\u6D88\u606F"
2681
2689
  }) {
2690
+ const resolvedInputLabel = inputLabel?.trim() || "\u8F93\u5165\u6D88\u606F";
2682
2691
  const [input, setInputInternal] = useState8(externalDraft?.value ?? "");
2683
2692
  const setInput = useEffectEvent2((value) => {
2684
2693
  setInputInternal(value);
@@ -3015,7 +3024,9 @@ function ChatInput({
3015
3024
  },
3016
3025
  editorProps: {
3017
3026
  attributes: {
3018
- "aria-label": "\u8F93\u5165\u6D88\u606F",
3027
+ "aria-label": resolvedInputLabel,
3028
+ "data-testid": "chat-message-input",
3029
+ "data-blade-input-label": resolvedInputLabel,
3019
3030
  class: "min-h-[40px] max-h-[240px] overflow-y-auto px-4 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"
3020
3031
  },
3021
3032
  handleDOMEvents: {
@@ -3076,6 +3087,12 @@ function ChatInput({
3076
3087
  }
3077
3088
  }
3078
3089
  });
3090
+ useEffect7(() => {
3091
+ const dom = editor?.view.dom;
3092
+ if (!dom) return;
3093
+ dom.setAttribute("aria-label", resolvedInputLabel);
3094
+ dom.setAttribute("data-blade-input-label", resolvedInputLabel);
3095
+ }, [editor, resolvedInputLabel]);
3079
3096
  useEffect7(() => {
3080
3097
  if (!editor || !activeSessionId || rewindDraft == null) {
3081
3098
  return;
@@ -3140,7 +3157,7 @@ function ChatInput({
3140
3157
  return;
3141
3158
  }
3142
3159
  applyDraftAppends();
3143
- }, [applyDraftAppends, draftAppends]);
3160
+ }, [applyDraftAppends, draftAppends, editor]);
3144
3161
  const applySendRequests = useEffectEvent2(() => {
3145
3162
  if (!activeSessionId) {
3146
3163
  return;
@@ -3183,7 +3200,16 @@ function ChatInput({
3183
3200
  }
3184
3201
  }, [activeSessionId, isRecording]);
3185
3202
  const handleSubmit = async () => {
3186
- if (isStreaming || connectionStatus !== "connected") {
3203
+ if (connectionStatus !== "connected") {
3204
+ return;
3205
+ }
3206
+ if (isStreaming) {
3207
+ if (!onAppend) return;
3208
+ const json = editor?.getJSON();
3209
+ const text = serializeEditorContent(json);
3210
+ if (!text.trim()) return;
3211
+ onAppend(text);
3212
+ editor?.commands.clearContent();
3187
3213
  return;
3188
3214
  }
3189
3215
  if (isModelLoading) {
@@ -6439,7 +6465,7 @@ function UserMessageBubble({ message, className }) {
6439
6465
  }
6440
6466
  ),
6441
6467
  /* @__PURE__ */ jsx29(MessageContextPills, { contexts: textContexts }),
6442
- trimmedClean && /* @__PURE__ */ jsx29("div", { className: "rounded-2xl border border-[hsl(var(--user-msg-border))] bg-[hsl(var(--user-msg-bg))] px-4 py-2.5 text-sm leading-relaxed text-[hsl(var(--user-msg-fg))] shadow-[inset_0_1px_0_rgba(255,255,255,0.04)]", children: /* @__PURE__ */ jsx29(
6468
+ trimmedClean && /* @__PURE__ */ jsx29("div", { className: "max-w-full rounded-2xl border border-[hsl(var(--user-msg-border))] bg-[hsl(var(--user-msg-bg))] px-4 py-2.5 text-sm leading-relaxed text-[hsl(var(--user-msg-fg))] shadow-[inset_0_1px_0_rgba(255,255,255,0.04)]", children: /* @__PURE__ */ jsx29(
6443
6469
  MarkdownContent,
6444
6470
  {
6445
6471
  className: USER_MESSAGE_MARKDOWN_CLASS,
@@ -8370,6 +8396,7 @@ function ChatView({
8370
8396
  canShareSession = false,
8371
8397
  onResyncSkills,
8372
8398
  isResyncingSkills = false,
8399
+ inputLabel,
8373
8400
  classNames,
8374
8401
  components,
8375
8402
  renderers
@@ -8379,6 +8406,7 @@ function ChatView({
8379
8406
  isStreaming,
8380
8407
  isStopping,
8381
8408
  send,
8409
+ append,
8382
8410
  stop
8383
8411
  } = useChat(sessionId);
8384
8412
  const session = useSessionStore((s) => s.sessions.find((ss) => ss.id === sessionId));
@@ -8431,6 +8459,7 @@ function ChatView({
8431
8459
  ChatInput,
8432
8460
  {
8433
8461
  onSend: (msg, _targetSessionId, model) => send(msg, mode, void 0, { model: model || void 0 }),
8462
+ onAppend: append,
8434
8463
  onStop: stop,
8435
8464
  isStreaming,
8436
8465
  isStopping,
@@ -8446,7 +8475,8 @@ function ChatView({
8446
8475
  skillStatusBarClassName: classNames?.skillStatusBarRoot,
8447
8476
  skillStatusBarInnerClassName: classNames?.skillStatusBarInner,
8448
8477
  onResyncSkills,
8449
- isResyncingSkills
8478
+ isResyncingSkills,
8479
+ inputLabel
8450
8480
  }
8451
8481
  )
8452
8482
  ] });
@@ -8503,4 +8533,4 @@ use-stick-to-bottom/dist/StickToBottom.js:
8503
8533
  * Licensed under the MIT License. See License.txt in the project root for license information.
8504
8534
  *--------------------------------------------------------------------------------------------*)
8505
8535
  */
8506
- //# sourceMappingURL=chunk-SENUKC7C.js.map
8536
+ //# sourceMappingURL=chunk-QCDNRR74.js.map