@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.cjs
CHANGED
|
@@ -70,6 +70,7 @@ function useChat({
|
|
|
70
70
|
persistAnonymousConversations,
|
|
71
71
|
welcomeMessage,
|
|
72
72
|
selectedModel: initialSelectedModel,
|
|
73
|
+
toolConsentSettings,
|
|
73
74
|
onVerificationStatus,
|
|
74
75
|
onConversationId,
|
|
75
76
|
onWorkflowEvent,
|
|
@@ -94,6 +95,8 @@ function useChat({
|
|
|
94
95
|
const abortControllerRef = React3.useRef(null);
|
|
95
96
|
const hasCheckedPersistRef = React3.useRef(false);
|
|
96
97
|
const streamingToolCallsRef = React3.useRef([]);
|
|
98
|
+
const toolConsentSettingsRef = React3.useRef(toolConsentSettings);
|
|
99
|
+
toolConsentSettingsRef.current = toolConsentSettings;
|
|
97
100
|
React3.useEffect(() => {
|
|
98
101
|
if (initialSelectedModel) {
|
|
99
102
|
setSelectedModel((prev) => prev !== initialSelectedModel ? initialSelectedModel : prev);
|
|
@@ -345,26 +348,43 @@ function useChat({
|
|
|
345
348
|
}
|
|
346
349
|
break;
|
|
347
350
|
case "client_tool_call":
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
351
|
+
{
|
|
352
|
+
const needsConsent = toolConsentSettingsRef.current?.[parsed.tool_name]?.requires_consent === true;
|
|
353
|
+
onToolCall?.({
|
|
354
|
+
type: "start",
|
|
355
|
+
toolName: parsed.tool_name,
|
|
356
|
+
arguments: parsed.arguments
|
|
357
|
+
});
|
|
358
|
+
if (needsConsent) {
|
|
359
|
+
const consentClientTc = {
|
|
360
|
+
id: parsed.tool_call_id || `tool-${Date.now()}`,
|
|
361
|
+
name: parsed.tool_name,
|
|
362
|
+
displayName: parsed.display_name || void 0,
|
|
363
|
+
arguments: parsed.arguments || {},
|
|
364
|
+
status: "awaiting_consent",
|
|
365
|
+
requiresConsent: true,
|
|
366
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
367
|
+
};
|
|
368
|
+
streamingToolCallsRef.current = [...streamingToolCallsRef.current, consentClientTc];
|
|
369
|
+
setActiveToolCalls((prev) => [...prev, consentClientTc]);
|
|
370
|
+
} else {
|
|
371
|
+
const clientToolCall = {
|
|
372
|
+
id: parsed.tool_call_id || `tool-${Date.now()}`,
|
|
373
|
+
name: parsed.tool_name,
|
|
374
|
+
displayName: parsed.display_name || void 0,
|
|
375
|
+
arguments: parsed.arguments || {},
|
|
376
|
+
status: "executing",
|
|
377
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
378
|
+
};
|
|
379
|
+
streamingToolCallsRef.current = [...streamingToolCallsRef.current, clientToolCall];
|
|
380
|
+
setActiveToolCalls((prev) => [...prev, clientToolCall]);
|
|
381
|
+
pendingClientTools.push({
|
|
382
|
+
toolName: parsed.tool_name,
|
|
383
|
+
toolCallId: parsed.tool_call_id,
|
|
384
|
+
arguments: parsed.arguments
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
}
|
|
368
388
|
break;
|
|
369
389
|
case "tool_consent_required":
|
|
370
390
|
onToolCall?.({
|
|
@@ -746,21 +766,36 @@ function useChat({
|
|
|
746
766
|
break;
|
|
747
767
|
case "client_tool_call":
|
|
748
768
|
{
|
|
749
|
-
const
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
769
|
+
const needsConsent2 = toolConsentSettingsRef.current?.[parsed.tool_name]?.requires_consent === true;
|
|
770
|
+
if (needsConsent2) {
|
|
771
|
+
const consentEntry2 = {
|
|
772
|
+
id: parsed.tool_call_id || `tool-${Date.now()}`,
|
|
773
|
+
name: parsed.tool_name,
|
|
774
|
+
displayName: parsed.display_name || void 0,
|
|
775
|
+
arguments: parsed.arguments || {},
|
|
776
|
+
status: "awaiting_consent",
|
|
777
|
+
requiresConsent: true,
|
|
778
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
779
|
+
};
|
|
780
|
+
streamingToolCallsRef.current = [...streamingToolCallsRef.current, consentEntry2];
|
|
781
|
+
setActiveToolCalls((prev) => [...prev, consentEntry2]);
|
|
782
|
+
} else {
|
|
783
|
+
const toolCallEntry = {
|
|
784
|
+
id: parsed.tool_call_id || `tool-${Date.now()}`,
|
|
785
|
+
name: parsed.tool_name,
|
|
786
|
+
displayName: parsed.display_name || void 0,
|
|
787
|
+
arguments: parsed.arguments || {},
|
|
788
|
+
status: "executing",
|
|
789
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
790
|
+
};
|
|
791
|
+
streamingToolCallsRef.current = [...streamingToolCallsRef.current, toolCallEntry];
|
|
792
|
+
setActiveToolCalls((prev) => [...prev, toolCallEntry]);
|
|
793
|
+
pendingClientTools.push({
|
|
794
|
+
toolName: parsed.tool_name,
|
|
795
|
+
toolCallId: parsed.tool_call_id,
|
|
796
|
+
arguments: parsed.arguments
|
|
797
|
+
});
|
|
798
|
+
}
|
|
764
799
|
}
|
|
765
800
|
break;
|
|
766
801
|
case "tool_consent_required":
|
|
@@ -1527,6 +1562,9 @@ function useWidgetStyles({
|
|
|
1527
1562
|
const [initialSuggestions, setInitialSuggestions] = React3.useState(
|
|
1528
1563
|
styleCache.get(key)?.initialSuggestions || []
|
|
1529
1564
|
);
|
|
1565
|
+
const [toolConsentSettings, setToolConsentSettings] = React3.useState(
|
|
1566
|
+
styleCache.get(key)?.toolConsentSettings || {}
|
|
1567
|
+
);
|
|
1530
1568
|
const [agentName, setAgentName] = React3.useState(
|
|
1531
1569
|
styleCache.get(key)?.agentName || "Assistant"
|
|
1532
1570
|
);
|
|
@@ -1567,6 +1605,7 @@ function useWidgetStyles({
|
|
|
1567
1605
|
setWelcomeMessage(config.welcomeMessage ?? void 0);
|
|
1568
1606
|
setSelectedModel(config.model ?? void 0);
|
|
1569
1607
|
setInitialSuggestions(config.initialSuggestions || []);
|
|
1608
|
+
setToolConsentSettings(config.toolConsentSettings || {});
|
|
1570
1609
|
} catch (err) {
|
|
1571
1610
|
console.error("[CrowWidget] Failed to fetch styles:", err);
|
|
1572
1611
|
setError(err instanceof Error ? err : new Error(String(err)));
|
|
@@ -1605,6 +1644,7 @@ function useWidgetStyles({
|
|
|
1605
1644
|
welcomeMessage,
|
|
1606
1645
|
selectedModel,
|
|
1607
1646
|
initialSuggestions,
|
|
1647
|
+
toolConsentSettings,
|
|
1608
1648
|
refetch: fetchStyles
|
|
1609
1649
|
};
|
|
1610
1650
|
}
|
|
@@ -1640,6 +1680,9 @@ function useCopilotStyles({
|
|
|
1640
1680
|
const [selectedModel, setSelectedModel] = React3.useState(
|
|
1641
1681
|
styleCache.get(key)?.model ?? void 0
|
|
1642
1682
|
);
|
|
1683
|
+
const [toolConsentSettings, setToolConsentSettings] = React3.useState(
|
|
1684
|
+
styleCache.get(key)?.toolConsentSettings || {}
|
|
1685
|
+
);
|
|
1643
1686
|
const hasFetchedRef = React3.useRef(false);
|
|
1644
1687
|
const fetchStyles = async () => {
|
|
1645
1688
|
if (skip) return;
|
|
@@ -1656,6 +1699,7 @@ function useCopilotStyles({
|
|
|
1656
1699
|
setPersistAnonymousConversations(config.persistAnonymousConversations ?? true);
|
|
1657
1700
|
setWelcomeMessage(config.welcomeMessage ?? void 0);
|
|
1658
1701
|
setSelectedModel(config.model ?? void 0);
|
|
1702
|
+
setToolConsentSettings(config.toolConsentSettings || {});
|
|
1659
1703
|
} catch (err) {
|
|
1660
1704
|
console.error("[CrowCopilot] Failed to fetch styles:", err);
|
|
1661
1705
|
setError(err instanceof Error ? err : new Error(String(err)));
|
|
@@ -1693,6 +1737,7 @@ function useCopilotStyles({
|
|
|
1693
1737
|
persistAnonymousConversations,
|
|
1694
1738
|
welcomeMessage,
|
|
1695
1739
|
selectedModel,
|
|
1740
|
+
toolConsentSettings,
|
|
1696
1741
|
refetch: fetchStyles
|
|
1697
1742
|
};
|
|
1698
1743
|
}
|
|
@@ -3348,7 +3393,8 @@ function CrowWidget({
|
|
|
3348
3393
|
persistAnonymousConversations,
|
|
3349
3394
|
welcomeMessage: welcomeMessageFromAPI,
|
|
3350
3395
|
selectedModel: selectedModelFromAPI,
|
|
3351
|
-
initialSuggestions
|
|
3396
|
+
initialSuggestions,
|
|
3397
|
+
toolConsentSettings
|
|
3352
3398
|
} = useWidgetStyles({
|
|
3353
3399
|
productId,
|
|
3354
3400
|
apiUrl,
|
|
@@ -3391,6 +3437,7 @@ function CrowWidget({
|
|
|
3391
3437
|
persistAnonymousConversations,
|
|
3392
3438
|
welcomeMessage,
|
|
3393
3439
|
selectedModel,
|
|
3440
|
+
toolConsentSettings,
|
|
3394
3441
|
onVerificationStatus: (isVerified) => {
|
|
3395
3442
|
setIsVerifiedUser(isVerified);
|
|
3396
3443
|
},
|
|
@@ -3693,14 +3740,47 @@ function CrowWidget({
|
|
|
3693
3740
|
const handleToolConsent = async (toolCallId, approved) => {
|
|
3694
3741
|
const toolCall = chat.activeToolCalls.find((tc) => tc.id === toolCallId) || chat.messages.flatMap((m) => m.toolCalls || []).find((tc) => tc.id === toolCallId);
|
|
3695
3742
|
if (!toolCall) return;
|
|
3743
|
+
const isClientSide = !toolCall.serverSideExecution;
|
|
3696
3744
|
if (approved) {
|
|
3697
3745
|
chat.updateToolCallStatus(toolCallId, "executing");
|
|
3698
|
-
if (
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3746
|
+
if (isClientSide) {
|
|
3747
|
+
try {
|
|
3748
|
+
const result = await executeClientToolRef.current?.(
|
|
3749
|
+
toolCall.name,
|
|
3750
|
+
toolCall.arguments || {}
|
|
3751
|
+
);
|
|
3752
|
+
const resultObj = result;
|
|
3753
|
+
const dataObj = resultObj?.data;
|
|
3754
|
+
const wasUserCancelled = dataObj?.declined === true || typeof resultObj?.error === "string" && resultObj.error.includes("cancelled by user") || typeof resultObj?.error === "string" && resultObj.error.includes("declined");
|
|
3755
|
+
if (wasUserCancelled) {
|
|
3756
|
+
console.log("[Crow Widget] Tool was cancelled by user after consent");
|
|
3757
|
+
return;
|
|
3758
|
+
}
|
|
3759
|
+
if (result && submitToolResultRef.current) {
|
|
3760
|
+
await submitToolResultRef.current(
|
|
3761
|
+
toolCallId,
|
|
3762
|
+
toolCall.name,
|
|
3763
|
+
result
|
|
3764
|
+
);
|
|
3765
|
+
}
|
|
3766
|
+
} catch (e) {
|
|
3767
|
+
console.error("[Crow Widget] Tool error after consent:", e);
|
|
3768
|
+
if (submitToolResultRef.current) {
|
|
3769
|
+
await submitToolResultRef.current(
|
|
3770
|
+
toolCallId,
|
|
3771
|
+
toolCall.name,
|
|
3772
|
+
{ success: false, error: String(e) }
|
|
3773
|
+
);
|
|
3774
|
+
}
|
|
3775
|
+
}
|
|
3776
|
+
} else {
|
|
3777
|
+
if (submitToolResultRef.current) {
|
|
3778
|
+
await submitToolResultRef.current(
|
|
3779
|
+
toolCallId,
|
|
3780
|
+
toolCall.name,
|
|
3781
|
+
{ consent_approved: true, tool_arguments: toolCall.arguments || {} }
|
|
3782
|
+
);
|
|
3783
|
+
}
|
|
3704
3784
|
}
|
|
3705
3785
|
} else {
|
|
3706
3786
|
chat.updateToolCallStatus(toolCallId, "denied");
|
|
@@ -4129,7 +4209,8 @@ function CrowCopilot({
|
|
|
4129
4209
|
pageNavigationRoutes,
|
|
4130
4210
|
persistAnonymousConversations,
|
|
4131
4211
|
welcomeMessage: welcomeMessageFromAPI,
|
|
4132
|
-
selectedModel
|
|
4212
|
+
selectedModel,
|
|
4213
|
+
toolConsentSettings
|
|
4133
4214
|
} = useCopilotStyles({
|
|
4134
4215
|
productId,
|
|
4135
4216
|
apiUrl,
|
|
@@ -4320,6 +4401,7 @@ function CrowCopilot({
|
|
|
4320
4401
|
persistAnonymousConversations,
|
|
4321
4402
|
welcomeMessage,
|
|
4322
4403
|
selectedModel,
|
|
4404
|
+
toolConsentSettings,
|
|
4323
4405
|
onVerificationStatus: (isVerified) => {
|
|
4324
4406
|
setIsVerifiedUser(isVerified);
|
|
4325
4407
|
},
|
|
@@ -4518,14 +4600,54 @@ function CrowCopilot({
|
|
|
4518
4600
|
const handleToolConsent = async (toolCallId, approved) => {
|
|
4519
4601
|
const toolCall = chat.activeToolCalls.find((tc) => tc.id === toolCallId) || chat.messages.flatMap((m) => m.toolCalls || []).find((tc) => tc.id === toolCallId);
|
|
4520
4602
|
if (!toolCall) return;
|
|
4603
|
+
const isClientSide = !toolCall.serverSideExecution;
|
|
4521
4604
|
if (approved) {
|
|
4522
4605
|
chat.updateToolCallStatus(toolCallId, "executing");
|
|
4523
|
-
if (
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
4606
|
+
if (isClientSide) {
|
|
4607
|
+
try {
|
|
4608
|
+
const result = await executeClientToolRef.current?.(
|
|
4609
|
+
toolCall.name,
|
|
4610
|
+
toolCall.arguments || {}
|
|
4611
|
+
);
|
|
4612
|
+
const resultObj = result;
|
|
4613
|
+
const dataObj = resultObj?.data;
|
|
4614
|
+
const wasUserCancelled = dataObj?.declined === true || typeof resultObj?.error === "string" && resultObj.error.includes("cancelled by user") || typeof resultObj?.error === "string" && resultObj.error.includes("declined");
|
|
4615
|
+
if (wasUserCancelled) {
|
|
4616
|
+
console.log("[Crow Copilot] Tool was cancelled by user after consent");
|
|
4617
|
+
if (submitToolResultRef.current) {
|
|
4618
|
+
await submitToolResultRef.current(
|
|
4619
|
+
toolCallId,
|
|
4620
|
+
toolCall.name,
|
|
4621
|
+
{ success: false, cancelled: true, error: "Action was cancelled by the user." }
|
|
4622
|
+
);
|
|
4623
|
+
}
|
|
4624
|
+
return;
|
|
4625
|
+
}
|
|
4626
|
+
if (result && submitToolResultRef.current) {
|
|
4627
|
+
await submitToolResultRef.current(
|
|
4628
|
+
toolCallId,
|
|
4629
|
+
toolCall.name,
|
|
4630
|
+
result
|
|
4631
|
+
);
|
|
4632
|
+
}
|
|
4633
|
+
} catch (e) {
|
|
4634
|
+
console.error("[Crow Copilot] Tool error after consent:", e);
|
|
4635
|
+
if (submitToolResultRef.current) {
|
|
4636
|
+
await submitToolResultRef.current(
|
|
4637
|
+
toolCallId,
|
|
4638
|
+
toolCall.name,
|
|
4639
|
+
{ success: false, error: String(e) }
|
|
4640
|
+
);
|
|
4641
|
+
}
|
|
4642
|
+
}
|
|
4643
|
+
} else {
|
|
4644
|
+
if (submitToolResultRef.current) {
|
|
4645
|
+
await submitToolResultRef.current(
|
|
4646
|
+
toolCallId,
|
|
4647
|
+
toolCall.name,
|
|
4648
|
+
{ consent_approved: true, tool_arguments: toolCall.arguments || {} }
|
|
4649
|
+
);
|
|
4650
|
+
}
|
|
4529
4651
|
}
|
|
4530
4652
|
} else {
|
|
4531
4653
|
chat.updateToolCallStatus(toolCallId, "denied");
|