@emblemvault/hustle-react 1.3.0 → 1.4.0
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/browser/hustle-react.js +101 -2
- package/dist/browser/hustle-react.js.map +1 -1
- package/dist/components/index.cjs +101 -2
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +101 -2
- package/dist/components/index.js.map +1 -1
- package/dist/index.cjs +101 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +101 -2
- package/dist/index.js.map +1 -1
- package/dist/plugins/index.cjs +1 -1
- package/dist/plugins/index.cjs.map +1 -1
- package/dist/plugins/index.js +1 -1
- package/dist/plugins/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -1609,7 +1609,7 @@ var screenshotExecutor = async (args2) => {
|
|
|
1609
1609
|
if (!window.html2canvas) {
|
|
1610
1610
|
await new Promise((resolve, reject) => {
|
|
1611
1611
|
const script = document.createElement("script");
|
|
1612
|
-
script.src = "https://
|
|
1612
|
+
script.src = "https://cdn.jsdelivr.net/npm/html2canvas-pro@1.5.0/dist/html2canvas-pro.min.js";
|
|
1613
1613
|
script.onload = () => resolve();
|
|
1614
1614
|
script.onerror = () => reject(new Error("Failed to load html2canvas"));
|
|
1615
1615
|
document.head.appendChild(script);
|
|
@@ -3315,7 +3315,11 @@ var styles = {
|
|
|
3315
3315
|
border: "none",
|
|
3316
3316
|
borderRadius: 0,
|
|
3317
3317
|
color: tokens.colors.textTertiary,
|
|
3318
|
-
flexShrink: 0
|
|
3318
|
+
flexShrink: 0,
|
|
3319
|
+
display: "flex",
|
|
3320
|
+
alignItems: "center",
|
|
3321
|
+
justifyContent: "center",
|
|
3322
|
+
cursor: "pointer"
|
|
3319
3323
|
},
|
|
3320
3324
|
inputWrapper: {
|
|
3321
3325
|
flex: 1
|
|
@@ -3537,6 +3541,7 @@ function HustleChat({
|
|
|
3537
3541
|
isLoading,
|
|
3538
3542
|
error: error2,
|
|
3539
3543
|
models,
|
|
3544
|
+
client,
|
|
3540
3545
|
chatStream,
|
|
3541
3546
|
uploadFile,
|
|
3542
3547
|
selectedModel,
|
|
@@ -3563,6 +3568,7 @@ function HustleChat({
|
|
|
3563
3568
|
const [showSettingsPanel, setShowSettingsPanel] = react.useState(false);
|
|
3564
3569
|
const messagesEndRef = react.useRef(null);
|
|
3565
3570
|
const fileInputRef = react.useRef(null);
|
|
3571
|
+
const messagesRef = react.useRef(messages);
|
|
3566
3572
|
react.useEffect(() => {
|
|
3567
3573
|
if (initialSystemPrompt && !systemPrompt) {
|
|
3568
3574
|
setSystemPrompt(initialSystemPrompt);
|
|
@@ -3571,6 +3577,9 @@ function HustleChat({
|
|
|
3571
3577
|
react.useEffect(() => {
|
|
3572
3578
|
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
3573
3579
|
}, [messages]);
|
|
3580
|
+
react.useEffect(() => {
|
|
3581
|
+
messagesRef.current = messages;
|
|
3582
|
+
}, [messages]);
|
|
3574
3583
|
const handleFileSelect = react.useCallback(
|
|
3575
3584
|
async (e) => {
|
|
3576
3585
|
const files = e.target.files;
|
|
@@ -3592,6 +3601,96 @@ function HustleChat({
|
|
|
3592
3601
|
const removeAttachment = react.useCallback((index) => {
|
|
3593
3602
|
setAttachments((prev) => prev.filter((_, i) => i !== index));
|
|
3594
3603
|
}, []);
|
|
3604
|
+
const sendContinue = react.useCallback(async () => {
|
|
3605
|
+
if (isStreaming || !isReady) return;
|
|
3606
|
+
console.log("[AUTO_CONTINUE] Sending continue message...");
|
|
3607
|
+
const userMessage = {
|
|
3608
|
+
id: generateId(),
|
|
3609
|
+
role: "user",
|
|
3610
|
+
content: "continue"
|
|
3611
|
+
};
|
|
3612
|
+
setMessages((prev) => [...prev, userMessage]);
|
|
3613
|
+
onMessage?.(userMessage);
|
|
3614
|
+
const assistantMessage = {
|
|
3615
|
+
id: generateId(),
|
|
3616
|
+
role: "assistant",
|
|
3617
|
+
content: "",
|
|
3618
|
+
isStreaming: true,
|
|
3619
|
+
toolCalls: []
|
|
3620
|
+
};
|
|
3621
|
+
setMessages((prev) => [...prev, assistantMessage]);
|
|
3622
|
+
setIsStreaming(true);
|
|
3623
|
+
setCurrentToolCalls([]);
|
|
3624
|
+
try {
|
|
3625
|
+
const chatMessages = messagesRef.current.filter((m) => !m.isStreaming).map((m) => ({ role: m.role, content: m.content }));
|
|
3626
|
+
chatMessages.push({ role: "user", content: "continue" });
|
|
3627
|
+
const stream = chatStream({
|
|
3628
|
+
messages: chatMessages,
|
|
3629
|
+
processChunks: true
|
|
3630
|
+
});
|
|
3631
|
+
let fullContent = "";
|
|
3632
|
+
const toolCallsAccumulated = [];
|
|
3633
|
+
for await (const chunk of stream) {
|
|
3634
|
+
if (chunk.type === "text") {
|
|
3635
|
+
fullContent += chunk.value;
|
|
3636
|
+
setMessages(
|
|
3637
|
+
(prev) => prev.map(
|
|
3638
|
+
(m) => m.id === assistantMessage.id ? { ...m, content: fullContent } : m
|
|
3639
|
+
)
|
|
3640
|
+
);
|
|
3641
|
+
} else if (chunk.type === "tool_call") {
|
|
3642
|
+
const toolCall = chunk.value;
|
|
3643
|
+
toolCallsAccumulated.push(toolCall);
|
|
3644
|
+
setCurrentToolCalls([...toolCallsAccumulated]);
|
|
3645
|
+
setMessages(
|
|
3646
|
+
(prev) => prev.map(
|
|
3647
|
+
(m) => m.id === assistantMessage.id ? { ...m, toolCalls: [...toolCallsAccumulated] } : m
|
|
3648
|
+
)
|
|
3649
|
+
);
|
|
3650
|
+
onToolCall?.(toolCall);
|
|
3651
|
+
} else if (chunk.type === "error") {
|
|
3652
|
+
console.error("Stream error:", chunk.value);
|
|
3653
|
+
}
|
|
3654
|
+
}
|
|
3655
|
+
const processedResponse = await stream.response;
|
|
3656
|
+
const finalContent = processedResponse?.content || fullContent || "(No response)";
|
|
3657
|
+
setMessages(
|
|
3658
|
+
(prev) => prev.map(
|
|
3659
|
+
(m) => m.id === assistantMessage.id ? { ...m, isStreaming: false, content: finalContent } : m
|
|
3660
|
+
)
|
|
3661
|
+
);
|
|
3662
|
+
onResponse?.(finalContent);
|
|
3663
|
+
} catch (err) {
|
|
3664
|
+
console.error("Continue error:", err);
|
|
3665
|
+
setMessages(
|
|
3666
|
+
(prev) => prev.map(
|
|
3667
|
+
(m) => m.id === assistantMessage.id ? { ...m, isStreaming: false, content: `Error: ${err instanceof Error ? err.message : "Unknown error"}` } : m
|
|
3668
|
+
)
|
|
3669
|
+
);
|
|
3670
|
+
} finally {
|
|
3671
|
+
setIsStreaming(false);
|
|
3672
|
+
setCurrentToolCalls([]);
|
|
3673
|
+
}
|
|
3674
|
+
}, [isStreaming, isReady, chatStream, onMessage, onToolCall, onResponse]);
|
|
3675
|
+
react.useEffect(() => {
|
|
3676
|
+
if (!client) return;
|
|
3677
|
+
const unsubMaxTools = client.on("max_tools_reached", (event) => {
|
|
3678
|
+
console.log(`[AUTO_CONTINUE] Max tools reached (${event.toolsExecuted}/${event.maxSteps}), auto-continuing...`);
|
|
3679
|
+
setTimeout(() => {
|
|
3680
|
+
sendContinue();
|
|
3681
|
+
}, 100);
|
|
3682
|
+
});
|
|
3683
|
+
const unsubTimeout = client.on("timeout", (event) => {
|
|
3684
|
+
console.log(`[AUTO_CONTINUE] Timeout: ${event.message}, auto-continuing...`);
|
|
3685
|
+
setTimeout(() => {
|
|
3686
|
+
sendContinue();
|
|
3687
|
+
}, 100);
|
|
3688
|
+
});
|
|
3689
|
+
return () => {
|
|
3690
|
+
unsubMaxTools();
|
|
3691
|
+
unsubTimeout();
|
|
3692
|
+
};
|
|
3693
|
+
}, [client, sendContinue]);
|
|
3595
3694
|
const sendMessage = react.useCallback(async () => {
|
|
3596
3695
|
const content = inputValue.trim();
|
|
3597
3696
|
if (!content || isStreaming || !isReady) return;
|