refactor(#1005): rename capabilities → tool-groups throughout UI
Section heading, element id, CSS classes, and JS functions all renamed from 'capabilities'/'cap-*' to 'tool-groups'/'tg-*' to accurately describe what the UI manages (tool-group permissions, not a capabilities system).
This commit is contained in:
parent
86a1591cfc
commit
a7d31046a6
3 changed files with 36 additions and 36 deletions
|
|
@ -2045,55 +2045,55 @@ body.logs-shell {
|
||||||
font-size: 0.85em;
|
font-size: 0.85em;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ─── capabilities (tool-group) table ──────────────────────────────
|
/* ─── tool-groups (permissions) table ──────────────────────────────
|
||||||
Agents × tool-groups matrix in the SYST3M tab. Horizontally
|
Agents × tool-groups matrix in the SYST3M tab. Horizontally
|
||||||
scrollable on narrow viewports. */
|
scrollable on narrow viewports. */
|
||||||
.cap-table-wrap {
|
.tg-table-wrap {
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
margin-top: 0.5em;
|
margin-top: 0.5em;
|
||||||
}
|
}
|
||||||
.cap-table {
|
.tg-table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
font-size: 0.82em;
|
font-size: 0.82em;
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
}
|
}
|
||||||
.cap-table th,
|
.tg-table th,
|
||||||
.cap-table td {
|
.tg-table td {
|
||||||
padding: 0.35em 0.6em;
|
padding: 0.35em 0.6em;
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
.cap-table thead th {
|
.tg-table thead th {
|
||||||
background: var(--bg-elev);
|
background: var(--bg-elev);
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
letter-spacing: 0.05em;
|
letter-spacing: 0.05em;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
.cap-agent-col {
|
.tg-agent-col {
|
||||||
text-align: left !important;
|
text-align: left !important;
|
||||||
min-width: 8em;
|
min-width: 8em;
|
||||||
}
|
}
|
||||||
.cap-agent-name {
|
.tg-agent-name {
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
.cap-default-label {
|
.tg-default-label {
|
||||||
margin-left: 0.4em;
|
margin-left: 0.4em;
|
||||||
font-size: 0.85em;
|
font-size: 0.85em;
|
||||||
}
|
}
|
||||||
.cap-cb {
|
.tg-cb {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
width: 1em;
|
width: 1em;
|
||||||
height: 1em;
|
height: 1em;
|
||||||
accent-color: var(--purple);
|
accent-color: var(--purple);
|
||||||
}
|
}
|
||||||
.cap-save-btn {
|
.tg-save-btn {
|
||||||
font-size: 0.78em;
|
font-size: 0.78em;
|
||||||
padding: 0.2em 0.6em;
|
padding: 0.2em 0.6em;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
.cap-row:hover td {
|
.tg-row:hover td {
|
||||||
background: var(--bg-elev);
|
background: var(--bg-elev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -172,15 +172,15 @@
|
||||||
<p class="meta">loading…</p>
|
<p class="meta">loading…</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- C4P4B1L1T13S: per-agent tool-group matrix. Rows = agents,
|
<!-- T00L GR0UPS: per-agent tool-group permission matrix. Rows = agents,
|
||||||
cols = tool groups fetched from GET /api/tool-groups.
|
cols = tool groups fetched from GET /api/tool-groups.
|
||||||
Checking / unchecking and saving POSTs to
|
Checking / unchecking and saving POSTs to
|
||||||
/api/tool-groups/{agent}; a rebuild is queued automatically.
|
/api/tool-groups/{agent}; a rebuild is queued automatically.
|
||||||
Absent agents default to the role default (shown in parens). -->
|
Absent agents default to the role default (shown in parens). -->
|
||||||
<h2>◆ C4P4B1L1T13S ◆</h2>
|
<h2>◆ T00L GR0UPS ◆</h2>
|
||||||
<div class="divider">══════════════════════════════════════════════════════════════</div>
|
<div class="divider">══════════════════════════════════════════════════════════════</div>
|
||||||
<p class="meta">per-agent tool-group assignments. columns are filled from the backend — adding a new group requires no UI change. agents without an explicit entry use the role default (agents: messaging, meta, inbox, execution; manager: all). saving queues a rebuild.</p>
|
<p class="meta">per-agent tool-group permissions. columns are filled from the backend — adding a new group requires no UI change. agents without an explicit entry use the role default (agents: messaging, meta, inbox, execution; manager: all). saving queues a rebuild.</p>
|
||||||
<div id="capabilities-section">
|
<div id="tool-groups-section">
|
||||||
<p class="meta">loading…</p>
|
<p class="meta">loading…</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -1204,13 +1204,13 @@ window.marked = marked;
|
||||||
root.append(ul);
|
root.append(ul);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── capabilities (tool-group) table ──────────────────────────────────────
|
// ── tool-groups (permissions) table ─────────────────────────────────────
|
||||||
// Fetched from GET /api/tool-groups on system tab activation and after
|
// Fetched from GET /api/tool-groups on system tab activation and after
|
||||||
// each save. Groups (columns) come from the backend so the UI doesn't
|
// each save. Groups (columns) come from the backend so the UI doesn't
|
||||||
// need updating when a new group is added.
|
// need updating when a new group is added.
|
||||||
|
|
||||||
async function fetchAndRenderCapabilities() {
|
async function fetchAndRenderToolGroups() {
|
||||||
const root = $('capabilities-section');
|
const root = $('tool-groups-section');
|
||||||
if (!root) return;
|
if (!root) return;
|
||||||
root.innerHTML = '';
|
root.innerHTML = '';
|
||||||
root.append(el('p', { class: 'meta' }, 'loading…'));
|
root.append(el('p', { class: 'meta' }, 'loading…'));
|
||||||
|
|
@ -1218,14 +1218,14 @@ window.marked = marked;
|
||||||
const resp = await fetch('/api/tool-groups');
|
const resp = await fetch('/api/tool-groups');
|
||||||
if (!resp.ok) throw new Error('HTTP ' + resp.status);
|
if (!resp.ok) throw new Error('HTTP ' + resp.status);
|
||||||
const data = await resp.json();
|
const data = await resp.json();
|
||||||
renderCapabilities(root, data);
|
renderToolGroups(root, data);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
root.innerHTML = '';
|
root.innerHTML = '';
|
||||||
root.append(el('p', { class: 'meta' }, 'fetch failed: ' + err));
|
root.append(el('p', { class: 'meta' }, 'fetch failed: ' + err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderCapabilities(root, data) {
|
function renderToolGroups(root, data) {
|
||||||
root.innerHTML = '';
|
root.innerHTML = '';
|
||||||
const { groups, assignments } = data;
|
const { groups, assignments } = data;
|
||||||
if (!groups || !groups.length) {
|
if (!groups || !groups.length) {
|
||||||
|
|
@ -1245,17 +1245,17 @@ window.marked = marked;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const wrap = el('div', { class: 'cap-table-wrap' });
|
const wrap = el('div', { class: 'tg-table-wrap' });
|
||||||
const table = el('table', { class: 'cap-table' });
|
const table = el('table', { class: 'tg-table' });
|
||||||
|
|
||||||
// Header row.
|
// Header row.
|
||||||
const thead = el('thead');
|
const thead = el('thead');
|
||||||
const hrow = el('tr');
|
const hrow = el('tr');
|
||||||
hrow.append(el('th', { class: 'cap-agent-col' }, 'agent'));
|
hrow.append(el('th', { class: 'tg-agent-col' }, 'agent'));
|
||||||
for (const g of groups) {
|
for (const g of groups) {
|
||||||
hrow.append(el('th', { class: 'cap-group-col', title: g }, g));
|
hrow.append(el('th', { class: 'tg-group-col', title: g }, g));
|
||||||
}
|
}
|
||||||
hrow.append(el('th', { class: 'cap-save-col' }, ''));
|
hrow.append(el('th', { class: 'tg-save-col' }, ''));
|
||||||
thead.append(hrow);
|
thead.append(hrow);
|
||||||
table.append(thead);
|
table.append(thead);
|
||||||
|
|
||||||
|
|
@ -1264,13 +1264,13 @@ window.marked = marked;
|
||||||
// Explicit assignment or empty = using role default.
|
// Explicit assignment or empty = using role default.
|
||||||
const assigned = assignments[name] || [];
|
const assigned = assignments[name] || [];
|
||||||
const hasExplicit = Object.prototype.hasOwnProperty.call(assignments, name);
|
const hasExplicit = Object.prototype.hasOwnProperty.call(assignments, name);
|
||||||
const tr = el('tr', { class: 'cap-row' });
|
const tr = el('tr', { class: 'tg-row' });
|
||||||
|
|
||||||
// Agent name cell.
|
// Agent name cell.
|
||||||
const nameTd = el('td', { class: 'cap-agent-col' });
|
const nameTd = el('td', { class: 'tg-agent-col' });
|
||||||
nameTd.append(el('span', { class: 'cap-agent-name' }, name));
|
nameTd.append(el('span', { class: 'tg-agent-name' }, name));
|
||||||
if (!hasExplicit) {
|
if (!hasExplicit) {
|
||||||
nameTd.append(el('span', { class: 'meta cap-default-label' }, '(default)'));
|
nameTd.append(el('span', { class: 'meta tg-default-label' }, '(default)'));
|
||||||
}
|
}
|
||||||
tr.append(nameTd);
|
tr.append(nameTd);
|
||||||
|
|
||||||
|
|
@ -1278,10 +1278,10 @@ window.marked = marked;
|
||||||
const checkboxes = [];
|
const checkboxes = [];
|
||||||
for (const g of groups) {
|
for (const g of groups) {
|
||||||
const checked = assigned.includes(g);
|
const checked = assigned.includes(g);
|
||||||
const td = el('td', { class: 'cap-group-col' });
|
const td = el('td', { class: 'tg-group-col' });
|
||||||
const cb = el('input', {
|
const cb = el('input', {
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
class: 'cap-cb',
|
class: 'tg-cb',
|
||||||
'data-group': g,
|
'data-group': g,
|
||||||
'aria-label': g,
|
'aria-label': g,
|
||||||
});
|
});
|
||||||
|
|
@ -1292,8 +1292,8 @@ window.marked = marked;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save button cell.
|
// Save button cell.
|
||||||
const saveTd = el('td', { class: 'cap-save-col' });
|
const saveTd = el('td', { class: 'tg-save-col' });
|
||||||
const saveBtn = el('button', { type: 'button', class: 'btn cap-save-btn' }, 'save');
|
const saveBtn = el('button', { type: 'button', class: 'btn tg-save-btn' }, 'save');
|
||||||
saveBtn.addEventListener('click', async () => {
|
saveBtn.addEventListener('click', async () => {
|
||||||
const selectedGroups = checkboxes
|
const selectedGroups = checkboxes
|
||||||
.filter((cb) => cb.checked)
|
.filter((cb) => cb.checked)
|
||||||
|
|
@ -1312,7 +1312,7 @@ window.marked = marked;
|
||||||
saveBtn.title = txt;
|
saveBtn.title = txt;
|
||||||
} else {
|
} else {
|
||||||
saveBtn.textContent = '✓';
|
saveBtn.textContent = '✓';
|
||||||
setTimeout(() => fetchAndRenderCapabilities(), 800);
|
setTimeout(() => fetchAndRenderToolGroups(), 800);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
saveBtn.textContent = 'err';
|
saveBtn.textContent = 'err';
|
||||||
|
|
@ -3516,7 +3516,7 @@ window.marked = marked;
|
||||||
if (target === 'schedules') refreshSchedules();
|
if (target === 'schedules') refreshSchedules();
|
||||||
// Capabilities table is on the system pane; fetch on each activation
|
// Capabilities table is on the system pane; fetch on each activation
|
||||||
// so it stays fresh without an SSE channel.
|
// so it stays fresh without an SSE channel.
|
||||||
if (target === 'system') fetchAndRenderCapabilities();
|
if (target === 'system') fetchAndRenderToolGroups();
|
||||||
}
|
}
|
||||||
function syncTabFromHash() {
|
function syncTabFromHash() {
|
||||||
const h = (window.location.hash || '#swarm').replace(/^#/, '');
|
const h = (window.location.hash || '#swarm').replace(/^#/, '');
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue