@yourgpt/copilot-sdk 0.1.0 → 0.1.1

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.
@@ -5,6 +5,7 @@ import { Components } from 'react-markdown';
5
5
  import * as class_variance_authority_types from 'class-variance-authority/types';
6
6
  import { VariantProps } from 'class-variance-authority';
7
7
  import * as use_stick_to_bottom from 'use-stick-to-bottom';
8
+ import { T as ToolDefinition } from '../tools-eeJ5iEC4.cjs';
8
9
  import { ClassValue } from 'clsx';
9
10
 
10
11
  interface LoaderProps {
@@ -821,6 +822,8 @@ interface ToolExecutionData {
821
822
  approvalStatus?: ToolApprovalStatus;
822
823
  /** Message shown in approval UI */
823
824
  approvalMessage?: string;
825
+ /** Data passed from user's approval action (e.g., selected item) */
826
+ approvalData?: Record<string, unknown>;
824
827
  }
825
828
 
826
829
  /**
@@ -865,6 +868,21 @@ type ChatMessage = {
865
868
  }>;
866
869
  };
867
870
 
871
+ /**
872
+ * Approval callbacks for custom tool renderers.
873
+ * Only provided when approvalStatus is 'required'.
874
+ */
875
+ interface ToolApprovalCallbacks {
876
+ /**
877
+ * Approve execution with optional extra data.
878
+ * The extraData is passed to the tool handler via context.approvalData.
879
+ */
880
+ onApprove: (extraData?: Record<string, unknown>) => void;
881
+ /** Reject the execution with optional reason */
882
+ onReject: (reason?: string) => void;
883
+ /** Custom message from tool config */
884
+ message?: string;
885
+ }
868
886
  /**
869
887
  * Props passed to custom tool renderer components
870
888
  *
@@ -879,6 +897,19 @@ type ChatMessage = {
879
897
  * const { city, temperature } = execution.result;
880
898
  * return <div>{city}: {temperature}°</div>;
881
899
  * }
900
+ *
901
+ * // With approval callbacks for interactive tools
902
+ * function EscalationCard({ execution, approval }: ToolRendererProps) {
903
+ * if (execution.approvalStatus === 'required' && approval) {
904
+ * return (
905
+ * <SelectionCard
906
+ * onSelect={(item) => approval.onApprove({ selectedItem: item })}
907
+ * onCancel={() => approval.onReject('Cancelled')}
908
+ * />
909
+ * );
910
+ * }
911
+ * // ... other states
912
+ * }
882
913
  * ```
883
914
  */
884
915
  interface ToolRendererProps {
@@ -897,7 +928,14 @@ interface ToolRendererProps {
897
928
  error?: string;
898
929
  /** Approval status for tools requiring confirmation */
899
930
  approvalStatus?: ToolApprovalStatus;
931
+ /** Data passed from user's approval action */
932
+ approvalData?: Record<string, unknown>;
900
933
  };
934
+ /**
935
+ * Approval callbacks - only provided when approvalStatus is 'required'.
936
+ * Use these to create custom approval UIs.
937
+ */
938
+ approval?: ToolApprovalCallbacks;
901
939
  }
902
940
  /**
903
941
  * Map of tool names to their custom renderer components
@@ -979,12 +1017,21 @@ type ChatProps = {
979
1017
  followUpButtonClassName?: string;
980
1018
  /** Whether waiting for server after tool completion (shows "Continuing..." loader) */
981
1019
  isProcessing?: boolean;
1020
+ /**
1021
+ * Registered tools for accessing tool's render function.
1022
+ * Passed automatically by CopilotChat from context.
1023
+ *
1024
+ * Priority: toolRenderers > tool.render > default ToolSteps
1025
+ */
1026
+ registeredTools?: ToolDefinition[];
982
1027
  /**
983
1028
  * Custom renderers for tool results (Generative UI)
984
1029
  *
985
1030
  * Map tool names to React components that render their results.
986
1031
  * When a tool execution matches a key, the custom component is rendered
987
- * instead of the default ToolSteps display.
1032
+ * instead of tool's render function or default ToolSteps display.
1033
+ *
1034
+ * Higher priority than tool's built-in render function.
988
1035
  *
989
1036
  * @example
990
1037
  * ```tsx
@@ -997,8 +1044,13 @@ type ChatProps = {
997
1044
  * ```
998
1045
  */
999
1046
  toolRenderers?: ToolRenderers;
1000
- /** Called when user approves a tool execution */
1001
- onApproveToolExecution?: (executionId: string, permissionLevel?: PermissionLevel) => void;
1047
+ /**
1048
+ * Called when user approves a tool execution.
1049
+ * @param executionId - The tool execution ID
1050
+ * @param extraData - Optional data from user's action (e.g., selected item)
1051
+ * @param permissionLevel - Optional permission level for persistence
1052
+ */
1053
+ onApproveToolExecution?: (executionId: string, extraData?: Record<string, unknown>, permissionLevel?: PermissionLevel) => void;
1002
1054
  /** Called when user rejects a tool execution */
1003
1055
  onRejectToolExecution?: (executionId: string, reason?: string, permissionLevel?: PermissionLevel) => void;
1004
1056
  /** Custom message renderer */
@@ -1023,7 +1075,7 @@ type ChatProps = {
1023
1075
  };
1024
1076
  };
