Spaces:
Paused
Paused
| 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) | |