@meetsmore-oss/use-ai-client 1.5.0 → 1.6.0

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.
package/dist/bundled.js CHANGED
@@ -1254,10 +1254,10 @@ var require_style_to_object = __commonJS({
1254
1254
  });
1255
1255
 
1256
1256
  // src/useAI.ts
1257
- import { useState as useState12, useEffect as useEffect11, useRef as useRef12, useCallback as useCallback11, useMemo as useMemo6 } from "react";
1257
+ import { useState as useState14, useEffect as useEffect11, useRef as useRef13, useCallback as useCallback12, useMemo as useMemo6 } from "react";
1258
1258
 
1259
1259
  // src/providers/useAIProvider.tsx
1260
- import { createContext as createContext4, useContext as useContext4, useState as useState11, useEffect as useEffect10, useCallback as useCallback10, useRef as useRef10 } from "react";
1260
+ import { createContext as createContext4, useContext as useContext4, useState as useState13, useEffect as useEffect10, useCallback as useCallback11, useRef as useRef11 } from "react";
1261
1261
 
1262
1262
  // ../core/dist/index.js
1263
1263
  var __create = Object.create;
@@ -5712,6 +5712,7 @@ var ErrorCode;
5712
5712
  ErrorCode2["RATE_LIMITED"] = "RATE_LIMITED";
5713
5713
  ErrorCode2["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
5714
5714
  })(ErrorCode ||= {});
5715
+ var TOOL_APPROVAL_REQUEST = "TOOL_APPROVAL_REQUEST";
5715
5716
  var export_EventType = import_core.EventType;
5716
5717
 
5717
5718
  // src/theme/strings.ts
@@ -5811,6 +5812,25 @@ var defaultStrings = {
5811
5812
  toolExecution: {
5812
5813
  /** Fallback messages when no tool title is provided (one randomly selected) */
5813
5814
  fallbackMessages: ["Working", "Processing", "Thinking"]
5815
+ },
5816
+ // Tool approval dialog
5817
+ toolApproval: {
5818
+ /** Title shown in the approval dialog */
5819
+ title: "Confirmation Required",
5820
+ /** Message shown in the approval dialog. {toolName} is replaced with tool name. */
5821
+ message: '"{toolName}" is waiting for your approval.',
5822
+ /** Message shown when multiple tools are awaiting approval. {count} is replaced with number. */
5823
+ batchMessage: "{count} actions are waiting for your approval.",
5824
+ /** Label for approve button */
5825
+ approve: "Allow",
5826
+ /** Label for approve all button (batch mode) */
5827
+ approveAll: "Allow All",
5828
+ /** Label for reject button */
5829
+ reject: "Deny",
5830
+ /** Label for reject all button (batch mode) */
5831
+ rejectAll: "Deny All",
5832
+ /** Label for showing tool arguments */
5833
+ showDetails: "Show details"
5814
5834
  }
5815
5835
  };
5816
5836
  var StringsContext = createContext(defaultStrings);
