@oddessentials/agent-guild 1.22.0 → 1.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/native/win32-arm64/agent-guild-report.exe +0 -0
- package/bin/native/win32-x64/agent-guild-report.exe +0 -0
- package/bin/windows/arm64/agent-guild-start.exe +0 -0
- package/bin/windows/x64/agent-guild-start.exe +0 -0
- package/docs/api.md +23 -12
- package/node_modules/node-pty/prebuilds/win32-arm64/conpty.node +0 -0
- package/node_modules/node-pty/prebuilds/win32-arm64/conpty_console_list.node +0 -0
- package/node_modules/node-pty/prebuilds/win32-x64/conpty.node +0 -0
- package/node_modules/node-pty/prebuilds/win32-x64/conpty_console_list.node +0 -0
- package/node_modules/smol-toml/LICENSE +24 -0
- package/node_modules/smol-toml/README.md +605 -0
- package/node_modules/smol-toml/dist/date.d.ts +41 -0
- package/node_modules/smol-toml/dist/date.js +156 -0
- package/node_modules/smol-toml/dist/error.d.ts +37 -0
- package/node_modules/smol-toml/dist/error.js +67 -0
- package/node_modules/smol-toml/dist/extract.js +293 -0
- package/node_modules/smol-toml/dist/index.cjs +771 -0
- package/node_modules/smol-toml/dist/index.d.ts +44 -0
- package/node_modules/smol-toml/dist/index.js +34 -0
- package/node_modules/smol-toml/dist/parse.d.ts +73 -0
- package/node_modules/smol-toml/dist/parse.js +164 -0
- package/node_modules/smol-toml/dist/primitive.js +151 -0
- package/node_modules/smol-toml/dist/stringify.d.ts +32 -0
- package/node_modules/smol-toml/dist/stringify.js +219 -0
- package/node_modules/smol-toml/dist/struct.js +156 -0
- package/node_modules/smol-toml/dist/util.d.ts +43 -0
- package/node_modules/smol-toml/dist/util.js +57 -0
- package/node_modules/smol-toml/package.json +68 -0
- package/package.json +2 -1
- package/src/manager/config.mjs +10 -10
- package/src/manager/mcp-connect.mjs +332 -98
- package/src/manager/server.mjs +6 -3
- package/web/app.js +180 -42
- package/web/index.html +23 -7
- package/web/styles.css +28 -9
- package/web/yard/art.json +1 -1
- package/web/yard/yard.css +1 -0
package/web/app.js
CHANGED
|
@@ -47,6 +47,7 @@ const DOCK_WIDTH_KEY = 'agentGuild.dockWidth';
|
|
|
47
47
|
const PANES_KEY = 'agentGuild.panes';
|
|
48
48
|
const SPLIT_RATIO_KEY = 'agentGuild.splitRatio';
|
|
49
49
|
const TERMINAL_FONT_KEY = 'agentGuild.terminalFontSize';
|
|
50
|
+
const TOOL_CARDS_KEY = 'agentGuild.toolCards';
|
|
50
51
|
const RELEASES_URL = 'https://github.com/oddessentials/agent-guild/releases';
|
|
51
52
|
const SUPPORT_URL = 'https://oddessentials.ai/donate/?ref=agent-guild';
|
|
52
53
|
const isMac = /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent);
|
|
@@ -1624,6 +1625,7 @@ function selectAccount(provider, id) {
|
|
|
1624
1625
|
renderAccounts(card, provider);
|
|
1625
1626
|
renderUsage(card, provider);
|
|
1626
1627
|
renderReportingSetup(card, provider);
|
|
1628
|
+
renderMcpSetup(card, provider);
|
|
1627
1629
|
}
|
|
1628
1630
|
refreshPendingActions();
|
|
1629
1631
|
notifyViews();
|
|
@@ -1966,6 +1968,7 @@ function renderAccounts(card, provider) {
|
|
|
1966
1968
|
renderAccounts(card, provider);
|
|
1967
1969
|
renderUsage(card, provider);
|
|
1968
1970
|
renderReportingSetup(card, provider);
|
|
1971
|
+
renderMcpSetup(card, provider);
|
|
1969
1972
|
});
|
|
1970
1973
|
return chip;
|
|
1971
1974
|
}));
|
|
@@ -2265,51 +2268,89 @@ function renderReportingSetup(card, provider) {
|
|
|
2265
2268
|
};
|
|
2266
2269
|
}
|
|
2267
2270
|
|
|
2268
|
-
const
|
|
2271
|
+
const openMcp = new Set();
|
|
2272
|
+
const mcpBusy = new Set();
|
|
2269
2273
|
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
if (
|
|
2277
|
-
|
|
2274
|
+
/** What the card's Agent Guild MCP section says about one account, and the change it offers. */
|
|
2275
|
+
function mcpView(provider, entry) {
|
|
2276
|
+
const tool = provider.tool;
|
|
2277
|
+
const from = entry.from ? `${tool} takes it from ${entry.from}'s settings. ` : '';
|
|
2278
|
+
const yours = !entry.managed && !entry.from ? 'You added it yourself. ' : '';
|
|
2279
|
+
const typing = entry.allowInput ? ' It can also type into sessions.' : '';
|
|
2280
|
+
if (entry.state === 'checking') return { label: 'Checking…', status: `Reading ${tool}'s MCP settings.` };
|
|
2281
|
+
if (entry.state === 'off') {
|
|
2282
|
+
return { label: 'Off', status: entry.detail ? `${entry.detail} Turn on adds Agent Guild's own server to ${tool}'s settings.` : `Not added to ${tool}.`, action: 'on', button: 'Turn on' };
|
|
2283
|
+
}
|
|
2284
|
+
if (entry.state === 'on') {
|
|
2285
|
+
return {
|
|
2286
|
+
label: 'On', status: `${from}${yours}New ${tool} sessions can use it.${typing}`, action: 'off', button: 'Turn off',
|
|
2287
|
+
ask: yours ? { message: `Remove the agent-guild server you added to ${tool}'s settings?\n\n${entry.command}`, ok: 'Remove' } : null,
|
|
2288
|
+
};
|
|
2289
|
+
}
|
|
2290
|
+
if (entry.state === 'disabled') {
|
|
2291
|
+
const replace = provider.mcp.mode === 'codex' && !entry.managed;
|
|
2292
|
+
return {
|
|
2293
|
+
label: 'Turned off', status: `${from}${yours}It is turned off in ${tool}.`, action: replace ? 'replace' : 'on', button: replace ? 'Replace…' : 'Turn on',
|
|
2294
|
+
ask: replace ? { message: `${tool} can turn this server on only by replacing it with Agent Guild's own. Replace it?\n\nNow: ${entry.command}`, ok: 'Replace' } : null,
|
|
2295
|
+
};
|
|
2296
|
+
}
|
|
2297
|
+
if (entry.state === 'conflict') {
|
|
2298
|
+
return {
|
|
2299
|
+
label: 'Conflict', warn: true, action: 'replace', button: 'Replace…',
|
|
2300
|
+
status: `${entry.from ? `${tool} takes a server named agent-guild from ${entry.from}'s settings that` : `${tool} already has a server named agent-guild that`} ${entry.detail}.`,
|
|
2301
|
+
ask: entry.from
|
|
2302
|
+
? { message: `Add Agent Guild's own MCP server to ${tool}'s settings? ${tool} then uses it instead of the one in ${entry.from}'s settings, which stays as it is.`, ok: 'Add' }
|
|
2303
|
+
: { message: `Replace the agent-guild server in ${tool}'s settings with Agent Guild's own?${entry.command ? `\n\nNow: ${entry.command}` : ''}`, ok: 'Replace' },
|
|
2304
|
+
};
|
|
2305
|
+
}
|
|
2306
|
+
return { label: 'Unreadable', warn: true, status: `Agent Guild can't read ${tool}'s MCP settings: ${entry.detail}.` };
|
|
2278
2307
|
}
|
|
2279
2308
|
|
|
2280
2309
|
function renderMcpSetup(card, provider) {
|
|
2281
|
-
const
|
|
2282
|
-
const
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2310
|
+
const box = card.querySelector('.mcp');
|
|
2311
|
+
const account = selectedAccount(provider);
|
|
2312
|
+
const entry = provider.mcp?.accounts.find((a) => a.id === account.id);
|
|
2313
|
+
box.hidden = !provider.available || !entry;
|
|
2314
|
+
if (box.hidden) return;
|
|
2315
|
+
const view = mcpView(provider, entry);
|
|
2316
|
+
const key = `${provider.id}:${entry.id}`;
|
|
2317
|
+
box.open = openMcp.has(provider.id);
|
|
2318
|
+
box.ontoggle = () => (box.open ? openMcp.add(provider.id) : openMcp.delete(provider.id));
|
|
2319
|
+
box.classList.toggle('warned', Boolean(view.warn));
|
|
2320
|
+
box.querySelector('.mcp-state').textContent = view.label;
|
|
2321
|
+
box.querySelector('.mcp-about').textContent = `Lets ${provider.tool} see your Agent Guild sessions, read their replies and screens, and start or stop sessions when you approve.`;
|
|
2322
|
+
box.querySelector('.mcp-status').textContent = (provider.mcp.accounts.length > 1 ? `${entry.label} account: ` : '') + view.status;
|
|
2323
|
+
const command = box.querySelector('.mcp-command');
|
|
2324
|
+
command.hidden = !entry.command || entry.managed;
|
|
2325
|
+
command.textContent = entry.command ?? '';
|
|
2326
|
+
const button = box.querySelector('.mcp-action');
|
|
2327
|
+
button.hidden = !view.action;
|
|
2328
|
+
button.textContent = view.button ?? '';
|
|
2329
|
+
button.disabled = mcpBusy.has(key);
|
|
2330
|
+
button.onclick = () => changeMcp(provider, entry, view);
|
|
2331
|
+
}
|
|
2332
|
+
|
|
2333
|
+
function repaintMcp(id) {
|
|
2334
|
+
const provider = state.providers.find((p) => p.id === id);
|
|
2335
|
+
if (!provider) return;
|
|
2336
|
+
for (const card of document.querySelectorAll('.provider[data-id]')) if (card.dataset.id === id) renderMcpSetup(card, provider);
|
|
2337
|
+
}
|
|
2338
|
+
|
|
2339
|
+
async function changeMcp(provider, entry, view) {
|
|
2340
|
+
if (view.ask && !(await ask(view.ask.message, { ok: view.ask.ok }))) return;
|
|
2341
|
+
const key = `${provider.id}:${entry.id}`;
|
|
2342
|
+
mcpBusy.add(key);
|
|
2343
|
+
repaintMcp(provider.id);
|
|
2344
|
+
try {
|
|
2345
|
+
const { result } = await api('POST', `/providers/${provider.id}/mcp`, { account: entry.id, action: view.action, expect: entry.fingerprint });
|
|
2346
|
+
if (result.outcome === 'failed') toast(result.detail, 12000);
|
|
2347
|
+
} catch (err) {
|
|
2348
|
+
if (err instanceof AuthError) return showAuth(err.message);
|
|
2349
|
+
toast(err.message, 10000);
|
|
2350
|
+
} finally {
|
|
2351
|
+
mcpBusy.delete(key);
|
|
2352
|
+
repaintMcp(provider.id);
|
|
2353
|
+
}
|
|
2313
2354
|
}
|
|
2314
2355
|
|
|
2315
2356
|
let dealt = false;
|
|
@@ -2391,11 +2432,87 @@ function buildProvider(provider) {
|
|
|
2391
2432
|
return node;
|
|
2392
2433
|
}
|
|
2393
2434
|
|
|
2435
|
+
function readToolCards() {
|
|
2436
|
+
let saved = null;
|
|
2437
|
+
try { saved = JSON.parse(load(TOOL_CARDS_KEY)); } catch {}
|
|
2438
|
+
const ids = (list) => new Set(Array.isArray(list) ? list.filter((id) => typeof id === 'string') : []);
|
|
2439
|
+
return { collapsed: ids(saved?.collapsed), hidden: ids(saved?.hidden) };
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2442
|
+
const toolCards = readToolCards();
|
|
2443
|
+
|
|
2444
|
+
function saveToolCards() {
|
|
2445
|
+
save(TOOL_CARDS_KEY, JSON.stringify({ collapsed: [...toolCards.collapsed], hidden: [...toolCards.hidden] }));
|
|
2446
|
+
}
|
|
2447
|
+
|
|
2448
|
+
function paintCollapse(card, provider) {
|
|
2449
|
+
const collapsed = toolCards.collapsed.has(provider.id);
|
|
2450
|
+
card.classList.toggle('collapsed', collapsed);
|
|
2451
|
+
const toggle = card.querySelector('.card-toggle');
|
|
2452
|
+
toggle.hidden = false;
|
|
2453
|
+
toggle.dataset.muxFocus = `${provider.id}:collapse`;
|
|
2454
|
+
toggle.setAttribute('aria-expanded', String(!collapsed));
|
|
2455
|
+
toggle.setAttribute('aria-label', `${collapsed ? 'Expand' : 'Collapse'} the ${provider.tool} card`);
|
|
2456
|
+
toggle.title = collapsed ? 'Show everything on this card' : 'Show only what starts a session';
|
|
2457
|
+
card.querySelector('.head-tools').hidden = false;
|
|
2458
|
+
}
|
|
2459
|
+
|
|
2460
|
+
function setCollapsed(ids, collapsed) {
|
|
2461
|
+
for (const id of ids) {
|
|
2462
|
+
if (collapsed) toolCards.collapsed.add(id);
|
|
2463
|
+
else toolCards.collapsed.delete(id);
|
|
2464
|
+
}
|
|
2465
|
+
saveToolCards();
|
|
2466
|
+
for (const card of $('providers').children) {
|
|
2467
|
+
const provider = state.providers.find((p) => p.id === card.dataset.id);
|
|
2468
|
+
if (provider && ids.includes(provider.id)) paintCollapse(card, provider);
|
|
2469
|
+
}
|
|
2470
|
+
}
|
|
2471
|
+
|
|
2472
|
+
function setHidden(ids, hidden) {
|
|
2473
|
+
for (const id of ids) {
|
|
2474
|
+
if (hidden) toolCards.hidden.add(id);
|
|
2475
|
+
else toolCards.hidden.delete(id);
|
|
2476
|
+
}
|
|
2477
|
+
saveToolCards();
|
|
2478
|
+
renderProviders();
|
|
2479
|
+
}
|
|
2480
|
+
|
|
2481
|
+
function renderCardsMenu() {
|
|
2482
|
+
const hidden = state.providers.filter((p) => toolCards.hidden.has(p.id)).length;
|
|
2483
|
+
const button = $('cards-open');
|
|
2484
|
+
button.textContent = hidden ? `Cards · ${hidden} hidden` : 'Cards';
|
|
2485
|
+
button.setAttribute('aria-label', hidden ? `Tool cards, ${hidden} hidden` : 'Tool cards');
|
|
2486
|
+
$('cards-none').hidden = !state.providers.length || hidden < state.providers.length;
|
|
2487
|
+
const box = $('cards-shown');
|
|
2488
|
+
const rows = JSON.stringify(state.providers.map((p) => [p.id, p.vendor, p.tool]));
|
|
2489
|
+
if (box.dataset.rows !== rows) {
|
|
2490
|
+
const focused = box.contains(document.activeElement) ? document.activeElement.value : null;
|
|
2491
|
+
box.dataset.rows = rows;
|
|
2492
|
+
box.replaceChildren(box.querySelector('legend'), ...state.providers.map((provider) => {
|
|
2493
|
+
const input = document.createElement('input');
|
|
2494
|
+
input.type = 'checkbox';
|
|
2495
|
+
input.name = 'card';
|
|
2496
|
+
input.value = provider.id;
|
|
2497
|
+
const label = el('label', 'choice', input, el('span', '', provider.tool));
|
|
2498
|
+
label.title = `${provider.vendor} ${provider.tool}`;
|
|
2499
|
+
return label;
|
|
2500
|
+
}));
|
|
2501
|
+
if (focused) [...box.querySelectorAll('input')].find((input) => input.value === focused)?.focus();
|
|
2502
|
+
}
|
|
2503
|
+
for (const input of box.querySelectorAll('input')) input.checked = !toolCards.hidden.has(input.value);
|
|
2504
|
+
}
|
|
2505
|
+
|
|
2394
2506
|
function renderProviders() {
|
|
2395
2507
|
const list = $('providers');
|
|
2396
2508
|
const focused = document.activeElement;
|
|
2397
2509
|
const focusKey = focused?.dataset?.muxFocus;
|
|
2398
|
-
list.replaceChildren(...state.providers.map(
|
|
2510
|
+
list.replaceChildren(...state.providers.filter((p) => !toolCards.hidden.has(p.id)).map((provider) => {
|
|
2511
|
+
const card = buildProvider(provider);
|
|
2512
|
+
paintCollapse(card, provider);
|
|
2513
|
+
return card;
|
|
2514
|
+
}));
|
|
2515
|
+
renderCardsMenu();
|
|
2399
2516
|
notifyViews();
|
|
2400
2517
|
if (focusKey) {
|
|
2401
2518
|
const controls = [...list.querySelectorAll('[data-mux-focus]')];
|
|
@@ -8421,6 +8538,26 @@ window.addEventListener('resize', () => {
|
|
|
8421
8538
|
placeMenu($('manager-menu'), $('manager'));
|
|
8422
8539
|
placeMenu($('panel-sessions'), sessionInvoker());
|
|
8423
8540
|
placeMenu($('panel-text-size'), $('panel-text-toggle'));
|
|
8541
|
+
placeMenu($('cards-menu'), $('cards-open'));
|
|
8542
|
+
});
|
|
8543
|
+
onMenu($('cards-menu'), (menu) => {
|
|
8544
|
+
placeMenu(menu, $('cards-open'));
|
|
8545
|
+
menu.querySelector('input')?.focus();
|
|
8546
|
+
}, (menu) => returnFocus(menu, $('cards-open')));
|
|
8547
|
+
$('cards-menu').addEventListener('change', (e) => {
|
|
8548
|
+
if (e.target.name === 'card') setHidden([e.target.value], !e.target.checked);
|
|
8549
|
+
});
|
|
8550
|
+
$('cards-collapse').addEventListener('click', () => setCollapsed(state.providers.map((p) => p.id), true));
|
|
8551
|
+
$('cards-expand').addEventListener('click', () => setCollapsed(state.providers.map((p) => p.id), false));
|
|
8552
|
+
$('cards-show-all').addEventListener('click', () => {
|
|
8553
|
+
setHidden(state.providers.map((p) => p.id), false);
|
|
8554
|
+
$('providers').querySelector('.card-toggle')?.focus();
|
|
8555
|
+
});
|
|
8556
|
+
$('providers').addEventListener('click', (e) => {
|
|
8557
|
+
const toggle = e.target.closest('.card-toggle');
|
|
8558
|
+
if (!toggle) return;
|
|
8559
|
+
setCollapsed([toggle.closest('.provider').dataset.id], toggle.getAttribute('aria-expanded') === 'true');
|
|
8560
|
+
toggle.scrollIntoView({ block: 'nearest' });
|
|
8424
8561
|
});
|
|
8425
8562
|
$('providers').addEventListener('animationend', (e) => {
|
|
8426
8563
|
if (e.target === e.currentTarget.lastElementChild) e.currentTarget.classList.remove('deal');
|
|
@@ -8595,6 +8732,7 @@ yardUi = initYard({
|
|
|
8595
8732
|
renderLaunchFlags(node, provider);
|
|
8596
8733
|
renderUsage(node, provider);
|
|
8597
8734
|
renderReportingSetup(node, provider);
|
|
8735
|
+
renderMcpSetup(node, provider);
|
|
8598
8736
|
renderModelStats(node, provider);
|
|
8599
8737
|
node.dataset.contentSignature = contentSignature;
|
|
8600
8738
|
}
|
package/web/index.html
CHANGED
|
@@ -98,7 +98,17 @@
|
|
|
98
98
|
<main id="app" hidden>
|
|
99
99
|
<section class="launcher" aria-labelledby="launch-heading">
|
|
100
100
|
<div class="section-head">
|
|
101
|
-
<
|
|
101
|
+
<div class="launch-title">
|
|
102
|
+
<h2 id="launch-heading">Start a session</h2>
|
|
103
|
+
<button id="cards-open" class="btn menu-button cards-open" type="button" popovertarget="cards-menu" aria-haspopup="dialog">Cards</button>
|
|
104
|
+
<div id="cards-menu" class="settings-menu menu cards-menu" popover role="dialog" aria-label="Tool cards">
|
|
105
|
+
<fieldset id="cards-shown"><legend>Show</legend></fieldset>
|
|
106
|
+
<fieldset>
|
|
107
|
+
<button id="cards-collapse" class="menu-item" type="button">Collapse all</button>
|
|
108
|
+
<button id="cards-expand" class="menu-item" type="button">Expand all</button>
|
|
109
|
+
</fieldset>
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
102
112
|
<div class="launch-tools">
|
|
103
113
|
<div class="cwd">
|
|
104
114
|
<label for="cwd">Working folder</label>
|
|
@@ -124,6 +134,7 @@
|
|
|
124
134
|
</div>
|
|
125
135
|
</div>
|
|
126
136
|
<div id="providers" class="providers" role="list"></div>
|
|
137
|
+
<p id="cards-none" class="cards-none" hidden>All tool cards are hidden. <button id="cards-show-all" class="btn" type="button">Show all</button></p>
|
|
127
138
|
</section>
|
|
128
139
|
|
|
129
140
|
<section id="yard" hidden aria-label="Yard">
|
|
@@ -799,6 +810,7 @@
|
|
|
799
810
|
<span class="state"></span>
|
|
800
811
|
</span>
|
|
801
812
|
<span class="head-tools">
|
|
813
|
+
<button class="card-toggle" type="button" aria-expanded="true" hidden></button>
|
|
802
814
|
<a class="cloud-link" target="_blank" rel="noopener noreferrer" hidden></a>
|
|
803
815
|
<button class="accounts-link" type="button" aria-haspopup="dialog" aria-label="Accounts" hidden></button>
|
|
804
816
|
</span>
|
|
@@ -817,12 +829,6 @@
|
|
|
817
829
|
<span class="reporting-text"></span>
|
|
818
830
|
<button class="btn reporting-toggle" type="button"></button>
|
|
819
831
|
</div>
|
|
820
|
-
<div class="reporting-row mcp-row" hidden>
|
|
821
|
-
<span class="mcp-text"></span>
|
|
822
|
-
<a class="console-link mcp-docs" href="https://github.com/oddessentials/agent-guild/blob/main/docs/mcp.md" target="_blank" rel="noopener noreferrer" title="What Agent Guild's MCP server lets a coding agent do">About</a>
|
|
823
|
-
<button class="btn mcp-on" type="button">Turn on</button>
|
|
824
|
-
<button class="btn mcp-off" type="button">Turn off</button>
|
|
825
|
-
</div>
|
|
826
832
|
<div class="provider-links">
|
|
827
833
|
<a class="console-link usage-link" target="_blank" rel="noopener noreferrer">Usage</a>
|
|
828
834
|
<a class="console-link billing-link" target="_blank" rel="noopener noreferrer">Billing</a>
|
|
@@ -838,6 +844,16 @@
|
|
|
838
844
|
<button class="btn multiplexer-refresh" type="button">Refresh</button>
|
|
839
845
|
<div class="multiplexer-list"></div>
|
|
840
846
|
</details>
|
|
847
|
+
<details class="mcp" hidden>
|
|
848
|
+
<summary><span class="mcp-title">Agent Guild MCP</span><span class="mcp-state"></span></summary>
|
|
849
|
+
<p class="mcp-about"></p>
|
|
850
|
+
<p class="mcp-status"></p>
|
|
851
|
+
<code class="mcp-command" hidden></code>
|
|
852
|
+
<div class="mcp-actions">
|
|
853
|
+
<a class="console-link" href="https://github.com/oddessentials/agent-guild/blob/main/docs/mcp.md" target="_blank" rel="noopener noreferrer">How it works</a>
|
|
854
|
+
<button class="btn mcp-action" type="button" hidden></button>
|
|
855
|
+
</div>
|
|
856
|
+
</details>
|
|
841
857
|
<p class="hint" hidden></p>
|
|
842
858
|
<div class="provider-actions">
|
|
843
859
|
<button class="btn primary new" type="button">New</button>
|
package/web/styles.css
CHANGED
|
@@ -243,7 +243,7 @@ main { max-width: calc(1200px + var(--dock-space, 0px)); margin: 0 auto; padding
|
|
|
243
243
|
font: inherit; font-size: 0.78rem; text-align: left; cursor: pointer;
|
|
244
244
|
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
245
245
|
}
|
|
246
|
-
.model-stats-head::after, .console-link::after, .menu-button::after, .model-name::before, .provider .copies summary::before {
|
|
246
|
+
.model-stats-head::after, .console-link::after, .menu-button::after, .model-name::before, .provider .copies summary::before, .provider .mcp summary::before {
|
|
247
247
|
content: ""; display: inline-block; flex: none; width: 0.75em; height: 0.75em; margin-left: 0.3em; vertical-align: -0.05em;
|
|
248
248
|
background: currentColor; mask: var(--icon-chevron) center / contain no-repeat;
|
|
249
249
|
}
|
|
@@ -308,8 +308,6 @@ main { max-width: calc(1200px + var(--dock-space, 0px)); margin: 0 auto; padding
|
|
|
308
308
|
}
|
|
309
309
|
.reporting-row { display: flex; align-items: center; gap: 10px; font-size: 0.78rem; color: var(--muted); }
|
|
310
310
|
.reporting-row .btn { padding: 2px 10px; font-size: 0.75rem; white-space: nowrap; }
|
|
311
|
-
.mcp-row { flex-wrap: wrap; row-gap: 4px; }
|
|
312
|
-
.mcp-row .mcp-text { flex-basis: 100%; }
|
|
313
311
|
.console-link { color: var(--accent); text-decoration: none; }
|
|
314
312
|
.console-link:hover { text-decoration: underline; }
|
|
315
313
|
.console-link:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: 3px; }
|
|
@@ -317,13 +315,23 @@ main { max-width: calc(1200px + var(--dock-space, 0px)); margin: 0 auto; padding
|
|
|
317
315
|
.memory-link, .hint-details { padding: 0; border: 0; background: none; color: var(--accent); font: inherit; cursor: pointer; }
|
|
318
316
|
.memory-link:hover, .hint-details:hover { text-decoration: underline; }
|
|
319
317
|
.memory-link:focus-visible, .hint-details:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: 3px; }
|
|
320
|
-
/* The bottom margin lets the second icon's padding overlap the gap below, so the header is no taller. */
|
|
321
318
|
.head-tools { display: flex; flex-direction: column; flex: none; align-self: flex-start; margin: -4px -6px -6px 0; }
|
|
322
|
-
.cloud-link, .accounts-link { display: block; width: 32px; height: 32px; padding: 0; border: 0; border-radius: 8px; background: none; color: var(--muted); cursor: pointer; }
|
|
323
|
-
.cloud-link::before, .accounts-link::before { content: ""; display: block; width: 100%; height: 100%; background: currentColor; mask: var(--icon-cloud) center / 20px no-repeat; }
|
|
319
|
+
.card-toggle, .cloud-link, .accounts-link { display: block; width: 32px; height: 32px; padding: 0; border: 0; border-radius: 8px; background: none; color: var(--muted); cursor: pointer; }
|
|
320
|
+
.card-toggle::before, .cloud-link::before, .accounts-link::before { content: ""; display: block; width: 100%; height: 100%; background: currentColor; mask: var(--icon-cloud) center / 20px no-repeat; }
|
|
324
321
|
.accounts-link::before { mask-image: var(--icon-accounts); }
|
|
325
|
-
.
|
|
326
|
-
.
|
|
322
|
+
.card-toggle::before { mask-image: var(--icon-chevron); mask-size: 16px; rotate: -90deg; transition: rotate 0.15s var(--ease); }
|
|
323
|
+
.card-toggle[aria-expanded="false"]::before { rotate: 90deg; }
|
|
324
|
+
.providers > .provider.collapsed { padding-top: 16px; align-self: start; }
|
|
325
|
+
:root[data-skin="guild"][data-art="on"] .providers > .provider.collapsed { padding-top: 18px; }
|
|
326
|
+
.providers > .provider.collapsed :is(.card-art, .usage, .model-stats, .reporting-row, .provider-links, .copies, .multiplexers, .mcp, .environment-summary, .hint-details) { display: none; }
|
|
327
|
+
.providers > .provider.collapsed::after { background: var(--brackets, none); background-repeat: no-repeat; }
|
|
328
|
+
.providers > .provider.collapsed.spent .provider-icon { filter: grayscale(1); }
|
|
329
|
+
.launch-title { display: flex; align-items: center; gap: 10px; min-width: 0; }
|
|
330
|
+
.cards-open { padding: 3px 10px; font-size: 0.78rem; }
|
|
331
|
+
#cards-shown .choice > span::before { content: none; }
|
|
332
|
+
.cards-none { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin: 0; color: var(--muted); font-size: 0.85rem; }
|
|
333
|
+
.card-toggle:hover, .cloud-link:hover, .accounts-link:hover { color: var(--accent); }
|
|
334
|
+
.card-toggle:focus-visible, .cloud-link:focus-visible, .accounts-link:focus-visible { color: var(--accent); outline: 2px solid var(--focus); outline-offset: 0; }
|
|
327
335
|
.provider-actions { margin-top: auto; display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
|
|
328
336
|
/* A card's note sits with its buttons at the foot of the card, above them. */
|
|
329
337
|
.provider .hint { margin: auto 0 0; font-size: 0.78rem; color: var(--muted); overflow-wrap: anywhere; }
|
|
@@ -338,6 +346,17 @@ main { max-width: calc(1200px + var(--dock-space, 0px)); margin: 0 auto; padding
|
|
|
338
346
|
.provider .copies li span { display: block; }
|
|
339
347
|
.provider .copies .copy-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 24px; }
|
|
340
348
|
.provider .copies .copy-name { color: var(--text); min-width: 0; }
|
|
349
|
+
.provider .mcp { font-size: 0.78rem; color: var(--muted); overflow-wrap: anywhere; }
|
|
350
|
+
.provider .mcp summary { display: flex; align-items: baseline; cursor: pointer; list-style: none; white-space: nowrap; }
|
|
351
|
+
.provider .mcp summary::-webkit-details-marker { display: none; }
|
|
352
|
+
.provider .mcp summary::before { margin: 0 0.3em 0 0; align-self: center; transition: transform 0.15s var(--ease); }
|
|
353
|
+
.provider .mcp[open] summary::before { transform: rotate(90deg); }
|
|
354
|
+
.provider .mcp .mcp-state { margin-left: auto; padding-left: 8px; font-weight: 600; white-space: nowrap; }
|
|
355
|
+
.provider .mcp.warned .mcp-state { color: var(--warn); }
|
|
356
|
+
.provider .mcp p { margin: 6px 0 0; line-height: 1.45; }
|
|
357
|
+
.provider .mcp .mcp-command { display: block; margin-top: 4px; font-size: 0.72rem; color: var(--text); }
|
|
358
|
+
.provider .mcp .mcp-actions { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 8px; }
|
|
359
|
+
.provider .mcp .mcp-action { padding: 2px 10px; font-size: 0.75rem; white-space: nowrap; }
|
|
341
360
|
.provider .copies .copy-path { font-family: var(--font-mono); font-size: 0.72rem; }
|
|
342
361
|
.provider .copies .copy-uninstall { flex: none; padding: 2px 10px; font-size: 0.75rem; }
|
|
343
362
|
.provider.busy { opacity: 0.6; pointer-events: none; }
|
|
@@ -1318,7 +1337,7 @@ body:has(#terminal-panel:not([hidden]) .terminal-controls:not([hidden])) .toast
|
|
|
1318
1337
|
|
|
1319
1338
|
@media (prefers-reduced-motion: reduce) {
|
|
1320
1339
|
.status-pill.active::before, .agent.working::after, .model-detail .stat-fill, .toast:not([hidden]), .tip:not([hidden]), .run-failed:not([hidden]), .menu:popover-open { animation: none; }
|
|
1321
|
-
.model-name::before, .provider .copies summary::before, .menu-button::after, .btn, .videos-play img, .videos-play-icon, .models, .news-panel, .models::backdrop, .news-panel::backdrop { transition: none; }
|
|
1340
|
+
.model-name::before, .provider .copies summary::before, .provider .mcp summary::before, .menu-button::after, .btn, .videos-play img, .videos-play-icon, .models, .news-panel, .models::backdrop, .news-panel::backdrop { transition: none; }
|
|
1322
1341
|
.github-waiting::before, .github-running, body:has(#app[hidden]):has(#auth[hidden]):has(#stopped[hidden])::after { animation: none; }
|
|
1323
1342
|
.btn:active:not(:disabled):not([aria-disabled="true"]) { transform: none; }
|
|
1324
1343
|
.btn.voice[aria-pressed="true"]::before { animation: none; }
|