jules / patch_app_timer.py
GraziePrego's picture
Upload folder using huggingface_hub
34450be verified
import re
with open("App.tsx", "r") as f:
content = f.read()
# 1. Add Timer State
state_search = "const [templateQueue, setTemplateQueue] = useState<Record<string, string[]>>({});"
state_replace = """const [templateQueue, setTemplateQueue] = useState<Record<string, string[]>>({});
const [hfTimerQueue, setHfTimerQueue] = useState<Record<string, { templates: string[], nextExecutionTime: number }>>(() => {
const stored = localStorage.getItem('jules_hf_timer_queue');
return stored ? JSON.parse(stored) : {};
});
const [hfWizardOpen, setHfWizardOpen] = useState(false);"""
content = content.replace(state_search, state_replace)
# 2. Add Timer logic & persist effect
effect_search = """ // --- Message Sending & Event Streaming ---"""
effect_replace = """ // Persist timer queue
useEffect(() => {
localStorage.setItem('jules_hf_timer_queue', JSON.stringify(hfTimerQueue));
}, [hfTimerQueue]);
// Timer interval to process HF Deployment Cues every 10 seconds
useEffect(() => {
const interval = setInterval(() => {
setHfTimerQueue(prevQueue => {
const now = Date.now();
const newQueue = { ...prevQueue };
let hasChanges = false;
for (const [sessionId, queueData] of Object.entries(newQueue)) {
if (queueData.templates.length > 0 && now >= queueData.nextExecutionTime) {
// Time to fire the next template
const templateToFire = queueData.templates[0];
const remainingTemplates = queueData.templates.slice(1);
// Check if we are currently loading or recording, maybe skip this tick?
// Actually, let's just fire it anyway.
console.log(`[TimerQueue] Firing template for session ${sessionId}`);
// Fire it by creating a synthetic local message and calling sendMessage
const fakeUserMessage = {
id: `local-timer-${Date.now()}`,
name: `local-msg-${Date.now()}`,
createTime: new Date().toISOString(),
originator: 'user' as const,
text: templateToFire
};
// We can't update localHistory cleanly inside a setState, but we can do a side-effect.
// Since we don't have direct access to setLocalHistory here cleanly, we will call _sendText out of band.
// Wait, let's handle the side effect via a setTimeout to break out of the setState context.
setTimeout(() => {
// Send the message
_sendText(sessionId, templateToFire).catch(e => console.error("Timer send failed", e));
}, 0);
if (remainingTemplates.length > 0) {
newQueue[sessionId] = {
templates: remainingTemplates,
// 30 minutes = 30 * 60 * 1000
nextExecutionTime: now + 30 * 60 * 1000
};
} else {
delete newQueue[sessionId];
}
hasChanges = true;
}
}
return hasChanges ? newQueue : prevQueue;
});
}, 10000); // check every 10 seconds
return () => clearInterval(interval);
}, []);
// --- Message Sending & Event Streaming ---"""
content = content.replace(effect_search, effect_replace)
# 3. Add handler for HF Wizard
handler_search = """ const handleHuggingFaceCue = async () => {
if (!currentSessionId) return;
const templates = [
"Please perform a deep investigation of the codebase to understand its current state and architecture. Look for dependencies, main entry points, and service patterns. READY",
"Based on the investigation, create a detailed project vision and implementation plan. Outline the necessary changes and new components. READY",
"Implement the changes according to the plan and prepare for deployment. Ensure all tests pass and documentation is updated. READY"
];
// Send the first template immediately if queue is empty and we aren't currently loading.
// Otherwise, add everything to the queue.
const currentQueue = templateQueue[currentSessionId] || [];
if (currentQueue.length === 0 && !isLoading) {
const first = templates[0];
const rest = templates.slice(1);
setTemplateQueue(prev => ({
...prev,
[currentSessionId]: rest
}));
await _sendText(currentSessionId, first);
} else {
setTemplateQueue(prev => ({
...prev,
[currentSessionId]: [...currentQueue, ...templates]
}));
}
};"""
handler_replace = """ const handleHuggingFaceCue = () => {
setHfWizardOpen(true);
};
const handleStartHfTimer = async (config: any) => {
if (config.targetType === 'new') {
try {
setIsLoading(true);
const session = await julesService.current.createSession(
config.githubRepoId.split('/')[1] || config.githubRepoId,
config.templates[0],
config.sourceId,
'AUTO_CREATE_PR'
);
setSessionAgentMap(prev => ({ ...prev, [session.id]: currentAgent.id }));
setSessions(prev => [session, ...prev]);
setCurrentSessionId(session.id);
if (config.templates.length > 1) {
setHfTimerQueue(prev => ({
...prev,
[session.id]: {
templates: config.templates.slice(1),
nextExecutionTime: Date.now() + 30 * 60 * 1000
}
}));
}
setIsLoading(false);
} catch (e) {
alert("Failed to create session: " + e);
setIsLoading(false);
}
} else if (config.targetType === 'current' && currentSessionId) {
// Immediately send the first template
await _sendText(currentSessionId, config.templates[0]);
if (config.templates.length > 1) {
setHfTimerQueue(prev => ({
...prev,
[currentSessionId]: {
templates: config.templates.slice(1),
nextExecutionTime: Date.now() + 30 * 60 * 1000
}
}));
}
}
};"""
content = content.replace(handler_search, handler_replace)
with open("App.tsx", "w") as f:
f.write(content)