@usecrow/ui 0.1.32 → 0.1.34
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 +167 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +35 -2
- package/dist/index.d.ts +35 -2
- package/dist/index.js +167 -16
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -187,6 +187,15 @@ interface WidgetConfigResponse {
|
|
|
187
187
|
welcomeMessage?: string | null;
|
|
188
188
|
/** AI model to use for this product */
|
|
189
189
|
model?: string;
|
|
190
|
+
/** Whether page navigation is enabled for this product */
|
|
191
|
+
pageNavigationEnabled?: boolean;
|
|
192
|
+
/** Route definitions for page navigation */
|
|
193
|
+
pageNavigationRoutes?: Array<{
|
|
194
|
+
name: string;
|
|
195
|
+
path: string;
|
|
196
|
+
description?: string;
|
|
197
|
+
params?: Record<string, string>;
|
|
198
|
+
}>;
|
|
190
199
|
}
|
|
191
200
|
|
|
192
201
|
/** Identity data passed to the identify function */
|
|
@@ -230,10 +239,12 @@ interface CrowWidgetProps {
|
|
|
230
239
|
onIdentify?: (identify: IdentifyFunction) => void;
|
|
231
240
|
/** Client-side tools the agent can call */
|
|
232
241
|
tools?: ToolsMap;
|
|
242
|
+
/** Custom navigation function for SPA-safe page navigation (e.g. router.push from Next.js or React Router) */
|
|
243
|
+
navigate?: (path: string) => void;
|
|
233
244
|
/** Callback fired when a server-side tool completes, with the tool name and full result data */
|
|
234
245
|
onToolResult?: (toolName: string, result: Record<string, unknown>) => void;
|
|
235
246
|
}
|
|
236
|
-
declare function CrowWidget({ productId, apiUrl, variant, styles: propStyles, previewMode, showThinking: showThinkingProp, agentName: agentNameProp, welcomeMessage: welcomeMessageProp, onReady, onIdentify, tools, onToolResult, }: CrowWidgetProps): react_jsx_runtime.JSX.Element;
|
|
247
|
+
declare function CrowWidget({ productId, apiUrl, variant, styles: propStyles, previewMode, showThinking: showThinkingProp, agentName: agentNameProp, welcomeMessage: welcomeMessageProp, onReady, onIdentify, tools, navigate, onToolResult, }: CrowWidgetProps): react_jsx_runtime.JSX.Element;
|
|
237
248
|
|
|
238
249
|
interface CrowCopilotProps {
|
|
239
250
|
/** Product ID for this copilot */
|
|
@@ -266,10 +277,12 @@ interface CrowCopilotProps {
|
|
|
266
277
|
className?: string;
|
|
267
278
|
/** Callback when copilot is ready */
|
|
268
279
|
onReady?: () => void;
|
|
280
|
+
/** Custom navigation function for SPA-safe page navigation (e.g. router.push from Next.js or React Router) */
|
|
281
|
+
navigate?: (path: string) => void;
|
|
269
282
|
/** Callback fired when a server-side tool completes, with the tool name and full result data */
|
|
270
283
|
onToolResult?: (toolName: string, result: Record<string, unknown>) => void;
|
|
271
284
|
}
|
|
272
|
-
declare function CrowCopilot({ productId, apiUrl, variant, title, agentName: agentNameProp, welcomeMessage: welcomeMessageProp, position, width, defaultOpen, showClose, onClose, styles: propStyles, previewMode, className, onReady, onToolResult, }: CrowCopilotProps): react_jsx_runtime.JSX.Element;
|
|
285
|
+
declare function CrowCopilot({ productId, apiUrl, variant, title, agentName: agentNameProp, welcomeMessage: welcomeMessageProp, position, width, defaultOpen, showClose, onClose, styles: propStyles, previewMode, className, onReady, navigate, onToolResult, }: CrowCopilotProps): react_jsx_runtime.JSX.Element;
|
|
273
286
|
|
|
274
287
|
interface CrowProviderProps extends CrowClientConfig {
|
|
275
288
|
children: React.ReactNode;
|
|
@@ -663,6 +676,15 @@ interface UseWidgetStylesResult {
|
|
|
663
676
|
agentName: string;
|
|
664
677
|
/** Whether browser_use is enabled for this product */
|
|
665
678
|
browserUseEnabled: boolean;
|
|
679
|
+
/** Whether page navigation is enabled for this product */
|
|
680
|
+
pageNavigationEnabled: boolean;
|
|
681
|
+
/** Route definitions for page navigation */
|
|
682
|
+
pageNavigationRoutes: Array<{
|
|
683
|
+
name: string;
|
|
684
|
+
path: string;
|
|
685
|
+
description?: string;
|
|
686
|
+
params?: Record<string, string>;
|
|
687
|
+
}>;
|
|
666
688
|
/** Whether to show thinking/reasoning to users */
|
|
667
689
|
showThinking: boolean;
|
|
668
690
|
/** Whether to persist anonymous conversations across page refreshes (undefined while loading) */
|
|
@@ -695,10 +717,21 @@ interface UseCopilotStylesResult {
|
|
|
695
717
|
error: Error | null;
|
|
696
718
|
/** Agent name from product config */
|
|
697
719
|
agentName: string;
|
|
720
|
+
/** Whether page navigation is enabled for this product */
|
|
721
|
+
pageNavigationEnabled: boolean;
|
|
722
|
+
/** Route definitions for page navigation */
|
|
723
|
+
pageNavigationRoutes: Array<{
|
|
724
|
+
name: string;
|
|
725
|
+
path: string;
|
|
726
|
+
description?: string;
|
|
727
|
+
params?: Record<string, string>;
|
|
728
|
+
}>;
|
|
698
729
|
/** Whether to persist anonymous conversations across page refreshes (undefined while loading) */
|
|
699
730
|
persistAnonymousConversations: boolean | undefined;
|
|
700
731
|
/** Custom welcome message (undefined uses SDK default) */
|
|
701
732
|
welcomeMessage: string | undefined;
|
|
733
|
+
/** AI model configured for this product */
|
|
734
|
+
selectedModel: string | undefined;
|
|
702
735
|
/** Refetch styles from API */
|
|
703
736
|
refetch: () => Promise<void>;
|
|
704
737
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -187,6 +187,15 @@ interface WidgetConfigResponse {
|
|
|
187
187
|
welcomeMessage?: string | null;
|
|
188
188
|
/** AI model to use for this product */
|
|
189
189
|
model?: string;
|
|
190
|
+
/** Whether page navigation is enabled for this product */
|
|
191
|
+
pageNavigationEnabled?: boolean;
|
|
192
|
+
/** Route definitions for page navigation */
|
|
193
|
+
pageNavigationRoutes?: Array<{
|
|
194
|
+
name: string;
|
|
195
|
+
path: string;
|
|
196
|
+
description?: string;
|
|
197
|
+
params?: Record<string, string>;
|
|
198
|
+
}>;
|
|
190
199
|
}
|
|
191
200
|
|
|
192
201
|
/** Identity data passed to the identify function */
|
|
@@ -230,10 +239,12 @@ interface CrowWidgetProps {
|
|
|
230
239
|
onIdentify?: (identify: IdentifyFunction) => void;
|
|
231
240
|
/** Client-side tools the agent can call */
|
|
232
241
|
tools?: ToolsMap;
|
|
242
|
+
/** Custom navigation function for SPA-safe page navigation (e.g. router.push from Next.js or React Router) */
|
|
243
|
+
navigate?: (path: string) => void;
|
|
233
244
|
/** Callback fired when a server-side tool completes, with the tool name and full result data */
|
|
234
245
|
onToolResult?: (toolName: string, result: Record<string, unknown>) => void;
|
|
235
246
|
}
|
|
236
|
-
declare function CrowWidget({ productId, apiUrl, variant, styles: propStyles, previewMode, showThinking: showThinkingProp, agentName: agentNameProp, welcomeMessage: welcomeMessageProp, onReady, onIdentify, tools, onToolResult, }: CrowWidgetProps): react_jsx_runtime.JSX.Element;
|
|
247
|
+
declare function CrowWidget({ productId, apiUrl, variant, styles: propStyles, previewMode, showThinking: showThinkingProp, agentName: agentNameProp, welcomeMessage: welcomeMessageProp, onReady, onIdentify, tools, navigate, onToolResult, }: CrowWidgetProps): react_jsx_runtime.JSX.Element;
|
|
237
248
|
|
|
238
249
|
interface CrowCopilotProps {
|
|
239
250
|
/** Product ID for this copilot */
|
|
@@ -266,10 +277,12 @@ interface CrowCopilotProps {
|
|
|
266
277
|
className?: string;
|
|
267
278
|
/** Callback when copilot is ready */
|
|
268
279
|
onReady?: () => void;
|
|
280
|
+
/** Custom navigation function for SPA-safe page navigation (e.g. router.push from Next.js or React Router) */
|
|
281
|
+
navigate?: (path: string) => void;
|
|
269
282
|
/** Callback fired when a server-side tool completes, with the tool name and full result data */
|
|
270
283
|
onToolResult?: (toolName: string, result: Record<string, unknown>) => void;
|
|
271
284
|
}
|
|
272
|
-
declare function CrowCopilot({ productId, apiUrl, variant, title, agentName: agentNameProp, welcomeMessage: welcomeMessageProp, position, width, defaultOpen, showClose, onClose, styles: propStyles, previewMode, className, onReady, onToolResult, }: CrowCopilotProps): react_jsx_runtime.JSX.Element;
|
|
285
|
+
declare function CrowCopilot({ productId, apiUrl, variant, title, agentName: agentNameProp, welcomeMessage: welcomeMessageProp, position, width, defaultOpen, showClose, onClose, styles: propStyles, previewMode, className, onReady, navigate, onToolResult, }: CrowCopilotProps): react_jsx_runtime.JSX.Element;
|
|
273
286
|
|
|
274
287
|
interface CrowProviderProps extends CrowClientConfig {
|
|
275
288
|
children: React.ReactNode;
|
|
@@ -663,6 +676,15 @@ interface UseWidgetStylesResult {
|
|
|
663
676
|
agentName: string;
|
|
664
677
|
/** Whether browser_use is enabled for this product */
|
|
665
678
|
browserUseEnabled: boolean;
|
|
679
|
+
/** Whether page navigation is enabled for this product */
|
|
680
|
+
pageNavigationEnabled: boolean;
|
|
681
|
+
/** Route definitions for page navigation */
|
|
682
|
+
pageNavigationRoutes: Array<{
|
|
683
|
+
name: string;
|
|
684
|
+
path: string;
|
|
685
|
+
description?: string;
|
|
686
|
+
params?: Record<string, string>;
|
|
687
|
+
}>;
|
|
666
688
|
/** Whether to show thinking/reasoning to users */
|
|
667
689
|
showThinking: boolean;
|
|
668
690
|
/** Whether to persist anonymous conversations across page refreshes (undefined while loading) */
|
|
@@ -695,10 +717,21 @@ interface UseCopilotStylesResult {
|
|
|
695
717
|
error: Error | null;
|
|
696
718
|
/** Agent name from product config */
|
|
697
719
|
agentName: string;
|
|
720
|
+
/** Whether page navigation is enabled for this product */
|
|
721
|
+
pageNavigationEnabled: boolean;
|
|
722
|
+
/** Route definitions for page navigation */
|
|
723
|
+
pageNavigationRoutes: Array<{
|
|
724
|
+
name: string;
|
|
725
|
+
path: string;
|
|
726
|
+
description?: string;
|
|
727
|
+
params?: Record<string, string>;
|
|
728
|
+
}>;
|
|
698
729
|
/** Whether to persist anonymous conversations across page refreshes (undefined while loading) */
|
|
699
730
|
persistAnonymousConversations: boolean | undefined;
|
|
700
731
|
/** Custom welcome message (undefined uses SDK default) */
|
|
701
732
|
welcomeMessage: string | undefined;
|
|
733
|
+
/** AI model configured for this product */
|
|
734
|
+
selectedModel: string | undefined;
|
|
702
735
|
/** Refetch styles from API */
|
|
703
736
|
refetch: () => Promise<void>;
|
|
704
737
|
}
|
package/dist/index.js
CHANGED
|
@@ -1164,6 +1164,10 @@ function useWidgetStyles({
|
|
|
1164
1164
|
const [browserUseEnabled, setBrowserUseEnabled] = useState(
|
|
1165
1165
|
styleCache.get(key)?.browserUseEnabled || false
|
|
1166
1166
|
);
|
|
1167
|
+
const [pageNavigationEnabled, setPageNavigationEnabled] = useState(
|
|
1168
|
+
styleCache.get(key)?.pageNavigationEnabled || false
|
|
1169
|
+
);
|
|
1170
|
+
const [pageNavigationRoutes, setPageNavigationRoutes] = useState(styleCache.get(key)?.pageNavigationRoutes || []);
|
|
1167
1171
|
const [showThinking, setShowThinking] = useState(
|
|
1168
1172
|
styleCache.get(key)?.showThinking ?? true
|
|
1169
1173
|
);
|
|
@@ -1187,6 +1191,8 @@ function useWidgetStyles({
|
|
|
1187
1191
|
setDbStyles(config.widgetStyles);
|
|
1188
1192
|
setAgentName(config.agentName || "Assistant");
|
|
1189
1193
|
setBrowserUseEnabled(config.browserUseEnabled || false);
|
|
1194
|
+
setPageNavigationEnabled(config.pageNavigationEnabled || false);
|
|
1195
|
+
setPageNavigationRoutes(config.pageNavigationRoutes || []);
|
|
1190
1196
|
setShowThinking(config.showThinking ?? true);
|
|
1191
1197
|
setPersistAnonymousConversations(config.persistAnonymousConversations ?? true);
|
|
1192
1198
|
setWelcomeMessage(config.welcomeMessage ?? void 0);
|
|
@@ -1222,6 +1228,8 @@ function useWidgetStyles({
|
|
|
1222
1228
|
error,
|
|
1223
1229
|
agentName,
|
|
1224
1230
|
browserUseEnabled,
|
|
1231
|
+
pageNavigationEnabled,
|
|
1232
|
+
pageNavigationRoutes,
|
|
1225
1233
|
showThinking,
|
|
1226
1234
|
persistAnonymousConversations,
|
|
1227
1235
|
welcomeMessage,
|
|
@@ -1245,12 +1253,19 @@ function useCopilotStyles({
|
|
|
1245
1253
|
const [agentName, setAgentName] = useState(
|
|
1246
1254
|
styleCache.get(key)?.agentName || "Assistant"
|
|
1247
1255
|
);
|
|
1256
|
+
const [pageNavigationEnabled, setPageNavigationEnabled] = useState(
|
|
1257
|
+
styleCache.get(key)?.pageNavigationEnabled || false
|
|
1258
|
+
);
|
|
1259
|
+
const [pageNavigationRoutes, setPageNavigationRoutes] = useState(styleCache.get(key)?.pageNavigationRoutes || []);
|
|
1248
1260
|
const [persistAnonymousConversations, setPersistAnonymousConversations] = useState(
|
|
1249
1261
|
styleCache.has(key) ? styleCache.get(key)?.persistAnonymousConversations ?? true : void 0
|
|
1250
1262
|
);
|
|
1251
1263
|
const [welcomeMessage, setWelcomeMessage] = useState(
|
|
1252
1264
|
styleCache.get(key)?.welcomeMessage ?? void 0
|
|
1253
1265
|
);
|
|
1266
|
+
const [selectedModel, setSelectedModel] = useState(
|
|
1267
|
+
styleCache.get(key)?.model ?? void 0
|
|
1268
|
+
);
|
|
1254
1269
|
const hasFetchedRef = useRef(false);
|
|
1255
1270
|
const fetchStyles = async () => {
|
|
1256
1271
|
if (skip) return;
|
|
@@ -1261,8 +1276,11 @@ function useCopilotStyles({
|
|
|
1261
1276
|
styleCache.set(key, config);
|
|
1262
1277
|
setDbStyles(config.copilotStyles);
|
|
1263
1278
|
setAgentName(config.agentName || "Assistant");
|
|
1279
|
+
setPageNavigationEnabled(config.pageNavigationEnabled || false);
|
|
1280
|
+
setPageNavigationRoutes(config.pageNavigationRoutes || []);
|
|
1264
1281
|
setPersistAnonymousConversations(config.persistAnonymousConversations ?? true);
|
|
1265
1282
|
setWelcomeMessage(config.welcomeMessage ?? void 0);
|
|
1283
|
+
setSelectedModel(config.model ?? void 0);
|
|
1266
1284
|
} catch (err) {
|
|
1267
1285
|
console.error("[CrowCopilot] Failed to fetch styles:", err);
|
|
1268
1286
|
setError(err instanceof Error ? err : new Error(String(err)));
|
|
@@ -1276,8 +1294,11 @@ function useCopilotStyles({
|
|
|
1276
1294
|
if (cached) {
|
|
1277
1295
|
setDbStyles(cached.copilotStyles);
|
|
1278
1296
|
setAgentName(cached.agentName || "Assistant");
|
|
1297
|
+
setPageNavigationEnabled(cached.pageNavigationEnabled || false);
|
|
1298
|
+
setPageNavigationRoutes(cached.pageNavigationRoutes || []);
|
|
1279
1299
|
setPersistAnonymousConversations(cached.persistAnonymousConversations ?? true);
|
|
1280
1300
|
setWelcomeMessage(cached.welcomeMessage ?? void 0);
|
|
1301
|
+
setSelectedModel(cached.model ?? void 0);
|
|
1281
1302
|
setIsLoading(false);
|
|
1282
1303
|
return;
|
|
1283
1304
|
}
|
|
@@ -1290,8 +1311,11 @@ function useCopilotStyles({
|
|
|
1290
1311
|
isLoading,
|
|
1291
1312
|
error,
|
|
1292
1313
|
agentName,
|
|
1314
|
+
pageNavigationEnabled,
|
|
1315
|
+
pageNavigationRoutes,
|
|
1293
1316
|
persistAnonymousConversations,
|
|
1294
1317
|
welcomeMessage,
|
|
1318
|
+
selectedModel,
|
|
1295
1319
|
refetch: fetchStyles
|
|
1296
1320
|
};
|
|
1297
1321
|
}
|
|
@@ -2836,6 +2860,7 @@ function CrowWidget({
|
|
|
2836
2860
|
onReady,
|
|
2837
2861
|
onIdentify,
|
|
2838
2862
|
tools,
|
|
2863
|
+
navigate,
|
|
2839
2864
|
onToolResult
|
|
2840
2865
|
}) {
|
|
2841
2866
|
const {
|
|
@@ -2843,6 +2868,8 @@ function CrowWidget({
|
|
|
2843
2868
|
isLoading: isLoadingStyles,
|
|
2844
2869
|
agentName: agentNameFromAPI,
|
|
2845
2870
|
browserUseEnabled,
|
|
2871
|
+
pageNavigationEnabled,
|
|
2872
|
+
pageNavigationRoutes,
|
|
2846
2873
|
showThinking: showThinkingFromAPI,
|
|
2847
2874
|
persistAnonymousConversations,
|
|
2848
2875
|
welcomeMessage: welcomeMessageFromAPI,
|
|
@@ -3048,17 +3075,33 @@ function CrowWidget({
|
|
|
3048
3075
|
};
|
|
3049
3076
|
}, [handleBrowserConfirmation, handleBrowserQuestion, handleBrowserProgress]);
|
|
3050
3077
|
useEffect(() => {
|
|
3051
|
-
if (browserUseEnabled && !isLoadingStyles &&
|
|
3078
|
+
if (browserUseEnabled && !isLoadingStyles && !autoTools.browser_use) {
|
|
3052
3079
|
import('@usecrow/client/browser').then(({ createBrowserUseTool }) => {
|
|
3053
|
-
setAutoTools({
|
|
3080
|
+
setAutoTools((prev) => ({
|
|
3081
|
+
...prev,
|
|
3054
3082
|
browser_use: createBrowserUseTool({ productId, apiUrl })
|
|
3055
|
-
});
|
|
3083
|
+
}));
|
|
3056
3084
|
console.log("[Crow] browser_use tool auto-loaded");
|
|
3057
3085
|
}).catch((err) => {
|
|
3058
3086
|
console.warn("[Crow] Failed to load browser_use:", err);
|
|
3059
3087
|
});
|
|
3060
3088
|
}
|
|
3061
3089
|
}, [browserUseEnabled, isLoadingStyles, productId, apiUrl, autoTools]);
|
|
3090
|
+
useEffect(() => {
|
|
3091
|
+
if (pageNavigationEnabled && pageNavigationRoutes.length > 0 && !isLoadingStyles) {
|
|
3092
|
+
import('@usecrow/client').then(({ createNavigateToPageTool }) => {
|
|
3093
|
+
setAutoTools((prev) => ({
|
|
3094
|
+
...prev,
|
|
3095
|
+
navigateToPage: createNavigateToPageTool(pageNavigationRoutes, navigate)
|
|
3096
|
+
}));
|
|
3097
|
+
console.log(
|
|
3098
|
+
`[Crow] navigateToPage tool auto-loaded with ${pageNavigationRoutes.length} routes`
|
|
3099
|
+
);
|
|
3100
|
+
}).catch((err) => {
|
|
3101
|
+
console.warn("[Crow] Failed to load navigateToPage:", err);
|
|
3102
|
+
});
|
|
3103
|
+
}
|
|
3104
|
+
}, [pageNavigationEnabled, pageNavigationRoutes, isLoadingStyles, navigate]);
|
|
3062
3105
|
const mergedTools = useMemo(() => ({ ...autoTools, ...tools }), [autoTools, tools]);
|
|
3063
3106
|
useEffect(() => {
|
|
3064
3107
|
if (Object.keys(mergedTools).length > 0) {
|
|
@@ -3355,14 +3398,18 @@ function CrowCopilot({
|
|
|
3355
3398
|
previewMode = false,
|
|
3356
3399
|
className,
|
|
3357
3400
|
onReady,
|
|
3401
|
+
navigate,
|
|
3358
3402
|
onToolResult
|
|
3359
3403
|
}) {
|
|
3360
3404
|
const {
|
|
3361
3405
|
styles,
|
|
3362
3406
|
isLoading: isLoadingStyles,
|
|
3363
3407
|
agentName: agentNameFromAPI,
|
|
3408
|
+
pageNavigationEnabled,
|
|
3409
|
+
pageNavigationRoutes,
|
|
3364
3410
|
persistAnonymousConversations,
|
|
3365
|
-
welcomeMessage: welcomeMessageFromAPI
|
|
3411
|
+
welcomeMessage: welcomeMessageFromAPI,
|
|
3412
|
+
selectedModel
|
|
3366
3413
|
} = useCopilotStyles({
|
|
3367
3414
|
productId,
|
|
3368
3415
|
apiUrl,
|
|
@@ -3371,9 +3418,31 @@ function CrowCopilot({
|
|
|
3371
3418
|
});
|
|
3372
3419
|
const agentName = agentNameProp ?? agentNameFromAPI ?? title;
|
|
3373
3420
|
const welcomeMessage = welcomeMessageProp ?? welcomeMessageFromAPI;
|
|
3421
|
+
const [autoTools, setAutoTools] = useState({});
|
|
3422
|
+
useEffect(() => {
|
|
3423
|
+
if (pageNavigationEnabled && pageNavigationRoutes.length > 0 && !isLoadingStyles) {
|
|
3424
|
+
import('@usecrow/client').then(({ createNavigateToPageTool }) => {
|
|
3425
|
+
setAutoTools((prev) => ({
|
|
3426
|
+
...prev,
|
|
3427
|
+
navigateToPage: createNavigateToPageTool(pageNavigationRoutes, navigate)
|
|
3428
|
+
}));
|
|
3429
|
+
console.log(
|
|
3430
|
+
`[Crow] navigateToPage tool auto-loaded with ${pageNavigationRoutes.length} routes`
|
|
3431
|
+
);
|
|
3432
|
+
}).catch((err) => {
|
|
3433
|
+
console.warn("[Crow] Failed to load navigateToPage:", err);
|
|
3434
|
+
});
|
|
3435
|
+
}
|
|
3436
|
+
}, [pageNavigationEnabled, pageNavigationRoutes, isLoadingStyles, navigate]);
|
|
3437
|
+
useEffect(() => {
|
|
3438
|
+
if (Object.keys(autoTools).length > 0) {
|
|
3439
|
+
window.crow?.("registerTools", autoTools);
|
|
3440
|
+
}
|
|
3441
|
+
}, [autoTools]);
|
|
3374
3442
|
const messagesContainerRef = useRef(null);
|
|
3375
3443
|
const tabsScrollRef = useRef(null);
|
|
3376
3444
|
const executeClientToolRef = useRef(null);
|
|
3445
|
+
const submitToolResultRef = useRef(null);
|
|
3377
3446
|
const [showConversationList, setShowConversationList] = useState(false);
|
|
3378
3447
|
const [isVerifiedUser, setIsVerifiedUser] = useState(false);
|
|
3379
3448
|
const [localTabs, setLocalTabs] = useState([
|
|
@@ -3392,24 +3461,71 @@ function CrowCopilot({
|
|
|
3392
3461
|
apiUrl,
|
|
3393
3462
|
persistAnonymousConversations,
|
|
3394
3463
|
welcomeMessage,
|
|
3464
|
+
selectedModel,
|
|
3395
3465
|
onVerificationStatus: (isVerified) => {
|
|
3396
3466
|
setIsVerifiedUser(isVerified);
|
|
3397
3467
|
},
|
|
3398
3468
|
onConversationId: () => {
|
|
3399
3469
|
},
|
|
3470
|
+
onWorkflowEvent: (event) => {
|
|
3471
|
+
switch (event.type) {
|
|
3472
|
+
case "started":
|
|
3473
|
+
if (event.name && event.todos) {
|
|
3474
|
+
startWorkflow(event.name, event.todos);
|
|
3475
|
+
}
|
|
3476
|
+
break;
|
|
3477
|
+
case "todo_updated":
|
|
3478
|
+
if (event.todoId && event.todoStatus) {
|
|
3479
|
+
updateTodo(event.todoId, event.todoStatus);
|
|
3480
|
+
}
|
|
3481
|
+
break;
|
|
3482
|
+
case "ended":
|
|
3483
|
+
endWorkflow(2e3);
|
|
3484
|
+
break;
|
|
3485
|
+
case "complete_prompt":
|
|
3486
|
+
markComplete();
|
|
3487
|
+
break;
|
|
3488
|
+
}
|
|
3489
|
+
},
|
|
3400
3490
|
onToolResult,
|
|
3401
|
-
onToolCall: (event) => {
|
|
3402
|
-
if (event.type === "client_call" && event.toolName) {
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3491
|
+
onToolCall: async (event) => {
|
|
3492
|
+
if (event.type === "client_call" && event.toolName && event.toolCallId) {
|
|
3493
|
+
try {
|
|
3494
|
+
const result = await executeClientToolRef.current?.(
|
|
3495
|
+
event.toolName,
|
|
3496
|
+
event.arguments || {}
|
|
3497
|
+
);
|
|
3498
|
+
const resultObj = result;
|
|
3499
|
+
const dataObj = resultObj?.data;
|
|
3500
|
+
const wasUserCancelled = dataObj?.declined === true || typeof resultObj?.error === "string" && resultObj.error.includes("cancelled by user") || typeof resultObj?.error === "string" && resultObj.error.includes("declined");
|
|
3501
|
+
if (wasUserCancelled) {
|
|
3502
|
+
console.log("[Crow Copilot] Tool was cancelled by user");
|
|
3503
|
+
if (submitToolResultRef.current) {
|
|
3504
|
+
await submitToolResultRef.current(
|
|
3505
|
+
event.toolCallId,
|
|
3506
|
+
event.toolName,
|
|
3507
|
+
{ success: false, cancelled: true, error: "Action was cancelled by the user." }
|
|
3508
|
+
);
|
|
3509
|
+
}
|
|
3510
|
+
return;
|
|
3511
|
+
}
|
|
3512
|
+
if (result && submitToolResultRef.current) {
|
|
3513
|
+
await submitToolResultRef.current(
|
|
3514
|
+
event.toolCallId,
|
|
3515
|
+
event.toolName,
|
|
3516
|
+
result
|
|
3517
|
+
);
|
|
3518
|
+
}
|
|
3519
|
+
} catch (e) {
|
|
3520
|
+
console.error("[Crow Copilot] Tool error:", e);
|
|
3521
|
+
if (submitToolResultRef.current) {
|
|
3522
|
+
await submitToolResultRef.current(
|
|
3523
|
+
event.toolCallId,
|
|
3524
|
+
event.toolName,
|
|
3525
|
+
{ success: false, error: String(e) }
|
|
3526
|
+
);
|
|
3527
|
+
}
|
|
3528
|
+
}
|
|
3413
3529
|
}
|
|
3414
3530
|
},
|
|
3415
3531
|
onRestoredConversation: () => {
|
|
@@ -3431,6 +3547,30 @@ function CrowCopilot({
|
|
|
3431
3547
|
injectCopilotBodyStyles();
|
|
3432
3548
|
}
|
|
3433
3549
|
}, [variant]);
|
|
3550
|
+
const {
|
|
3551
|
+
activeWorkflow,
|
|
3552
|
+
startWorkflow,
|
|
3553
|
+
updateTodo,
|
|
3554
|
+
markComplete,
|
|
3555
|
+
endWorkflow,
|
|
3556
|
+
exitWorkflow
|
|
3557
|
+
} = useWorkflow({
|
|
3558
|
+
productId,
|
|
3559
|
+
apiUrl,
|
|
3560
|
+
conversationId: chat.conversationId,
|
|
3561
|
+
selectedModel: chat.selectedModel,
|
|
3562
|
+
onMessage: (content) => {
|
|
3563
|
+
chat.loadMessages([
|
|
3564
|
+
...chat.messages,
|
|
3565
|
+
{
|
|
3566
|
+
id: `bot-${Date.now()}`,
|
|
3567
|
+
content,
|
|
3568
|
+
isBot: true,
|
|
3569
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
3570
|
+
}
|
|
3571
|
+
]);
|
|
3572
|
+
}
|
|
3573
|
+
});
|
|
3434
3574
|
const { executeClientTool } = useCrowAPI({
|
|
3435
3575
|
onIdentified: async () => {
|
|
3436
3576
|
setIsVerifiedUser(true);
|
|
@@ -3442,6 +3582,7 @@ function CrowCopilot({
|
|
|
3442
3582
|
}
|
|
3443
3583
|
});
|
|
3444
3584
|
executeClientToolRef.current = executeClientTool;
|
|
3585
|
+
submitToolResultRef.current = chat.submitToolResult;
|
|
3445
3586
|
const handleBrowserConfirmation = useCallback(
|
|
3446
3587
|
(instruction) => {
|
|
3447
3588
|
return new Promise((resolve) => {
|
|
@@ -3458,6 +3599,9 @@ function CrowCopilot({
|
|
|
3458
3599
|
},
|
|
3459
3600
|
[]
|
|
3460
3601
|
);
|
|
3602
|
+
const handleExitWorkflow = async () => {
|
|
3603
|
+
await exitWorkflow();
|
|
3604
|
+
};
|
|
3461
3605
|
useEffect(() => {
|
|
3462
3606
|
window.__crow_browser_callbacks = {
|
|
3463
3607
|
onConfirmation: handleBrowserConfirmation,
|
|
@@ -3783,6 +3927,13 @@ function CrowCopilot({
|
|
|
3783
3927
|
),
|
|
3784
3928
|
showConversationList && !isVerifiedUser && /* @__PURE__ */ jsx("div", { className: "crow-mb-3 crow-rounded-xl crow-bg-gray-50 crow-border crow-border-gray-200 crow-p-4", children: /* @__PURE__ */ jsx("div", { className: "crow-text-sm crow-text-gray-600", children: "Sign in to view conversation history." }) })
|
|
3785
3929
|
] }),
|
|
3930
|
+
/* @__PURE__ */ jsx(AnimatePresence, { children: activeWorkflow && /* @__PURE__ */ jsx(
|
|
3931
|
+
WorkflowPanel,
|
|
3932
|
+
{
|
|
3933
|
+
workflow: activeWorkflow,
|
|
3934
|
+
onExit: handleExitWorkflow
|
|
3935
|
+
}
|
|
3936
|
+
) }),
|
|
3786
3937
|
/* @__PURE__ */ jsxs(MessagesContainer, { ref: messagesContainerRef, children: [
|
|
3787
3938
|
/* @__PURE__ */ jsx(
|
|
3788
3939
|
MessageList,
|