1025
1077
 
1026
- declare function Chat({ messages, onSendMessage, onStop, isLoading, placeholder, welcomeMessage, title, showHeader, onClose, showPoweredBy, showUserAvatar, userAvatar, assistantAvatar, loaderVariant, fontSize, maxFileSize, allowedFileTypes, attachmentsEnabled, attachmentsDisabledTooltip, processAttachment: processAttachmentProp, suggestions, onSuggestionClick, isProcessing, toolRenderers, onApproveToolExecution, onRejectToolExecution, showFollowUps, followUpClassName, followUpButtonClassName, renderMessage, renderInput, renderHeader, className, classNames, }: ChatProps): react_jsx_runtime.JSX.Element;
1078
+ declare function Chat({ messages, onSendMessage, onStop, isLoading, placeholder, welcomeMessage, title, showHeader, onClose, showPoweredBy, showUserAvatar, userAvatar, assistantAvatar, loaderVariant, fontSize, maxFileSize, allowedFileTypes, attachmentsEnabled, attachmentsDisabledTooltip, processAttachment: processAttachmentProp, suggestions, onSuggestionClick, isProcessing, registeredTools, toolRenderers, onApproveToolExecution, onRejectToolExecution, showFollowUps, followUpClassName, followUpButtonClassName, renderMessage, renderInput, renderHeader, className, classNames, }: ChatProps): react_jsx_runtime.JSX.Element;
1027
1079
 
1028
1080
  interface ToolExecutionMessageProps {
1029
1081
  executions: ToolExecutionData[];
@@ -1031,15 +1083,25 @@ interface ToolExecutionMessageProps {
1031
1083
  src?: string;
1032
1084
  fallback?: string;
1033
1085
  };
1034
- onApprove?: (executionId: string, permissionLevel?: PermissionLevel) => void;
1086
+ /** Called when user approves with optional extraData from custom UI */
1087
+ onApprove?: (executionId: string, extraData?: Record<string, unknown>, permissionLevel?: PermissionLevel) => void;
1035
1088
  onReject?: (executionId: string, reason?: string, permissionLevel?: PermissionLevel) => void;
1089
+ /** Custom tool renderers that can handle approval UI */
1090
+ toolRenderers?: Record<string, React$1.ComponentType<{
1091
+ execution: ToolExecutionData;
1092
+ approval?: {
1093
+ onApprove: (extraData?: Record<string, unknown>) => void;
1094
+ onReject: (reason?: string) => void;
1095
+ message?: string;
1096
+ };
1097
+ }>>;
1036
1098
  className?: string;
1037
1099
  }
1038
1100
  /**
1039
1101
  * Standalone tool execution message shown during agentic loop
1040
1102
  * Displays tool calls with status, progress, and approval UI
1041
1103
  */
1042
- declare function ToolExecutionMessage({ executions, assistantAvatar, onApprove, onReject, className, }: ToolExecutionMessageProps): react_jsx_runtime.JSX.Element | null;
1104
+ declare function ToolExecutionMessage({ executions, assistantAvatar, onApprove, onReject, toolRenderers, className, }: ToolExecutionMessageProps): react_jsx_runtime.JSX.Element | null;
1043
1105
 
