@usecrow/ui 0.1.50 → 0.1.52
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 +188 -55
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -3
- package/dist/index.d.ts +18 -3
- package/dist/index.js +189 -56
- 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
|
}
|
|
@@ -1937,7 +1982,6 @@ function WidgetHeader({
|
|
|
1937
1982
|
onNewChat,
|
|
1938
1983
|
onToggleHistory,
|
|
1939
1984
|
showMinimize = false,
|
|
1940
|
-
isMinimized = false,
|
|
1941
1985
|
onToggleMinimize
|
|
1942
1986
|
}) {
|
|
1943
1987
|
const { agentName, styles } = useWidgetStyleContext();
|
|
@@ -1959,7 +2003,7 @@ function WidgetHeader({
|
|
|
1959
2003
|
}
|
|
1960
2004
|
) }),
|
|
1961
2005
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "crow-flex crow-items-center crow-gap-1", children: [
|
|
1962
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2006
|
+
isVerifiedUser ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1963
2007
|
"button",
|
|
1964
2008
|
{
|
|
1965
2009
|
onClick: onNewChat,
|
|
@@ -1968,6 +2012,15 @@ function WidgetHeader({
|
|
|
1968
2012
|
title: "New Chat",
|
|
1969
2013
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { size: 18, className: "crow-text-gray-700" })
|
|
1970
2014
|
}
|
|
2015
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2016
|
+
"button",
|
|
2017
|
+
{
|
|
2018
|
+
onClick: onNewChat,
|
|
2019
|
+
className: "crow-p-1.5 hover:crow-bg-gray-200 crow-rounded crow-transition-colors",
|
|
2020
|
+
"aria-label": "Restart Chat",
|
|
2021
|
+
title: "Restart Chat",
|
|
2022
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCcw, { size: 16, className: "crow-text-gray-700" })
|
|
2023
|
+
}
|
|
1971
2024
|
),
|
|
1972
2025
|
isVerifiedUser && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1973
2026
|
"button",
|
|
@@ -1983,9 +2036,10 @@ function WidgetHeader({
|
|
|
1983
2036
|
"button",
|
|
1984
2037
|
{
|
|
1985
2038
|
onClick: onToggleMinimize,
|
|
1986
|
-
className: "crow-p-1 hover:crow-bg-gray-200 crow-rounded crow-transition-colors",
|
|
1987
|
-
"aria-label":
|
|
1988
|
-
|
|
2039
|
+
className: "crow-p-1.5 hover:crow-bg-gray-200 crow-rounded crow-transition-colors",
|
|
2040
|
+
"aria-label": "Close chat",
|
|
2041
|
+
title: "Close chat",
|
|
2042
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 18, className: "crow-text-gray-700" })
|
|
1989
2043
|
}
|
|
1990
2044
|
)
|
|
1991
2045
|
] })
|
|
@@ -3348,7 +3402,8 @@ function CrowWidget({
|
|
|
3348
3402
|
persistAnonymousConversations,
|
|
3349
3403
|
welcomeMessage: welcomeMessageFromAPI,
|
|
3350
3404
|
selectedModel: selectedModelFromAPI,
|
|
3351
|
-
initialSuggestions
|
|
3405
|
+
initialSuggestions,
|
|
3406
|
+
toolConsentSettings
|
|
3352
3407
|
} = useWidgetStyles({
|
|
3353
3408
|
productId,
|
|
3354
3409
|
apiUrl,
|
|
@@ -3391,6 +3446,7 @@ function CrowWidget({
|
|
|
3391
3446
|
persistAnonymousConversations,
|
|
3392
3447
|
welcomeMessage,
|
|
3393
3448
|
selectedModel,
|
|
3449
|
+
toolConsentSettings,
|
|
3394
3450
|
onVerificationStatus: (isVerified) => {
|
|
3395
3451
|
setIsVerifiedUser(isVerified);
|
|
3396
3452
|
},
|
|
@@ -3693,14 +3749,47 @@ function CrowWidget({
|
|
|
3693
3749
|
const handleToolConsent = async (toolCallId, approved) => {
|
|
3694
3750
|
const toolCall = chat.activeToolCalls.find((tc) => tc.id === toolCallId) || chat.messages.flatMap((m) => m.toolCalls || []).find((tc) => tc.id === toolCallId);
|
|
3695
3751
|
if (!toolCall) return;
|
|
3752
|
+
const isClientSide = !toolCall.serverSideExecution;
|
|
3696
3753
|
if (approved) {
|
|
3697
3754
|
chat.updateToolCallStatus(toolCallId, "executing");
|
|
3698
|
-
if (
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3755
|
+
if (isClientSide) {
|
|
3756
|
+
try {
|
|
3757
|
+
const result = await executeClientToolRef.current?.(
|
|
3758
|
+
toolCall.name,
|
|
3759
|
+
toolCall.arguments || {}
|
|
3760
|
+
);
|
|
3761
|
+
const resultObj = result;
|
|
3762
|
+
const dataObj = resultObj?.data;
|
|
3763
|
+
const wasUserCancelled = dataObj?.declined === true || typeof resultObj?.error === "string" && resultObj.error.includes("cancelled by user") || typeof resultObj?.error === "string" && resultObj.error.includes("declined");
|
|
3764
|
+
if (wasUserCancelled) {
|
|
3765
|
+
console.log("[Crow Widget] Tool was cancelled by user after consent");
|
|
3766
|
+
return;
|
|
3767
|
+
}
|
|
3768
|
+
if (result && submitToolResultRef.current) {
|
|
3769
|
+
await submitToolResultRef.current(
|
|
3770
|
+
toolCallId,
|
|
3771
|
+
toolCall.name,
|
|
3772
|
+
result
|
|
3773
|
+
);
|
|
3774
|
+
}
|
|
3775
|
+
} catch (e) {
|
|
3776
|
+
console.error("[Crow Widget] Tool error after consent:", e);
|
|
3777
|
+
if (submitToolResultRef.current) {
|
|
3778
|
+
await submitToolResultRef.current(
|
|
3779
|
+
toolCallId,
|
|
3780
|
+
toolCall.name,
|
|
3781
|
+
{ success: false, error: String(e) }
|
|
3782
|
+
);
|
|
3783
|
+
}
|
|
3784
|
+
}
|
|
3785
|
+
} else {
|
|
3786
|
+
if (submitToolResultRef.current) {
|
|
3787
|
+
await submitToolResultRef.current(
|
|
3788
|
+
toolCallId,
|
|
3789
|
+
toolCall.name,
|
|
3790
|
+
{ consent_approved: true, tool_arguments: toolCall.arguments || {} }
|
|
3791
|
+
);
|
|
3792
|
+
}
|
|
3704
3793
|
}
|
|
3705
3794
|
} else {
|
|
3706
3795
|
chat.updateToolCallStatus(toolCallId, "denied");
|
|
@@ -3748,7 +3837,9 @@ function CrowWidget({
|
|
|
3748
3837
|
isVerifiedUser,
|
|
3749
3838
|
showConversationList,
|
|
3750
3839
|
onNewChat: handleNewChat,
|
|
3751
|
-
onToggleHistory: handleToggleHistory
|
|
3840
|
+
onToggleHistory: handleToggleHistory,
|
|
3841
|
+
showMinimize: variant === "floating",
|
|
3842
|
+
onToggleMinimize: () => setIsCollapsed(true)
|
|
3752
3843
|
}
|
|
3753
3844
|
),
|
|
3754
3845
|
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: showConversationList && isVerifiedUser && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -4129,7 +4220,8 @@ function CrowCopilot({
|
|
|
4129
4220
|
pageNavigationRoutes,
|
|
4130
4221
|
persistAnonymousConversations,
|
|
4131
4222
|
welcomeMessage: welcomeMessageFromAPI,
|
|
4132
|
-
selectedModel
|
|
4223
|
+
selectedModel,
|
|
4224
|
+
toolConsentSettings
|
|
4133
4225
|
} = useCopilotStyles({
|
|
4134
4226
|
productId,
|
|
4135
4227
|
apiUrl,
|
|
@@ -4320,6 +4412,7 @@ function CrowCopilot({
|
|
|
4320
4412
|
persistAnonymousConversations,
|
|
4321
4413
|
welcomeMessage,
|
|
4322
4414
|
selectedModel,
|
|
4415
|
+
toolConsentSettings,
|
|
4323
4416
|
onVerificationStatus: (isVerified) => {
|
|
4324
4417
|
setIsVerifiedUser(isVerified);
|
|
4325
4418
|
},
|
|
@@ -4518,14 +4611,54 @@ function CrowCopilot({
|
|
|
4518
4611
|
const handleToolConsent = async (toolCallId, approved) => {
|
|
4519
4612
|
const toolCall = chat.activeToolCalls.find((tc) => tc.id === toolCallId) || chat.messages.flatMap((m) => m.toolCalls || []).find((tc) => tc.id === toolCallId);
|
|
4520
4613
|
if (!toolCall) return;
|
|
4614
|
+
const isClientSide = !toolCall.serverSideExecution;
|
|
4521
4615
|
if (approved) {
|
|
4522
4616
|
chat.updateToolCallStatus(toolCallId, "executing");
|
|
4523
|
-
if (
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
4617
|
+
if (isClientSide) {
|
|
4618
|
+
try {
|
|
4619
|
+
const result = await executeClientToolRef.current?.(
|
|
4620
|
+
toolCall.name,
|
|
4621
|
+
toolCall.arguments || {}
|
|
4622
|
+
);
|
|
4623
|
+
const resultObj = result;
|
|
4624
|
+
const dataObj = resultObj?.data;
|
|
4625
|
+
const wasUserCancelled = dataObj?.declined === true || typeof resultObj?.error === "string" && resultObj.error.includes("cancelled by user") || typeof resultObj?.error === "string" && resultObj.error.includes("declined");
|
|
4626
|
+
if (wasUserCancelled) {
|
|
4627
|
+
console.log("[Crow Copilot] Tool was cancelled by user after consent");
|
|
4628
|
+
if (submitToolResultRef.current) {
|
|
4629
|
+
await submitToolResultRef.current(
|
|
4630
|
+
toolCallId,
|
|
4631
|
+
toolCall.name,
|
|
4632
|
+
{ success: false, cancelled: true, error: "Action was cancelled by the user." }
|
|
4633
|
+
);
|
|
4634
|
+
}
|
|
4635
|
+
return;
|
|
4636
|
+
}
|
|
4637
|
+
if (result && submitToolResultRef.current) {
|
|
4638
|
+
await submitToolResultRef.current(
|
|
4639
|
+
toolCallId,
|
|
4640
|
+
toolCall.name,
|
|
4641
|
+
result
|
|
4642
|
+
);
|
|
4643
|
+
}
|
|
4644
|
+
} catch (e) {
|
|
4645
|
+
console.error("[Crow Copilot] Tool error after consent:", e);
|
|
4646
|
+
if (submitToolResultRef.current) {
|
|
4647
|
+
await submitToolResultRef.current(
|
|
4648
|
+
toolCallId,
|
|
4649
|
+
toolCall.name,
|
|
4650
|
+
{ success: false, error: String(e) }
|
|
4651
|
+
);
|
|
4652
|
+
}
|
|
4653
|
+
}
|
|
4654
|
+
} else {
|
|
4655
|
+
if (submitToolResultRef.current) {
|
|
4656
|
+
await submitToolResultRef.current(
|
|
4657
|
+
toolCallId,
|
|
4658
|
+
toolCall.name,
|
|
4659
|
+
{ consent_approved: true, tool_arguments: toolCall.arguments || {} }
|
|
4660
|
+
);
|
|
4661
|
+
}
|
|
4529
4662
|
}
|
|
4530
4663
|
} else {
|
|
4531
4664
|
chat.updateToolCallStatus(toolCallId, "denied");
|