@usecrow/ui 0.1.50 → 0.1.51
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/index.cjs +171 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -1
- package/dist/index.d.ts +17 -1
- package/dist/index.js +171 -49
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -201,6 +201,10 @@ interface WidgetConfigResponse {
|
|
|
201
201
|
label: string;
|
|
202
202
|
message: string;
|
|
203
203
|
}>;
|
|
204
|
+
/** Per-tool consent settings from dashboard (shield icon) */
|
|
205
|
+
toolConsentSettings?: Record<string, {
|
|
206
|
+
requires_consent: boolean;
|
|
207
|
+
}>;
|
|
204
208
|
}
|
|
205
209
|
|
|
206
210
|
/**
|
|
@@ -649,6 +653,10 @@ interface UseChatOptions {
|
|
|
649
653
|
welcomeMessage?: string;
|
|
650
654
|
/** AI model to use for this chat (defaults to DEFAULT_MODEL) */
|
|
651
655
|
selectedModel?: string;
|
|
656
|
+
/** Per-tool consent settings — when a tool has requires_consent, show Allow/Deny before executing */
|
|
657
|
+
toolConsentSettings?: Record<string, {
|
|
658
|
+
requires_consent: boolean;
|
|
659
|
+
}>;
|
|
652
660
|
onVerificationStatus?: (isVerified: boolean) => void;
|
|
653
661
|
onConversationId?: (id: string) => void;
|
|
654
662
|
onWorkflowEvent?: (event: WorkflowEvent) => void;
|
|
@@ -656,7 +664,7 @@ interface UseChatOptions {
|
|
|
656
664
|
onToolResult?: (toolName: string, result: Record<string, unknown>) => void;
|
|
657
665
|
onRestoredConversation?: (conversationId: string) => void;
|
|
658
666
|
}
|
|
659
|
-
declare function useChat({ productId, apiUrl, persistAnonymousConversations, welcomeMessage, selectedModel: initialSelectedModel, onVerificationStatus, onConversationId, onWorkflowEvent, onToolCall, onToolResult, onRestoredConversation, }: UseChatOptions): {
|
|
667
|
+
declare function useChat({ productId, apiUrl, persistAnonymousConversations, welcomeMessage, selectedModel: initialSelectedModel, toolConsentSettings, onVerificationStatus, onConversationId, onWorkflowEvent, onToolCall, onToolResult, onRestoredConversation, }: UseChatOptions): {
|
|
660
668
|
messages: Message[];
|
|
661
669
|
isLoading: boolean;
|
|
662
670
|
activeToolCalls: ToolCall[];
|
|
@@ -781,6 +789,10 @@ interface UseWidgetStylesResult {
|
|
|
781
789
|
label: string;
|
|
782
790
|
message: string;
|
|
783
791
|
}>;
|
|
792
|
+
/** Per-tool consent settings from dashboard */
|
|
793
|
+
toolConsentSettings: Record<string, {
|
|
794
|
+
requires_consent: boolean;
|
|
795
|
+
}>;
|
|
784
796
|
/** Refetch styles from API */
|
|
785
797
|
refetch: () => Promise<void>;
|
|
786
798
|
}
|
|
@@ -822,6 +834,10 @@ interface UseCopilotStylesResult {
|
|
|
822
834
|
welcomeMessage: string | undefined;
|
|
823
835
|
/** AI model configured for this product */
|
|
824
836
|
selectedModel: string | undefined;
|
|
837
|
+
/** Per-tool consent settings from dashboard */
|
|
838
|
+
toolConsentSettings: Record<string, {
|
|
839
|
+
requires_consent: boolean;
|
|
840
|
+
}>;
|
|
825
841
|
/** Refetch styles from API */
|
|
826
842
|
refetch: () => Promise<void>;
|
|
827
843
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -201,6 +201,10 @@ interface WidgetConfigResponse {
|
|
|
201
201
|
label: string;
|
|
202
202
|
message: string;
|
|
203
203
|
}>;
|
|
204
|
+
/** Per-tool consent settings from dashboard (shield icon) */
|
|
205
|
+
toolConsentSettings?: Record<string, {
|
|
206
|
+
requires_consent: boolean;
|
|
207
|
+
}>;
|
|
204
208
|
}
|
|
205
209
|
|
|
206
210
|
/**
|
|
@@ -649,6 +653,10 @@ interface UseChatOptions {
|
|
|
649
653
|
welcomeMessage?: string;
|
|
650
654
|
/** AI model to use for this chat (defaults to DEFAULT_MODEL) */
|
|
651
655
|
selectedModel?: string;
|
|
656
|
+
/** Per-tool consent settings — when a tool has requires_consent, show Allow/Deny before executing */
|
|
657
|
+
toolConsentSettings?: Record<string, {
|
|
658
|
+
requires_consent: boolean;
|
|
659
|
+
}>;
|
|
652
660
|
onVerificationStatus?: (isVerified: boolean) => void;
|
|
653
661
|
onConversationId?: (id: string) => void;
|
|
654
662
|
onWorkflowEvent?: (event: WorkflowEvent) => void;
|
|
@@ -656,7 +664,7 @@ interface UseChatOptions {
|
|
|
656
664
|
onToolResult?: (toolName: string, result: Record<string, unknown>) => void;
|
|
657
665
|
onRestoredConversation?: (conversationId: string) => void;
|
|
658
666
|
}
|
|
659
|
-
declare function useChat({ productId, apiUrl, persistAnonymousConversations, welcomeMessage, selectedModel: initialSelectedModel, onVerificationStatus, onConversationId, onWorkflowEvent, onToolCall, onToolResult, onRestoredConversation, }: UseChatOptions): {
|
|
667
|
+
declare function useChat({ productId, apiUrl, persistAnonymousConversations, welcomeMessage, selectedModel: initialSelectedModel, toolConsentSettings, onVerificationStatus, onConversationId, onWorkflowEvent, onToolCall, onToolResult, onRestoredConversation, }: UseChatOptions): {
|
|
660
668
|
messages: Message[];
|
|
661
669
|
isLoading: boolean;
|
|
662
670
|
activeToolCalls: ToolCall[];
|
|
@@ -781,6 +789,10 @@ interface UseWidgetStylesResult {
|
|
|
781
789
|
label: string;
|
|
782
790
|
message: string;
|
|
783
791
|
}>;
|
|
792
|
+
/** Per-tool consent settings from dashboard */
|
|
793
|
+
toolConsentSettings: Record<string, {
|
|
794
|
+
requires_consent: boolean;
|
|
795
|
+
}>;
|
|
784
796
|
/** Refetch styles from API */
|
|
785
797
|
refetch: () => Promise<void>;
|
|
786
798
|
}
|
|
@@ -822,6 +834,10 @@ interface UseCopilotStylesResult {
|
|
|
822
834
|
welcomeMessage: string | undefined;
|
|
823
835
|
/** AI model configured for this product */
|
|
824
836
|
selectedModel: string | undefined;
|
|
837
|
+
/** Per-tool consent settings from dashboard */
|
|
838
|
+
toolConsentSettings: Record<string, {
|
|
839
|
+
requires_consent: boolean;
|
|
840
|
+
}>;
|
|
825
841
|
/** Refetch styles from API */
|
|
826
842
|
refetch: () => Promise<void>;
|
|
827
843
|
}
|
package/dist/index.js
CHANGED
|
@@ -44,6 +44,7 @@ function useChat({
|
|
|
44
44
|
persistAnonymousConversations,
|
|
45
45
|
welcomeMessage,
|
|
46
46
|
selectedModel: initialSelectedModel,
|
|
47
|
+
toolConsentSettings,
|
|
47
48
|
onVerificationStatus,
|
|
48
49
|
onConversationId,
|
|
49
50
|
onWorkflowEvent,
|
|
@@ -68,6 +69,8 @@ function useChat({
|
|
|
68
69
|
const abortControllerRef = useRef(null);
|
|
69
70
|
const hasCheckedPersistRef = useRef(false);
|
|
70
71
|
const streamingToolCallsRef = useRef([]);
|
|
72
|
+
const toolConsentSettingsRef = useRef(toolConsentSettings);
|
|
73
|
+
toolConsentSettingsRef.current = toolConsentSettings;
|
|
71
74
|
useEffect(() => {
|
|
72
75
|
if (initialSelectedModel) {
|
|
73
76
|
setSelectedModel((prev) => prev !== initialSelectedModel ? initialSelectedModel : prev);
|
|
@@ -319,26 +322,43 @@ function useChat({
|
|
|
319
322
|
}
|
|
320
323
|
break;
|
|
321
324
|
case "client_tool_call":
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
325
|
+
{
|
|
326
|
+
const needsConsent = toolConsentSettingsRef.current?.[parsed.tool_name]?.requires_consent === true;
|
|
327
|
+
onToolCall?.({
|
|
328
|
+
type: "start",
|
|
329
|
+
toolName: parsed.tool_name,
|
|
330
|
+
arguments: parsed.arguments
|
|
331
|
+
});
|
|
332
|
+
if (needsConsent) {
|
|
333
|
+
const consentClientTc = {
|
|
334
|
+
id: parsed.tool_call_id || `tool-${Date.now()}`,
|
|
335
|
+
name: parsed.tool_name,
|
|
336
|
+
displayName: parsed.display_name || void 0,
|
|
337
|
+
arguments: parsed.arguments || {},
|
|
338
|
+
status: "awaiting_consent",
|
|
339
|
+
requiresConsent: true,
|
|
340
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
341
|
+
};
|
|
342
|
+
streamingToolCallsRef.current = [...streamingToolCallsRef.current, consentClientTc];
|
|
343
|
+
setActiveToolCalls((prev) => [...prev, consentClientTc]);
|
|
344
|
+
} else {
|
|
345
|
+
const clientToolCall = {
|
|
346
|
+
id: parsed.tool_call_id || `tool-${Date.now()}`,
|
|
347
|
+
name: parsed.tool_name,
|
|
348
|
+
displayName: parsed.display_name || void 0,
|
|
349
|
+
arguments: parsed.arguments || {},
|
|
350
|
+
status: "executing",
|
|
351
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
352
|
+
};
|
|
353
|
+
streamingToolCallsRef.current = [...streamingToolCallsRef.current, clientToolCall];
|
|
354
|
+
setActiveToolCalls((prev) => [...prev, clientToolCall]);
|
|
355
|
+
pendingClientTools.push({
|
|
356
|
+
toolName: parsed.tool_name,
|
|
357
|
+
toolCallId: parsed.tool_call_id,
|
|
358
|
+
arguments: parsed.arguments
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
}
|
|
342
362
|
break;
|
|
343
363
|
case "tool_consent_required":
|
|
344
364
|
onToolCall?.({
|
|
@@ -720,21 +740,36 @@ function useChat({
|
|
|
720
740
|
break;
|
|
721
741
|
case "client_tool_call":
|
|
722
742
|
{
|
|
723
|
-
const
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
743
|
+
const needsConsent2 = toolConsentSettingsRef.current?.[parsed.tool_name]?.requires_consent === true;
|
|
744
|
+
if (needsConsent2) {
|
|
745
|
+
const consentEntry2 = {
|
|
746
|
+
id: parsed.tool_call_id || `tool-${Date.now()}`,
|
|
747
|
+
name: parsed.tool_name,
|
|
748
|
+
displayName: parsed.display_name || void 0,
|
|
749
|
+
arguments: parsed.arguments || {},
|
|
750
|
+
status: "awaiting_consent",
|
|
751
|
+
requiresConsent: true,
|
|
752
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
753
|
+
};
|
|
754
|
+
streamingToolCallsRef.current = [...streamingToolCallsRef.current, consentEntry2];
|
|
755
|
+
setActiveToolCalls((prev) => [...prev, consentEntry2]);
|
|
756
|
+
} else {
|
|
757
|
+
const toolCallEntry = {
|
|
758
|
+
id: parsed.tool_call_id || `tool-${Date.now()}`,
|
|
759
|
+
name: parsed.tool_name,
|
|
760
|
+
displayName: parsed.display_name || void 0,
|
|
761
|
+
arguments: parsed.arguments || {},
|
|
762
|
+
status: "executing",
|
|
763
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
764
|
+
};
|
|
765
|
+
streamingToolCallsRef.current = [...streamingToolCallsRef.current, toolCallEntry];
|
|
766
|
+
setActiveToolCalls((prev) => [...prev, toolCallEntry]);
|
|
767
|
+
pendingClientTools.push({
|
|
768
|
+
toolName: parsed.tool_name,
|
|
769
|
+
toolCallId: parsed.tool_call_id,
|
|
770
|
+
arguments: parsed.arguments
|
|
771
|
+
});
|
|
772
|
+
}
|
|
738
773
|
}
|
|
739
774
|
break;
|
|
740
775
|
case "tool_consent_required":
|
|
@@ -1501,6 +1536,9 @@ function useWidgetStyles({
|
|
|
1501
1536
|
const [initialSuggestions, setInitialSuggestions] = useState(
|
|
1502
1537
|
styleCache.get(key)?.initialSuggestions || []
|
|
1503
1538
|
);
|
|
1539
|
+
const [toolConsentSettings, setToolConsentSettings] = useState(
|
|
1540
|
+
styleCache.get(key)?.toolConsentSettings || {}
|
|
1541
|
+
);
|
|
1504
1542
|
const [agentName, setAgentName] = useState(
|
|
1505
1543
|
styleCache.get(key)?.agentName || "Assistant"
|
|
1506
1544
|
);
|
|
@@ -1541,6 +1579,7 @@ function useWidgetStyles({
|
|
|
1541
1579
|
setWelcomeMessage(config.welcomeMessage ?? void 0);
|
|
1542
1580
|
setSelectedModel(config.model ?? void 0);
|
|
1543
1581
|
setInitialSuggestions(config.initialSuggestions || []);
|
|
1582
|
+
setToolConsentSettings(config.toolConsentSettings || {});
|
|
1544
1583
|
} catch (err) {
|
|
1545
1584
|
console.error("[CrowWidget] Failed to fetch styles:", err);
|
|
1546
1585
|
setError(err instanceof Error ? err : new Error(String(err)));
|
|
@@ -1579,6 +1618,7 @@ function useWidgetStyles({
|
|
|
1579
1618
|
welcomeMessage,
|
|
1580
1619
|
selectedModel,
|
|
1581
1620
|
initialSuggestions,
|
|
1621
|
+
toolConsentSettings,
|
|
1582
1622
|
refetch: fetchStyles
|
|
1583
1623
|
};
|
|
1584
1624
|
}
|
|
@@ -1614,6 +1654,9 @@ function useCopilotStyles({
|
|
|
1614
1654
|
const [selectedModel, setSelectedModel] = useState(
|
|
1615
1655
|
styleCache.get(key)?.model ?? void 0
|
|
1616
1656
|
);
|
|
1657
|
+
const [toolConsentSettings, setToolConsentSettings] = useState(
|
|
1658
|
+
styleCache.get(key)?.toolConsentSettings || {}
|
|
1659
|
+
);
|
|
1617
1660
|
const hasFetchedRef = useRef(false);
|
|
1618
1661
|
const fetchStyles = async () => {
|
|
1619
1662
|
if (skip) return;
|
|
@@ -1630,6 +1673,7 @@ function useCopilotStyles({
|
|
|
1630
1673
|
setPersistAnonymousConversations(config.persistAnonymousConversations ?? true);
|
|
1631
1674
|
setWelcomeMessage(config.welcomeMessage ?? void 0);
|
|
1632
1675
|
setSelectedModel(config.model ?? void 0);
|
|
1676
|
+
setToolConsentSettings(config.toolConsentSettings || {});
|
|
1633
1677
|
} catch (err) {
|
|
1634
1678
|
console.error("[CrowCopilot] Failed to fetch styles:", err);
|
|
1635
1679
|
setError(err instanceof Error ? err : new Error(String(err)));
|
|
@@ -1667,6 +1711,7 @@ function useCopilotStyles({
|
|
|
1667
1711
|
persistAnonymousConversations,
|
|
1668
1712
|
welcomeMessage,
|
|
1669
1713
|
selectedModel,
|
|
1714
|
+
toolConsentSettings,
|
|
1670
1715
|
refetch: fetchStyles
|
|
1671
1716
|
};
|
|
1672
1717
|
}
|
|
@@ -3322,7 +3367,8 @@ function CrowWidget({
|
|
|
3322
3367
|
persistAnonymousConversations,
|
|
3323
3368
|
welcomeMessage: welcomeMessageFromAPI,
|
|
3324
3369
|
selectedModel: selectedModelFromAPI,
|
|
3325
|
-
initialSuggestions
|
|
3370
|
+
initialSuggestions,
|
|
3371
|
+
toolConsentSettings
|
|
3326
3372
|
} = useWidgetStyles({
|
|
3327
3373
|
productId,
|
|
3328
3374
|
apiUrl,
|
|
@@ -3365,6 +3411,7 @@ function CrowWidget({
|
|
|
3365
3411
|
persistAnonymousConversations,
|
|
3366
3412
|
welcomeMessage,
|
|
3367
3413
|
selectedModel,
|
|
3414
|
+
toolConsentSettings,
|
|
3368
3415
|
onVerificationStatus: (isVerified) => {
|
|
3369
3416
|
setIsVerifiedUser(isVerified);
|
|
3370
3417
|
},
|
|
@@ -3667,14 +3714,47 @@ function CrowWidget({
|
|
|
3667
3714
|
const handleToolConsent = async (toolCallId, approved) => {
|
|
3668
3715
|
const toolCall = chat.activeToolCalls.find((tc) => tc.id === toolCallId) || chat.messages.flatMap((m) => m.toolCalls || []).find((tc) => tc.id === toolCallId);
|
|
3669
3716
|
if (!toolCall) return;
|
|
3717
|
+
const isClientSide = !toolCall.serverSideExecution;
|
|
3670
3718
|
if (approved) {
|
|
3671
3719
|
chat.updateToolCallStatus(toolCallId, "executing");
|
|
3672
|
-
if (
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3720
|
+
if (isClientSide) {
|
|
3721
|
+
try {
|
|
3722
|
+
const result = await executeClientToolRef.current?.(
|
|
3723
|
+
toolCall.name,
|
|
3724
|
+
toolCall.arguments || {}
|
|
3725
|
+
);
|
|
3726
|
+
const resultObj = result;
|
|
3727
|
+
const dataObj = resultObj?.data;
|
|
3728
|
+
const wasUserCancelled = dataObj?.declined === true || typeof resultObj?.error === "string" && resultObj.error.includes("cancelled by user") || typeof resultObj?.error === "string" && resultObj.error.includes("declined");
|
|
3729
|
+
if (wasUserCancelled) {
|
|
3730
|
+
console.log("[Crow Widget] Tool was cancelled by user after consent");
|
|
3731
|
+
return;
|
|
3732
|
+
}
|
|
3733
|
+
if (result && submitToolResultRef.current) {
|
|
3734
|
+
await submitToolResultRef.current(
|
|
3735
|
+
toolCallId,
|
|
3736
|
+
toolCall.name,
|
|
3737
|
+
result
|
|
3738
|
+
);
|
|
3739
|
+
}
|
|
3740
|
+
} catch (e) {
|
|
3741
|
+
console.error("[Crow Widget] Tool error after consent:", e);
|
|
3742
|
+
if (submitToolResultRef.current) {
|
|
3743
|
+
await submitToolResultRef.current(
|
|
3744
|
+
toolCallId,
|
|
3745
|
+
toolCall.name,
|
|
3746
|
+
{ success: false, error: String(e) }
|
|
3747
|
+
);
|
|
3748
|
+
}
|
|
3749
|
+
}
|
|
3750
|
+
} else {
|
|
3751
|
+
if (submitToolResultRef.current) {
|
|
3752
|
+
await submitToolResultRef.current(
|
|
3753
|
+
toolCallId,
|
|
3754
|
+
toolCall.name,
|
|
3755
|
+
{ consent_approved: true, tool_arguments: toolCall.arguments || {} }
|
|
3756
|
+
);
|
|
3757
|
+
}
|
|
3678
3758
|
}
|
|
3679
3759
|
} else {
|
|
3680
3760
|
chat.updateToolCallStatus(toolCallId, "denied");
|
|
@@ -4103,7 +4183,8 @@ function CrowCopilot({
|
|
|
4103
4183
|
pageNavigationRoutes,
|
|
4104
4184
|
persistAnonymousConversations,
|
|
4105
4185
|
welcomeMessage: welcomeMessageFromAPI,
|
|
4106
|
-
selectedModel
|
|
4186
|
+
selectedModel,
|
|
4187
|
+
toolConsentSettings
|
|
4107
4188
|
} = useCopilotStyles({
|
|
4108
4189
|
productId,
|
|
4109
4190
|
apiUrl,
|
|
@@ -4294,6 +4375,7 @@ function CrowCopilot({
|
|
|
4294
4375
|
persistAnonymousConversations,
|
|
4295
4376
|
welcomeMessage,
|
|
4296
4377
|
selectedModel,
|
|
4378
|
+
toolConsentSettings,
|
|
4297
4379
|
onVerificationStatus: (isVerified) => {
|
|
4298
4380
|
setIsVerifiedUser(isVerified);
|
|
4299
4381
|
},
|
|
@@ -4492,14 +4574,54 @@ function CrowCopilot({
|
|
|
4492
4574
|
const handleToolConsent = async (toolCallId, approved) => {
|
|
4493
4575
|
const toolCall = chat.activeToolCalls.find((tc) => tc.id === toolCallId) || chat.messages.flatMap((m) => m.toolCalls || []).find((tc) => tc.id === toolCallId);
|
|
4494
4576
|
if (!toolCall) return;
|
|
4577
|
+
const isClientSide = !toolCall.serverSideExecution;
|
|
4495
4578
|
if (approved) {
|
|
4496
4579
|
chat.updateToolCallStatus(toolCallId, "executing");
|
|
4497
|
-
if (
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4580
|
+
if (isClientSide) {
|
|
4581
|
+
try {
|
|
4582
|
+
const result = await executeClientToolRef.current?.(
|
|
4583
|
+
toolCall.name,
|
|
4584
|
+
toolCall.arguments || {}
|
|
4585
|
+
);
|
|
4586
|
+
const resultObj = result;
|
|
4587
|
+
const dataObj = resultObj?.data;
|
|
4588
|
+
const wasUserCancelled = dataObj?.declined === true || typeof resultObj?.error === "string" && resultObj.error.includes("cancelled by user") || typeof resultObj?.error === "string" && resultObj.error.includes("declined");
|
|
4589
|
+
if (wasUserCancelled) {
|
|
4590
|
+
console.log("[Crow Copilot] Tool was cancelled by user after consent");
|
|
4591
|
+
if (submitToolResultRef.current) {
|
|
4592
|
+
await submitToolResultRef.current(
|
|
4593
|
+
toolCallId,
|
|
4594
|
+
toolCall.name,
|
|
4595
|
+
{ success: false, cancelled: true, error: "Action was cancelled by the user." }
|
|
4596
|
+
);
|
|
4597
|
+
}
|
|
4598
|
+
return;
|
|
4599
|
+
}
|
|
4600
|
+
if (result && submitToolResultRef.current) {
|
|
4601
|
+
await submitToolResultRef.current(
|
|
4602
|
+
toolCallId,
|
|
4603
|
+
toolCall.name,
|
|
4604
|
+
result
|
|
4605
|
+
);
|
|
4606
|
+
}
|
|
4607
|
+
} catch (e) {
|
|
4608
|
+
console.error("[Crow Copilot] Tool error after consent:", e);
|
|
4609
|
+
if (submitToolResultRef.current) {
|
|
4610
|
+
await submitToolResultRef.current(
|
|
4611
|
+
toolCallId,
|
|
4612
|
+
toolCall.name,
|
|
4613
|
+
{ success: false, error: String(e) }
|
|
4614
|
+
);
|
|
4615
|
+
}
|
|
4616
|
+
}
|
|
4617
|
+
} else {
|
|
4618
|
+
if (submitToolResultRef.current) {
|
|
4619
|
+
await submitToolResultRef.current(
|
|
4620
|
+
toolCallId,
|
|
4621
|
+
toolCall.name,
|
|
4622
|
+
{ consent_approved: true, tool_arguments: toolCall.arguments || {} }
|
|
4623
|
+
);
|
|
4624
|
+
}
|
|
4503
4625
|
}
|
|
4504
4626
|
} else {
|
|
4505
4627
|
chat.updateToolCallStatus(toolCallId, "denied");
|