1044
1106
  /**
1045
1107
  * Props for CopilotChat - auto-connects to CopilotProvider context
@@ -5,6 +5,7 @@ import { Components } from 'react-markdown';
5
5
  import * as class_variance_authority_types from 'class-variance-authority/types';
6
6
  import { VariantProps } from 'class-variance-authority';
7
7
  import * as use_stick_to_bottom from 'use-stick-to-bottom';
8
+ import { T as ToolDefinition } from '../tools-eeJ5iEC4.js';
8
9
  import { ClassValue } from 'clsx';
9
10
 
10
11
  interface LoaderProps {
@@ -821,6 +822,8 @@ interface ToolExecutionData {
821
822
  approvalStatus?: ToolApprovalStatus;
822
823
  /** Message shown in approval UI */
823
824
  approvalMessage?: string;
825
+ /** Data passed from user's approval action (e.g., selected item) */
826
+ approvalData?: Record<string, unknown>;
824
827
  }
825
828
 
826
829
  /**
@@ -865,6 +868,21 @@ type ChatMessage = {
865
868
  }>;
866
869
  };
867
870
 
871
+ /**
872
+ * Approval callbacks for custom tool renderers.
873
+ * Only provided when approvalStatus is 'required'.
874
+ */
875
+ interface ToolApprovalCallbacks {
876
+ /**
877
+ * Approve execution with optional extra data.
878
+ * The extraData is passed to the tool handler via context.approvalData.
879
+ */
880
+ onApprove: (extraData?: Record<string, unknown>) => void;
881
+ /** Reject the execution with optional reason */
882
+ onReject: (reason?: string) => void;
883
+ /** Custom message from tool config */
884
+ message?: string;
885
+ }
868
886
  /**
869
887
  * Props passed to custom tool renderer components
870
888
  *
@@ -879,6 +897,19 @@ type ChatMessage = {
879
897
  * const { city, temperature } = execution.result;
880
898
  * return <div>{city}: {temperature}°</div>;
881
899
  * }
900
+ *
901
+ * // With approval callbacks for interactive tools
902
+ * function EscalationCard({ execution, approval }: ToolRendererProps) {
903
+ * if (execution.approvalStatus === 'required' && approval) {
904
+ * return (
905
+ * <SelectionCard
906
+ * onSelect={(item) => approval.onApprove({ selectedItem: item })}
907
+ * onCancel={() => approval.onReject('Cancelled')}
908
+ * />
909
+ * );
910
+ * }
911
+ * // ... other states
912
+ * }
882
913
  * ```
883
914
  */
884
915
  interface ToolRendererProps {
@@ -897,7 +928,14 @@ interface ToolRendererProps {
897
928
  error?: string;
898
929
  /** Approval status for tools requiring confirmation */
899
930
  approvalStatus?: ToolApprovalStatus;
931
+ /** Data passed from user's approval action */
932
+ approvalData?: Record<string, unknown>;
900
933
  };
934
+ /**
935
+ * Approval callbacks - only provided when approvalStatus is 'required'.
936
+ * Use these to create custom approval UIs.
937
+ */
938
+ approval?: ToolApprovalCallbacks;
901
939
  }
902
940
  /**
903
941
  * Map of tool names to their custom renderer components
@@ -979,12 +1017,21 @@ type ChatProps = {
979
1017
  followUpButtonClassName?: string;
980
1018
  /** Whether waiting for server after tool completion (shows "Continuing..." loader) */
981
1019
  isProcessing?: boolean;
1020
+ /**
1021
+ * Registered tools for accessing tool's render function.
1022
+ * Passed automatically by CopilotChat from context.
1023
+ *
1024
+ * Priority: toolRenderers > tool.render > default ToolSteps
1025
+ */
1026
+ registeredTools?: ToolDefinition[];
982
1027
  /**
983
1028
  * Custom renderers for tool results (Generative UI)
984
1029
  *
985
1030
  * Map tool names to React components that render their results.
986
1031
  * When a tool execution matches a key, the custom component is rendered
987
- * instead of the default ToolSteps display.
1032
+ * instead of tool's render function or default ToolSteps display.
1033
+ *
1034
+ * Higher priority than tool's built-in render function.
988
1035
  *
989
1036
  * @example
990
1037
  * ```tsx
@@ -997,8 +1044,13 @@ type ChatProps = {
997
1044
  * ```
998
1045
  */
