summaryrefslogtreecommitdiff
path: root/web/app.js
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-03-08 01:02:41 +0000
committerPeter Stone <thepeterstone@gmail.com>2026-03-08 06:31:50 +0000
commit560f42ba271ffc06eae1f93bccb26593cf93b150 (patch)
tree2c61732110dd2faf4eddbcd52ad6dbb98f7b431c /web/app.js
parent73d0d0a7fd49dee324c2cfc8816c6be93b07dac1 (diff)
feat(web): support agent type selection and rename Claude to Agent in UI
Diffstat (limited to 'web/app.js')
-rw-r--r--web/app.js105
1 files changed, 64 insertions, 41 deletions
diff --git a/web/app.js b/web/app.js
index a3c425e..05f548a 100644
--- a/web/app.js
+++ b/web/app.js
@@ -439,7 +439,7 @@ async function updateTask(taskId, body) {
}
function createEditForm(task) {
- const c = task.claude || {};
+ const a = task.agent || {};
const form = document.createElement('div');
form.className = 'task-inline-edit';
@@ -460,10 +460,25 @@ function createEditForm(task) {
form.appendChild(makeField('Name', 'input', { type: 'text', name: 'name', value: task.name || '' }));
form.appendChild(makeField('Description', 'textarea', { name: 'description', rows: '2', value: task.description || '' }));
- form.appendChild(makeField('Instructions', 'textarea', { name: 'instructions', rows: '4', value: c.instructions || '' }));
- form.appendChild(makeField('Model', 'input', { type: 'text', name: 'model', value: c.model || 'sonnet' }));
- form.appendChild(makeField('Working Directory', 'input', { type: 'text', name: 'working_dir', value: c.working_dir || '', placeholder: '/path/to/repo' }));
- form.appendChild(makeField('Max Budget (USD)', 'input', { type: 'number', name: 'max_budget_usd', step: '0.01', value: c.max_budget_usd != null ? String(c.max_budget_usd) : '1.00' }));
+ form.appendChild(makeField('Instructions', 'textarea', { name: 'instructions', rows: '4', value: a.instructions || '' }));
+
+ const typeLabel = document.createElement('label');
+ typeLabel.textContent = 'Agent Type';
+ const typeSel = document.createElement('select');
+ typeSel.name = 'type';
+ for (const val of ['claude', 'gemini']) {
+ const opt = document.createElement('option');
+ opt.value = val;
+ opt.textContent = val.charAt(0).toUpperCase() + val.slice(1);
+ if (val === (a.type || 'claude')) opt.selected = true;
+ typeSel.appendChild(opt);
+ }
+ typeLabel.appendChild(typeSel);
+ form.appendChild(typeLabel);
+
+ form.appendChild(makeField('Model', 'input', { type: 'text', name: 'model', value: a.model || 'sonnet' }));
+ form.appendChild(makeField('Working Directory', 'input', { type: 'text', name: 'working_dir', value: a.working_dir || '', placeholder: '/path/to/repo' }));
+ form.appendChild(makeField('Max Budget (USD)', 'input', { type: 'number', name: 'max_budget_usd', step: '0.01', value: a.max_budget_usd != null ? String(a.max_budget_usd) : '1.00' }));
form.appendChild(makeField('Timeout', 'input', { type: 'text', name: 'timeout', value: formatDurationForInput(task.timeout) || '15m', placeholder: '15m' }));
const prioLabel = document.createElement('label');
@@ -511,7 +526,8 @@ async function handleEditSave(taskId, form, saveBtn) {
const body = {
name: get('name'),
description: get('description'),
- claude: {
+ agent: {
+ type: get('type'),
model: get('model'),
instructions: get('instructions'),
working_dir: get('working_dir'),
@@ -986,11 +1002,12 @@ function buildValidatePayload() {
const instructions = f.querySelector('[name="instructions"]').value;
const working_dir = f.querySelector('[name="working_dir"]').value;
const model = f.querySelector('[name="model"]').value;
+ const type = f.querySelector('[name="type"]').value;
const allowedToolsEl = f.querySelector('[name="allowed_tools"]');
const allowed_tools = allowedToolsEl
? allowedToolsEl.value.split(',').map(s => s.trim()).filter(Boolean)
: [];
- return { name, claude: { instructions, working_dir, model, allowed_tools } };
+ return { name, agent: { type, instructions, working_dir, model, allowed_tools } };
}
function renderValidationResult(result) {
@@ -1079,6 +1096,7 @@ function initProjectSelect() {
const select = document.getElementById('project-select');
const newRow = document.getElementById('new-project-row');
const newInput = document.getElementById('new-project-input');
+ if (!select) return;
select.addEventListener('change', () => {
if (select.value === '__new__') {
newRow.hidden = false;
@@ -1110,7 +1128,8 @@ async function createTask(formData) {
const body = {
name: formData.get('name'),
description: '',
- claude: {
+ agent: {
+ type: formData.get('type'),
model: formData.get('model'),
instructions: formData.get('instructions'),
working_dir: workingDir,
@@ -1154,7 +1173,8 @@ async function saveTemplate(formData) {
const body = {
name: formData.get('name'),
description: formData.get('description'),
- claude: {
+ agent: {
+ type: formData.get('type'),
model: formData.get('model'),
instructions: formData.get('instructions'),
working_dir: formData.get('working_dir'),
@@ -1329,31 +1349,32 @@ function renderTaskPanel(task, executions) {
overview.appendChild(overviewGrid);
content.appendChild(overview);
- // ── Claude Config ──
- const c = task.claude || {};
- const claudeSection = makeSection('Claude Config');
- const claudeGrid = document.createElement('div');
- claudeGrid.className = 'meta-grid';
- claudeGrid.append(
- makeMetaItem('Model', c.model),
- makeMetaItem('Max Budget', c.max_budget_usd != null ? `$${c.max_budget_usd.toFixed(2)}` : '—'),
- makeMetaItem('Working Dir', c.working_dir),
- makeMetaItem('Permission Mode', c.permission_mode || 'default'),
+ // ── Agent Config ──
+ const a = task.agent || {};
+ const agentSection = makeSection('Agent Config');
+ const agentGrid = document.createElement('div');
+ agentGrid.className = 'meta-grid';
+ agentGrid.append(
+ makeMetaItem('Type', a.type || 'claude'),
+ makeMetaItem('Model', a.model),
+ makeMetaItem('Max Budget', a.max_budget_usd != null ? `$${a.max_budget_usd.toFixed(2)}` : '—'),
+ makeMetaItem('Working Dir', a.working_dir),
+ makeMetaItem('Permission Mode', a.permission_mode || 'default'),
);
- if (c.allowed_tools && c.allowed_tools.length > 0) {
- claudeGrid.append(makeMetaItem('Allowed Tools', c.allowed_tools.join(', '), { fullWidth: true }));
+ if (a.allowed_tools && a.allowed_tools.length > 0) {
+ agentGrid.append(makeMetaItem('Allowed Tools', a.allowed_tools.join(', '), { fullWidth: true }));
}
- if (c.disallowed_tools && c.disallowed_tools.length > 0) {
- claudeGrid.append(makeMetaItem('Disallowed Tools', c.disallowed_tools.join(', '), { fullWidth: true }));
+ if (a.disallowed_tools && a.disallowed_tools.length > 0) {
+ agentGrid.append(makeMetaItem('Disallowed Tools', a.disallowed_tools.join(', '), { fullWidth: true }));
}
- if (c.instructions) {
- claudeGrid.append(makeMetaItem('Instructions', c.instructions, { fullWidth: true, code: true }));
+ if (a.instructions) {
+ agentGrid.append(makeMetaItem('Instructions', a.instructions, { fullWidth: true, code: true }));
}
- if (c.system_prompt_append) {
- claudeGrid.append(makeMetaItem('System Prompt Append', c.system_prompt_append, { fullWidth: true, code: true }));
+ if (a.system_prompt_append) {
+ agentGrid.append(makeMetaItem('System Prompt Append', a.system_prompt_append, { fullWidth: true, code: true }));
}
- claudeSection.appendChild(claudeGrid);
- content.appendChild(claudeSection);
+ agentSection.appendChild(agentGrid);
+ content.appendChild(agentSection);
// ── Execution Settings ──
const settingsSection = makeSection('Execution Settings');
@@ -1709,23 +1730,25 @@ if (typeof document !== 'undefined') document.addEventListener('DOMContentLoaded
const f = document.getElementById('task-form');
if (result.name)
f.querySelector('[name="name"]').value = result.name;
- if (result.claude && result.claude.instructions)
- f.querySelector('[name="instructions"]').value = result.claude.instructions;
- if (result.claude && result.claude.working_dir) {
- const sel = document.getElementById('project-select');
- const exists = [...sel.options].some(o => o.value === result.claude.working_dir);
+ if (result.agent && result.agent.instructions)
+ f.querySelector('[name="instructions"]').value = result.agent.instructions;
+ if (result.agent && result.agent.working_dir) {
+ const pSel = document.getElementById('project-select');
+ const exists = [...pSel.options].some(o => o.value === result.agent.working_dir);
if (exists) {
- sel.value = result.claude.working_dir;
+ pSel.value = result.agent.working_dir;
} else {
- sel.value = '__new__';
+ pSel.value = '__new__';
document.getElementById('new-project-row').hidden = false;
- document.getElementById('new-project-input').value = result.claude.working_dir;
+ document.getElementById('new-project-input').value = result.agent.working_dir;
}
}
- if (result.claude && result.claude.model)
- f.querySelector('[name="model"]').value = result.claude.model;
- if (result.claude && result.claude.max_budget_usd != null)
- f.querySelector('[name="max_budget_usd"]').value = result.claude.max_budget_usd;
+ if (result.agent && result.agent.model)
+ f.querySelector('[name="model"]').value = result.agent.model;
+ if (result.agent && result.agent.type)
+ f.querySelector('[name="type"]').value = result.agent.type;
+ if (result.agent && result.agent.max_budget_usd != null)
+ f.querySelector('[name="max_budget_usd"]').value = result.agent.max_budget_usd;
if (result.timeout)
f.querySelector('[name="timeout"]').value = result.timeout;
if (result.priority) {