diff --git a/frontend/packages/dashboard/src/dashboard.css b/frontend/packages/dashboard/src/dashboard.css
index cf4e0ab1..e10073be 100644
--- a/frontend/packages/dashboard/src/dashboard.css
+++ b/frontend/packages/dashboard/src/dashboard.css
@@ -2045,55 +2045,55 @@ body.logs-shell {
font-size: 0.85em;
}
-/* ─── capabilities (tool-group) table ──────────────────────────────
+/* ─── tool-groups (permissions) table ──────────────────────────────
Agents × tool-groups matrix in the SYST3M tab. Horizontally
scrollable on narrow viewports. */
-.cap-table-wrap {
+.tg-table-wrap {
overflow-x: auto;
margin-top: 0.5em;
}
-.cap-table {
+.tg-table {
border-collapse: collapse;
font-size: 0.82em;
min-width: 100%;
}
-.cap-table th,
-.cap-table td {
+.tg-table th,
+.tg-table td {
padding: 0.35em 0.6em;
border: 1px solid var(--border);
text-align: center;
vertical-align: middle;
}
-.cap-table thead th {
+.tg-table thead th {
background: var(--bg-elev);
color: var(--muted);
letter-spacing: 0.05em;
white-space: nowrap;
}
-.cap-agent-col {
+.tg-agent-col {
text-align: left !important;
min-width: 8em;
}
-.cap-agent-name {
+.tg-agent-name {
color: var(--fg);
font-weight: 600;
}
-.cap-default-label {
+.tg-default-label {
margin-left: 0.4em;
font-size: 0.85em;
}
-.cap-cb {
+.tg-cb {
cursor: pointer;
width: 1em;
height: 1em;
accent-color: var(--purple);
}
-.cap-save-btn {
+.tg-save-btn {
font-size: 0.78em;
padding: 0.2em 0.6em;
white-space: nowrap;
}
-.cap-row:hover td {
+.tg-row:hover td {
background: var(--bg-elev);
}
diff --git a/frontend/packages/dashboard/src/index.html b/frontend/packages/dashboard/src/index.html
index 2f43eb19..47902292 100644
--- a/frontend/packages/dashboard/src/index.html
+++ b/frontend/packages/dashboard/src/index.html
@@ -172,15 +172,15 @@
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.
-
+
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.
+
diff --git a/frontend/packages/dashboard/src/tabs.js b/frontend/packages/dashboard/src/tabs.js
index f639de0c..f99afc04 100644
--- a/frontend/packages/dashboard/src/tabs.js
+++ b/frontend/packages/dashboard/src/tabs.js
@@ -1204,13 +1204,13 @@ window.marked = marked;
root.append(ul);
}
- // ── capabilities (tool-group) table ──────────────────────────────────────
+ // ── tool-groups (permissions) table ─────────────────────────────────────
// 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
// need updating when a new group is added.
- async function fetchAndRenderCapabilities() {
- const root = $('capabilities-section');
+ async function fetchAndRenderToolGroups() {
+ const root = $('tool-groups-section');
if (!root) return;
root.innerHTML = '';
root.append(el('p', { class: 'meta' }, 'loading…'));
@@ -1218,14 +1218,14 @@ window.marked = marked;
const resp = await fetch('/api/tool-groups');
if (!resp.ok) throw new Error('HTTP ' + resp.status);
const data = await resp.json();
- renderCapabilities(root, data);
+ renderToolGroups(root, data);
} catch (err) {
root.innerHTML = '';
root.append(el('p', { class: 'meta' }, 'fetch failed: ' + err));
}
}
- function renderCapabilities(root, data) {
+ function renderToolGroups(root, data) {
root.innerHTML = '';
const { groups, assignments } = data;
if (!groups || !groups.length) {
@@ -1245,17 +1245,17 @@ window.marked = marked;
return;
}
- const wrap = el('div', { class: 'cap-table-wrap' });
- const table = el('table', { class: 'cap-table' });
+ const wrap = el('div', { class: 'tg-table-wrap' });
+ const table = el('table', { class: 'tg-table' });
// Header row.
const thead = el('thead');
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) {
- 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);
table.append(thead);
@@ -1264,13 +1264,13 @@ window.marked = marked;
// Explicit assignment or empty = using role default.
const assigned = 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.
- const nameTd = el('td', { class: 'cap-agent-col' });
- nameTd.append(el('span', { class: 'cap-agent-name' }, name));
+ const nameTd = el('td', { class: 'tg-agent-col' });
+ nameTd.append(el('span', { class: 'tg-agent-name' }, name));
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);
@@ -1278,10 +1278,10 @@ window.marked = marked;
const checkboxes = [];
for (const g of groups) {
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', {
type: 'checkbox',
- class: 'cap-cb',
+ class: 'tg-cb',
'data-group': g,
'aria-label': g,
});
@@ -1292,8 +1292,8 @@ window.marked = marked;
}
// Save button cell.
- const saveTd = el('td', { class: 'cap-save-col' });
- const saveBtn = el('button', { type: 'button', class: 'btn cap-save-btn' }, 'save');
+ const saveTd = el('td', { class: 'tg-save-col' });
+ const saveBtn = el('button', { type: 'button', class: 'btn tg-save-btn' }, 'save');
saveBtn.addEventListener('click', async () => {
const selectedGroups = checkboxes
.filter((cb) => cb.checked)
@@ -1312,7 +1312,7 @@ window.marked = marked;
saveBtn.title = txt;
} else {
saveBtn.textContent = '✓';
- setTimeout(() => fetchAndRenderCapabilities(), 800);
+ setTimeout(() => fetchAndRenderToolGroups(), 800);
}
} catch (err) {
saveBtn.textContent = 'err';
@@ -3516,7 +3516,7 @@ window.marked = marked;
if (target === 'schedules') refreshSchedules();
// Capabilities table is on the system pane; fetch on each activation
// so it stays fresh without an SSE channel.
- if (target === 'system') fetchAndRenderCapabilities();
+ if (target === 'system') fetchAndRenderToolGroups();
}
function syncTabFromHash() {
const h = (window.location.hash || '#swarm').replace(/^#/, '');