999
1046
  toolRenderers?: ToolRenderers;
1000
- /** Called when user approves a tool execution */
1001
- onApproveToolExecution?: (executionId: string, permissionLevel?: PermissionLevel) => void;
1047
+ /**
1048
+ * Called when user approves a tool execution.
1049
+ * @param executionId - The tool execution ID
1050
+ * @param extraData - Optional data from user's action (e.g., selected item)
1051
+ * @param permissionLevel - Optional permission level for persistence
1052
+ */
1053
+ onApproveToolExecution?: (executionId: string, extraData?: Record<string, unknown>, permissionLevel?: PermissionLevel) => void;
1002
1054
  /** Called when user rejects a tool execution */
1003
1055
  onRejectToolExecution?: (executionId: string, reason?: string, permissionLevel?: PermissionLevel) => void;
1004
1056
  /** Custom message renderer */
@@ -1023,7 +1075,7 @@ type ChatProps = {
1023
1075
  };
1024
1076
  };
1025
1077
 
1026
- declare function Chat({ messages, onSendMessage, onStop, isLoading, placeholder, welcomeMessage, title, showHeader, onClose, showPoweredBy, showUserAvatar, userAvatar, assistantAvatar, loaderVariant, fontSize, maxFileSize, allowedFileTypes, attachmentsEnabled, attachmentsDisabledTooltip, processAttachment: processAttachmentProp, suggestions, onSuggestionClick, isProcessing, toolRenderers, onApproveToolExecution, onRejectToolExecution, showFollowUps, followUpClassName, followUpButtonClassName, renderMessage, renderInput, renderHeader, className, classNames, }: ChatProps): react_jsx_runtime.JSX.Element;
1078
+ declare function Chat({ messages, onSendMessage, onStop, isLoading, placeholder, welcomeMessage, title, showHeader, onClose, showPoweredBy, showUserAvatar, userAvatar, assistantAvatar, loaderVariant, fontSize, maxFileSize, allowedFileTypes, attachmentsEnabled, attachmentsDisabledTooltip, processAttachment: processAttachmentProp, suggestions, onSuggestionClick, isProcessing, registeredTools, toolRenderers, onApproveToolExecution, onRejectToolExecution, showFollowUps, followUpClassName, followUpButtonClassName, renderMessage, renderInput, renderHeader, className, classNames, }: ChatProps): react_jsx_runtime.JSX.Element;
1027
1079
 
1028
1080
  interface ToolExecutionMessageProps {
1029
1081
  executions: ToolExecutionData[];
@@ -1031,15 +1083,25 @@ interface ToolExecutionMessageProps {
1031
1083
  src?: string;
1032
1084
  fallback?: string;
1033
1085
  };
1034
- onApprove?: (executionId: string, permissionLevel?: PermissionLevel) => void;
1086
+ /** Called when user approves with optional extraData from custom UI */
1087
+ onApprove?: (executionId: string, extraData?: Record<string, unknown>, permissionLevel?: PermissionLevel) => void;
1035
1088
  onReject?: (executionId: string, reason?: string, permissionLevel?: PermissionLevel) => void;
1089
+ /** Custom tool renderers that can handle approval UI */
1090
+ toolRenderers?: Record<string, React$1.ComponentType<{
1091
+ execution: ToolExecutionData;
1092
+ approval?: {
1093
+ onApprove: (extraData?: Record<string, unknown>) => void;
1094
+ onReject: (reason?: string) => void;
1095
+ message?: string;
1096
+ };
1097
+ }>>;
1036
1098
  className?: string;
1037
1099
  }
1038
1100
  /**
1039
1101
  * Standalone tool execution message shown during agentic loop
1040
1102
  * Displays tool calls with status, progress, and approval UI
1041
1103
  */
1042
- declare function ToolExecutionMessage({ executions, assistantAvatar, onApprove, onReject, className, }: ToolExecutionMessageProps): react_jsx_runtime.JSX.Element | null;
1104
+ declare function ToolExecutionMessage({ executions, assistantAvatar, onApprove, onReject, toolRenderers, className, }: ToolExecutionMessageProps): react_jsx_runtime.JSX.Element | null;
1043
1105
 
