@cadraos/sdk 0.3.14-p139.0 → 0.3.14-p139.3

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.
@@ -12,6 +12,28 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
12
12
  var ReactMarkdown__default = /*#__PURE__*/_interopDefault(ReactMarkdown);
13
13
  var remarkGfm__default = /*#__PURE__*/_interopDefault(remarkGfm);
14
14
 
15
+ // src/streaming/steered-refs.ts
16
+ function readSteeredRefs(data) {
17
+ if (!data || typeof data !== "object") return void 0;
18
+ const record = data;
19
+ const metadata = record.metadata;
20
+ const candidates = [
21
+ record.steeredRefs,
22
+ metadata && typeof metadata === "object" ? metadata.steeredRefs : void 0
23
+ ];
24
+ for (const value of candidates) {
25
+ if (Array.isArray(value)) {
26
+ const refs = value.filter((v) => typeof v === "string" && v.length > 0);
27
+ if (refs.length > 0) return refs;
28
+ }
29
+ }
30
+ return void 0;
31
+ }
32
+ function readSteeredRefsField(data) {
33
+ const steeredRefs = readSteeredRefs(data);
34
+ return steeredRefs ? { steeredRefs } : {};
35
+ }
36
+
15
37
  // src/resources/base.ts
16
38
  var BaseResourceAPI = class {
17
39
  http;
@@ -65,6 +87,19 @@ var BaseResourceAPI = class {
65
87
  }
66
88
  };
67
89
 
90
+ // src/utils/api-paths.ts
91
+ var API_V1 = "/api/v1";
92
+ var EXECUTION_PATH = `${API_V1}/executions`;
93
+ function executionPath(executionId) {
94
+ return `${EXECUTION_PATH}/${executionId}`;
95
+ }
96
+ function executionSteerPath(executionId) {
97
+ return `${EXECUTION_PATH}/${executionId}/steer`;
98
+ }
99
+ function executionCancelPath(executionId) {
100
+ return `${EXECUTION_PATH}/${executionId}/cancel`;
101
+ }
102
+
68
103
  // src/errors/sdk-errors.ts
69
104
  var CadraError = class extends Error {
70
105
  /** Error code */
@@ -1306,7 +1341,9 @@ var ExecutionStreamControllerImpl = class {
1306
1341
  tokenUsage: data.tokenUsage,
1307
1342
  cost: data.cost,
1308
1343
  queuedAt: "",
1309
- ...data
1344
+ ...data,
1345
+ // p139: normalise steeredRefs (event top level or record metadata).
1346
+ ...readSteeredRefsField(data)
1310
1347
  };
1311
1348
  this.finalExecution = execution;
1312
1349
  this.emit("complete", { execution });
@@ -1760,16 +1797,6 @@ async function collectImagesFromStream(stream, options = {}) {
1760
1797
  });
1761
1798
  }
1762
1799
 
1763
- // src/utils/api-paths.ts
1764
- var API_V1 = "/api/v1";
1765
- var EXECUTION_PATH = `${API_V1}/executions`;
1766
- function executionPath(executionId) {
1767
- return `${EXECUTION_PATH}/${executionId}`;
1768
- }
1769
- function executionCancelPath(executionId) {
1770
- return `${EXECUTION_PATH}/${executionId}/cancel`;
1771
- }
1772
-
1773
1800
  // src/resources/agents.ts
1774
1801
  var AgentsAPI = class extends BaseResourceAPI {
1775
1802
  constructor(http, getStreamConfig) {
@@ -2108,6 +2135,20 @@ var AgentsAPI = class extends BaseResourceAPI {
2108
2135
  await new Promise((resolve) => setTimeout(resolve, pollInterval));
2109
2136
  }
2110
2137
  }
2138
+ // ===== p139 steer =====
2139
+ /**
2140
+ * p139 — forward messages typed while an execution runs. The server answers
2141
+ * `ACCEPTED` (the run will read them between steps), `QUEUED_BEHIND` (not
2142
+ * read yet; send them after the run) or `ENDED` (run finished; send them as
2143
+ * a new turn). Answered = listed in the run's `steeredRefs` on completion.
2144
+ */
2145
+ async steerExecution(executionId, messages) {
2146
+ return this.http.post(
2147
+ executionSteerPath(executionId),
2148
+ { messages },
2149
+ { skipRetry: true }
2150
+ );
2151
+ }
2111
2152
  };
