@usecrow/ui 0.1.6 → 0.1.7
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 +135 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +135 -8
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -126,6 +126,7 @@ function useChat({
|
|
|
126
126
|
async (message, botMsgId) => {
|
|
127
127
|
let accumulatedText = "";
|
|
128
128
|
let firstChunk = true;
|
|
129
|
+
const pendingClientTools = [];
|
|
129
130
|
abortControllerRef.current = new AbortController();
|
|
130
131
|
try {
|
|
131
132
|
const identityToken = window.__crow_identity_token;
|
|
@@ -157,6 +158,14 @@ function useChat({
|
|
|
157
158
|
const data = line.slice(6).trim();
|
|
158
159
|
if (data === "[DONE]") {
|
|
159
160
|
setIsLoading(false);
|
|
161
|
+
for (const tool of pendingClientTools) {
|
|
162
|
+
onToolCall?.({
|
|
163
|
+
type: "client_call",
|
|
164
|
+
toolName: tool.toolName,
|
|
165
|
+
toolCallId: tool.toolCallId,
|
|
166
|
+
arguments: tool.arguments
|
|
167
|
+
});
|
|
168
|
+
}
|
|
160
169
|
return;
|
|
161
170
|
}
|
|
162
171
|
try {
|
|
@@ -253,9 +262,9 @@ function useChat({
|
|
|
253
262
|
);
|
|
254
263
|
break;
|
|
255
264
|
case "client_tool_call":
|
|
256
|
-
|
|
257
|
-
type: "client_call",
|
|
265
|
+
pendingClientTools.push({
|
|
258
266
|
toolName: parsed.tool_name,
|
|
267
|
+
toolCallId: parsed.tool_call_id,
|
|
259
268
|
arguments: parsed.arguments
|
|
260
269
|
});
|
|
261
270
|
break;
|
|
@@ -369,6 +378,102 @@ function useChat({
|
|
|
369
378
|
const loadMessages = React3.useCallback((historyMessages) => {
|
|
370
379
|
setMessages(historyMessages);
|
|
371
380
|
}, []);
|
|
381
|
+
const submitToolResult = React3.useCallback(
|
|
382
|
+
async (toolCallId, toolName, result) => {
|
|
383
|
+
if (!conversationId) {
|
|
384
|
+
console.error("[Crow] Cannot submit tool result: no conversation ID");
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
const botMsgId = generateMessageId("bot");
|
|
388
|
+
const pendingClientTools = [];
|
|
389
|
+
setMessages((prev) => [
|
|
390
|
+
...prev,
|
|
391
|
+
{
|
|
392
|
+
id: botMsgId,
|
|
393
|
+
content: "",
|
|
394
|
+
isBot: true,
|
|
395
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
396
|
+
}
|
|
397
|
+
]);
|
|
398
|
+
setIsLoading(true);
|
|
399
|
+
try {
|
|
400
|
+
const identityToken = window.__crow_identity_token;
|
|
401
|
+
const response = await fetch(`${apiUrl}/api/chat/tool-result`, {
|
|
402
|
+
method: "POST",
|
|
403
|
+
headers: { "Content-Type": "application/json" },
|
|
404
|
+
body: JSON.stringify({
|
|
405
|
+
product_id: productId,
|
|
406
|
+
conversation_id: conversationId,
|
|
407
|
+
tool_call_id: toolCallId,
|
|
408
|
+
tool_name: toolName,
|
|
409
|
+
result,
|
|
410
|
+
identity_token: identityToken,
|
|
411
|
+
model: selectedModel
|
|
412
|
+
})
|
|
413
|
+
});
|
|
414
|
+
if (!response.ok) {
|
|
415
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
416
|
+
}
|
|
417
|
+
const reader = response.body?.getReader();
|
|
418
|
+
const decoder = new TextDecoder();
|
|
419
|
+
let accumulatedText = "";
|
|
420
|
+
if (reader) {
|
|
421
|
+
while (true) {
|
|
422
|
+
const { done, value } = await reader.read();
|
|
423
|
+
if (done) break;
|
|
424
|
+
const chunk = decoder.decode(value);
|
|
425
|
+
const lines = chunk.split("\n");
|
|
426
|
+
for (const line of lines) {
|
|
427
|
+
if (line.startsWith("data: ")) {
|
|
428
|
+
const data = line.slice(6).trim();
|
|
429
|
+
if (data === "[DONE]") {
|
|
430
|
+
setIsLoading(false);
|
|
431
|
+
for (const tool of pendingClientTools) {
|
|
432
|
+
onToolCall?.({
|
|
433
|
+
type: "client_call",
|
|
434
|
+
toolName: tool.toolName,
|
|
435
|
+
toolCallId: tool.toolCallId,
|
|
436
|
+
arguments: tool.arguments
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
try {
|
|
442
|
+
const parsed = JSON.parse(data);
|
|
443
|
+
if (parsed.type === "content") {
|
|
444
|
+
accumulatedText += parsed.content;
|
|
445
|
+
setMessages(
|
|
446
|
+
(prev) => prev.map(
|
|
447
|
+
(msg) => msg.id === botMsgId ? { ...msg, content: accumulatedText } : msg
|
|
448
|
+
)
|
|
449
|
+
);
|
|
450
|
+
} else if (parsed.type === "client_tool_call") {
|
|
451
|
+
pendingClientTools.push({
|
|
452
|
+
toolName: parsed.tool_name,
|
|
453
|
+
toolCallId: parsed.tool_call_id,
|
|
454
|
+
arguments: parsed.arguments
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
} catch (e) {
|
|
458
|
+
console.error("[Crow] Parse error in tool result response:", e);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
} catch (error) {
|
|
465
|
+
console.error("[Crow] Error submitting tool result:", error);
|
|
466
|
+
setMessages(
|
|
467
|
+
(prev) => prev.map(
|
|
468
|
+
(msg) => msg.id === botMsgId ? { ...msg, content: "Sorry, I encountered an error processing the tool result." } : msg
|
|
469
|
+
)
|
|
470
|
+
);
|
|
471
|
+
} finally {
|
|
472
|
+
setIsLoading(false);
|
|
473
|
+
}
|
|
474
|
+
},
|
|
475
|
+
[apiUrl, productId, conversationId, selectedModel]
|
|
476
|
+
);
|
|
372
477
|
return {
|
|
373
478
|
messages,
|
|
374
479
|
isLoading,
|
|
@@ -380,7 +485,8 @@ function useChat({
|
|
|
380
485
|
sendMessage,
|
|
381
486
|
stopGeneration,
|
|
382
487
|
resetMessages,
|
|
383
|
-
loadMessages
|
|
488
|
+
loadMessages,
|
|
489
|
+
submitToolResult
|
|
384
490
|
};
|
|
385
491
|
}
|
|
386
492
|
function useConversations({ productId, apiUrl = "" }) {
|
|
@@ -2114,6 +2220,7 @@ function CrowWidget({
|
|
|
2114
2220
|
});
|
|
2115
2221
|
const messagesContainerRef = React3.useRef(null);
|
|
2116
2222
|
const executeClientToolRef = React3.useRef(null);
|
|
2223
|
+
const submitToolResultRef = React3.useRef(null);
|
|
2117
2224
|
const [isCollapsed, setIsCollapsed] = React3.useState(variant === "floating");
|
|
2118
2225
|
const [showConversationList, setShowConversationList] = React3.useState(false);
|
|
2119
2226
|
const [isVerifiedUser, setIsVerifiedUser] = React3.useState(false);
|
|
@@ -2160,11 +2267,30 @@ function CrowWidget({
|
|
|
2160
2267
|
break;
|
|
2161
2268
|
}
|
|
2162
2269
|
},
|
|
2163
|
-
onToolCall: (event) => {
|
|
2164
|
-
if (event.type === "client_call" && event.toolName) {
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2270
|
+
onToolCall: async (event) => {
|
|
2271
|
+
if (event.type === "client_call" && event.toolName && event.toolCallId) {
|
|
2272
|
+
try {
|
|
2273
|
+
const result = await executeClientToolRef.current?.(
|
|
2274
|
+
event.toolName,
|
|
2275
|
+
event.arguments || {}
|
|
2276
|
+
);
|
|
2277
|
+
if (result && submitToolResultRef.current) {
|
|
2278
|
+
await submitToolResultRef.current(
|
|
2279
|
+
event.toolCallId,
|
|
2280
|
+
event.toolName,
|
|
2281
|
+
result
|
|
2282
|
+
);
|
|
2283
|
+
}
|
|
2284
|
+
} catch (e) {
|
|
2285
|
+
console.error("[Crow Widget] Tool error:", e);
|
|
2286
|
+
if (submitToolResultRef.current) {
|
|
2287
|
+
await submitToolResultRef.current(
|
|
2288
|
+
event.toolCallId,
|
|
2289
|
+
event.toolName,
|
|
2290
|
+
{ success: false, error: String(e) }
|
|
2291
|
+
);
|
|
2292
|
+
}
|
|
2293
|
+
}
|
|
2168
2294
|
}
|
|
2169
2295
|
},
|
|
2170
2296
|
onRestoredConversation: () => {
|
|
@@ -2210,6 +2336,7 @@ function CrowWidget({
|
|
|
2210
2336
|
}
|
|
2211
2337
|
});
|
|
2212
2338
|
executeClientToolRef.current = executeClientTool;
|
|
2339
|
+
submitToolResultRef.current = chat.submitToolResult;
|
|
2213
2340
|
React3.useEffect(() => {
|
|
2214
2341
|
if (!isLoadingStyles) {
|
|
2215
2342
|
onReady?.();
|