1044
1106
  /**
1045
1107
  * Props for CopilotChat - auto-connects to CopilotProvider context
package/dist/ui/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { useCopilot } from '../chunk-QUGTRQSS.js';
2
- import '../chunk-N4OA2J32.js';
1
+ import { useCopilot } from '../chunk-FO75W5UI.js';
2
+ import '../chunk-QWQELTEB.js';
3
3
  import { clsx } from 'clsx';
4
4
  import { twMerge } from 'tailwind-merge';
5
5
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
@@ -3027,6 +3027,7 @@ function DefaultMessage({
3027
3027
  size = "sm",
3028
3028
  isLastMessage = false,
3029
3029
  isLoading = false,
3030
+ registeredTools,
3030
3031
  toolRenderers,
3031
3032
  onApproveToolExecution,
3032
3033
  onRejectToolExecution,
@@ -3086,13 +3087,19 @@ function DefaultMessage({
3086
3087
  const completedTools = message.toolExecutions?.filter(
3087
3088
  (exec) => exec.approvalStatus !== "required"
3088
3089
  );
3089
- const toolsWithCustomRenderer = completedTools?.filter(
3090
- (exec) => toolRenderers && toolRenderers[exec.name]
3090
+ const hasCustomRender = (toolName) => {
3091
+ if (toolRenderers?.[toolName]) return true;
3092
+ const toolDef = registeredTools?.find((t) => t.name === toolName);
3093
+ if (toolDef?.render) return true;
3094
+ return false;
3095
+ };
3096
+ const toolsWithCustomRender = completedTools?.filter(
3097
+ (exec) => hasCustomRender(exec.name)
3091
3098
  );
3092
- const toolsWithoutCustomRenderer = completedTools?.filter(
3093
- (exec) => !toolRenderers || !toolRenderers[exec.name]
3099
+ const toolsWithoutCustomRender = completedTools?.filter(
3100
+ (exec) => !hasCustomRender(exec.name)
3094
3101
  );
3095
- const toolSteps = toolsWithoutCustomRenderer?.map((exec) => ({
3102
+ const toolSteps = toolsWithoutCustomRender?.map((exec) => ({
3096
3103
  id: exec.id,
3097
3104
  name: exec.name,
3098
3105
  args: exec.args,
@@ -3131,36 +3138,97 @@ function DefaultMessage({
3131
3138
  children: cleanContent
3132
3139
  }
3133
3140
  ),
3134
- toolsWithCustomRenderer && toolsWithCustomRenderer.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 space-y-2", children: toolsWithCustomRenderer.map((exec) => {
3135
- const Renderer = toolRenderers[exec.name];
3141
+ toolsWithCustomRender && toolsWithCustomRender.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 space-y-2", children: toolsWithCustomRender.map((exec) => {
3142
+ const Renderer = toolRenderers?.[exec.name];
3143
+ if (Renderer) {
3144
+ return /* @__PURE__ */ jsx(
3145
+ Renderer,
3146
+ {
3147
+ execution: {
3148
+ id: exec.id,
3149
+ name: exec.name,
3150
+ args: exec.args,
3151
+ status: exec.status,
3152
+ result: exec.result,
3153
+ error: exec.error,
3154
+ approvalStatus: exec.approvalStatus
3155
+ }
3156
+ },
3157
+ exec.id
3158
+ );
3159
+ }
3160
+ const toolDef = registeredTools?.find(
3161
+ (t) => t.name === exec.name
3162
+ );
3163
+ if (toolDef?.render) {
3164
+ let status = "pending";
3165
+ if (exec.status === "executing") status = "executing";
3166
+ else if (exec.status === "completed") status = "completed";
3167
+ else if (exec.status === "error" || exec.status === "failed" || exec.status === "rejected")
3168
+ status = "error";
3169
+ const renderProps = {
3170
+ status,
3171
+ args: exec.args,
3172
+ result: exec.result,
3173
+ error: exec.error,
3174
+ toolCallId: exec.id,
3175
+ toolName: exec.name
3176
+ };
3177
+ const output = toolDef.render(renderProps);
3178
+ return /* @__PURE__ */ jsx(React8.Fragment, { children: output }, exec.id);
3179
+ }
3180
+ return null;
3181
+ }) }),
3182
+ toolSteps && toolSteps.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 rounded-lg bg-muted/50 px-3 py-2", children: /* @__PURE__ */ jsx(ToolSteps, { steps: toolSteps }) }),
3183
+ pendingApprovalTools && pendingApprovalTools.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 space-y-2", children: pendingApprovalTools.map((tool) => {
3184
+ const approvalCallbacks = {
3185
+ onApprove: (extraData) => onApproveToolExecution?.(tool.id, extraData),
3186
+ onReject: (reason) => onRejectToolExecution?.(tool.id, reason),
3187
+ message: tool.approvalMessage
3188
+ };
3189
+ const CustomRenderer = toolRenderers?.[tool.name];
3190
+ if (CustomRenderer) {
3191
+ return /* @__PURE__ */ jsx(
3192
+ CustomRenderer,
3193
+ {
3194
+ execution: tool,
3195
+ approval: approvalCallbacks
3196
+ },
3197
+ tool.id
3198
+ );
3199
+ }
3200
+ const toolDef = registeredTools?.find(
3201
+ (t) => t.name === tool.name
3202
+ );
3203
+ if (toolDef?.render) {
3204
+ const renderProps = {
3205
+ status: "approval-required",
3206
+ args: tool.args,
3207
+ result: tool.result,
3208
+ error: tool.error,
3209
+ toolCallId: tool.id,
3210
+ toolName: tool.name,
3211
+ approval: approvalCallbacks
3212
+ };
3213
+ const output = toolDef.render(renderProps);
3214
+ return /* @__PURE__ */ jsx(React8.Fragment, { children: output }, tool.id);
3215
+ }
3136
3216
  return /* @__PURE__ */ jsx(
3137
- Renderer,
3217
+ PermissionConfirmation,
3138
3218
  {
3139
- execution: {
3140
- id: exec.id,
3141
- name: exec.name,
3142
- args: exec.args,
3143
- status: exec.status,
3144
- result: exec.result,
3145
- error: exec.error,
3146
- approvalStatus: exec.approvalStatus
3147
- }
3219
+ state: "pending",
3220
+ toolName: tool.name,
3221
+ message: tool.approvalMessage || `This tool wants to execute. Do you approve?`,
3222
+ onApprove: (permissionLevel) => onApproveToolExecution?.(
3223
+ tool.id,
3224
+ void 0,
3225
+ permissionLevel
3226
+ ),
3227
+ onReject: (permissionLevel) => onRejectToolExecution?.(tool.id, void 0, permissionLevel)
3148
3228
  },
3149
- exec.id
3229
+ tool.id
3150
3230
  );
