Adicionar campo diretório de trabalho no modal de execução

- Campo execute-workdir no modal com valor pré-preenchido do agente
- Frontend envia workingDirectory na API de execução
- Backend aceita e aplica override de workingDirectory via metadata
- Pré-preenche com config do agente selecionado ao abrir modal
- Adiciona stopAll ao scheduler e limpa README
This commit is contained in:
Frederico Castro
2026-02-28 02:20:09 -03:00
parent 7a4ab2279d
commit fa47538a8f
8 changed files with 38 additions and 17 deletions

View File

@@ -122,18 +122,6 @@ git deploy # Push + deploy completo
bash scripts/deploy.sh --skip-push # Apenas deploy, sem push 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áveis de Ambiente
| Variável | Descrição | Padrão | | Variável | Descrição | Padrão |

View File

@@ -998,6 +998,17 @@
></textarea> ></textarea>
</div> </div>
<div class="form-group">
<label class="form-label" for="execute-workdir">Diretório de Trabalho</label>
<input
type="text"
class="input"
id="execute-workdir"
value="/home/projetos/"
autocomplete="off"
/>
</div>
<div class="form-group"> <div class="form-group">
<label class="form-label">Arquivos de Contexto</label> <label class="form-label">Arquivos de Contexto</label>
<div class="dropzone" id="execute-dropzone"> <div class="dropzone" id="execute-dropzone">

View File

@@ -38,8 +38,9 @@ const API = {
create(data) { return API.request('POST', '/agents', data); }, create(data) { return API.request('POST', '/agents', data); },
update(id, data) { return API.request('PUT', `/agents/${id}`, data); }, update(id, data) { return API.request('PUT', `/agents/${id}`, data); },
delete(id) { return API.request('DELETE', `/agents/${id}`); }, delete(id) { return API.request('DELETE', `/agents/${id}`); },
execute(id, task, instructions, contextFiles) { execute(id, task, instructions, contextFiles, workingDirectory) {
const body = { task, instructions }; const body = { task, instructions };
if (workingDirectory) body.workingDirectory = workingDirectory;
if (contextFiles && contextFiles.length > 0) body.contextFiles = contextFiles; if (contextFiles && contextFiles.length > 0) body.contextFiles = contextFiles;
return API.request('POST', `/agents/${id}/execute`, body); return API.request('POST', `/agents/${id}/execute`, body);
}, },

View File

@@ -874,6 +874,7 @@ const App = {
} }
const instructions = document.getElementById('execute-instructions')?.value.trim() || ''; const instructions = document.getElementById('execute-instructions')?.value.trim() || '';
const workingDirectory = document.getElementById('execute-workdir')?.value.trim() || '';
try { try {
const selectEl = document.getElementById('execute-agent-select'); const selectEl = document.getElementById('execute-agent-select');
@@ -890,7 +891,7 @@ const App = {
Terminal.disableChat(); Terminal.disableChat();
App._lastAgentName = agentName; App._lastAgentName = agentName;
await API.agents.execute(agentId, task, instructions, contextFiles); await API.agents.execute(agentId, task, instructions, contextFiles, workingDirectory);
if (dropzone) dropzone.reset(); if (dropzone) dropzone.reset();
Modal.close('execute-modal-overlay'); Modal.close('execute-modal-overlay');

View File

@@ -366,6 +366,12 @@ const AgentsUI = {
if (App._executeDropzone) App._executeDropzone.reset(); 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(); AgentsUI._loadSavedTasks();
Modal.open('execute-modal-overlay'); Modal.open('execute-modal-overlay');

View File

@@ -180,8 +180,13 @@ export function executeTask(agentId, task, instructions, wsCallback, metadata =
effectiveInstructions += `\n\n<agentes_disponiveis>\n${agentList}\n</agentes_disponiveis>`; effectiveInstructions += `\n\n<agentes_disponiveis>\n${agentList}\n</agentes_disponiveis>`;
} }
const effectiveConfig = { ...agent.config };
if (metadata.workingDirectoryOverride) {
effectiveConfig.workingDirectory = metadata.workingDirectoryOverride;
}
const executionId = executor.execute( const executionId = executor.execute(
agent.config, effectiveConfig,
{ description: task, instructions: effectiveInstructions }, { description: task, instructions: effectiveInstructions },
{ {
onData: (parsed, execId) => { onData: (parsed, execId) => {

View File

@@ -160,6 +160,13 @@ export function restoreSchedules(executeFn) {
if (restored > 0) console.log(`[scheduler] ${restored} agendamento(s) restaurado(s)`); 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) { export function on(event, listener) {
emitter.on(event, listener); emitter.on(event, listener);
} }

View File

@@ -167,12 +167,14 @@ function buildContextFilesPrompt(contextFiles) {
router.post('/agents/:id/execute', (req, res) => { router.post('/agents/:id/execute', (req, res) => {
try { 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' }); if (!task) return res.status(400).json({ error: 'task é obrigatório' });
const clientId = req.headers['x-client-id'] || null; const clientId = req.headers['x-client-id'] || null;
const filesPrompt = buildContextFilesPrompt(contextFiles); const filesPrompt = buildContextFilesPrompt(contextFiles);
const fullTask = task + filesPrompt; 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' }); res.status(202).json({ executionId, status: 'started' });
} catch (err) { } catch (err) {
const status = err.message.includes('não encontrado') ? 404 : 400; const status = err.message.includes('não encontrado') ? 404 : 400;