2112
2153
 
2113
2154
  // src/resources/skills.ts
@@ -3581,6 +3622,9 @@ function resolveBaseUrl(config) {
3581
3622
  if (config.baseUrl) return config.baseUrl;
3582
3623
  return "https://api.cadraos.com";
3583
3624
  }
3625
+ function steerableField(result) {
3626
+ return typeof result.steerable === "boolean" ? { steerable: result.steerable } : {};
3627
+ }
3584
3628
  function createDefaultAdapter(config) {
3585
3629
  const client = resolveClient(config);
3586
3630
  const baseUrl = resolveBaseUrl(config);
@@ -3600,7 +3644,8 @@ function createDefaultAdapter(config) {
3600
3644
  });
3601
3645
  return {
3602
3646
  executionId: result2.executionId,
3603
- sessionId: result2.sessionId ?? input.sessionId
3647
+ sessionId: result2.sessionId ?? input.sessionId,
3648
+ ...steerableField(result2)
3604
3649
  };
3605
3650
  }
3606
3651
  const pathId = input.agentId || input.teamId || "";
@@ -3617,7 +3662,8 @@ function createDefaultAdapter(config) {
3617
3662
  });
3618
3663
  return {
3619
3664
  executionId: result.executionId,
3620
- sessionId: result.sessionId ?? ""
3665
+ sessionId: result.sessionId ?? "",
3666
+ ...steerableField(result)
3621
3667
  };
3622
3668
  },
3623
3669
  async sendMessage(input) {
@@ -3632,7 +3678,8 @@ function createDefaultAdapter(config) {
3632
3678
  });
3633
3679
  return {
3634
3680
  executionId: result.executionId,
3635
- sessionId: result.sessionId ?? input.sessionId
3681
+ sessionId: result.sessionId ?? input.sessionId,
3682
+ ...steerableField(result)
3636
3683
  };
3637
3684
  },
3638
3685
  async cancelExecution(uuid) {
@@ -3644,9 +3691,15 @@ function createDefaultAdapter(config) {
3644
3691
  uuid: exec.uuid,
3645
3692
  status: exec.status === "queued" ? "pending" : exec.status,
3646
3693
  result: exec.output,
3647
- error: exec.error
3694
+ error: exec.error,
3695
+ ...readSteeredRefsField(exec)
3648
3696
  };
3649
3697
  },
3698
+ // p139: steer a running execution (REST `POST /api/v1/executions/{id}/steer`).
3699
+ async steerExecution(executionId, message) {
3700
+ const res = await client.agents.steerExecution(executionId, [message]);
3701
+ return res.state;
3702
+ },
3650
3703
  // -------------------------------------------------------------------------
3651
3704
  // Attachment Methods (delegates to CadraClient.attachments)
3652
3705
  // -------------------------------------------------------------------------
@@ -4036,7 +4089,7 @@ function useExecutionStream(options) {
4036
4089
  clearTimeout(activityTimeoutRef.current);
4037
4090
  activityTimeoutRef.current = null;
4038
4091
  }
4039
- onComplete?.();
4092
+ onComplete?.(data);
4040
4093
  break;
4041
4094
  case "error":
4042
4095
  const errorMsg = data.error || "Unknown error";
@@ -4503,7 +4556,9 @@ function useAgentChat(options) {
4503
4556
  onClarification,
4504
4557
  pollingInterval,
4505
4558
  pollingEnabled,
4506
- historyStaleMs = DEFAULT_HISTORY_STALE_MS
4559
+ historyStaleMs = DEFAULT_HISTORY_STALE_MS,
4560
+ allowSendWhileRunning = true,
4561
+ onSteer
4507
4562
  } = options;
4508
4563
  const contextConfig = useChatConfigOptional();
4509
4564
  const adapter = propsAdapter ?? contextConfig?.adapter;
