@emblemvault/hustle-react 1.3.0 → 1.4.1
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 +108 -2
- package/dist/browser/hustle-react.js.map +1 -1
- package/dist/components/index.cjs +107 -2
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +107 -2
- package/dist/components/index.js.map +1 -1
- package/dist/index.cjs +107 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +107 -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
package/dist/index.js
CHANGED
|
@@ -2006,7 +2006,7 @@ var screenshotExecutor = async (args2) => {
|
|
|
2006
2006
|
if (!window.html2canvas) {
|
|
2007
2007
|
await new Promise((resolve, reject) => {
|
|
2008
2008
|
const script = document.createElement("script");
|
|
2009
|
-
script.src = "https://
|
|
2009
|
+
script.src = "https://cdn.jsdelivr.net/npm/html2canvas-pro@1.5.0/dist/html2canvas-pro.min.js";
|
|
2010
2010
|
script.onload = () => resolve();
|
|
2011
2011
|
script.onerror = () => reject(new Error("Failed to load html2canvas"));
|
|
2012
2012
|
document.head.appendChild(script);
|
|
@@ -3715,7 +3715,11 @@ var styles = {
|
|
|
3715
3715
|
border: "none",
|
|
3716
3716
|
borderRadius: 0,
|
|
3717
3717
|
color: tokens.colors.textTertiary,
|
|
3718
|
-
flexShrink: 0
|
|
3718
|
+
flexShrink: 0,
|
|
3719
|
+
display: "flex",
|
|
3720
|
+
alignItems: "center",
|
|
3721
|
+
justifyContent: "center",
|
|
3722
|
+
cursor: "pointer"
|
|
3719
3723
|
},
|
|
3720
3724
|
inputWrapper: {
|
|
3721
3725
|
flex: 1
|
|
@@ -3937,6 +3941,7 @@ function HustleChat({
|
|
|
3937
3941
|
isLoading,
|
|
3938
3942
|
error: error2,
|
|
3939
3943
|
models,
|
|
3944
|
+
client,
|
|
3940
3945
|
chatStream,
|
|
3941
3946
|
uploadFile,
|
|
3942
3947
|
selectedModel,
|
|
@@ -3963,6 +3968,8 @@ function HustleChat({
|
|
|
3963
3968
|
const [showSettingsPanel, setShowSettingsPanel] = useState(false);
|
|
3964
3969
|
const messagesEndRef = useRef(null);
|
|
3965
3970
|
const fileInputRef = useRef(null);
|
|
3971
|
+
const messagesRef = useRef(messages);
|
|
3972
|
+
const pendingAutoContinueRef = useRef(false);
|
|
3966
3973
|
useEffect(() => {
|
|
3967
3974
|
if (initialSystemPrompt && !systemPrompt) {
|
|
3968
3975
|
setSystemPrompt(initialSystemPrompt);
|
|
@@ -3971,6 +3978,9 @@ function HustleChat({
|
|
|
3971
3978
|
useEffect(() => {
|
|
3972
3979
|
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
3973
3980
|
}, [messages]);
|
|
3981
|
+
useEffect(() => {
|
|
3982
|
+
messagesRef.current = messages;
|
|
3983
|
+
}, [messages]);
|
|
3974
3984
|
const handleFileSelect = useCallback(
|
|
3975
3985
|
async (e) => {
|
|
3976
3986
|
const files = e.target.files;
|
|
@@ -3992,6 +4002,101 @@ function HustleChat({
|
|
|
3992
4002
|
const removeAttachment = useCallback((index) => {
|
|
3993
4003
|
setAttachments((prev) => prev.filter((_, i) => i !== index));
|
|
3994
4004
|
}, []);
|
|
4005
|
+
const sendContinue = useCallback(async () => {
|
|
4006
|
+
if (isStreaming || !isReady) return;
|
|
4007
|
+
console.log("[AUTO_CONTINUE] Sending continue message...");
|
|
4008
|
+
const userMessage = {
|
|
4009
|
+
id: generateId(),
|
|
4010
|
+
role: "user",
|
|
4011
|
+
content: "continue"
|
|
4012
|
+
};
|
|
4013
|
+
setMessages((prev) => [...prev, userMessage]);
|
|
4014
|
+
onMessage?.(userMessage);
|
|
4015
|
+
const assistantMessage = {
|
|
4016
|
+
id: generateId(),
|
|
4017
|
+
role: "assistant",
|
|
4018
|
+
content: "",
|
|
4019
|
+
isStreaming: true,
|
|
4020
|
+
toolCalls: []
|
|
4021
|
+
};
|
|
4022
|
+
setMessages((prev) => [...prev, assistantMessage]);
|
|
4023
|
+
setIsStreaming(true);
|
|
4024
|
+
setCurrentToolCalls([]);
|
|
4025
|
+
try {
|
|
4026
|
+
const chatMessages = messagesRef.current.filter((m) => !m.isStreaming).map((m) => ({ role: m.role, content: m.content }));
|
|
4027
|
+
chatMessages.push({ role: "user", content: "continue" });
|
|
4028
|
+
const stream = chatStream({
|
|
4029
|
+
messages: chatMessages,
|
|
4030
|
+
processChunks: true
|
|
4031
|
+
});
|
|
4032
|
+
let fullContent = "";
|
|
4033
|
+
const toolCallsAccumulated = [];
|
|
4034
|
+
for await (const chunk of stream) {
|
|
4035
|
+
if (chunk.type === "text") {
|
|
4036
|
+
fullContent += chunk.value;
|
|
4037
|
+
setMessages(
|
|
4038
|
+
(prev) => prev.map(
|
|
4039
|
+
(m) => m.id === assistantMessage.id ? { ...m, content: fullContent } : m
|
|
4040
|
+
)
|
|
4041
|
+
);
|
|
4042
|
+
} else if (chunk.type === "tool_call") {
|
|
4043
|
+
const toolCall = chunk.value;
|
|
4044
|
+
toolCallsAccumulated.push(toolCall);
|
|
4045
|
+
setCurrentToolCalls([...toolCallsAccumulated]);
|
|
4046
|
+
setMessages(
|
|
4047
|
+
(prev) => prev.map(
|
|
4048
|
+
(m) => m.id === assistantMessage.id ? { ...m, toolCalls: [...toolCallsAccumulated] } : m
|
|
4049
|
+
)
|
|
4050
|
+
);
|
|
4051
|
+
onToolCall?.(toolCall);
|
|
4052
|
+
} else if (chunk.type === "error") {
|
|
4053
|
+
console.error("Stream error:", chunk.value);
|
|
4054
|
+
}
|
|
4055
|
+
}
|
|
4056
|
+
const processedResponse = await stream.response;
|
|
4057
|
+
const finalContent = processedResponse?.content || fullContent || "(No response)";
|
|
4058
|
+
setMessages(
|
|
4059
|
+
(prev) => prev.map(
|
|
4060
|
+
(m) => m.id === assistantMessage.id ? { ...m, isStreaming: false, content: finalContent } : m
|
|
4061
|
+
)
|
|
4062
|
+
);
|
|
4063
|
+
onResponse?.(finalContent);
|
|
4064
|
+
} catch (err) {
|
|
4065
|
+
console.error("Continue error:", err);
|
|
4066
|
+
setMessages(
|
|
4067
|
+
(prev) => prev.map(
|
|
4068
|
+
(m) => m.id === assistantMessage.id ? { ...m, isStreaming: false, content: `Error: ${err instanceof Error ? err.message : "Unknown error"}` } : m
|
|
4069
|
+
)
|
|
4070
|
+
);
|
|
4071
|
+
} finally {
|
|
4072
|
+
setIsStreaming(false);
|
|
4073
|
+
setCurrentToolCalls([]);
|
|
4074
|
+
}
|
|
4075
|
+
}, [isStreaming, isReady, chatStream, onMessage, onToolCall, onResponse]);
|
|
4076
|
+
useEffect(() => {
|
|
4077
|
+
if (!client) return;
|
|
4078
|
+
const unsubMaxTools = client.on("max_tools_reached", (event) => {
|
|
4079
|
+
console.log(`[AUTO_CONTINUE] Max tools reached (${event.toolsExecuted}/${event.maxSteps}), queuing auto-continue...`);
|
|
4080
|
+
pendingAutoContinueRef.current = true;
|
|
4081
|
+
});
|
|
4082
|
+
const unsubTimeout = client.on("timeout", (event) => {
|
|
4083
|
+
console.log(`[AUTO_CONTINUE] Timeout: ${event.message}, queuing auto-continue...`);
|
|
4084
|
+
pendingAutoContinueRef.current = true;
|
|
4085
|
+
});
|
|
4086
|
+
return () => {
|
|
4087
|
+
unsubMaxTools();
|
|
4088
|
+
unsubTimeout();
|
|
4089
|
+
};
|
|
4090
|
+
}, [client]);
|
|
4091
|
+
useEffect(() => {
|
|
4092
|
+
if (!isStreaming && pendingAutoContinueRef.current && isReady) {
|
|
4093
|
+
console.log("[AUTO_CONTINUE] Streaming ended, triggering continue...");
|
|
4094
|
+
pendingAutoContinueRef.current = false;
|
|
4095
|
+
setTimeout(() => {
|
|
4096
|
+
sendContinue();
|
|
4097
|
+
}, 50);
|
|
4098
|
+
}
|
|
4099
|
+
}, [isStreaming, isReady, sendContinue]);
|
|
3995
4100
|
const sendMessage = useCallback(async () => {
|
|
3996
4101
|
const content = inputValue.trim();
|
|
3997
4102
|
if (!content || isStreaming || !isReady) return;
|