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:
12
README.md
12
README.md
@@ -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 |
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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');
|
||||||
|
|||||||
@@ -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');
|
||||||
|
|||||||
@@ -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) => {
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user