@@ -4540,6 +4595,29 @@ function useAgentChat(options) {
4540
4595
  const firedToolResultsRef = react.useRef(/* @__PURE__ */ new Set());
4541
4596
  const streamControllerRef = react.useRef(null);
4542
4597
  const pendingDelegationsRef = react.useRef(/* @__PURE__ */ new Map());
4598
+ const onSteerRef = react.useRef(onSteer);
4599
+ onSteerRef.current = onSteer;
4600
+ const adapterRef = react.useRef(adapter);
4601
+ adapterRef.current = adapter;
4602
+ const hasSteerHandler = !!onSteer || typeof adapter.steerExecution === "function";
4603
+ const [runSteerable, setRunSteerable] = react.useState(void 0);
4604
+ const canSendWhileRunning = allowSendWhileRunning !== false && hasSteerHandler && runSteerable === true;
4605
+ const canSendWhileRunningRef = react.useRef(canSendWhileRunning);
4606
+ canSendWhileRunningRef.current = canSendWhileRunning;
4607
+ const runActiveRef = react.useRef(false);
4608
+ const currentExecutionIdRef = react.useRef(null);
4609
+ const pendingSteersRef = react.useRef([]);
4610
+ const flushPendingRef = react.useRef(() => {
4611
+ });
4612
+ const settlePendingSteers = react.useCallback((steeredRefs) => {
4613
+ const pending = pendingSteersRef.current;
4614
+ if (pending.length === 0) return;
4615
+ pendingSteersRef.current = [];
4616
+ const answered = new Set(steeredRefs ?? []);
4617
+ const remaining = pending.filter((p) => !answered.has(p.ref));
4618
+ if (remaining.length === 0) return;
4619
+ setTimeout(() => flushPendingRef.current(remaining), 0);
4620
+ }, []);
4543
4621
  const onDelegationRef = react.useRef(options.onDelegation);
4544
4622
  react.useEffect(() => {
4545
4623
  onDelegationRef.current = options.onDelegation;
@@ -4966,19 +5044,22 @@ function useAgentChat(options) {
4966
5044
  [onClarification]
4967
5045
  );
4968
5046
  const completedRef = react.useRef(false);
4969
- const handleComplete = react.useCallback((finalOutput) => {
5047
+ const handleComplete = react.useCallback((finalOutput, steeredRefs) => {
4970
5048
  if (completedRef.current) {
4971
5049
  if (__DEV__) console.log("[useAgentChat] handleComplete: skipping duplicate complete");
4972
5050
  return;
4973
5051
  }
4974
5052
  completedRef.current = true;
4975
5053
  if (__DEV__) console.log("[useAgentChat] handleComplete called");
5054
+ runActiveRef.current = false;
5055
+ currentExecutionIdRef.current = null;
4976
5056
  setIsLoading(false);
4977
5057
  setIsStreamControllerConnected(false);
4978
5058
  finalizeStreamingMessage(finalOutput);
4979
5059
  setCurrentExecutionId(null);
4980
5060
  streamControllerRef.current = null;
4981
- }, [finalizeStreamingMessage]);
5061
+ settlePendingSteers(steeredRefs);
5062
+ }, [finalizeStreamingMessage, settlePendingSteers]);
4982
5063
  const handleError = react.useCallback(
4983
5064
  (errorMsg) => {
4984
5065
  if (__DEV__) console.log("[useAgentChat] handleError called:", errorMsg);
@@ -4987,6 +5068,8 @@ function useAgentChat(options) {
4987
5068
  message: errorMsg,
4988
5069
  retryable: true
4989
5070
  };
5071
+ runActiveRef.current = false;
5072
+ currentExecutionIdRef.current = null;
4990
5073
  setError(chatError);
4991
5074
  setIsLoading(false);
4992
5075
  setIsStreamControllerConnected(false);
@@ -4994,8 +5077,9 @@ function useAgentChat(options) {
4994
5077
  setCurrentExecutionId(null);
4995
5078
  streamControllerRef.current = null;
4996
5079
  onError?.(chatError);
5080
+ settlePendingSteers(void 0);
4997
5081
  },
4998
- [finalizeStreamingMessage, onError]
5082
+ [finalizeStreamingMessage, onError, settlePendingSteers]
4999
5083
  );
5000
5084
  const legacyExecutionId = useStreamController ? void 0 : currentExecutionId;
5001
5085
  const { isConnected: legacyIsConnected, isUsingFallback, disconnect } = useExecutionStream({
@@ -5004,7 +5088,7 @@ function useAgentChat(options) {
5004
5088
  enabled: !!legacyExecutionId,
5005
5089
  onLog: handleStreamLog,
5006
5090
  onClarification: handleClarification,
5007
- onComplete: handleComplete,
5091
+ onComplete: (data) => handleComplete(void 0, readSteeredRefs(data)),
5008
5092
  onError: handleError,
5009
5093
  // P25 — Action 1: render `progress` / `status_update` / `started`
5010
5094
  // labels in the streaming bubble's thinking pill.
@@ -5074,7 +5158,7 @@ function useAgentChat(options) {
5074
5158
  if (execution.status === "completed") {
5075
5159
  if (__DEV__) console.log("[useAgentChat] Polling: execution completed");
5076
5160
  stopPolling();
5077
- handleComplete(execution.result || void 0);
5161
+ handleComplete(execution.result || void 0, readSteeredRefs(execution));
5078
5162
  return;
5079
5163
  }
5080
5164
  if (execution.status === "failed") {
@@ -5301,7 +5385,7 @@ function useAgentChat(options) {
5301
5385
  });
5302
5386
  controller.on("complete", ({ execution }) => {
5303
5387
  const output = execution?.output || void 0;
5304
- handleComplete(output);
5388
+ handleComplete(output, readSteeredRefs(execution));
5305
5389
  });
5306
5390
  controller.on("error", (errorEvent) => {
5307
5391
  handleError(errorEvent.error);
@@ -5317,22 +5401,25 @@ function useAgentChat(options) {
5317
5401
  },
5318
5402
  [adapter, handleExecutionLog, updateStreamingMessage, setStreamingMessageStep, updateToolCall, updateMessageImages, addDelegationEvent, handleClarification, handleComplete, handleError]
5319
5403
  );
5320
- const sendMessage = react.useCallback(
5321
- async (content, options2) => {
5322
- if (!content.trim()) return;
5323
- const attachmentUuids = options2?.attachmentUuids;
5404
+ const startTurn = react.useCallback(
5405
+ async (content, attachmentUuids, addUserBubble) => {
5324
5406
  lastMessageContentRef.current = content;
5407
+ runActiveRef.current = true;
5408
+ currentExecutionIdRef.current = null;
5409
+ setRunSteerable(void 0);
5325
5410
  setIsLoading(true);
5326
5411
  setError(null);
5327
5412
  setClarification(null);
5328
- const userMessage = {
5329
- id: generateId(),
5330
- role: "user",
5331
- content: content.trim(),
5332
- timestamp: /* @__PURE__ */ new Date()
5333
- };
5334
- setMessages((prev) => [...prev, userMessage]);
5335
- onMessage?.(userMessage);
5413
+ if (addUserBubble) {
5414
+ const userMessage = {
5415
+ id: generateId(),
5416
+ role: "user",
5417
+ content: content.trim(),
5418
+ timestamp: /* @__PURE__ */ new Date()
5419
+ };
5420
+ setMessages((prev) => [...prev, userMessage]);
5421
+ onMessage?.(userMessage);
5422
+ }
5336
5423
  const preparedExecutionId = generateExecutionId2();
5337
5424
  const assistantMessageId = generateId();
5338
5425
  const assistantMessage = {
@@ -5377,6 +5464,10 @@ function useAgentChat(options) {
5377
5464
  onSessionCreated?.(result.sessionId);
5378
5465
  onSessionStart?.(result.sessionId);
5379
5466
  }
5467
+ if (runActiveRef.current && !completedRef.current) {
5468
+ currentExecutionIdRef.current = result.executionId;
5469
+ }
5470
+ setRunSteerable(result.steerable);
5380
5471
  if (useStreamController) {
5381
5472
  connectStreamController(
5382
5473
  result.executionId,
@@ -5409,6 +5500,64 @@ function useAgentChat(options) {
5409
5500
  handleError
5410
5501
  ]
5411
5502
  );
5503
+ flushPendingRef.current = (pending) => {
5504
+ const attachments = pending.flatMap((p) => p.attachmentUuids ?? []);
5505
+ void startTurn(
5506
+ pending.map((p) => p.text).join("\n\n"),
5507
+ attachments.length > 0 ? attachments : void 0,
5508
+ false
5509
+ );
5510
+ };
5511
+ const steerWhileRunning = react.useCallback(
5512
+ async (text, attachmentUuids) => {
5513
+ const ref = generateExecutionId2();
5514
+ pendingSteersRef.current.push({ ref, text, attachmentUuids });
5515
+ const userMessage = {
5516
+ id: ref,
5517
+ role: "user",
5518
+ content: text,
5519
+ timestamp: /* @__PURE__ */ new Date(),
5520
+ steerState: "pending"
5521
+ };
5522
+ setMessages((prev) => [...prev, userMessage]);
5523
+ onMessage?.(userMessage);
5524
+ const executionId = currentExecutionIdRef.current;
5525
+ if (!executionId) return;
5526
+ let outcome;
5527
+ try {
5528
+ const handler = onSteerRef.current;
5529
+ const steerMessage = { ref, text, ...attachmentUuids?.length ? { attachmentUuids } : {} };
5530
+ outcome = handler ? await handler(executionId, steerMessage) : await adapterRef.current.steerExecution(executionId, steerMessage);
5531
+ } catch {
5532
+ return;
5533
+ }
5534
+ if (outcome === "ACCEPTED") {
5535
+ setMessages(
5536
+ (prev) => prev.map((m) => m.id === ref ? { ...m, steerState: "delivered" } : m)
5537
+ );
5538
+ return;
5539
+ }
5540
+ if (outcome === "ENDED" && !runActiveRef.current) {
5541
+ const idx = pendingSteersRef.current.findIndex((p) => p.ref === ref);
5542
+ if (idx >= 0) {
5543
+ const entry = pendingSteersRef.current.splice(idx, 1)[0];
5544
+ flushPendingRef.current([entry]);
5545
+ }
5546
+ }
5547
+ },
5548
+ [onMessage]
5549
+ );
5550
+ const sendMessage = react.useCallback(
5551
+ async (content, options2) => {
5552
+ if (!content.trim()) return;
5553
+ if (runActiveRef.current && canSendWhileRunningRef.current) {
5554
+ await steerWhileRunning(content.trim(), options2?.attachmentUuids);
5555
+ return;
5556
+ }
5557
+ await startTurn(content, options2?.attachmentUuids, true);
5558
+ },
5559
+ [startTurn, steerWhileRunning]
5560
+ );
5412
5561
  const respondToClarification = react.useCallback(
5413
5562
  async (response) => {
5414
5563
  if (!clarification) return;
@@ -5418,7 +5567,10 @@ function useAgentChat(options) {
5418
5567
  [clarification, sendMessage]
5419
5568
  );
5420
5569
  const cancel = react.useCallback(async () => {
5570
+ pendingSteersRef.current = [];
5421
5571
  if (currentExecutionId) {
5572
+ runActiveRef.current = false;
5573
+ currentExecutionIdRef.current = null;
5422
5574
  try {
5423
5575
  await adapter.cancelExecution(currentExecutionId);
5424
5576
  } catch {
@@ -5444,6 +5596,7 @@ function useAgentChat(options) {
5444
5596
  setError(null);
5445
5597
  }, []);
5446
5598
  const clearMessages = react.useCallback(() => {
5599
+ pendingSteersRef.current = [];
5447
5600
  setMessages([]);
5448
5601
  setCurrentSessionId(null);
5449
5602
  hasLoadedInitialSession.current = false;
@@ -5657,7 +5810,8 @@ function useAgentChat(options) {
5657
5810
  retry,
5658
5811
  clearError,
5659
5812
  clearMessages,
5660
- loadSession
5813
+ loadSession,
5814
+ canSendWhileRunning
5661
5815
  };
5662
5816
  }
5663
5817
 
@@ -6607,6 +6761,7 @@ function ChatInput({
6607
6761
  placeholder = "Type a message...",
6608
6762
  disabled = false,
6609
6763
  isLoading = false,
6764
+ allowSendWhileRunning = false,
6610
6765
  enableAttachments = false,
6611
6766
  attachments = [],
6612
6767
  onRemoveAttachment,
@@ -6632,6 +6787,7 @@ function ChatInput({
6632
6787
  });
6633
6788
  }, [onInputControlReady, onInputChange]);
6634
6789
  const hasAttachments = enableAttachments && attachments.length > 0;
6790
+ const lockedByRun = isLoading && !allowSendWhileRunning;
6635
6791
  react.useEffect(() => {
6636
6792
  const textarea = textareaRef.current;
6637
6793
  if (textarea) {
@@ -6641,10 +6797,10 @@ function ChatInput({
6641
6797
  }, [content]);
6642
6798
  const handleSubmit = react.useCallback(async () => {
6643
6799
  const trimmedContent = content.trim();
6644
- if (!trimmedContent && !hasAttachments || disabled || isLoading || isUploadingAttachments) return;
6800
+ if (!trimmedContent && !hasAttachments || disabled || lockedByRun || isUploadingAttachments) return;
6645
6801
  setContent("");
6646
6802
  await onSend(trimmedContent);
6647
- }, [content, hasAttachments, disabled, isLoading, isUploadingAttachments, onSend]);
6803
+ }, [content, hasAttachments, disabled, lockedByRun, isUploadingAttachments, onSend]);
6648
6804
  const handleKeyDown = react.useCallback(
6649
6805
  (e) => {
6650
6806
  if (e.key === "Enter" && !e.shiftKey) {
@@ -6660,7 +6816,7 @@ function ChatInput({
6660
6816
  const handleAttachClick = react.useCallback(() => {
6661
6817
  dropZoneRef?.current?.openFileDialog();
6662
6818
  }, [dropZoneRef]);
6663
- const canSend = (content.trim().length > 0 || hasAttachments) && !disabled && !isLoading && !isUploadingAttachments;
6819
+ const canSend = (content.trim().length > 0 || hasAttachments) && !disabled && !lockedByRun && !isUploadingAttachments;
6664
6820
  const showStopButton = isLoading && onStop;
6665
6821
  return /* @__PURE__ */ jsxRuntime.jsxs(
6666
6822
  "div",
@@ -6685,7 +6841,7 @@ function ChatInput({
6685
6841
  {
6686
6842
  type: "button",
6687
6843
  onClick: handleAttachClick,
6688
- disabled: disabled || isLoading,
6844
+ disabled: disabled || lockedByRun,
6689
6845
  className: cn3(
6690
6846
  "flex-shrink-0 p-3 rounded-lg transition-colors",
6691
6847
  "text-gray-500 dark:text-gray-400",
@@ -9078,7 +9234,9 @@ function AgentChat({
9078
9234
  hideTypingIndicator = false,
9079
9235
  onInputChange,
9080
9236
  onInputControlReady,
9081
- injectedMessages
9237
+ injectedMessages,
9238
+ allowSendWhileRunning = true,
9239
+ onSteer
9082
9240
  }) {
9083
9241
  const {
9084
9242
  messages,
@@ -9092,7 +9250,8 @@ function AgentChat({
9092
9250
  respondToClarification,
9093
9251
  cancel,
9094
9252
  retry,
9095
- clearError
9253
+ clearError,
9254
+ canSendWhileRunning
9096
9255
  } = useAgentChat({
9097
9256
  agentId,
9098
9257
  teamId,
@@ -9108,7 +9267,9 @@ function AgentChat({
9108
9267
  onClarification,
9109
9268
  onDelegation,
9110
9269
  pollingInterval,
9111
- pollingEnabled
9270
+ pollingEnabled,
9271
+ allowSendWhileRunning,
9272
+ onSteer
9112
9273
  });
9113
9274
  const effectiveVerbosity = showToolCalls === false ? "hidden" : toolCallVerbosity ?? "compact";
9114
9275
  const dropZoneRef = react.useRef(null);
@@ -9190,6 +9351,7 @@ function AgentChat({
9190
9351
  placeholder,
9191
9352
  disabled: !!clarification || isLoadingHistory,
9192
9353
  isLoading,
9354
+ allowSendWhileRunning: canSendWhileRunning,
9193
9355
  enableAttachments,
9194
9356
  attachments: enableAttachments ? attachments.files : void 0,
9195
9357
  onRemoveAttachment: enableAttachments ? attachments.removeFile : void 0,
@@ -9205,7 +9367,7 @@ function AgentChat({
9205
9367
  {
9206
9368
  ref: dropZoneRef,
9207
9369
  ...attachments.dropZoneProps,
9208
- disabled: isLoading || !!clarification || isLoadingHistory,
9370
+ disabled: isLoading && !canSendWhileRunning || !!clarification || isLoadingHistory,
9209
9371
  children: chatContent
9210
9372
  }
9211
9373
  ) : chatContent });