diff --git a/README.md b/README.md index 139efe5..83670e7 100644 --- a/README.md +++ b/README.md @@ -122,18 +122,6 @@ git deploy # Push + deploy completo bash scripts/deploy.sh --skip-push # Apenas deploy, sem push ``` -### Verificar status - -```bash -ssh -p 2222 fred@192.168.1.151 "docker logs agents-orchestrator --tail 20" -``` - -### Reiniciar - -```bash -ssh -p 2222 fred@192.168.1.151 "cd ~/vps && docker compose restart agents-orchestrator" -``` - ## Variáveis de Ambiente | Variável | Descrição | Padrão | diff --git a/public/app.html b/public/app.html index e3b5f12..0c32d63 100644 --- a/public/app.html +++ b/public/app.html @@ -998,6 +998,17 @@ > +
+ + +
+
diff --git a/public/js/api.js b/public/js/api.js index 424c30c..813618d 100644 --- a/public/js/api.js +++ b/public/js/api.js @@ -38,8 +38,9 @@ const API = { create(data) { return API.request('POST', '/agents', data); }, update(id, data) { return API.request('PUT', `/agents/${id}`, data); }, delete(id) { return API.request('DELETE', `/agents/${id}`); }, - execute(id, task, instructions, contextFiles) { + execute(id, task, instructions, contextFiles, workingDirectory) { const body = { task, instructions }; + if (workingDirectory) body.workingDirectory = workingDirectory; if (contextFiles && contextFiles.length > 0) body.contextFiles = contextFiles; return API.request('POST', `/agents/${id}/execute`, body); }, diff --git a/public/js/app.js b/public/js/app.js index 97739a6..f15da09 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -874,6 +874,7 @@ const App = { } const instructions = document.getElementById('execute-instructions')?.value.trim() || ''; + const workingDirectory = document.getElementById('execute-workdir')?.value.trim() || ''; try { const selectEl = document.getElementById('execute-agent-select'); @@ -890,7 +891,7 @@ const App = { Terminal.disableChat(); App._lastAgentName = agentName; - await API.agents.execute(agentId, task, instructions, contextFiles); + await API.agents.execute(agentId, task, instructions, contextFiles, workingDirectory); if (dropzone) dropzone.reset(); Modal.close('execute-modal-overlay'); diff --git a/public/js/components/agents.js b/public/js/components/agents.js index 086b5ff..2aadb7e 100644 --- a/public/js/components/agents.js +++ b/public/js/components/agents.js @@ -366,6 +366,12 @@ const AgentsUI = { if (App._executeDropzone) App._executeDropzone.reset(); + const selectedAgent = allAgents.find(a => a.id === agentId); + const workdirEl = document.getElementById('execute-workdir'); + if (workdirEl) { + workdirEl.value = (selectedAgent?.config?.workingDirectory) || '/home/projetos/'; + } + AgentsUI._loadSavedTasks(); Modal.open('execute-modal-overlay'); diff --git a/src/agents/manager.js b/src/agents/manager.js index 4aefc07..6e81e98 100644 --- a/src/agents/manager.js +++ b/src/agents/manager.js @@ -180,8 +180,13 @@ export function executeTask(agentId, task, instructions, wsCallback, metadata = effectiveInstructions += `\n\n\n${agentList}\n`; } + const effectiveConfig = { ...agent.config }; + if (metadata.workingDirectoryOverride) { + effectiveConfig.workingDirectory = metadata.workingDirectoryOverride; + } + const executionId = executor.execute( - agent.config, + effectiveConfig, { description: task, instructions: effectiveInstructions }, { onData: (parsed, execId) => { diff --git a/src/agents/scheduler.js b/src/agents/scheduler.js index 9abd90c..959b391 100644 --- a/src/agents/scheduler.js +++ b/src/agents/scheduler.js @@ -160,6 +160,13 @@ export function restoreSchedules(executeFn) { if (restored > 0) console.log(`[scheduler] ${restored} agendamento(s) restaurado(s)`); } +export function stopAll() { + for (const [, entry] of schedules) { + entry.task.stop(); + } + schedules.clear(); +} + export function on(event, listener) { emitter.on(event, listener); } diff --git a/src/routes/api.js b/src/routes/api.js index 2ab856e..6a65769 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -167,12 +167,14 @@ function buildContextFilesPrompt(contextFiles) { router.post('/agents/:id/execute', (req, res) => { try { - const { task, instructions, contextFiles } = req.body; + const { task, instructions, contextFiles, workingDirectory } = req.body; if (!task) return res.status(400).json({ error: 'task é obrigatório' }); const clientId = req.headers['x-client-id'] || null; const filesPrompt = buildContextFilesPrompt(contextFiles); const fullTask = task + filesPrompt; - const executionId = manager.executeTask(req.params.id, fullTask, instructions, (msg) => wsCallback(msg, clientId)); + const metadata = {}; + if (workingDirectory) metadata.workingDirectoryOverride = workingDirectory; + const executionId = manager.executeTask(req.params.id, fullTask, instructions, (msg) => wsCallback(msg, clientId), metadata); res.status(202).json({ executionId, status: 'started' }); } catch (err) { const status = err.message.includes('não encontrado') ? 404 : 400;