@@ -5957,7 +5977,7 @@ function UseAIFloatingButton({
5957
5977
  }
5958
5978
 
5959
5979
  // src/components/UseAIChatPanel.tsx
5960
- import { useState as useState4, useRef as useRef4, useEffect as useEffect4 } from "react";
5980
+ import { useState as useState5, useRef as useRef4, useEffect as useEffect4 } from "react";
5961
5981
 
5962
5982
  // ../../node_modules/.bun/react-markdown@8.0.7+9cdd050739dc4c16/node_modules/react-markdown/lib/uri-transformer.js
5963
5983
  var protocols = ["http", "https", "mailto", "tel"];
@@ -15479,30 +15499,30 @@ function matchesMimeType(mimeType, pattern) {
15479
15499
  const regex = new RegExp(`^${regexPattern}$`);
15480
15500
  return regex.test(mimeType);
15481
15501
  }
15482
- function findTransformer(mimeType, transformers) {
15502
+ function findTransformerPattern(mimeType, transformers) {
15483
15503
  if (!transformers) {
15484
15504
  return void 0;
15485
15505
  }
15486
- let bestMatch;
15506
+ let bestKey;
15487
15507
  let bestIsExact = false;
15488
15508
  let bestLength = -1;
15489
- for (const [pattern, transformer] of Object.entries(transformers)) {
15509
+ for (const pattern of Object.keys(transformers)) {
15490
15510
  if (!matchesMimeType(mimeType, pattern)) {
15491
15511
  continue;
15492
15512
  }
15493
15513
  const isExact = !pattern.includes("*");
15494
15514
  if (isExact && !bestIsExact) {
15495
- bestMatch = transformer;
15515
+ bestKey = pattern;
15496
15516
  bestIsExact = true;
15497
15517
  bestLength = pattern.length;
15498
15518
  continue;
15499
15519
  }
15500
15520
  if (isExact === bestIsExact && pattern.length > bestLength) {
15501
- bestMatch = transformer;
15521
+ bestKey = pattern;
15502
15522
  bestLength = pattern.length;
15503
15523
  }
15504
15524
  }
15505
- return bestMatch;
15525
+ return bestKey;
15506
15526
  }
15507
15527
 
15508
15528
  // src/fileUpload/EmbedFileUploadBackend.ts
@@ -15533,75 +15553,104 @@ var EmbedFileUploadBackend = class {
15533
15553
  };
15534
15554
 
15535
15555
  // src/fileUpload/processAttachments.ts
15556
+ function groupBy(items, keyFn) {
15557
+ const map2 = /* @__PURE__ */ new Map();
15558
+ for (const item of items) {
15559
+ const key = keyFn(item);
15560
+ const list3 = map2.get(key);
15561
+ list3 ? list3.push(item) : map2.set(key, [item]);
15562
+ }
15563
+ return map2;
15564
+ }
15536
15565
  var transformationCache = /* @__PURE__ */ new Map();
15537
15566
  function getFileCacheKey(file2) {
15538
15567
  return `${file2.name}:${file2.size}:${file2.lastModified}`;
15539
15568
  }
15540
- async function getTransformedContent(file2, transformer, context, onProgress) {
15541
- const cacheKey = getFileCacheKey(file2);
15569
+ async function hashGroupCacheKey(files) {
15570
+ const raw = files.map(getFileCacheKey).join(", ");
15571
+ const data = new TextEncoder().encode(raw);
15572
+ const hash2 = await crypto.subtle.digest("SHA-256", data);
15573
+ return Array.from(new Uint8Array(hash2)).map((b) => b.toString(16).padStart(2, "0")).join("");
15574
+ }
15575
+ async function getTransformedContent(files, transformer, context, onProgress) {
15576
+ if (files.length === 0) {
15577
+ return [];
15578
+ }
15579
+ const cacheKey = await hashGroupCacheKey(files);
15542
15580
  const cached2 = transformationCache.get(cacheKey);
15543
- if (cached2 !== void 0) {
15581
+ if (cached2) {
15544
15582
  return cached2;
15545
15583
  }
15546
- const result = await transformer.transform(file2, context, onProgress);
15547
- transformationCache.set(cacheKey, result);
15548
- return result;
15584
+ const results = await transformer.transform(files, context, onProgress);
15585
+ transformationCache.set(cacheKey, results);
15586
+ return results;
15587
+ }
15588
+ async function toContentPart(attachment, backend) {
15589
+ if (attachment.transformedContent !== void 0) {
15590
+ return {
15591
+ type: "transformed_file",
15592
+ text: attachment.transformedContent,
15593
+ originalFile: {
15594
+ name: attachment.file.name,
15595
+ mimeType: attachment.file.type,
15596
+ size: attachment.file.size
15597
+ }
15598
+ };
15599
+ }
15600
+ const url3 = await backend.prepareForSend(attachment.file);
15601
+ if (attachment.file.type.startsWith("image/")) {
15602
+ return { type: "image", url: url3 };
15603
+ }
15604
+ return {
15605
+ type: "file",
15606
+ url: url3,
15607
+ mimeType: attachment.file.type,
15608
+ name: attachment.file.name
15609
+ };
15549
15610
  }
15550
15611
  async function processAttachments(attachments, config2) {
15551
15612
  const { getCurrentChat, backend = new EmbedFileUploadBackend(), transformers = {}, onFileProgress } = config2;
15552
15613
  const contentParts = [];
15553
15614
  const chat = await getCurrentChat();
15554
15615
  const context = { chat };
15555
- for (const attachment of attachments) {
15616
+ const groups = groupBy(
15617
+ attachments,
15618
+ (attachment) => attachment.transformedContent !== void 0 ? null : findTransformerPattern(attachment.file.type, transformers) ?? null
15619
+ );
15620
+ for (const [key, groupAttachments] of groups) {
15621
+ if (key === null) {
15622
+ const parts2 = await Promise.all(
15623
+ groupAttachments.map((a) => toContentPart(a, backend))
15624
+ );
15625
+ contentParts.push(...parts2);
15626
+ continue;
15627
+ }
15628
+ const transformer = transformers[key];
15629
+ const files = groupAttachments.map((a) => a.file);
15630
+ groupAttachments.forEach((a) => onFileProgress?.(a.id, { status: "processing" }));
15556
15631
  try {
15557
- if (attachment.transformedContent !== void 0) {
15558
- contentParts.push({
15559
- type: "transformed_file",
15560
- text: attachment.transformedContent,
15561
- originalFile: {
15562
- name: attachment.file.name,
15563
- mimeType: attachment.file.type,
15564
- size: attachment.file.size
15565
- }
15566
- });
15567
- continue;
15568
- }
15569
- const transformer = findTransformer(attachment.file.type, transformers);
15570
- if (transformer) {
15571
- onFileProgress?.(attachment.id, { status: "processing" });
15572
- const transformedText = await getTransformedContent(
15573
- attachment.file,
15574
- transformer,
15575
- context,
15576
- (progress) => {
15577
- onFileProgress?.(attachment.id, { status: "processing", progress });
15578
- }
15579
- );
15632
+ const results = await getTransformedContent(
15633
+ files,
15634
+ transformer,
15635
+ context,
15636
+ (progress) => {
15637
+ groupAttachments.forEach((a) => onFileProgress?.(a.id, { status: "processing", progress }));
15638
+ }
15639
+ );
15640
+ results.forEach((text4, i) => {
15580
15641
  contentParts.push({
15581
15642
  type: "transformed_file",
15582
- text: transformedText,
15643
+ text: text4,
15583
15644
  originalFile: {
15584
- name: attachment.file.name,
15585
- mimeType: attachment.file.type,
15586
- size: attachment.file.size
15645
+ name: files[i].name,
15646
+ mimeType: files[i].type,
15647
+ size: files[i].size
15587
15648
  }
15588
15649
  });
15589
- onFileProgress?.(attachment.id, { status: "done" });
15590
- } else {
15591
- const url3 = await backend.prepareForSend(attachment.file);
15592
- if (attachment.file.type.startsWith("image/")) {
15593
- contentParts.push({ type: "image", url: url3 });
15594
- } else {
15595
- contentParts.push({
15596
- type: "file",
15597
- url: url3,
15598
- mimeType: attachment.file.type,
15599
- name: attachment.file.name
15600
- });
15601
- }
15602
- }
15650
+ onFileProgress?.(groupAttachments[i].id, { status: "done" });
15651
+ });
15603
15652
  } catch (error48) {
15604
- onFileProgress?.(attachment.id, { status: "error" });
15653
+ groupAttachments.forEach((a) => onFileProgress?.(a.id, { status: "error" }));
15605
15654
  throw error48;
15606
15655
  }
15607
15656
  }
@@ -15723,12 +15772,14 @@ function useFileUpload({
15723
15772
  setFileError(null);
15724
15773
  setProcessingState(/* @__PURE__ */ new Map());
15725
15774
  }, [resetDependency]);
15726
- const runTransformer = useCallback2(async (attachmentId, file2, transformer) => {
15775
+ const runTransformer = useCallback2(async (attachmentId, file2, transformerKey) => {
15776
+ const transformer = transformers?.[transformerKey];
15777
+ if (!transformer) return;
15727
15778
  setProcessingState((prev) => new Map(prev).set(attachmentId, { status: "processing" }));
15728
15779
  try {
15729
15780
  const chat = await getCurrentChat();
15730
15781
  const context = { chat };
15731
- const transformedContent = await getTransformedContent(file2, transformer, context, (progress) => {
15782
+ const [transformedContent] = await getTransformedContent([file2], transformer, context, (progress) => {
15732
15783
  setProcessingState((prev) => new Map(prev).set(attachmentId, {
15733
15784
  status: "processing",
15734
15785
  progress
@@ -15742,7 +15793,7 @@ function useFileUpload({
15742
15793
  console.error(`[useFileUpload] Transformation failed for ${file2.name}:`, error48);
15743
15794
  setProcessingState((prev) => new Map(prev).set(attachmentId, { status: "error" }));
15744
15795
  }
15745
- }, [getCurrentChat]);
15796
+ }, [getCurrentChat, transformers]);
15746
15797
  const handleFiles = useCallback2(async (files) => {
15747
15798
  const fileArray = Array.from(files);
15748
15799
  for (const file2 of fileArray) {
@@ -15764,9 +15815,9 @@ function useFileUpload({
15764
15815
  preview
15765
15816
  };
15766
15817
  setAttachments((prev) => [...prev, attachment]);
15767
- const transformer = findTransformer(file2.type, transformers);
15768
- if (transformer) {
15769
- runTransformer(attachmentId, file2, transformer);
15818
+ const transformerKey = findTransformerPattern(file2.type, transformers);
15819
+ if (transformerKey) {
15820
+ runTransformer(attachmentId, file2, transformerKey);
15770
15821
  }
15771
15822
  }
15772
15823
  }, [maxFileSize, acceptedTypes, strings, transformers, runTransformer]);
@@ -15927,8 +15978,210 @@ function useDropdownState(options = {}) {
15927
15978
  };
15928
15979
  }
15929
15980
 
15981
+ // src/components/ToolApprovalDialog.tsx
15982
+ import { useState as useState4 } from "react";
15983
+ import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
15984
+ function ToolApprovalDialog({
15985
+ toolCallName,
15986
+ toolCallArgs,
15987
+ annotations,
15988
+ toolCount = 1,
15989
+ pendingTools = [],
15990
+ onApprove,
15991
+ onReject,
15992
+ theme,
15993
+ strings
15994
+ }) {
15995
+ const [showDetails, setShowDetails] = useState4(false);
15996
+ const displayName = annotations?.title || toolCallName;
15997
+ const isBatch = toolCount > 1;
15998
+ const message = isBatch ? strings.toolApproval.batchMessage?.replace("{count}", String(toolCount)) ?? `${toolCount} actions are waiting for your approval` : strings.toolApproval.message.replace("{toolName}", displayName);
15999
+ const getToolDisplayName = (tool) => tool.annotations?.title || tool.toolCallName;
16000
+ return /* @__PURE__ */ jsxs7(
16001
+ "div",
16002
+ {
16003
+ "data-testid": "tool-approval-dialog",
16004
+ style: {
16005
+ border: `2px solid ${theme.primaryColor}`,
16006
+ borderRadius: "12px",
16007
+ background: theme.backgroundColor,
16008
+ overflow: "hidden"
16009
+ },
16010
+ children: [
16011
+ /* @__PURE__ */ jsxs7(
16012
+ "div",
16013
+ {
16014
+ style: {
16015
+ padding: "12px 14px",
16016
+ borderBottom: `1px solid ${theme.borderColor}`,
16017
+ background: theme.assistantMessageBackground
16018
+ },
16019
+ children: [
16020
+ /* @__PURE__ */ jsxs7("div", { style: {
16021
+ display: "flex",
16022
+ alignItems: "center",
16023
+ gap: "8px",
16024
+ marginBottom: "4px"
16025
+ }, children: [
16026
+ /* @__PURE__ */ jsxs7("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: theme.primaryColor, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
16027
+ /* @__PURE__ */ jsx10("path", { d: "M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" }),
16028
+ /* @__PURE__ */ jsx10("line", { x1: "12", y1: "9", x2: "12", y2: "13" }),
16029
+ /* @__PURE__ */ jsx10("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
16030
+ ] }),
16031
+ /* @__PURE__ */ jsx10("span", { style: {
16032
+ fontWeight: 600,
16033
+ fontSize: "14px",
16034
+ color: theme.textColor
16035
+ }, children: strings.toolApproval.title })
16036
+ ] }),
16037
+ /* @__PURE__ */ jsx10("div", { style: {
16038
+ fontSize: "13px",
16039
+ color: theme.secondaryTextColor,
16040
+ paddingLeft: "24px"
16041
+ }, children: message })
16042
+ ]
16043
+ }
16044
+ ),
16045
+ /* @__PURE__ */ jsxs7("div", { style: { padding: "8px 14px" }, children: [
16046
+ /* @__PURE__ */ jsxs7(
16047
+ "button",
16048
+ {
16049
+ onClick: () => setShowDetails(!showDetails),
16050
+ style: {
16051
+ background: "transparent",
16052
+ border: "none",
16053
+ padding: 0,
16054
+ cursor: "pointer",
16055
+ fontSize: "12px",
16056
+ color: theme.secondaryTextColor,
16057
+ display: "flex",
16058
+ alignItems: "center",
16059
+ gap: "4px"
16060
+ },
16061
+ children: [
16062
+ /* @__PURE__ */ jsx10(
16063
+ "svg",
16064
+ {
16065
+ width: "10",
16066
+ height: "10",
16067
+ viewBox: "0 0 12 12",
16068
+ fill: "none",
16069
+ style: {
16070
+ transform: showDetails ? "rotate(90deg)" : "rotate(0deg)",
16071
+ transition: "transform 0.15s"
16072
+ },
16073
+ children: /* @__PURE__ */ jsx10("path", { d: "M4 2L8 6L4 10", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
16074
+ }
16075
+ ),
16076
+ strings.toolApproval.showDetails
16077
+ ]
16078
+ }
16079
+ ),
16080
+ showDetails && /* @__PURE__ */ jsx10("div", { style: {
16081
+ marginTop: "6px",
16082
+ display: "flex",
16083
+ flexDirection: "column",
16084
+ gap: "8px",
16085
+ maxHeight: "200px",
16086
+ overflow: "auto"
16087
+ }, children: (pendingTools.length > 0 ? pendingTools : [{
16088
+ toolCallId: "single",
16089
+ toolCallName,
16090
+ toolCallArgs,
16091
+ annotations
16092
+ }]).map((tool, index2) => /* @__PURE__ */ jsxs7(
16093
+ "div",
16094
+ {
16095
+ style: {
16096
+ padding: "8px",
16097
+ background: theme.hoverBackground,
16098
+ borderRadius: "6px"
16099
+ },
16100
+ children: [
16101
+ /* @__PURE__ */ jsx10("div", { style: {
16102
+ fontSize: "12px",
16103
+ fontWeight: 500,
16104
+ color: theme.textColor,
16105
+ marginBottom: "4px"
16106
+ }, children: getToolDisplayName(tool) }),
16107
+ /* @__PURE__ */ jsx10("pre", { style: {
16108
+ margin: 0,
16109
+ fontSize: "11px",
16110
+ overflow: "auto",
16111
+ color: theme.secondaryTextColor,
16112
+ whiteSpace: "pre-wrap",
16113
+ wordBreak: "break-word"
16114
+ }, children: JSON.stringify(tool.toolCallArgs, null, 2) })
16115
+ ]
16116
+ },
16117
+ tool.toolCallId
16118
+ )) })
16119
+ ] }),
16120
+ /* @__PURE__ */ jsxs7("div", { style: {
16121
+ display: "flex",
16122
+ gap: "8px",
16123
+ padding: "8px 14px 12px"
16124
+ }, children: [
16125
+ /* @__PURE__ */ jsx10(
16126
+ "button",
16127
+ {
16128
+ "data-testid": "approve-tool-button",
16129
+ onClick: onApprove,
16130
+ style: {
16131
+ flex: 1,
16132
+ padding: "8px 16px",
16133
+ borderRadius: "8px",
16134
+ border: "none",
16135
+ background: theme.primaryGradient,
16136
+ color: "white",
16137
+ fontWeight: 500,
16138
+ cursor: "pointer",
16139
+ fontSize: "13px",
16140
+ transition: "opacity 0.15s"
16141
+ },
16142
+ onMouseEnter: (e) => {
16143
+ e.currentTarget.style.opacity = "0.9";
16144
+ },
16145
+ onMouseLeave: (e) => {
16146
+ e.currentTarget.style.opacity = "1";
16147
+ },
16148
+ children: isBatch ? strings.toolApproval.approveAll ?? "Approve All" : strings.toolApproval.approve
16149
+ }
16150
+ ),
16151
+ /* @__PURE__ */ jsx10(
16152
+ "button",
16153
+ {
16154
+ "data-testid": "reject-tool-button",
16155
+ onClick: () => onReject(),
16156
+ style: {
16157
+ flex: 1,
16158
+ padding: "8px 16px",
16159
+ borderRadius: "8px",
16160
+ border: `1px solid ${theme.borderColor}`,
16161
+ background: "transparent",
16162
+ color: theme.textColor,
16163
+ fontWeight: 500,
16164
+ cursor: "pointer",
16165
+ fontSize: "13px",
16166
+ transition: "all 0.15s"
16167
+ },
16168
+ onMouseEnter: (e) => {
16169
+ e.currentTarget.style.background = theme.hoverBackground;
16170
+ },
16171
+ onMouseLeave: (e) => {
16172
+ e.currentTarget.style.background = "transparent";
16173
+ },
16174
+ children: isBatch ? strings.toolApproval.rejectAll ?? "Reject All" : strings.toolApproval.reject
16175
+ }
16176
+ )
16177
+ ] })
16178
+ ]
16179
+ }
16180
+ );
16181
+ }
16182
+
15930
16183
  // src/components/UseAIChatPanel.tsx
15931
- import { Fragment, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
16184
+ import { Fragment, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
15932
16185
  function FeedbackButton({ type, isSelected, onClick, selectedColor, unselectedColor }) {
15933
16186
  const buttonRef = useRef4(null);
15934
16187
  const handleClick = () => {
@@ -15944,7 +16197,7 @@ function FeedbackButton({ type, isSelected, onClick, selectedColor, unselectedCo
15944
16197
  };
15945
16198
  const thumbsUpPath = "M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3";
15946
16199
  const thumbsDownPath = "M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17";
15947
- return /* @__PURE__ */ jsx10(
16200
+ return /* @__PURE__ */ jsx11(
15948
16201
  "button",
15949
16202
  {
15950
16203
  ref: buttonRef,
@@ -15977,7 +16230,7 @@ function FeedbackButton({ type, isSelected, onClick, selectedColor, unselectedCo
15977
16230
  e.currentTarget.style.color = unselectedColor;
15978
16231
  }
15979
16232
  },
15980
- children: /* @__PURE__ */ jsx10(
16233
+ children: /* @__PURE__ */ jsx11(
15981
16234
  "svg",
15982
16235
  {
15983
16236
  width: "14",
@@ -15988,7 +16241,7 @@ function FeedbackButton({ type, isSelected, onClick, selectedColor, unselectedCo
15988
16241
  strokeWidth: "2",
15989
16242
  strokeLinecap: "round",
15990
16243
  strokeLinejoin: "round",
15991
- children: /* @__PURE__ */ jsx10("path", { d: type === "upvote" ? thumbsUpPath : thumbsDownPath })
16244
+ children: /* @__PURE__ */ jsx11("path", { d: type === "upvote" ? thumbsUpPath : thumbsDownPath })
15992
16245
  }
15993
16246
  )
15994
16247
  }
@@ -16029,18 +16282,21 @@ function UseAIChatPanel({
16029
16282
  closeButton,
16030
16283
  executingTool,
16031
16284
  feedbackEnabled,
16032
- onFeedback
16285
+ onFeedback,
16286
+ pendingApprovals = [],
16287
+ onApproveToolCall,
16288
+ onRejectToolCall
16033
16289
  }) {
16034
16290
  const strings = useStrings();
16035
16291
  const theme = useTheme();
16036
- const [input, setInput] = useState4("");
16292
+ const [input, setInput] = useState5("");
16037
16293
  const chatHistoryDropdown = useDropdownState();
16038
16294
  const agentDropdown = useDropdownState();
16039
- const [chatHistory, setChatHistory] = useState4([]);
16295
+ const [chatHistory, setChatHistory] = useState5([]);
16040
16296
  const messagesEndRef = useRef4(null);
16041
- const [displayedSuggestions, setDisplayedSuggestions] = useState4([]);
16297
+ const [displayedSuggestions, setDisplayedSuggestions] = useState5([]);
16042
16298
  const textareaRef = useRef4(null);
16043
- const [hoveredMessageId, setHoveredMessageId] = useState4(null);
16299
+ const [hoveredMessageId, setHoveredMessageId] = useState5(null);
16044
16300
  const {
16045
16301
  attachments,
16046
16302
  fileError,
@@ -16127,7 +16383,7 @@ function UseAIChatPanel({
16127
16383
  chatHistoryDropdown.close();
16128
16384
  }
16129
16385
  };
16130
- return /* @__PURE__ */ jsxs7(
16386
+ return /* @__PURE__ */ jsxs8(
16131
16387
  "div",
16132
16388
  {
16133
16389
  onClick: () => {
@@ -16145,7 +16401,7 @@ function UseAIChatPanel({
16145
16401
  },
16146
16402
  children: [
16147
16403
  DropZoneOverlay,
16148
- /* @__PURE__ */ jsxs7(
16404
+ /* @__PURE__ */ jsxs8(
16149
16405
  "div",
16150
16406
  {
16151
16407
  style: {
@@ -16158,7 +16414,7 @@ function UseAIChatPanel({
16158
16414
  gap: "12px"
16159
16415
  },
16160
16416
  children: [
16161
- /* @__PURE__ */ jsx10("div", { style: { flex: 1, minWidth: 0, position: "relative" }, children: onListChats ? /* @__PURE__ */ jsxs7(
16417
+ /* @__PURE__ */ jsx11("div", { style: { flex: 1, minWidth: 0, position: "relative" }, children: onListChats ? /* @__PURE__ */ jsxs8(
16162
16418
  "button",
16163
16419
  {
16164
16420
  "data-testid": "chat-history-dropdown-button",
@@ -16191,7 +16447,7 @@ function UseAIChatPanel({
16191
16447
  e.currentTarget.style.background = "transparent";
16192
16448
  },
16193
16449
  children: [
16194
- /* @__PURE__ */ jsx10("span", { style: {
16450
+ /* @__PURE__ */ jsx11("span", { style: {
16195
16451
  overflow: "hidden",
16196
16452
  textOverflow: "ellipsis",
16197
16453
  whiteSpace: "nowrap",
@@ -16208,13 +16464,13 @@ function UseAIChatPanel({
16208
16464
  }
16209
16465
  return strings.header.newChat;
16210
16466
  })() }),
16211
- /* @__PURE__ */ jsx10("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx10("path", { d: "M3 4.5L6 7.5L9 4.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
16467
+ /* @__PURE__ */ jsx11("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx11("path", { d: "M3 4.5L6 7.5L9 4.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
16212
16468
  ]
16213
16469
  }
16214
- ) : /* @__PURE__ */ jsx10("div", { style: { fontSize: "14px", fontWeight: "600", color: theme.textColor, padding: "6px 8px" }, children: strings.header.aiAssistant }) }),
16215
- /* @__PURE__ */ jsxs7("div", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
16216
- availableAgents && availableAgents.length > 1 && onAgentChange && /* @__PURE__ */ jsxs7("div", { style: { position: "relative" }, children: [
16217
- /* @__PURE__ */ jsxs7(
16470
+ ) : /* @__PURE__ */ jsx11("div", { style: { fontSize: "14px", fontWeight: "600", color: theme.textColor, padding: "6px 8px" }, children: strings.header.aiAssistant }) }),
16471
+ /* @__PURE__ */ jsxs8("div", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
16472
+ availableAgents && availableAgents.length > 1 && onAgentChange && /* @__PURE__ */ jsxs8("div", { style: { position: "relative" }, children: [
16473
+ /* @__PURE__ */ jsxs8(
16218
16474
  "button",
16219
16475
  {
16220
16476
  "data-testid": "agent-selector",
@@ -16243,7 +16499,7 @@ function UseAIChatPanel({
16243
16499
  },
16244
16500
  title: "Select AI model",
16245
16501
  children: [
16246
- /* @__PURE__ */ jsx10("span", { style: {
16502
+ /* @__PURE__ */ jsx11("span", { style: {
16247
16503
  overflow: "hidden",
16248
16504
  textOverflow: "ellipsis",
16249
16505
  whiteSpace: "nowrap",
@@ -16252,11 +16508,11 @@ function UseAIChatPanel({
16252
16508
  const agent = availableAgents.find((a) => a.id === (selectedAgent ?? defaultAgent));
16253
16509
  return agent?.name || "AI";
16254
16510
  })() }),
16255
- /* @__PURE__ */ jsx10("svg", { width: "10", height: "10", viewBox: "0 0 12 12", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx10("path", { d: "M3 4.5L6 7.5L9 4.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
16511
+ /* @__PURE__ */ jsx11("svg", { width: "10", height: "10", viewBox: "0 0 12 12", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx11("path", { d: "M3 4.5L6 7.5L9 4.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
16256
16512
  ]
16257
16513
  }
16258
16514
  ),
16259
- agentDropdown.isOpen && /* @__PURE__ */ jsx10(
16515
+ agentDropdown.isOpen && /* @__PURE__ */ jsx11(
16260
16516
  "div",
16261
16517
  {
16262
16518
  style: {
@@ -16276,7 +16532,7 @@ function UseAIChatPanel({
16276
16532
  },
16277
16533
  children: availableAgents.map((agent) => {
16278
16534
  const isSelected = agent.id === (selectedAgent ?? defaultAgent);
16279
- return /* @__PURE__ */ jsxs7(
16535
+ return /* @__PURE__ */ jsxs8(
16280
16536
  "div",
16281
16537
  {
16282
16538
  "data-testid": "agent-option",
@@ -16306,13 +16562,13 @@ function UseAIChatPanel({
16306
16562
  }
16307
16563
  },
16308
16564
  children: [
16309
- /* @__PURE__ */ jsxs7("div", { style: { flex: 1, minWidth: 0 }, children: [
16310
- /* @__PURE__ */ jsx10("div", { style: {
16565
+ /* @__PURE__ */ jsxs8("div", { style: { flex: 1, minWidth: 0 }, children: [
16566
+ /* @__PURE__ */ jsx11("div", { style: {
16311
16567
  fontSize: "13px",
16312
16568
  fontWeight: isSelected ? "600" : "500",
16313
16569
  color: isSelected ? theme.primaryColor : theme.textColor
16314
16570
  }, children: agent.name }),
16315
- agent.annotation && /* @__PURE__ */ jsx10("div", { style: {
16571
+ agent.annotation && /* @__PURE__ */ jsx11("div", { style: {
16316
16572
  fontSize: "11px",
16317
16573
  color: theme.secondaryTextColor,
16318
16574
  marginTop: "2px",
@@ -16321,7 +16577,7 @@ function UseAIChatPanel({
16321
16577
  whiteSpace: "nowrap"
16322
16578
  }, children: agent.annotation })
16323
16579
  ] }),
16324
- isSelected && /* @__PURE__ */ jsx10("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx10("path", { d: "M2 7L5.5 10.5L12 4", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
16580
+ isSelected && /* @__PURE__ */ jsx11("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx11("path", { d: "M2 7L5.5 10.5L12 4", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
16325
16581
  ]
16326
16582
  },
16327
16583
  agent.id
@@ -16330,7 +16586,7 @@ function UseAIChatPanel({
16330
16586
  }
16331
16587
  )
16332
16588
  ] }),
16333
- onNewChat && /* @__PURE__ */ jsx10(
16589
+ onNewChat && /* @__PURE__ */ jsx11(
16334
16590
  "button",
16335
16591
  {
16336
16592
  "data-testid": "new-chat-button",
@@ -16357,10 +16613,10 @@ function UseAIChatPanel({
16357
16613
  e.currentTarget.style.color = theme.secondaryTextColor;
16358
16614
  },
16359
16615
  title: strings.header.newChat,
16360
- children: /* @__PURE__ */ jsx10("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx10("path", { d: "M8 3.5V12.5M3.5 8H12.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) })
16616
+ children: /* @__PURE__ */ jsx11("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx11("path", { d: "M8 3.5V12.5M3.5 8H12.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) })
16361
16617
  }
16362
16618
  ),
16363
- onDeleteChat && messages.length > 0 && /* @__PURE__ */ jsx10(
16619
+ onDeleteChat && messages.length > 0 && /* @__PURE__ */ jsx11(
16364
16620
  "button",
16365
16621
  {
16366
16622
  "data-testid": "delete-chat-button",
@@ -16384,7 +16640,7 @@ function UseAIChatPanel({
16384
16640
  e.currentTarget.style.color = theme.secondaryTextColor;
16385
16641
  },
16386
16642
  title: strings.header.deleteChat,
16387
- children: /* @__PURE__ */ jsx10("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx10("path", { d: "M2 4H14M6.5 7V11M9.5 7V11M3 4L4 13C4 13.5304 4.21071 14.0391 4.58579 14.4142C4.96086 14.7893 5.46957 15 6 15H10C10.5304 15 11.0391 14.7893 11.4142 14.4142C11.7893 14.0391 12 13.5304 12 13L13 4M5.5 4V2.5C5.5 2.23478 5.60536 1.98043 5.79289 1.79289C5.98043 1.60536 6.23478 1.5 6.5 1.5H9.5C9.76522 1.5 10.0196 1.60536 10.2071 1.79289C10.3946 1.98043 10.5 2.23478 10.5 2.5V4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
16643
+ children: /* @__PURE__ */ jsx11("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx11("path", { d: "M2 4H14M6.5 7V11M9.5 7V11M3 4L4 13C4 13.5304 4.21071 14.0391 4.58579 14.4142C4.96086 14.7893 5.46957 15 6 15H10C10.5304 15 11.0391 14.7893 11.4142 14.4142C11.7893 14.0391 12 13.5304 12 13L13 4M5.5 4V2.5C5.5 2.23478 5.60536 1.98043 5.79289 1.79289C5.98043 1.60536 6.23478 1.5 6.5 1.5H9.5C9.76522 1.5 10.0196 1.60536 10.2071 1.79289C10.3946 1.98043 10.5 2.23478 10.5 2.5V4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
16388
16644
  }
16389
16645
  ),
16390
16646
  closeButton
@@ -16392,7 +16648,7 @@ function UseAIChatPanel({
16392
16648
  ]
16393
16649
  }
16394
16650
  ),
16395
- chatHistoryDropdown.isOpen && onListChats && /* @__PURE__ */ jsx10(
16651
+ chatHistoryDropdown.isOpen && onListChats && /* @__PURE__ */ jsx11(
16396
16652
  "div",
16397
16653
  {
16398
16654
  style: {
@@ -16409,7 +16665,7 @@ function UseAIChatPanel({
16409
16665
  flexDirection: "column",
16410
16666
  overflow: "hidden"
16411
16667
  },
16412
- children: /* @__PURE__ */ jsx10(
16668
+ children: /* @__PURE__ */ jsx11(
16413
16669
  "div",
16414
16670
  {
16415
16671
  style: {
@@ -16417,7 +16673,7 @@ function UseAIChatPanel({
16417
16673
  overflowY: "auto",
16418
16674
  padding: "8px"
16419
16675
  },
16420
- children: chatHistory.length === 0 ? /* @__PURE__ */ jsx10(
16676
+ children: chatHistory.length === 0 ? /* @__PURE__ */ jsx11(
16421
16677
  "div",
16422
16678
  {
16423
16679
  style: {
@@ -16426,9 +16682,9 @@ function UseAIChatPanel({
16426
16682
  padding: "32px 16px",
16427
16683
  fontSize: "13px"
16428
16684
  },
16429
- children: /* @__PURE__ */ jsx10("p", { style: { margin: 0 }, children: strings.chatHistory.noChatHistory })
16685
+ children: /* @__PURE__ */ jsx11("p", { style: { margin: 0 }, children: strings.chatHistory.noChatHistory })
16430
16686
  }
16431
- ) : chatHistory.map((chat) => /* @__PURE__ */ jsxs7(
16687
+ ) : chatHistory.map((chat) => /* @__PURE__ */ jsxs8(
16432
16688
  "div",
16433
16689
  {
16434
16690
  "data-testid": "chat-history-item",
@@ -16452,10 +16708,10 @@ function UseAIChatPanel({
16452
16708
  }
16453
16709
  },
16454
16710
  children: [
16455
- /* @__PURE__ */ jsx10("div", { style: { fontSize: "13px", fontWeight: "500", color: theme.textColor, marginBottom: "4px", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: chat.title || strings.header.newChat }),
16456
- /* @__PURE__ */ jsxs7("div", { style: { fontSize: "11px", color: theme.secondaryTextColor }, children: [
16711
+ /* @__PURE__ */ jsx11("div", { style: { fontSize: "13px", fontWeight: "500", color: theme.textColor, marginBottom: "4px", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: chat.title || strings.header.newChat }),
16712
+ /* @__PURE__ */ jsxs8("div", { style: { fontSize: "11px", color: theme.secondaryTextColor }, children: [
16457
16713
  new Date(chat.updatedAt).toLocaleDateString([], { month: "short", day: "numeric" }),
16458
- currentChatId === chat.id && /* @__PURE__ */ jsxs7("span", { style: {
16714
+ currentChatId === chat.id && /* @__PURE__ */ jsxs8("span", { style: {
16459
16715
  marginLeft: "8px",
16460
16716
  color: theme.primaryColor,
16461
16717
  fontWeight: "600"
@@ -16474,7 +16730,7 @@ function UseAIChatPanel({
16474
16730
  ),
16475
16731
  chatHistoryDropdown.Backdrop,
16476
16732
  agentDropdown.Backdrop,
16477
- /* @__PURE__ */ jsxs7(
16733
+ /* @__PURE__ */ jsxs8(
16478
16734
  "div",
16479
16735
  {
16480
16736
  style: {
@@ -16486,7 +16742,7 @@ function UseAIChatPanel({
16486
16742
  gap: "12px"
16487
16743
  },
16488
16744
  children: [
16489
- messages.length === 0 && /* @__PURE__ */ jsxs7(
16745
+ messages.length === 0 && /* @__PURE__ */ jsxs8(
16490
16746
  "div",
16491
16747
  {
16492
16748
  style: {
@@ -16497,12 +16753,12 @@ function UseAIChatPanel({
16497
16753
  gap: "20px"
16498
16754
  },
16499
16755
  children: [
16500
- /* @__PURE__ */ jsxs7("div", { style: { textAlign: "center", color: theme.secondaryTextColor, fontSize: "14px" }, children: [
16501
- /* @__PURE__ */ jsx10("p", { style: { margin: 0, fontSize: "32px", marginBottom: "12px" }, children: "\u{1F4AC}" }),
16502
- /* @__PURE__ */ jsx10("p", { style: { margin: 0 }, children: strings.emptyChat.startConversation }),
16503
- /* @__PURE__ */ jsx10("p", { style: { margin: "8px 0 0", fontSize: "12px" }, children: strings.emptyChat.askMeToHelp })
16756
+ /* @__PURE__ */ jsxs8("div", { style: { textAlign: "center", color: theme.secondaryTextColor, fontSize: "14px" }, children: [
16757
+ /* @__PURE__ */ jsx11("p", { style: { margin: 0, fontSize: "32px", marginBottom: "12px" }, children: "\u{1F4AC}" }),
16758
+ /* @__PURE__ */ jsx11("p", { style: { margin: 0 }, children: strings.emptyChat.startConversation }),
16759
+ /* @__PURE__ */ jsx11("p", { style: { margin: "8px 0 0", fontSize: "12px" }, children: strings.emptyChat.askMeToHelp })
16504
16760
  ] }),
16505
- displayedSuggestions.length > 0 && /* @__PURE__ */ jsx10(
16761
+ displayedSuggestions.length > 0 && /* @__PURE__ */ jsx11(
16506
16762
  "div",
16507
16763
  {
16508
16764
  style: {
@@ -16512,7 +16768,7 @@ function UseAIChatPanel({
16512
16768
  width: "100%",
16513
16769
  maxWidth: "320px"
16514
16770
  },
16515
- children: displayedSuggestions.map((suggestion, index2) => /* @__PURE__ */ jsx10(
16771
+ children: displayedSuggestions.map((suggestion, index2) => /* @__PURE__ */ jsx11(
16516
16772
  "button",
16517
16773
  {
16518
16774
  "data-testid": "chat-suggestion-button",
@@ -16556,7 +16812,7 @@ function UseAIChatPanel({
16556
16812
  ]
16557
16813
  }
16558
16814
  ),
16559
- messages.map((message) => /* @__PURE__ */ jsxs7(
16815
+ messages.map((message) => /* @__PURE__ */ jsxs8(
16560
16816
  "div",
16561
16817
  {
16562
16818
  "data-testid": `chat-message-${message.role}`,
@@ -16569,7 +16825,7 @@ function UseAIChatPanel({
16569
16825
  onMouseEnter: () => message.role === "user" && setHoveredMessageId(message.id),
16570
16826
  onMouseLeave: () => setHoveredMessageId(null),
16571
16827
  children: [
16572
- /* @__PURE__ */ jsxs7(
16828
+ /* @__PURE__ */ jsxs8(
16573
16829
  "div",
16574
16830
  {
16575
16831
  style: {
@@ -16577,7 +16833,7 @@ function UseAIChatPanel({
16577
16833
  maxWidth: "80%"
16578
16834
  },
16579
16835
  children: [
16580
- message.role === "user" && hoveredMessageId === message.id && onSaveCommand && !slashCommands.isSavingCommand(message.id) && /* @__PURE__ */ jsx10(
16836
+ message.role === "user" && hoveredMessageId === message.id && onSaveCommand && !slashCommands.isSavingCommand(message.id) && /* @__PURE__ */ jsx11(
16581
16837
  "button",
16582
16838
  {
16583
16839
  "data-testid": "save-command-button",
@@ -16613,14 +16869,14 @@ function UseAIChatPanel({
16613
16869
  e.currentTarget.style.transform = "scale(1)";
16614
16870
  e.currentTarget.style.boxShadow = "0 2px 6px rgba(0, 0, 0, 0.15)";
16615
16871
  },
16616
- children: /* @__PURE__ */ jsxs7("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
16617
- /* @__PURE__ */ jsx10("path", { d: "M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" }),
16618
- /* @__PURE__ */ jsx10("polyline", { points: "17 21 17 13 7 13 7 21" }),
16619
- /* @__PURE__ */ jsx10("polyline", { points: "7 3 7 8 15 8" })
16872
+ children: /* @__PURE__ */ jsxs8("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
16873
+ /* @__PURE__ */ jsx11("path", { d: "M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" }),
16874
+ /* @__PURE__ */ jsx11("polyline", { points: "17 21 17 13 7 13 7 21" }),
16875
+ /* @__PURE__ */ jsx11("polyline", { points: "7 3 7 8 15 8" })
16620
16876
  ] })
16621
16877
  }
16622
16878
  ),
16623
- /* @__PURE__ */ jsxs7(
16879
+ /* @__PURE__ */ jsxs8(
16624
16880
  "div",
16625
16881
  {
16626
16882
  "data-testid": "chat-message-content",
@@ -16635,7 +16891,7 @@ function UseAIChatPanel({
16635
16891
  wordWrap: "break-word"
16636
16892
  },
16637
16893
  children: [
16638
- message.role === "user" && hasFileContent(message.content) && /* @__PURE__ */ jsx10("div", { style: { display: "flex", flexWrap: "wrap", gap: "6px", marginBottom: "8px" }, children: message.content.filter((part) => part.type === "file").map((part, idx) => /* @__PURE__ */ jsx10(
16894
+ message.role === "user" && hasFileContent(message.content) && /* @__PURE__ */ jsx11("div", { style: { display: "flex", flexWrap: "wrap", gap: "6px", marginBottom: "8px" }, children: message.content.filter((part) => part.type === "file").map((part, idx) => /* @__PURE__ */ jsx11(
16639
16895
  FilePlaceholder,
16640
16896
  {
16641
16897
  name: part.file.name,
@@ -16643,7 +16899,7 @@ function UseAIChatPanel({
16643
16899
  },
16644
16900
  idx
16645
16901
  )) }),
16646
- message.role === "assistant" ? /* @__PURE__ */ jsx10(MarkdownContent, { content: getTextContent(message.content) }) : getTextContent(message.content)
16902
+ message.role === "assistant" ? /* @__PURE__ */ jsx11(MarkdownContent, { content: getTextContent(message.content) }) : getTextContent(message.content)
16647
16903
  ]
16648
16904
  }
16649
16905
  ),
@@ -16654,7 +16910,7 @@ function UseAIChatPanel({
16654
16910
  ]
16655
16911
  }
16656
16912
  ),
16657
- message.role === "assistant" && message.traceId && feedbackEnabled && onFeedback && /* @__PURE__ */ jsxs7(
16913
+ message.role === "assistant" && message.traceId && feedbackEnabled && onFeedback && /* @__PURE__ */ jsxs8(
16658
16914
  "div",
16659
16915
  {
16660
16916
  "data-testid": "feedback-buttons",
@@ -16665,7 +16921,7 @@ function UseAIChatPanel({
16665
16921
  padding: "0 4px"
16666
16922
  },
16667
16923
  children: [
16668
- /* @__PURE__ */ jsx10(
16924
+ /* @__PURE__ */ jsx11(
16669
16925
  FeedbackButton,
16670
16926
  {
16671
16927
  type: "upvote",
@@ -16678,7 +16934,7 @@ function UseAIChatPanel({
16678
16934
  unselectedColor: theme.secondaryTextColor
16679
16935
  }
16680
16936
  ),
16681
- /* @__PURE__ */ jsx10(
16937
+ /* @__PURE__ */ jsx11(
16682
16938
  FeedbackButton,
16683
16939
  {
16684
16940
  type: "downvote",
@@ -16694,7 +16950,7 @@ function UseAIChatPanel({
16694
16950
  ]
16695
16951
  }
16696
16952
  ),
16697
- /* @__PURE__ */ jsx10(
16953
+ /* @__PURE__ */ jsx11(
16698
16954
  "div",
16699
16955
  {
16700
16956
  style: {
@@ -16713,14 +16969,14 @@ function UseAIChatPanel({
16713
16969
  },
16714
16970
  message.id
16715
16971
  )),
16716
- loading && /* @__PURE__ */ jsx10(
16972
+ loading && /* @__PURE__ */ jsx11(
16717
16973
  "div",
16718
16974
  {
16719
16975
  style: {
16720
16976
  display: "flex",
16721
16977
  alignItems: "flex-start"
16722
16978
  },
16723
- children: /* @__PURE__ */ jsx10(
16979
+ children: /* @__PURE__ */ jsx11(
16724
16980
  "div",
16725
16981
  {
16726
16982
  className: "markdown-content",
@@ -16733,20 +16989,20 @@ function UseAIChatPanel({
16733
16989
  color: theme.textColor,
16734
16990
  maxWidth: "80%"
16735
16991
  },
16736
- children: streamingText ? /* @__PURE__ */ jsx10(MarkdownContent, { content: streamingText }) : fileProcessing && fileProcessing.status === "processing" ? /* @__PURE__ */ jsxs7("div", { children: [
16737
- /* @__PURE__ */ jsx10("span", { style: { opacity: 0.6 }, children: strings.input.processingFile }),
16738
- fileProcessing.progress != null && /* @__PURE__ */ jsxs7(Fragment, { children: [
16739
- /* @__PURE__ */ jsxs7("span", { style: { opacity: 0.6, marginLeft: "4px" }, children: [
16992
+ children: streamingText ? /* @__PURE__ */ jsx11(MarkdownContent, { content: streamingText }) : fileProcessing && fileProcessing.status === "processing" ? /* @__PURE__ */ jsxs8("div", { children: [
16993
+ /* @__PURE__ */ jsx11("span", { style: { opacity: 0.6 }, children: strings.input.processingFile }),
16994
+ fileProcessing.progress != null && /* @__PURE__ */ jsxs8(Fragment, { children: [
16995
+ /* @__PURE__ */ jsxs8("span", { style: { opacity: 0.6, marginLeft: "4px" }, children: [
16740
16996
  Math.round(fileProcessing.progress),
16741
16997
  "%"
16742
16998
  ] }),
16743
- /* @__PURE__ */ jsx10("div", { style: {
16999
+ /* @__PURE__ */ jsx11("div", { style: {
16744
17000
  marginTop: "6px",
16745
17001
  height: "4px",
16746
17002
  borderRadius: "2px",
16747
17003
  background: theme.borderColor,
16748
17004
  overflow: "hidden"
16749
- }, children: /* @__PURE__ */ jsx10("div", { style: {
17005
+ }, children: /* @__PURE__ */ jsx11("div", { style: {
16750
17006
  height: "100%",
16751
17007
  width: `${fileProcessing.progress}%`,
16752
17008
  borderRadius: "2px",
@@ -16754,17 +17010,17 @@ function UseAIChatPanel({
16754
17010
  transition: "width 0.3s ease"
16755
17011
  } }) })
16756
17012
  ] }),
16757
- fileProcessing.progress == null && /* @__PURE__ */ jsx10("span", { className: "dots", style: { marginLeft: "4px" }, children: "..." })
16758
- ] }) : /* @__PURE__ */ jsx10("span", { className: "dots", style: { opacity: 0.6 }, children: "..." })
17013
+ fileProcessing.progress == null && /* @__PURE__ */ jsx11("span", { className: "dots", style: { marginLeft: "4px" }, children: "..." })
17014
+ ] }) : /* @__PURE__ */ jsx11("span", { className: "dots", style: { opacity: 0.6 }, children: "..." })
16759
17015
  }
16760
17016
  )
16761
17017
  }
16762
17018
  ),
16763
- /* @__PURE__ */ jsx10("div", { ref: messagesEndRef })
17019
+ /* @__PURE__ */ jsx11("div", { ref: messagesEndRef })
16764
17020
  ]
16765
17021
  }
16766
17022
  ),
16767
- /* @__PURE__ */ jsxs7(
17023
+ /* @__PURE__ */ jsxs8(
16768
17024
  "div",
16769
17025
  {
16770
17026
  style: {
@@ -16772,7 +17028,7 @@ function UseAIChatPanel({
16772
17028
  borderTop: `1px solid ${theme.borderColor}`
16773
17029
  },
16774
17030
  children: [
16775
- fileError && /* @__PURE__ */ jsx10(
17031
+ fileError && /* @__PURE__ */ jsx11(
16776
17032
  "div",
16777
17033
  {
16778
17034
  "data-testid": "file-error",
@@ -16787,7 +17043,7 @@ function UseAIChatPanel({
16787
17043
  children: fileError
16788
17044
  }
16789
17045
  ),
16790
- attachments.length > 0 && /* @__PURE__ */ jsx10(
17046
+ attachments.length > 0 && /* @__PURE__ */ jsx11(
16791
17047
  "div",
16792
17048
  {
16793
17049
  "data-testid": "file-attachments",
@@ -16797,7 +17053,7 @@ function UseAIChatPanel({
16797
17053
  gap: "8px",
16798
17054
  marginBottom: "8px"
16799
17055
  },
16800
- children: attachments.map((attachment) => /* @__PURE__ */ jsx10(
17056
+ children: attachments.map((attachment) => /* @__PURE__ */ jsx11(
16801
17057
  FileChip,
16802
17058
  {
16803
17059
  attachment,
@@ -16809,143 +17065,159 @@ function UseAIChatPanel({
16809
17065
  ))
16810
17066
  }
16811
17067
  ),
16812
- /* @__PURE__ */ jsxs7(
16813
- "div",
17068
+ /* @__PURE__ */ jsx11(
17069
+ "input",
16814
17070
  {
16815
- style: {
16816
- border: `1px solid ${theme.borderColor}`,
16817
- borderRadius: "12px",
16818
- background: theme.backgroundColor,
16819
- overflow: "hidden",
16820
- position: "relative"
16821
- },
16822
- children: [
16823
- slashCommands.AutocompleteComponent,
16824
- /* @__PURE__ */ jsx10(
16825
- "input",
16826
- {
16827
- ref: fileInputRef,
16828
- type: "file",
16829
- multiple: true,
16830
- "data-testid": "file-input",
16831
- style: { display: "none" },
16832
- onChange: handleFileInputChange,
16833
- accept: acceptedTypes?.join(",")
16834
- }
16835
- ),
16836
- /* @__PURE__ */ jsx10(
16837
- "textarea",
16838
- {
16839
- ref: textareaRef,
16840
- "data-testid": "chat-input",
16841
- className: "chat-input",
16842
- value: input,
16843
- onChange: handleInputChange,
16844
- onKeyDown: handleKeyDown,
16845
- placeholder: !connected ? strings.input.connectingPlaceholder : loading ? `${executingTool?.displayText ?? strings.input.thinking}...` : strings.input.placeholder,
16846
- disabled: !connected || loading,
16847
- rows: 1,
16848
- style: {
16849
- width: "100%",
16850
- padding: "10px 14px 6px",
16851
- border: "none",
16852
- fontSize: "14px",
16853
- lineHeight: "1.4",
16854
- resize: "none",
16855
- maxHeight: `${maxTextareaHeight}px`,
16856
- fontFamily: "inherit",
16857
- outline: "none",
16858
- background: "transparent",
16859
- overflowY: "auto",
16860
- boxSizing: "border-box"
16861
- }
16862
- }
16863
- ),
16864
- /* @__PURE__ */ jsxs7(
16865
- "div",
16866
- {
16867
- style: {
16868
- display: "flex",
16869
- alignItems: "center",
16870
- justifyContent: "space-between",
16871
- padding: "4px 8px"
16872
- },
16873
- children: [
16874
- /* @__PURE__ */ jsx10("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: fileUploadEnabled && /* @__PURE__ */ jsx10(
16875
- "button",
16876
- {
16877
- "data-testid": "file-picker-button",
16878
- onClick: openFilePicker,
16879
- disabled: !connected || loading,
16880
- style: {
16881
- padding: "4px",
16882
- background: "transparent",
16883
- border: `1px solid ${theme.borderColor}`,
16884
- borderRadius: "50%",
16885
- cursor: connected && !loading ? "pointer" : "not-allowed",
16886
- color: theme.secondaryTextColor,
16887
- display: "flex",
16888
- alignItems: "center",
16889
- justifyContent: "center",
16890
- width: "28px",
16891
- height: "28px",
16892
- transition: "all 0.15s",
16893
- opacity: connected && !loading ? 1 : 0.5
16894
- },
16895
- onMouseEnter: (e) => {
16896
- if (connected && !loading) {
16897
- e.currentTarget.style.color = theme.primaryColor;
16898
- e.currentTarget.style.borderColor = theme.primaryColor;
16899
- }
16900
- },
16901
- onMouseLeave: (e) => {
16902
- e.currentTarget.style.color = theme.secondaryTextColor;
16903
- e.currentTarget.style.borderColor = theme.borderColor;
16904
- },
16905
- title: strings.fileUpload.attachFiles,
16906
- children: /* @__PURE__ */ jsxs7("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
16907
- /* @__PURE__ */ jsx10("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
16908
- /* @__PURE__ */ jsx10("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
16909
- ] })
16910
- }
16911
- ) }),
16912
- /* @__PURE__ */ jsx10(
16913
- "button",
16914
- {
16915
- "data-testid": "chat-send-button",
16916
- className: "chat-send-button",
16917
- onClick: handleSend,
16918
- disabled: !connected || loading || !input.trim() && attachments.length === 0,
16919
- style: {
16920
- padding: "6px",
16921
- background: connected && !loading && (input.trim() || attachments.length > 0) ? theme.primaryGradient : theme.buttonDisabledBackground,
16922
- color: connected && !loading && (input.trim() || attachments.length > 0) ? "white" : theme.secondaryTextColor,
16923
- border: "none",
16924
- borderRadius: "50%",
16925
- cursor: connected && !loading && (input.trim() || attachments.length > 0) ? "pointer" : "not-allowed",
16926
- display: "flex",
16927
- alignItems: "center",
16928
- justifyContent: "center",
16929
- width: "32px",
16930
- height: "32px",
16931
- transition: "all 0.2s"
16932
- },
16933
- children: /* @__PURE__ */ jsxs7("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
16934
- /* @__PURE__ */ jsx10("line", { x1: "12", y1: "19", x2: "12", y2: "5" }),
16935
- /* @__PURE__ */ jsx10("polyline", { points: "5 12 12 5 19 12" })
16936
- ] })
16937
- }
16938
- )
16939
- ]
16940
- }
16941
- )
16942
- ]
17071
+ ref: fileInputRef,
17072
+ type: "file",
17073
+ multiple: true,
17074
+ "data-testid": "file-input",
17075
+ style: { display: "none" },
17076
+ onChange: handleFileInputChange,
17077
+ accept: acceptedTypes?.join(",")
16943
17078
  }
17079
+ ),
17080
+ pendingApprovals.length > 0 && onApproveToolCall && onRejectToolCall ? /* @__PURE__ */ jsx11(
17081
+ ToolApprovalDialog,
17082
+ {
17083
+ toolCallName: pendingApprovals[0].toolCallName,
17084
+ toolCallArgs: pendingApprovals[0].toolCallArgs,
17085
+ annotations: pendingApprovals[0].annotations,
17086
+ toolCount: pendingApprovals.length,
17087
+ pendingTools: pendingApprovals,
17088
+ onApprove: onApproveToolCall,
17089
+ onReject: onRejectToolCall,
17090
+ theme,
17091
+ strings
17092
+ }
17093
+ ) : (
17094
+ /* Input container - single border around everything */
17095
+ /* @__PURE__ */ jsxs8(
17096
+ "div",
17097
+ {
17098
+ style: {
17099
+ border: `1px solid ${theme.borderColor}`,
17100
+ borderRadius: "12px",
17101
+ background: theme.backgroundColor,
17102
+ overflow: "hidden",
17103
+ position: "relative"
17104
+ },
17105
+ children: [
17106
+ slashCommands.AutocompleteComponent,
17107
+ /* @__PURE__ */ jsx11(
17108
+ "textarea",
17109
+ {
17110
+ ref: textareaRef,
17111
+ "data-testid": "chat-input",
17112
+ className: "chat-input",
17113
+ value: input,
17114
+ onChange: handleInputChange,
17115
+ onKeyDown: handleKeyDown,
17116
+ placeholder: !connected ? strings.input.connectingPlaceholder : loading ? `${executingTool?.displayText ?? strings.input.thinking}...` : strings.input.placeholder,
17117
+ disabled: !connected || loading || pendingApprovals.length > 0,
17118
+ rows: 1,
17119
+ style: {
17120
+ width: "100%",
17121
+ padding: "10px 14px 6px",
17122
+ border: "none",
17123
+ fontSize: "14px",
17124
+ lineHeight: "1.4",
17125
+ resize: "none",
17126
+ maxHeight: `${maxTextareaHeight}px`,
17127
+ fontFamily: "inherit",
17128
+ outline: "none",
17129
+ background: "transparent",
17130
+ overflowY: "auto",
17131
+ boxSizing: "border-box"
17132
+ }
17133
+ }
17134
+ ),
17135
+ /* @__PURE__ */ jsxs8(
17136
+ "div",
17137
+ {
17138
+ style: {
17139
+ display: "flex",
17140
+ alignItems: "center",
17141
+ justifyContent: "space-between",
17142
+ padding: "4px 8px"
17143
+ },
17144
+ children: [
17145
+ /* @__PURE__ */ jsx11("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: fileUploadEnabled && /* @__PURE__ */ jsx11(
17146
+ "button",
17147
+ {
17148
+ "data-testid": "file-picker-button",
17149
+ onClick: openFilePicker,
17150
+ disabled: !connected || loading || pendingApprovals.length > 0,
17151
+ style: {
17152
+ padding: "4px",
17153
+ background: "transparent",
17154
+ border: `1px solid ${theme.borderColor}`,
17155
+ borderRadius: "50%",
17156
+ cursor: connected && !loading && pendingApprovals.length === 0 ? "pointer" : "not-allowed",
17157
+ color: theme.secondaryTextColor,
17158
+ display: "flex",
17159
+ alignItems: "center",
17160
+ justifyContent: "center",
17161
+ width: "28px",
17162
+ height: "28px",
17163
+ transition: "all 0.15s",
17164
+ opacity: connected && !loading && pendingApprovals.length === 0 ? 1 : 0.5
17165
+ },
17166
+ onMouseEnter: (e) => {
17167
+ if (connected && !loading && pendingApprovals.length === 0) {
17168
+ e.currentTarget.style.color = theme.primaryColor;
17169
+ e.currentTarget.style.borderColor = theme.primaryColor;
17170
+ }
17171
+ },
17172
+ onMouseLeave: (e) => {
17173
+ e.currentTarget.style.color = theme.secondaryTextColor;
17174
+ e.currentTarget.style.borderColor = theme.borderColor;
17175
+ },
17176
+ title: strings.fileUpload.attachFiles,
17177
+ children: /* @__PURE__ */ jsxs8("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
17178
+ /* @__PURE__ */ jsx11("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
17179
+ /* @__PURE__ */ jsx11("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
17180
+ ] })
17181
+ }
17182
+ ) }),
17183
+ /* @__PURE__ */ jsx11(
17184
+ "button",
17185
+ {
17186
+ "data-testid": "chat-send-button",
17187
+ className: "chat-send-button",
17188
+ onClick: handleSend,
17189
+ disabled: !connected || loading || pendingApprovals.length > 0 || !input.trim() && attachments.length === 0,
17190
+ style: {
17191
+ padding: "6px",
17192
+ background: connected && !loading && pendingApprovals.length === 0 && (input.trim() || attachments.length > 0) ? theme.primaryGradient : theme.buttonDisabledBackground,
17193
+ color: connected && !loading && pendingApprovals.length === 0 && (input.trim() || attachments.length > 0) ? "white" : theme.secondaryTextColor,
17194
+ border: "none",
17195
+ borderRadius: "50%",
17196
+ cursor: connected && !loading && pendingApprovals.length === 0 && (input.trim() || attachments.length > 0) ? "pointer" : "not-allowed",
17197
+ display: "flex",
17198
+ alignItems: "center",
17199
+ justifyContent: "center",
17200
+ width: "32px",
17201
+ height: "32px",
17202
+ transition: "all 0.2s"
17203
+ },
17204
+ children: /* @__PURE__ */ jsxs8("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
17205
+ /* @__PURE__ */ jsx11("line", { x1: "12", y1: "19", x2: "12", y2: "5" }),
17206
+ /* @__PURE__ */ jsx11("polyline", { points: "5 12 12 5 19 12" })
17207
+ ] })
17208
+ }
17209
+ )
17210
+ ]
17211
+ }
17212
+ )
17213
+ ]
17214
+ }
17215
+ )
16944
17216
  )
16945
17217
  ]
16946
17218
  }
16947
17219
  ),
16948
- /* @__PURE__ */ jsx10("style", { children: `
17220
+ /* @__PURE__ */ jsx11("style", { children: `
16949
17221
  /* Markdown content styles */
16950
17222
  .markdown-content > :first-child {
16951
17223
  margin-top: 0 !important;
@@ -16970,7 +17242,7 @@ function UseAIChatPanel({
16970
17242
  }
16971
17243
 
16972
17244
  // src/components/UseAIFloatingChatWrapper.tsx
16973
- import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
17245
+ import { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
16974
17246
  function UseAIFloatingChatWrapper({
16975
17247
  isOpen,
16976
17248
  onClose,
@@ -16978,8 +17250,8 @@ function UseAIFloatingChatWrapper({
16978
17250
  }) {
16979
17251
  const theme = useTheme();
16980
17252
  if (!isOpen) return null;
16981
- return /* @__PURE__ */ jsxs8(Fragment2, { children: [
16982
- /* @__PURE__ */ jsx11(
17253
+ return /* @__PURE__ */ jsxs9(Fragment2, { children: [
17254
+ /* @__PURE__ */ jsx12(
16983
17255
  "div",
16984
17256
  {
16985
17257
  style: {
@@ -16995,7 +17267,7 @@ function UseAIFloatingChatWrapper({
16995
17267
  onClick: onClose
16996
17268
  }
16997
17269
  ),
16998
- /* @__PURE__ */ jsx11(
17270
+ /* @__PURE__ */ jsx12(
16999
17271
  "div",
17000
17272
  {
17001
17273
  style: {
@@ -17014,7 +17286,7 @@ function UseAIFloatingChatWrapper({
17014
17286
  children
17015
17287
  }
17016
17288
  ),
17017
- /* @__PURE__ */ jsx11("style", { children: `
17289
+ /* @__PURE__ */ jsx12("style", { children: `
17018
17290
  @keyframes fadeIn {
17019
17291
  from { opacity: 0; }
17020
17292
  to { opacity: 1; }
@@ -17034,7 +17306,7 @@ function UseAIFloatingChatWrapper({
17034
17306
  }
17035
17307
  function CloseButton({ onClick }) {
17036
17308
  const theme = useTheme();
17037
- return /* @__PURE__ */ jsx11(
17309
+ return /* @__PURE__ */ jsx12(
17038
17310
  "button",
17039
17311
  {
17040
17312
  "data-testid": "chat-close-button",
@@ -17069,7 +17341,7 @@ function CloseButton({ onClick }) {
17069
17341
 
17070
17342
  // src/components/UseAIChat.tsx
17071
17343
  import { createContext as createContext3, useContext as useContext3 } from "react";
17072
- import { jsx as jsx12 } from "react/jsx-runtime";
17344
+ import { jsx as jsx13 } from "react/jsx-runtime";
17073
17345
  var __UseAIChatContext = createContext3(null);
17074
17346
  function useChatUIContext() {
17075
17347
  const context = useContext3(__UseAIChatContext);
@@ -17105,27 +17377,30 @@ function UseAIChat({ floating = false }) {
17105
17377
  onSaveCommand: ctx.commands.save,
17106
17378
  onRenameCommand: ctx.commands.rename,
17107
17379
  onDeleteCommand: ctx.commands.delete,
17108
- executingTool: ctx.executingTool,
17380
+ executingTool: ctx.tools.executing,
17109
17381
  feedbackEnabled: ctx.feedback?.enabled,
17110
- onFeedback: ctx.feedback?.submit
17382
+ onFeedback: ctx.feedback?.submit,
17383
+ pendingApprovals: ctx.tools.pending.tools,
17384
+ onApproveToolCall: ctx.tools.pending.tools.length > 0 ? ctx.tools.pending.approveAll : void 0,
17385
+ onRejectToolCall: ctx.tools.pending.tools.length > 0 ? ctx.tools.pending.rejectAll : void 0
17111
17386
  };
17112
17387
  if (floating) {
17113
- return /* @__PURE__ */ jsx12(
17388
+ return /* @__PURE__ */ jsx13(
17114
17389
  UseAIFloatingChatWrapper,
17115
17390
  {
17116
17391
  isOpen: ctx.ui.isOpen,
17117
17392
  onClose: () => ctx.ui.setOpen(false),
17118
- children: /* @__PURE__ */ jsx12(
17393
+ children: /* @__PURE__ */ jsx13(
17119
17394
  UseAIChatPanel,
17120
17395
  {
17121
17396
  ...chatPanelProps,
17122
- closeButton: /* @__PURE__ */ jsx12(CloseButton, { onClick: () => ctx.ui.setOpen(false) })
17397
+ closeButton: /* @__PURE__ */ jsx13(CloseButton, { onClick: () => ctx.ui.setOpen(false) })
17123
17398
  }
17124
17399
  )
17125
17400
  }
17126
17401
  );
17127
17402
  }
17128
- return /* @__PURE__ */ jsx12(UseAIChatPanel, { ...chatPanelProps });
17403
+ return /* @__PURE__ */ jsx13(UseAIChatPanel, { ...chatPanelProps });
17129
17404
  }
17130
17405
 
17131
17406
  // ../../node_modules/.bun/engine.io-parser@5.2.3/node_modules/engine.io-parser/build/esm/commons.js
@@ -20763,7 +21038,8 @@ var UseAIClient = class {
20763
21038
  tools: this._tools.map((t) => ({
20764
21039
  name: t.name,
20765
21040
  description: t.description,
20766
- parameters: t.parameters
21041
+ parameters: t.parameters,
21042
+ annotations: t.annotations
20767
21043
  })),
20768
21044
  state: this._state,
20769
21045
  context: [],
@@ -20806,6 +21082,24 @@ var UseAIClient = class {
20806
21082
  this._messages.push(toolResultMsg);
20807
21083
  this.send(toolResultMessage);
20808
21084
  }
21085
+ /**
21086
+ * Sends a tool approval response back to the server.
21087
+ *
21088
+ * @param toolCallId - The ID of the tool call being approved/rejected
21089
+ * @param approved - Whether the tool execution is approved
21090
+ * @param reason - Optional reason for rejection (shown to AI)
21091
+ */
21092
+ sendToolApprovalResponse(toolCallId, approved, reason) {
21093
+ const message = {
21094
+ type: "tool_approval_response",
21095
+ data: {
21096
+ toolCallId,
21097
+ approved,
21098
+ reason
21099
+ }
21100
+ };
21101
+ this.send(message);
21102
+ }
20809
21103
  /**
20810
21104
  * Retrieves accumulated tool call data for a specific tool call ID.
20811
21105
  * Used to get the complete tool name and arguments after they've been streamed
@@ -35045,7 +35339,7 @@ var LocalStorageChatRepository = class {
35045
35339
  };
35046
35340
 
35047
35341
  // src/hooks/useChatManagement.ts
35048
- import { useState as useState5, useCallback as useCallback4, useRef as useRef5, useEffect as useEffect5 } from "react";
35342
+ import { useState as useState6, useCallback as useCallback4, useRef as useRef5, useEffect as useEffect5 } from "react";
35049
35343
  var CHAT_TITLE_MAX_LENGTH = 50;
35050
35344
  function deepEquals(a, b) {
35051
35345
  return JSON.stringify(a) === JSON.stringify(b);
@@ -35088,10 +35382,11 @@ function useChatManagement({
35088
35382
  onSendMessage,
35089
35383
  setOpen,
35090
35384
  connected,
35091
- loading
35385
+ loading,
35386
+ hasPendingApproval
35092
35387
  }) {
35093
- const [currentChatId, setCurrentChatId] = useState5(null);
35094
- const [pendingChatId, setPendingChatId] = useState5(null);
35388
+ const [currentChatId, setCurrentChatId] = useState6(null);
35389
+ const [pendingChatId, setPendingChatId] = useState6(null);
35095
35390
  const currentChatIdSnapshot = useRef5(null);
35096
35391
  const pendingChatIdSnapshot = useRef5(null);
35097
35392
  useEffect5(() => {
@@ -35310,6 +35605,10 @@ function useChatManagement({
35310
35605
  useEffect5(() => {
35311
35606
  loadingRef.current = loading;
35312
35607
  }, [loading]);
35608
+ const hasPendingApprovalRef = useRef5(hasPendingApproval);
35609
+ useEffect5(() => {
35610
+ hasPendingApprovalRef.current = hasPendingApproval;
35611
+ }, [hasPendingApproval]);
35313
35612
  const processMessageQueue = useCallback4(async () => {
35314
35613
  if (isProcessingQueueRef.current || pendingMessagesRef.current.length === 0 || !onSendMessage) {
35315
35614
  return;
@@ -35344,16 +35643,16 @@ function useChatManagement({
35344
35643
  setOpen(true);
35345
35644
  }
35346
35645
  await new Promise((resolve) => {
35347
- const checkLoading = () => {
35646
+ const checkReady = () => {
35348
35647
  setTimeout(() => {
35349
- if (!loadingRef.current) {
35648
+ if (!loadingRef.current && !hasPendingApprovalRef.current) {
35350
35649
  resolve();
35351
35650
  } else {
35352
- checkLoading();
35651
+ checkReady();
35353
35652
  }
35354
35653
  }, 100);
35355
35654
  };
35356
- checkLoading();
35655
+ checkReady();
35357
35656
  });
35358
35657
  }
35359
35658
  isProcessingQueueRef.current = false;
@@ -35390,7 +35689,7 @@ function useChatManagement({
35390
35689
  }
35391
35690
 
35392
35691
  // src/hooks/useAgentSelection.ts
35393
- import { useState as useState6, useCallback as useCallback5, useEffect as useEffect6, useMemo as useMemo3 } from "react";
35692
+ import { useState as useState7, useCallback as useCallback5, useEffect as useEffect6, useMemo as useMemo3 } from "react";
35394
35693
  function filterAgents(serverAgents, defaultAgentId, visibleAgentIds) {
35395
35694
  const getDefaultAgentFallback = () => {
35396
35695
  const defaultAgentInfo = serverAgents.find((a) => a.id === defaultAgentId);
@@ -35416,9 +35715,9 @@ function useAgentSelection({
35416
35715
  connected,
35417
35716
  visibleAgentIds
35418
35717
  }) {
35419
- const [serverAgents, setServerAgents] = useState6([]);
35420
- const [defaultAgent, setDefaultAgent] = useState6(null);
35421
- const [selectedAgent, setSelectedAgent] = useState6(null);
35718
+ const [serverAgents, setServerAgents] = useState7([]);
35719
+ const [defaultAgent, setDefaultAgent] = useState7(null);
35720
+ const [selectedAgent, setSelectedAgent] = useState7(null);
35422
35721
  const availableAgents = useMemo3(
35423
35722
  () => filterAgents(serverAgents, defaultAgent, visibleAgentIds),
35424
35723
  [serverAgents, defaultAgent, visibleAgentIds]
@@ -35455,7 +35754,7 @@ function useAgentSelection({
35455
35754
  }
35456
35755
 
35457
35756
  // src/hooks/useCommandManagement.ts
35458
- import { useState as useState7, useCallback as useCallback6, useRef as useRef6, useEffect as useEffect7 } from "react";
35757
+ import { useState as useState8, useCallback as useCallback6, useRef as useRef6, useEffect as useEffect7 } from "react";
35459
35758
 
35460
35759
  // src/commands/LocalStorageCommandRepository.ts
35461
35760
  var STORAGE_KEY_PREFIX2 = "use-ai:command:";
@@ -35588,7 +35887,7 @@ function useCommandManagement({
35588
35887
  const repositoryRef = useRef6(
35589
35888
  repository || new LocalStorageCommandRepository()
35590
35889
  );
35591
- const [commands, setCommands] = useState7([]);
35890
+ const [commands, setCommands] = useState8([]);
35592
35891
  const refreshCommands = useCallback6(async () => {
35593
35892
  try {
35594
35893
  const cmdList = await repositoryRef.current.listCommands();
@@ -35630,10 +35929,10 @@ function useCommandManagement({
35630
35929
  }
35631
35930
 
35632
35931
  // src/hooks/useToolRegistry.ts
35633
- import { useState as useState8, useCallback as useCallback7, useRef as useRef7, useMemo as useMemo4 } from "react";
35932
+ import { useState as useState9, useCallback as useCallback7, useRef as useRef7, useMemo as useMemo4 } from "react";
35634
35933
  function useToolRegistry() {
35635
35934
  const toolRegistryRef = useRef7(/* @__PURE__ */ new Map());
35636
- const [toolRegistryVersion, setToolRegistryVersion] = useState8(0);
35935
+ const [toolRegistryVersion, setToolRegistryVersion] = useState9(0);
35637
35936
  const toolOwnershipRef = useRef7(/* @__PURE__ */ new Map());
35638
35937
  const invisibleRef = useRef7(/* @__PURE__ */ new Set());
35639
35938
  const registerTools = useCallback7((id, tools, options) => {
@@ -35693,7 +35992,7 @@ function useToolRegistry() {
35693
35992
  }
35694
35993
 
35695
35994
  // src/hooks/usePromptState.ts
35696
- import { useState as useState9, useCallback as useCallback8, useRef as useRef8, useMemo as useMemo5, useEffect as useEffect8 } from "react";
35995
+ import { useState as useState10, useCallback as useCallback8, useRef as useRef8, useMemo as useMemo5, useEffect as useEffect8 } from "react";
35697
35996
  function usePromptState({
35698
35997
  systemPrompt,
35699
35998
  clientRef,
@@ -35702,7 +36001,7 @@ function usePromptState({
35702
36001
  const promptsRef = useRef8(/* @__PURE__ */ new Map());
35703
36002
  const suggestionsRef = useRef8(/* @__PURE__ */ new Map());
35704
36003
  const waitersRef = useRef8(/* @__PURE__ */ new Map());
35705
- const [suggestionsVersion, setSuggestionsVersion] = useState9(0);
36004
+ const [suggestionsVersion, setSuggestionsVersion] = useState10(0);
35706
36005
  const buildStateFromPrompts = useCallback8(() => {
35707
36006
  const promptParts = [];
35708
36007
  if (systemPrompt) {
@@ -35765,14 +36064,14 @@ function usePromptState({
35765
36064
  }
35766
36065
 
35767
36066
  // src/hooks/useFeedback.ts
35768
- import { useState as useState10, useEffect as useEffect9, useRef as useRef9, useCallback as useCallback9 } from "react";
36067
+ import { useState as useState11, useEffect as useEffect9, useRef as useRef9, useCallback as useCallback9 } from "react";
35769
36068
  function useFeedback({
35770
36069
  clientRef,
35771
36070
  repository,
35772
36071
  getDisplayedChatId,
35773
36072
  setMessages
35774
36073
  }) {
35775
- const [enabled, setEnabled] = useState10(false);
36074
+ const [enabled, setEnabled] = useState11(false);
35776
36075
  const enabledRef = useRef9(false);
35777
36076
  useEffect9(() => {
35778
36077
  enabledRef.current = enabled;
@@ -35826,8 +36125,120 @@ function useFeedback({
35826
36125
  };
35827
36126
  }
35828
36127
 
36128
+ // src/hooks/useToolExecution.ts
36129
+ import { useState as useState12, useCallback as useCallback10, useRef as useRef10 } from "react";
36130
+ function useToolExecution({
36131
+ clientRef,
36132
+ aggregatedToolsRef,
36133
+ toolOwnershipRef,
36134
+ promptsRef,
36135
+ isInvisible,
36136
+ getWaiter
36137
+ }) {
36138
+ const [pendingApprovals, setPendingApprovals] = useState12([]);
36139
+ const pendingApprovalToolCallsRef = useRef10(/* @__PURE__ */ new Map());
36140
+ const handleApprovalRequest = useCallback10((event) => {
36141
+ console.log("[useToolExecution] Tool approval requested:", event.toolCallName, event.toolCallId);
36142
+ setPendingApprovals((prev) => [
36143
+ ...prev,
36144
+ {
36145
+ toolCallId: event.toolCallId,
36146
+ toolCallName: event.toolCallName,
36147
+ toolCallArgs: event.toolCallArgs,
36148
+ annotations: event.annotations
36149
+ }
36150
+ ]);
36151
+ }, []);
36152
+ const executeToolCall = useCallback10(async (toolCallId, name, input) => {
36153
+ const client = clientRef.current;
36154
+ if (!client) {
36155
+ console.error("[useToolExecution] No client available for tool execution");
36156
+ return;
36157
+ }
36158
+ try {
36159
+ const ownerId = toolOwnershipRef.current.get(name);
36160
+ console.log(`[useToolExecution] Tool "${name}" owned by component:`, ownerId);
36161
+ console.log("[useToolExecution] Executing tool...");
36162
+ const result = await executeDefinedTool(aggregatedToolsRef.current, name, input);
36163
+ const isErrorResult = result && typeof result === "object" && ("error" in result || result.success === false);
36164
+ const ownerIsInvisible = ownerId ? isInvisible(ownerId) : false;
36165
+ if (ownerId && !isErrorResult && !ownerIsInvisible) {
36166
+ const waiter = getWaiter(ownerId);
36167
+ if (waiter) {
36168
+ console.log(`[useToolExecution] Waiting for prompt change from ${ownerId}...`);
36169
+ await waiter();
36170
+ console.log("[useToolExecution] Prompt change wait complete");
36171
+ }
36172
+ } else if (isErrorResult) {
36173
+ console.log("[useToolExecution] Tool returned error, skipping prompt wait");
36174
+ } else if (ownerIsInvisible) {
36175
+ console.log("[useToolExecution] Component is invisible, skipping prompt wait");
36176
+ }
36177
+ let updatedState = null;
36178
+ if (ownerId) {
36179
+ const prompt = promptsRef.current.get(ownerId);
36180
+ if (prompt) {
36181
+ updatedState = { context: prompt };
36182
+ console.log(`[useToolExecution] Updated state from ${ownerId}`);
36183
+ }
36184
+ }
36185
+ client.sendToolResponse(toolCallId, result, updatedState);
36186
+ } catch (err) {
36187
+ console.error("Tool execution error:", err);
36188
+ client.sendToolResponse(toolCallId, {
36189
+ error: err instanceof Error ? err.message : "Unknown error"
36190
+ });
36191
+ }
36192
+ }, [clientRef, aggregatedToolsRef, toolOwnershipRef, promptsRef, isInvisible, getWaiter]);
36193
+ const storePendingToolCall = useCallback10((toolCallId, name, input, toolCallData) => {
36194
+ console.log(`[useToolExecution] Storing pending tool call "${name}" for approval`);
36195
+ pendingApprovalToolCallsRef.current.set(toolCallId, { name, input, toolCallData });
36196
+ }, []);
36197
+ const executePendingToolAfterApproval = useCallback10(async (toolCallId) => {
36198
+ const pendingTool = pendingApprovalToolCallsRef.current.get(toolCallId);
36199
+ if (!pendingTool) {
36200
+ console.warn(`[useToolExecution] No pending tool found for ${toolCallId}`);
36201
+ return;
36202
+ }
36203
+ pendingApprovalToolCallsRef.current.delete(toolCallId);
36204
+ await executeToolCall(toolCallId, pendingTool.name, pendingTool.input);
36205
+ }, [executeToolCall]);
36206
+ const approveAll = useCallback10(async () => {
36207
+ if (!clientRef.current) return;
36208
+ console.log("[useToolExecution] Approving all tool calls:", pendingApprovals.length);
36209
+ const pendingTools = [...pendingApprovals];
36210
+ for (const pending of pendingTools) {
36211
+ clientRef.current.sendToolApprovalResponse(pending.toolCallId, true);
36212
+ }
36213
+ setPendingApprovals([]);
36214
+ for (const tool of pendingTools) {
36215
+ await executePendingToolAfterApproval(tool.toolCallId);
36216
+ }
36217
+ }, [clientRef, pendingApprovals, executePendingToolAfterApproval]);
36218
+ const rejectAll = useCallback10((reason) => {
36219
+ if (!clientRef.current) return;
36220
+ console.log("[useToolExecution] Rejecting all tool calls:", pendingApprovals.length, reason);
36221
+ const pendingTools = [...pendingApprovals];
36222
+ for (const pending of pendingTools) {
36223
+ clientRef.current.sendToolApprovalResponse(pending.toolCallId, false, reason);
36224
+ }
36225
+ setPendingApprovals([]);
36226
+ for (const tool of pendingTools) {
36227
+ pendingApprovalToolCallsRef.current.delete(tool.toolCallId);
36228
+ }
36229
+ }, [clientRef, pendingApprovals]);
36230
+ return {
36231
+ pendingApprovals,
36232
+ handleApprovalRequest,
36233
+ executeToolCall,
36234
+ storePendingToolCall,
36235
+ approveAll,
36236
+ rejectAll
36237
+ };
36238
+ }
36239
+
35829
36240
  // src/providers/useAIProvider.tsx
35830
- import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
36241
+ import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
35831
36242
  var __UseAIContext = createContext4(null);
35832
36243
  var hasWarnedAboutMissingProvider = false;
35833
36244
  var noOpContextValue = {
@@ -35907,24 +36318,24 @@ function UseAIProvider({
35907
36318
  const fileUploadConfig = fileUploadConfigProp === false ? void 0 : fileUploadConfigProp ?? DEFAULT_FILE_UPLOAD_CONFIG;
35908
36319
  const theme = { ...defaultTheme, ...customTheme };
35909
36320
  const strings = { ...defaultStrings, ...customStrings };
35910
- const [connected, setConnected] = useState11(false);
35911
- const [isChatOpen, setIsChatOpen] = useState11(false);
35912
- const [loading, setLoading] = useState11(false);
35913
- const [messages, setMessages] = useState11([]);
35914
- const [fileProcessingState, setFileProcessingState] = useState11(null);
35915
- const handleSetChatOpen = useCallback10((open) => {
36321
+ const [connected, setConnected] = useState13(false);
36322
+ const [isChatOpen, setIsChatOpen] = useState13(false);
36323
+ const [loading, setLoading] = useState13(false);
36324
+ const [messages, setMessages] = useState13([]);
36325
+ const [fileProcessingState, setFileProcessingState] = useState13(null);
36326
+ const handleSetChatOpen = useCallback11((open) => {
35916
36327
  setIsChatOpen(open);
35917
36328
  onOpenChange?.(open);
35918
36329
  }, [onOpenChange]);
35919
- const [streamingText, setStreamingText] = useState11("");
35920
- const streamingChatIdRef = useRef10(null);
35921
- const [executingTool, setExecutingTool] = useState11(null);
35922
- const executingToolFallbackRef = useRef10(null);
35923
- const clientRef = useRef10(null);
35924
- const repositoryRef = useRef10(
36330
+ const [streamingText, setStreamingText] = useState13("");
36331
+ const streamingChatIdRef = useRef11(null);
36332
+ const [executingTool, setExecutingTool] = useState13(null);
36333
+ const executingToolFallbackRef = useRef11(null);
36334
+ const clientRef = useRef11(null);
36335
+ const repositoryRef = useRef11(
35925
36336
  chatRepository || new LocalStorageChatRepository()
35926
36337
  );
35927
- const handleSendMessageRef = useRef10(null);
36338
+ const handleSendMessageRef = useRef11(null);
35928
36339
  const {
35929
36340
  registerTools,
35930
36341
  unregisterTools,
@@ -35946,11 +36357,19 @@ function UseAIProvider({
35946
36357
  clientRef,
35947
36358
  connected
35948
36359
  });
35949
- const stableSendMessage = useCallback10(async (message, attachments) => {
36360
+ const stableSendMessage = useCallback11(async (message, attachments) => {
35950
36361
  if (handleSendMessageRef.current) {
35951
36362
  await handleSendMessageRef.current(message, attachments);
35952
36363
  }
35953
36364
  }, []);
36365
+ const toolExecution = useToolExecution({
36366
+ clientRef,
36367
+ aggregatedToolsRef,
36368
+ toolOwnershipRef,
36369
+ promptsRef,
36370
+ isInvisible,
36371
+ getWaiter
36372
+ });
35954
36373
  const chatManagement = useChatManagement({
35955
36374
  repository: repositoryRef.current,
35956
36375
  clientRef,
@@ -35959,7 +36378,8 @@ function UseAIProvider({
35959
36378
  onSendMessage: stableSendMessage,
35960
36379
  setOpen: handleSetChatOpen,
35961
36380
  connected,
35962
- loading
36381
+ loading,
36382
+ hasPendingApproval: toolExecution.pendingApprovals.length > 0
35963
36383
  });
35964
36384
  const {
35965
36385
  currentChatId,
@@ -36029,44 +36449,20 @@ function UseAIProvider({
36029
36449
  }
36030
36450
  const name = toolCallData.name;
36031
36451
  const input = JSON.parse(toolCallData.args);
36032
- if (!aggregatedToolsRef.current[name]) {
36452
+ const tool = aggregatedToolsRef.current[name];
36453
+ if (!tool) {
36033
36454
  console.log(`[Provider] Tool "${name}" not found in useAI tools, skipping (likely a workflow tool)`);
36034
36455
  return;
36035
36456
  }
36036
- try {
36037
- const ownerId = toolOwnershipRef.current.get(name);
36038
- console.log(`[useAI] Tool "${name}" owned by component:`, ownerId);
36039
- console.log("[useAI] Executing tool...");
36040
- const result = await executeDefinedTool(aggregatedToolsRef.current, name, input);
36041
- const isErrorResult = result && typeof result === "object" && ("error" in result || result.success === false);
36042
- const ownerIsInvisible = ownerId ? isInvisible(ownerId) : false;
36043
- if (ownerId && !isErrorResult && !ownerIsInvisible) {
36044
- const waiter = getWaiter(ownerId);
36045
- if (waiter) {
36046
- console.log(`[useAI] Waiting for prompt change from ${ownerId}...`);
36047
- await waiter();
36048
- console.log("[useAI] Prompt change wait complete");
36049
- }
36050
- } else if (isErrorResult) {
36051
- console.log("[useAI] Tool returned error, skipping prompt wait");
36052
- } else if (ownerIsInvisible) {
36053
- console.log("[useAI] Component is invisible, skipping prompt wait");
36054
- }
36055
- let updatedState = null;
36056
- if (ownerId) {
36057
- const prompt = promptsRef.current.get(ownerId);
36058
- if (prompt) {
36059
- updatedState = { context: prompt };
36060
- console.log(`[useAI] Updated state from ${ownerId}`);
36061
- }
36062
- }
36063
- client.sendToolResponse(toolCallId, result, updatedState);
36064
- } catch (err) {
36065
- console.error("Tool execution error:", err);
36066
- client.sendToolResponse(toolCallId, {
36067
- error: err instanceof Error ? err.message : "Unknown error"
36068
- });
36457
+ if (tool._options?.annotations?.destructiveHint === true) {
36458
+ console.log(`[Provider] Tool "${name}" requires approval, deferring execution`);
36459
+ toolExecution.storePendingToolCall(toolCallId, name, input, toolCallData);
36460
+ return;
36069
36461
  }
36462
+ await toolExecution.executeToolCall(toolCallId, name, input);
36463
+ } else if (event.type === TOOL_APPROVAL_REQUEST) {
36464
+ const e = event;
36465
+ toolExecution.handleApprovalRequest(e);
36070
36466
  } else if (event.type === export_EventType.TEXT_MESSAGE_CONTENT) {
36071
36467
  const contentEvent = event;
36072
36468
  setStreamingText((prev) => prev + contentEvent.delta);
@@ -36106,7 +36502,7 @@ function UseAIProvider({
36106
36502
  client.setMcpHeadersProvider(mcpHeadersProvider);
36107
36503
  }
36108
36504
  }, [mcpHeadersProvider]);
36109
- const lastRegisteredToolsRef = useRef10("");
36505
+ const lastRegisteredToolsRef = useRef11("");
36110
36506
  useEffect10(() => {
36111
36507
  const client = clientRef.current;
36112
36508
  if (!client || !client.isConnected() || !hasTools) return;
@@ -36125,7 +36521,7 @@ function UseAIProvider({
36125
36521
  console.error("Failed to register tools:", err);
36126
36522
  }
36127
36523
  }, [hasTools, aggregatedTools, connected]);
36128
- const handleSendMessage = useCallback10(async (message, attachments) => {
36524
+ const handleSendMessage = useCallback11(async (message, attachments) => {
36129
36525
  if (!clientRef.current) return;
36130
36526
  setStreamingText("");
36131
36527
  const activatedChatId = activatePendingChat();
@@ -36257,7 +36653,14 @@ function UseAIProvider({
36257
36653
  isOpen: isChatOpen,
36258
36654
  setOpen: handleSetChatOpen
36259
36655
  },
36260
- executingTool: executingToolDisplay,
36656
+ tools: {
36657
+ executing: executingToolDisplay,
36658
+ pending: {
36659
+ tools: toolExecution.pendingApprovals,
36660
+ approveAll: toolExecution.approveAll,
36661
+ rejectAll: toolExecution.rejectAll
36662
+ }
36663
+ },
36261
36664
  feedback: {
36262
36665
  enabled: feedback.enabled,
36263
36666
  submit: feedback.submitFeedback
@@ -36290,21 +36693,24 @@ function UseAIProvider({
36290
36693
  onDeleteCommand: deleteCommand,
36291
36694
  executingTool: executingToolDisplay,
36292
36695
  feedbackEnabled: feedback.enabled,
36293
- onFeedback: feedback.submitFeedback
36696
+ onFeedback: feedback.submitFeedback,
36697
+ pendingApprovals: toolExecution.pendingApprovals,
36698
+ onApproveToolCall: toolExecution.pendingApprovals.length > 0 ? toolExecution.approveAll : void 0,
36699
+ onRejectToolCall: toolExecution.pendingApprovals.length > 0 ? toolExecution.rejectAll : void 0
36294
36700
  };
36295
36701
  const renderDefaultChat = () => {
36296
36702
  if (isUIDisabled) return null;
36297
- return /* @__PURE__ */ jsx13(UseAIFloatingChatWrapper, { isOpen: isChatOpen, onClose: () => handleSetChatOpen(false), children: /* @__PURE__ */ jsx13(
36703
+ return /* @__PURE__ */ jsx14(UseAIFloatingChatWrapper, { isOpen: isChatOpen, onClose: () => handleSetChatOpen(false), children: /* @__PURE__ */ jsx14(
36298
36704
  UseAIChatPanel,
36299
36705
  {
36300
36706
  ...chatPanelProps,
36301
- closeButton: /* @__PURE__ */ jsx13(CloseButton, { onClick: () => handleSetChatOpen(false) })
36707
+ closeButton: /* @__PURE__ */ jsx14(CloseButton, { onClick: () => handleSetChatOpen(false) })
36302
36708
  }
36303
36709
  ) });
36304
36710
  };
36305
36711
  const renderCustomChat = () => {
36306
36712
  if (!CustomChat) return null;
36307
- return /* @__PURE__ */ jsx13(
36713
+ return /* @__PURE__ */ jsx14(
36308
36714
  CustomChat,
36309
36715
  {
36310
36716
  isOpen: isChatOpen,
@@ -36323,8 +36729,8 @@ function UseAIProvider({
36323
36729
  };
36324
36730
  const renderBuiltInChat = () => {
36325
36731
  if (!renderChat) return null;
36326
- return /* @__PURE__ */ jsxs9(Fragment3, { children: [
36327
- ButtonComponent && /* @__PURE__ */ jsx13(
36732
+ return /* @__PURE__ */ jsxs10(Fragment3, { children: [
36733
+ ButtonComponent && /* @__PURE__ */ jsx14(
36328
36734
  ButtonComponent,
36329
36735
  {
36330
36736
  onClick: () => handleSetChatOpen(true),
@@ -36334,7 +36740,7 @@ function UseAIProvider({
36334
36740
  hasCustomChat ? renderCustomChat() : renderDefaultChat()
36335
36741
  ] });
36336
36742
  };
36337
- return /* @__PURE__ */ jsx13(ThemeContext.Provider, { value: theme, children: /* @__PURE__ */ jsx13(StringsContext.Provider, { value: strings, children: /* @__PURE__ */ jsx13(__UseAIContext.Provider, { value: value2, children: /* @__PURE__ */ jsxs9(__UseAIChatContext.Provider, { value: chatUIContextValue, children: [
36743
+ return /* @__PURE__ */ jsx14(ThemeContext.Provider, { value: theme, children: /* @__PURE__ */ jsx14(StringsContext.Provider, { value: strings, children: /* @__PURE__ */ jsx14(__UseAIContext.Provider, { value: value2, children: /* @__PURE__ */ jsxs10(__UseAIChatContext.Provider, { value: chatUIContextValue, children: [
36338
36744
  children,
36339
36745
  renderBuiltInChat()
36340
36746
  ] }) }) }) });
@@ -36354,11 +36760,11 @@ function useAIContext() {
36354
36760
  }
36355
36761
 
36356
36762
  // src/hooks/useStableTools.ts
36357
- import { useRef as useRef11 } from "react";
36763
+ import { useRef as useRef12 } from "react";
36358
36764
  function useStableTools(tools) {
36359
- const latestToolsRef = useRef11({});
36360
- const stableToolsRef = useRef11({});
36361
- const prevToolNamesRef = useRef11("");
36765
+ const latestToolsRef = useRef12({});
36766
+ const stableToolsRef = useRef12({});
36767
+ const prevToolNamesRef = useRef12("");
36362
36768
  if (!tools) {
36363
36769
  latestToolsRef.current = {};
36364
36770
  return void 0;
@@ -36428,13 +36834,13 @@ function useAI(options = {}) {
36428
36834
  const { connected, tools, client, prompts } = useAIContext();
36429
36835
  const { register: registerTools, unregister: unregisterTools } = tools;
36430
36836
  const { update: updatePrompt, registerWaiter, unregisterWaiter } = prompts;
36431
- const [response, setResponse] = useState12(null);
36432
- const [loading, setLoading] = useState12(false);
36433
- const [error48, setError] = useState12(null);
36434
- const hookId = useRef12(`useAI-${Math.random().toString(36).substr(2, 9)}`);
36435
- const toolsRef = useRef12({});
36436
- const componentRef = useRef12(null);
36437
- const promptChangeResolvers = useRef12([]);
36837
+ const [response, setResponse] = useState14(null);
36838
+ const [loading, setLoading] = useState14(false);
36839
+ const [error48, setError] = useState14(null);
36840
+ const hookId = useRef13(`useAI-${Math.random().toString(36).substr(2, 9)}`);
36841
+ const toolsRef = useRef13({});
36842
+ const componentRef = useRef13(null);
36843
+ const promptChangeResolvers = useRef13([]);
36438
36844
  const stableTools = useStableTools(options.tools);
36439
36845
  const toolsKey = useMemo6(() => {
36440
36846
  if (!options.tools) return "";
@@ -36446,7 +36852,7 @@ function useAI(options = {}) {
36446
36852
  componentRef.current.setAttribute("data-useai-context", "true");
36447
36853
  }
36448
36854
  }, []);
36449
- const waitForPromptChange = useCallback11(() => {
36855
+ const waitForPromptChange = useCallback12(() => {
36450
36856
  return new Promise((resolve) => {
36451
36857
  const timeoutMs = 100;
36452
36858
  const timeoutId = setTimeout(() => {
@@ -36478,7 +36884,7 @@ function useAI(options = {}) {
36478
36884
  promptChangeResolvers.current = [];
36479
36885
  }
36480
36886
  }, [enabled, options.prompt, memoizedSuggestions, updatePrompt]);
36481
- const updatePromptRef = useRef12(updatePrompt);
36887
+ const updatePromptRef = useRef13(updatePrompt);
36482
36888
  updatePromptRef.current = updatePrompt;
36483
36889
  useEffect11(() => {
36484
36890
  const id = hookId.current;
@@ -36509,7 +36915,7 @@ function useAI(options = {}) {
36509
36915
  unsubscribe();
36510
36916
  };
36511
36917
  }, [enabled, client]);
36512
- const handleAGUIEvent = useCallback11(async (event) => {
36918
+ const handleAGUIEvent = useCallback12(async (event) => {
36513
36919
  switch (event.type) {
36514
36920
  case export_EventType.TEXT_MESSAGE_END: {
36515
36921
  const content3 = client?.currentMessageContent;
@@ -36529,7 +36935,7 @@ function useAI(options = {}) {
36529
36935
  }
36530
36936
  }
36531
36937
  }, [client, options.onError]);
36532
- const generate = useCallback11(async (prompt) => {
36938
+ const generate = useCallback12(async (prompt) => {
36533
36939
  if (!enabled) {
36534
36940
  const error49 = new Error("AI features are disabled");
36535
36941
  setError(error49);
@@ -36565,15 +36971,15 @@ function useAI(options = {}) {
36565
36971
  }
36566
36972
 
36567
36973
  // src/useAIWorkflow.ts
36568
- import { useState as useState13, useCallback as useCallback12, useRef as useRef13, useEffect as useEffect12 } from "react";
36974
+ import { useState as useState15, useCallback as useCallback13, useRef as useRef14, useEffect as useEffect12 } from "react";
36569
36975
  function useAIWorkflow(runner, workflowId) {
36570
36976
  const { connected, client } = useAIContext();
36571
- const [status, setStatus] = useState13("idle");
36572
- const [text4, setText] = useState13(null);
36573
- const [error48, setError] = useState13(null);
36574
- const currentWorkflowRef = useRef13(null);
36575
- const eventListenerIdRef = useRef13(`useAIWorkflow-${Math.random().toString(36).substr(2, 9)}`);
36576
- const handleWorkflowEvent = useCallback12(async (event) => {
36977
+ const [status, setStatus] = useState15("idle");
36978
+ const [text4, setText] = useState15(null);
36979
+ const [error48, setError] = useState15(null);
36980
+ const currentWorkflowRef = useRef14(null);
36981
+ const eventListenerIdRef = useRef14(`useAIWorkflow-${Math.random().toString(36).substr(2, 9)}`);
36982
+ const handleWorkflowEvent = useCallback13(async (event) => {
36577
36983
  const currentWorkflow = currentWorkflowRef.current;
36578
36984
  if (!currentWorkflow) return;
36579
36985
  if (event.type === export_EventType.RUN_STARTED) {
@@ -36665,7 +37071,7 @@ function useAIWorkflow(runner, workflowId) {
36665
37071
  unsubscribe();
36666
37072
  };
36667
37073
  }, [client, handleWorkflowEvent]);
36668
- const trigger = useCallback12(async (options) => {
37074
+ const trigger = useCallback13(async (options) => {
36669
37075
  if (!client?.isConnected()) {
36670
37076
  const err = new Error("Not connected to server");
36671
37077
  setError(err);
@@ -36738,7 +37144,7 @@ export {
36738
37144
  defaultTheme,
36739
37145
  defineTool,
36740
37146
  executeDefinedTool,
36741
- findTransformer,
37147
+ findTransformerPattern,
36742
37148
  generateChatId,
36743
37149
  generateCommandId,
36744
37150
  generateMessageId,