3151
3231
  }) }),
3152
- toolSteps && toolSteps.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 rounded-lg bg-muted/50 px-3 py-2", children: /* @__PURE__ */ jsx(ToolSteps, { steps: toolSteps }) }),
3153
- pendingApprovalTools && pendingApprovalTools.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 space-y-2", children: pendingApprovalTools.map((tool) => /* @__PURE__ */ jsx(
3154
- PermissionConfirmation,
3155
- {
3156
- state: "pending",
3157
- toolName: tool.name,
3158
- message: tool.approvalMessage || `This tool wants to execute. Do you approve?`,
3159
- onApprove: (permissionLevel) => onApproveToolExecution?.(tool.id, permissionLevel),
3160
- onReject: (permissionLevel) => onRejectToolExecution?.(tool.id, void 0, permissionLevel)
3161
- },
3162
- tool.id
3163
- )) }),
3164
3232
  message.attachments && message.attachments.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 flex flex-wrap gap-2", children: message.attachments.map((attachment, index) => /* @__PURE__ */ jsx(AttachmentPreview, { attachment }, index)) }),
3165
3233
  shouldShowFollowUps && /* @__PURE__ */ jsx(
3166
3234
  FollowUpQuestions,
@@ -3311,6 +3379,7 @@ function Chat({
3311
3379
  onSuggestionClick,
3312
3380
  // Tool Executions
3313
3381
  isProcessing = false,
3382
+ registeredTools,
3314
3383
  toolRenderers,
3315
3384
  onApproveToolExecution,
3316
3385
  onRejectToolExecution,
@@ -3555,6 +3624,7 @@ function Chat({
3555
3624
  size: fontSize,
3556
3625
  isLastMessage,
3557
3626
  isLoading,
3627
+ registeredTools,
3558
3628
  toolRenderers,
3559
3629
  onApproveToolExecution,
3560
3630
  onRejectToolExecution,
@@ -3733,6 +3803,7 @@ function ToolExecutionMessage({
3733
3803
  assistantAvatar = { fallback: "AI" },
3734
3804
  onApprove,
3735
3805
  onReject,
3806
+ toolRenderers,
3736
3807
  className
3737
3808
  }) {
3738
3809
  if (!executions || executions.length === 0) return null;
@@ -3816,17 +3887,34 @@ function ToolExecutionMessage({
3816
3887
  ),
3817
3888
  /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-muted-foreground", children: hasExecuting ? "Running tools..." : allCompleted ? `${executions.length} tool${executions.length > 1 ? "s" : ""} completed` : "Tools" })
3818
3889
  ] }) }),
3819
- pendingApprovals.length > 0 && /* @__PURE__ */ jsx("div", { className: "mb-2 space-y-2", children: pendingApprovals.map((tool) => /* @__PURE__ */ jsx(
3820
- PermissionConfirmation,
3821
- {
3822
- state: "pending",
3823
- toolName: tool.name,
3824
- message: tool.approvalMessage || `This tool wants to execute. Do you approve?`,
3825
- onApprove: (permissionLevel) => onApprove?.(tool.id, permissionLevel),
3826
- onReject: (permissionLevel) => onReject?.(tool.id, void 0, permissionLevel)
3827
- },
3828
- tool.id
3829
- )) }),
3890
+ pendingApprovals.length > 0 && /* @__PURE__ */ jsx("div", { className: "mb-2 space-y-2", children: pendingApprovals.map((tool) => {
3891
+ const CustomRenderer = toolRenderers?.[tool.name];
3892
+ if (CustomRenderer) {
3893
+ return /* @__PURE__ */ jsx(
3894
+ CustomRenderer,
3895
+ {
3896
+ execution: tool,
3897
+ approval: {
3898
+ onApprove: (extraData) => onApprove?.(tool.id, extraData),
3899
+ onReject: (reason) => onReject?.(tool.id, reason),
3900
+ message: tool.approvalMessage
3901
+ }
3902
+ },
3903
+ tool.id
3904
+ );
3905
+ }
3906
+ return /* @__PURE__ */ jsx(
3907
+ PermissionConfirmation,
3908
+ {
3909
+ state: "pending",
3910
+ toolName: tool.name,
3911
+ message: tool.approvalMessage || `This tool wants to execute. Do you approve?`,
3912
+ onApprove: (permissionLevel) => onApprove?.(tool.id, void 0, permissionLevel),
3913
+ onReject: (permissionLevel) => onReject?.(tool.id, void 0, permissionLevel)
3914
+ },
3915
+ tool.id
3916
+ );
3917
+ }) }),
3830
3918
  toolSteps.length > 0 && /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card px-3 py-2.5 shadow-sm", children: /* @__PURE__ */ jsx(ToolSteps, { steps: toolSteps }) })
3831
3919
  ] })
3832
3920
  ] });
@@ -3839,7 +3927,8 @@ function CopilotChat(props) {
3839
3927
  stop,
3840
3928
  toolExecutions: rawToolExecutions,
3841
3929
  approveToolExecution,
3842
- rejectToolExecution
3930
+ rejectToolExecution,
3931
+ registeredTools
3843
3932
  } = useCopilot();
3844
3933
  const toolExecutions = rawToolExecutions.map(
3845
3934
  (exec) => ({
@@ -3963,7 +4052,8 @@ function CopilotChat(props) {
3963
4052
  suggestions,
3964
4053
  isProcessing: isProcessingToolResults,
3965
4054
  onApproveToolExecution: approveToolExecution,
3966
- onRejectToolExecution: rejectToolExecution
4055
+ onRejectToolExecution: rejectToolExecution,
4056
+ registeredTools
3967
4057
  }
3968
4058
  );
3969
4059
  }