@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
package/dist/index.cjs
CHANGED
|
@@ -2032,7 +2032,7 @@ var screenshotExecutor = async (args2) => {
|
|
|
2032
2032
|
if (!window.html2canvas) {
|
|
2033
2033
|
await new Promise((resolve, reject) => {
|
|
2034
2034
|
const script = document.createElement("script");
|
|
2035
|
-
script.src = "https://
|
|
2035
|
+
script.src = "https://cdn.jsdelivr.net/npm/html2canvas-pro@1.5.0/dist/html2canvas-pro.min.js";
|
|
2036
2036
|
script.onload = () => resolve();
|
|
2037
2037
|
script.onerror = () => reject(new Error("Failed to load html2canvas"));
|
|
2038
2038
|
document.head.appendChild(script);
|
|
@@ -3741,7 +3741,11 @@ var styles = {
|
|
|
3741
3741
|
border: "none",
|
|
3742
3742
|
borderRadius: 0,
|
|
3743
3743
|
color: tokens.colors.textTertiary,
|
|
3744
|
-
flexShrink: 0
|
|
3744
|
+
flexShrink: 0,
|
|
3745
|
+
display: "flex",
|
|
3746
|
+
alignItems: "center",
|
|
3747
|
+
justifyContent: "center",
|
|
3748
|
+
cursor: "pointer"
|
|
3745
3749
|
},
|
|
3746
3750
|
inputWrapper: {
|
|
3747
3751
|
flex: 1
|
|
@@ -3963,6 +3967,7 @@ function HustleChat({
|
|
|
3963
3967
|
isLoading,
|
|
3964
3968
|
error: error2,
|
|
3965
3969
|
models,
|
|
3970
|
+
client,
|
|
3966
3971
|
chatStream,
|
|
3967
3972
|
uploadFile,
|
|
3968
3973
|
selectedModel,
|
|
@@ -3989,6 +3994,7 @@ function HustleChat({
|
|
|
3989
3994
|
const [showSettingsPanel, setShowSettingsPanel] = react.useState(false);
|
|
3990
3995
|
const messagesEndRef = react.useRef(null);
|
|
3991
3996
|
const fileInputRef = react.useRef(null);
|
|
3997
|
+
const messagesRef = react.useRef(messages);
|
|
3992
3998
|
react.useEffect(() => {
|
|
3993
3999
|
if (initialSystemPrompt && !systemPrompt) {
|
|
3994
4000
|
setSystemPrompt(initialSystemPrompt);
|
|
@@ -3997,6 +4003,9 @@ function HustleChat({
|
|
|
3997
4003
|
react.useEffect(() => {
|
|
3998
4004
|
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
3999
4005
|
}, [messages]);
|
|
4006
|
+
react.useEffect(() => {
|
|
4007
|
+
messagesRef.current = messages;
|
|
4008
|
+
}, [messages]);
|
|
4000
4009
|
const handleFileSelect = react.useCallback(
|
|
4001
4010
|
async (e) => {
|
|
4002
4011
|
const files = e.target.files;
|
|
@@ -4018,6 +4027,96 @@ function HustleChat({
|
|
|
4018
4027
|
const removeAttachment = react.useCallback((index) => {
|
|
4019
4028
|
setAttachments((prev) => prev.filter((_, i) => i !== index));
|
|
4020
4029
|
}, []);
|
|
4030
|
+
const sendContinue = react.useCallback(async () => {
|
|
4031
|
+
if (isStreaming || !isReady) return;
|
|
4032
|
+
console.log("[AUTO_CONTINUE] Sending continue message...");
|
|
4033
|
+
const userMessage = {
|
|
4034
|
+
id: generateId(),
|
|
4035
|
+
role: "user",
|
|
4036
|
+
content: "continue"
|
|
4037
|
+
};
|
|
4038
|
+
setMessages((prev) => [...prev, userMessage]);
|
|
4039
|
+
onMessage?.(userMessage);
|
|
4040
|
+
const assistantMessage = {
|
|
4041
|
+
id: generateId(),
|
|
4042
|
+
role: "assistant",
|
|
4043
|
+
content: "",
|
|
4044
|
+
isStreaming: true,
|
|
4045
|
+
toolCalls: []
|
|
4046
|
+
};
|
|
4047
|
+
setMessages((prev) => [...prev, assistantMessage]);
|
|
4048
|
+
setIsStreaming(true);
|
|
4049
|
+
setCurrentToolCalls([]);
|
|
4050
|
+
try {
|
|
4051
|
+
const chatMessages = messagesRef.current.filter((m) => !m.isStreaming).map((m) => ({ role: m.role, content: m.content }));
|
|
4052
|
+
chatMessages.push({ role: "user", content: "continue" });
|
|
4053
|
+
const stream = chatStream({
|
|
4054
|
+
messages: chatMessages,
|
|
4055
|
+
processChunks: true
|
|
4056
|
+
});
|
|
4057
|
+
let fullContent = "";
|
|
4058
|
+
const toolCallsAccumulated = [];
|
|
4059
|
+
for await (const chunk of stream) {
|
|
4060
|
+
if (chunk.type === "text") {
|
|
4061
|
+
fullContent += chunk.value;
|
|
4062
|
+
setMessages(
|
|
4063
|
+
(prev) => prev.map(
|
|
4064
|
+
(m) => m.id === assistantMessage.id ? { ...m, content: fullContent } : m
|
|
4065
|
+
)
|
|
4066
|
+
);
|
|
4067
|
+
} else if (chunk.type === "tool_call") {
|
|
4068
|
+
const toolCall = chunk.value;
|
|
4069
|
+
toolCallsAccumulated.push(toolCall);
|
|
4070
|
+
setCurrentToolCalls([...toolCallsAccumulated]);
|
|
4071
|
+
setMessages(
|
|
4072
|
+
(prev) => prev.map(
|
|
4073
|
+
(m) => m.id === assistantMessage.id ? { ...m, toolCalls: [...toolCallsAccumulated] } : m
|
|
4074
|
+
)
|
|
4075
|
+
);
|
|
4076
|
+
onToolCall?.(toolCall);
|
|
4077
|
+
} else if (chunk.type === "error") {
|
|
4078
|
+
console.error("Stream error:", chunk.value);
|
|
4079
|
+
}
|
|
4080
|
+
}
|
|
4081
|
+
const processedResponse = await stream.response;
|
|
4082
|
+
const finalContent = processedResponse?.content || fullContent || "(No response)";
|
|
4083
|
+
setMessages(
|
|
4084
|
+
(prev) => prev.map(
|
|
4085
|
+
(m) => m.id === assistantMessage.id ? { ...m, isStreaming: false, content: finalContent } : m
|
|
4086
|
+
)
|
|
4087
|
+
);
|
|
4088
|
+
onResponse?.(finalContent);
|
|
4089
|
+
} catch (err) {
|
|
4090
|
+
console.error("Continue error:", err);
|
|
4091
|
+
setMessages(
|
|
4092
|
+
(prev) => prev.map(
|
|
4093
|
+
(m) => m.id === assistantMessage.id ? { ...m, isStreaming: false, content: `Error: ${err instanceof Error ? err.message : "Unknown error"}` } : m
|
|
4094
|
+
)
|
|
4095
|
+
);
|
|
4096
|
+
} finally {
|
|
4097
|
+
setIsStreaming(false);
|
|
4098
|
+
setCurrentToolCalls([]);
|
|
4099
|
+
}
|
|
4100
|
+
}, [isStreaming, isReady, chatStream, onMessage, onToolCall, onResponse]);
|
|
4101
|
+
react.useEffect(() => {
|
|
4102
|
+
if (!client) return;
|
|
4103
|
+
const unsubMaxTools = client.on("max_tools_reached", (event) => {
|
|
4104
|
+
console.log(`[AUTO_CONTINUE] Max tools reached (${event.toolsExecuted}/${event.maxSteps}), auto-continuing...`);
|
|
4105
|
+
setTimeout(() => {
|
|
4106
|
+
sendContinue();
|
|
4107
|
+
}, 100);
|
|
4108
|
+
});
|
|
4109
|
+
const unsubTimeout = client.on("timeout", (event) => {
|
|
4110
|
+
console.log(`[AUTO_CONTINUE] Timeout: ${event.message}, auto-continuing...`);
|
|
4111
|
+
setTimeout(() => {
|
|
4112
|
+
sendContinue();
|
|
4113
|
+
}, 100);
|
|
4114
|
+
});
|
|
4115
|
+
return () => {
|
|
4116
|
+
unsubMaxTools();
|
|
4117
|
+
unsubTimeout();
|
|
4118
|
+
};
|
|
4119
|
+
}, [client, sendContinue]);
|
|
4021
4120
|
const sendMessage = react.useCallback(async () => {
|
|
4022
4121
|
const content = inputValue.trim();
|
|
4023
4122
|
if (!content || isStreaming || !isReady) return;
|