@agentproto/apps 0.13.1 → 0.15.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/dist/bin/sync.mjs +299 -2
- package/dist/bin/sync.mjs.map +1 -1
- package/dist/config/fragment.d.ts +2 -2
- package/dist/config/fragment.d.ts.map +1 -1
- package/dist/config/ui.d.ts +1 -1
- package/dist/config/ui.d.ts.map +1 -1
- package/dist/config.mjs +300 -3
- package/dist/config.mjs.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +357 -4
- package/dist/index.mjs.map +1 -1
- package/dist/review-panel/index.d.ts +70 -0
- package/dist/review-panel/index.d.ts.map +1 -0
- package/dist/review-panel/panel.d.ts +50 -0
- package/dist/review-panel/panel.d.ts.map +1 -0
- package/dist/review-panel/panel.generated.d.ts +13 -0
- package/dist/review-panel/panel.generated.d.ts.map +1 -0
- package/dist/review-panel/panel.mjs +24 -0
- package/dist/review-panel/panel.mjs.map +1 -0
- package/dist/review-panel.mjs +60 -0
- package/dist/review-panel.mjs.map +1 -0
- package/dist/session-chat/index.d.ts.map +1 -1
- package/dist/session-chat.mjs +9 -1
- package/dist/session-chat.mjs.map +1 -1
- package/package.json +15 -3
- package/repo-maintenance/README.md +4 -0
package/dist/bin/sync.mjs
CHANGED
|
@@ -2362,7 +2362,7 @@ var opsPanel = defineApp({
|
|
|
2362
2362
|
|
|
2363
2363
|
// src/config/fragment.ts
|
|
2364
2364
|
function parseConfigFragment(hash) {
|
|
2365
|
-
var SECTIONS2 = ["wallets", "harnesses", "models", "defaults", "remote", "advanced"];
|
|
2365
|
+
var SECTIONS2 = ["wallets", "harnesses", "models", "capabilities", "defaults", "remote", "advanced"];
|
|
2366
2366
|
var raw = String(hash || "").replace(/^#/, "");
|
|
2367
2367
|
var parts = raw.split("/").filter(function(p) {
|
|
2368
2368
|
return p.length > 0;
|
|
@@ -2411,6 +2411,11 @@ var CONFIG_TOOLS = [
|
|
|
2411
2411
|
"auth_profile_update",
|
|
2412
2412
|
"adapter_list",
|
|
2413
2413
|
"harness_capabilities",
|
|
2414
|
+
"capabilities_inventory",
|
|
2415
|
+
"mcp_imported_tool_list",
|
|
2416
|
+
"mcp_imported_status",
|
|
2417
|
+
"mcp_import",
|
|
2418
|
+
"mcp_imported_remove",
|
|
2414
2419
|
"harness_preset_list",
|
|
2415
2420
|
"harness_preset_create",
|
|
2416
2421
|
"harness_preset_delete",
|
|
@@ -2436,6 +2441,7 @@ var SECTIONS = [
|
|
|
2436
2441
|
{ id: "wallets", label: "Wallets" },
|
|
2437
2442
|
{ id: "harnesses", label: "Harnesses" },
|
|
2438
2443
|
{ id: "models", label: "Models" },
|
|
2444
|
+
{ id: "capabilities", label: "Capabilities" },
|
|
2439
2445
|
{ id: "defaults", label: "Defaults" },
|
|
2440
2446
|
{ id: "remote", label: "Remote" },
|
|
2441
2447
|
{ id: "advanced", label: "Advanced" }
|
|
@@ -2583,6 +2589,7 @@ td.matrix-cell.disabled{opacity:.35;cursor:default}
|
|
|
2583
2589
|
<div class="section" data-section="wallets" id="sec-wallets"></div>
|
|
2584
2590
|
<div class="section" data-section="harnesses" id="sec-harnesses"></div>
|
|
2585
2591
|
<div class="section" data-section="models" id="sec-models"></div>
|
|
2592
|
+
<div class="section" data-section="capabilities" id="sec-capabilities"></div>
|
|
2586
2593
|
<div class="section" data-section="defaults" id="sec-defaults"></div>
|
|
2587
2594
|
<div class="section" data-section="remote" id="sec-remote"></div>
|
|
2588
2595
|
<div class="section" data-section="advanced" id="sec-advanced"></div>
|
|
@@ -3120,11 +3127,31 @@ function showSection(sectionId) {
|
|
|
3120
3127
|
function applyDeepLink(sectionId, id, sub) {
|
|
3121
3128
|
var notfound = document.getElementById("notfound");
|
|
3122
3129
|
notfound.style.display = "none";
|
|
3123
|
-
var prevHl = document.querySelectorAll(".card.hl, tr.hl");
|
|
3130
|
+
var prevHl = document.querySelectorAll(".card.hl, tr.hl, th.hl");
|
|
3124
3131
|
for (var p = 0; p < prevHl.length; p++) prevHl[p].classList.remove("hl");
|
|
3125
3132
|
if (id === undefined) return;
|
|
3126
3133
|
var container = document.getElementById("sec-" + sectionId);
|
|
3127
3134
|
if (!container) return;
|
|
3135
|
+
// #capabilities/<mcp|skills>/<sub>: 'id' selects the TAB, not a card \u2014
|
|
3136
|
+
// switch tab (re-rendering the section) before looking for 'sub's card.
|
|
3137
|
+
if (sectionId === "capabilities") {
|
|
3138
|
+
var capTab = id === "skills" ? "skills" : "mcp";
|
|
3139
|
+
if (capabilitiesState.tab !== capTab) {
|
|
3140
|
+
capabilitiesState.tab = capTab;
|
|
3141
|
+
renderCapabilities();
|
|
3142
|
+
container = document.getElementById("sec-" + sectionId);
|
|
3143
|
+
}
|
|
3144
|
+
if (sub === undefined) return;
|
|
3145
|
+
var capTarget = container.querySelector('[data-card-id="' + cssEscape(sub) + '"]');
|
|
3146
|
+
if (!capTarget) {
|
|
3147
|
+
notfound.textContent = "not found: " + id + "/" + sub;
|
|
3148
|
+
notfound.style.display = "block";
|
|
3149
|
+
return;
|
|
3150
|
+
}
|
|
3151
|
+
capTarget.classList.add("hl");
|
|
3152
|
+
scrollIntoViewSafe(capTarget);
|
|
3153
|
+
return;
|
|
3154
|
+
}
|
|
3128
3155
|
var targetId = sectionId === "remote" && id === "pairing" ? "pairing" : id;
|
|
3129
3156
|
var target = container.querySelector('[data-card-id="' + cssEscape(targetId) + '"]');
|
|
3130
3157
|
if (!target) {
|
|
@@ -3225,6 +3252,7 @@ var SECTION_LOADERS = {
|
|
|
3225
3252
|
wallets: loadWallets,
|
|
3226
3253
|
harnesses: loadHarnesses,
|
|
3227
3254
|
models: loadModels,
|
|
3255
|
+
capabilities: loadCapabilities,
|
|
3228
3256
|
defaults: loadDefaults,
|
|
3229
3257
|
remote: loadRemote,
|
|
3230
3258
|
advanced: loadAdvanced,
|
|
@@ -4308,6 +4336,275 @@ function renderTitlerModelCard() {
|
|
|
4308
4336
|
});
|
|
4309
4337
|
}
|
|
4310
4338
|
|
|
4339
|
+
// ============================================================
|
|
4340
|
+
// Capabilities (MCP & Skills)
|
|
4341
|
+
// ============================================================
|
|
4342
|
+
|
|
4343
|
+
var capabilitiesState = {
|
|
4344
|
+
tab: "mcp", // "mcp" | "skills"
|
|
4345
|
+
invResult: null,
|
|
4346
|
+
expandedImports: {}, // importId -> bool
|
|
4347
|
+
};
|
|
4348
|
+
|
|
4349
|
+
function loadCapabilities() {
|
|
4350
|
+
return loadTool("capabilities_inventory", {}).then(function (r) {
|
|
4351
|
+
capabilitiesState.invResult = r;
|
|
4352
|
+
renderCapabilities();
|
|
4353
|
+
});
|
|
4354
|
+
}
|
|
4355
|
+
|
|
4356
|
+
function capTabsHtml() {
|
|
4357
|
+
return '<span class="pillbar">'
|
|
4358
|
+
+ '<button type="button" class="' + (capabilitiesState.tab === "mcp" ? "active" : "") + '" data-cap-tab="mcp">MCP</button>'
|
|
4359
|
+
+ '<button type="button" class="' + (capabilitiesState.tab === "skills" ? "active" : "") + '" data-cap-tab="skills">Skills</button>'
|
|
4360
|
+
+ '</span>';
|
|
4361
|
+
}
|
|
4362
|
+
|
|
4363
|
+
function capStatusTagHtml(status) {
|
|
4364
|
+
var cls = status === "connected" ? "ok" : status === "error" ? "bad" : status === "idle" ? "" : "warn-tag";
|
|
4365
|
+
return '<span class="tag ' + cls + '">' + escHtml(status) + '</span>';
|
|
4366
|
+
}
|
|
4367
|
+
|
|
4368
|
+
function renderCapabilities() {
|
|
4369
|
+
var el = document.getElementById("sec-capabilities");
|
|
4370
|
+
var r = capabilitiesState.invResult;
|
|
4371
|
+
var html = '<div class="sect-h">Capabilities' + capTabsHtml() + '</div>';
|
|
4372
|
+
if (!r) { el.innerHTML = html; return; }
|
|
4373
|
+
if (!r.ok) {
|
|
4374
|
+
html += r.unknown
|
|
4375
|
+
? '<div class="muted-note">Capabilities inventory needs a newer agentproto daemon (capabilities_inventory).</div>'
|
|
4376
|
+
: '<div class="muted-note">capabilities_inventory: ' + escHtml(r.message) + '</div>';
|
|
4377
|
+
el.innerHTML = html;
|
|
4378
|
+
return;
|
|
4379
|
+
}
|
|
4380
|
+
var inv = r.data;
|
|
4381
|
+
html += capabilitiesState.tab === "skills" ? renderSkillsTabHtml(inv.skills || {}) : renderMcpTabHtml(inv.mcp || {});
|
|
4382
|
+
el.innerHTML = html;
|
|
4383
|
+
wireCapabilitiesTabs(el);
|
|
4384
|
+
if (capabilitiesState.tab === "mcp") wireMcpTab(el);
|
|
4385
|
+
}
|
|
4386
|
+
|
|
4387
|
+
function wireCapabilitiesTabs(container) {
|
|
4388
|
+
var btns = container.querySelectorAll("[data-cap-tab]");
|
|
4389
|
+
for (var i = 0; i < btns.length; i++) {
|
|
4390
|
+
(function (btn) {
|
|
4391
|
+
btn.addEventListener("click", function () {
|
|
4392
|
+
capabilitiesState.tab = btn.getAttribute("data-cap-tab");
|
|
4393
|
+
renderCapabilities();
|
|
4394
|
+
});
|
|
4395
|
+
})(btns[i]);
|
|
4396
|
+
}
|
|
4397
|
+
}
|
|
4398
|
+
|
|
4399
|
+
function renderMcpTabHtml(mcp) {
|
|
4400
|
+
var imported = mcp.imported || [];
|
|
4401
|
+
var discovered = mcp.discovered || [];
|
|
4402
|
+
var reach = mcp.daemonMountByHarness || {};
|
|
4403
|
+
var html = "";
|
|
4404
|
+
if (mcp.error) html += '<div class="muted-note">mcp: ' + escHtml(mcp.error) + '</div>';
|
|
4405
|
+
|
|
4406
|
+
html += '<div class="sect-h">Imported MCP servers</div>';
|
|
4407
|
+
if (imported.length === 0) {
|
|
4408
|
+
html += '<div class="empty">No MCP servers imported yet.</div>';
|
|
4409
|
+
} else {
|
|
4410
|
+
html += '<div class="card"><div class="body"><table><thead><tr><th>Name</th><th>Source</th><th>Status</th><th>Tools</th><th>Used by</th><th></th><th></th></tr></thead><tbody>';
|
|
4411
|
+
for (var i = 0; i < imported.length; i++) {
|
|
4412
|
+
var m = imported[i];
|
|
4413
|
+
var expanded = !!capabilitiesState.expandedImports[m.id];
|
|
4414
|
+
var usedBy = (m.usedBySessions || []).length;
|
|
4415
|
+
html += '<tr data-card-id="' + escHtml(m.id) + '" data-row-id="' + escHtml(m.id) + '">'
|
|
4416
|
+
+ '<td>' + escHtml(m.alias || m.name) + '</td>'
|
|
4417
|
+
+ '<td>' + escHtml(m.source) + '</td>'
|
|
4418
|
+
+ '<td>' + capStatusTagHtml(m.status) + (m.error ? ' <span class="tag bad" title="' + escHtml(m.error) + '">!</span>' : '') + '</td>'
|
|
4419
|
+
+ '<td>' + (m.toolCount != null ? String(m.toolCount) : "–") + '</td>'
|
|
4420
|
+
+ '<td>' + (usedBy > 0 ? "used by " + usedBy + " session" + (usedBy === 1 ? "" : "s") : "unused") + '</td>'
|
|
4421
|
+
+ '<td><button type="button" class="btn-sm" data-cap-import-tools="' + escHtml(m.id) + '" data-cap-import-alias="' + escHtml(m.alias || m.name) + '">' + (expanded ? "hide tools" : "show tools") + '</button></td>'
|
|
4422
|
+
+ '<td><button type="button" class="btn-sm danger" data-cap-import-remove="' + escHtml(m.id) + '">remove</button></td>'
|
|
4423
|
+
+ '</tr>'
|
|
4424
|
+
+ '<tr><td colspan="7"><div id="cap-import-tools-' + escHtml(pathId(m.id)) + '"></div></td></tr>';
|
|
4425
|
+
}
|
|
4426
|
+
html += '</tbody></table></div></div>';
|
|
4427
|
+
}
|
|
4428
|
+
|
|
4429
|
+
html += '<div class="sect-h">Reach</div>';
|
|
4430
|
+
var slugs = Object.keys(reach);
|
|
4431
|
+
if (slugs.length === 0) {
|
|
4432
|
+
html += '<div class="empty">No adapters installed.</div>';
|
|
4433
|
+
} else {
|
|
4434
|
+
html += '<div class="card"><div class="body">';
|
|
4435
|
+
for (var s = 0; s < slugs.length; s++) {
|
|
4436
|
+
var r2 = reach[slugs[s]];
|
|
4437
|
+
var cls = r2 === "default" ? "ok" : r2 === "on-request" ? "" : "bad";
|
|
4438
|
+
html += '<span class="tag ' + cls + '" style="margin:2px 4px 2px 0">' + escHtml(slugs[s]) + ": " + escHtml(r2) + '</span>';
|
|
4439
|
+
}
|
|
4440
|
+
html += '<div class="muted-note">"default" harnesses get the imported pool automatically; "on-request" harnesses can mount it explicitly via <code>mcpServers</code>; "none" harnesses cannot reach it at all. Either way, reach is via <code>mcp_imported_tool_list</code> / <code>mcp_imported_call</code>, not a direct per-server mount.</div>';
|
|
4441
|
+
html += '</div></div>';
|
|
4442
|
+
}
|
|
4443
|
+
|
|
4444
|
+
html += '<div class="sect-h">Discovered, not imported</div>';
|
|
4445
|
+
var notImported = discovered.filter(function (d) { return !d.imported; });
|
|
4446
|
+
if (notImported.length === 0) {
|
|
4447
|
+
html += '<div class="empty">Nothing new discovered.</div>';
|
|
4448
|
+
} else {
|
|
4449
|
+
html += '<div class="card"><div class="body"><table><thead><tr><th>Name</th><th>Source</th><th>Type</th><th></th></tr></thead><tbody>';
|
|
4450
|
+
for (var d = 0; d < notImported.length; d++) {
|
|
4451
|
+
var disc = notImported[d];
|
|
4452
|
+
html += '<tr data-card-id="' + escHtml(disc.id) + '" data-row-id="' + escHtml(disc.id) + '"><td>' + escHtml(disc.name) + '</td><td>' + escHtml(disc.source) + '</td><td>' + escHtml(disc.type) + '</td>'
|
|
4453
|
+
+ '<td><button type="button" class="btn-sm primary" data-cap-import="' + escHtml(disc.id) + '">import</button></td></tr>';
|
|
4454
|
+
}
|
|
4455
|
+
html += '</tbody></table></div></div>';
|
|
4456
|
+
}
|
|
4457
|
+
return html;
|
|
4458
|
+
}
|
|
4459
|
+
|
|
4460
|
+
function wireMcpTab(container) {
|
|
4461
|
+
var toolBtns = container.querySelectorAll("[data-cap-import-tools]");
|
|
4462
|
+
for (var i = 0; i < toolBtns.length; i++) {
|
|
4463
|
+
(function (btn) {
|
|
4464
|
+
btn.addEventListener("click", function () {
|
|
4465
|
+
var id = btn.getAttribute("data-cap-import-tools");
|
|
4466
|
+
var alias = btn.getAttribute("data-cap-import-alias");
|
|
4467
|
+
var expanded = !capabilitiesState.expandedImports[id];
|
|
4468
|
+
capabilitiesState.expandedImports[id] = expanded;
|
|
4469
|
+
btn.textContent = expanded ? "hide tools" : "show tools";
|
|
4470
|
+
var host = document.getElementById("cap-import-tools-" + pathId(id));
|
|
4471
|
+
if (!host) return;
|
|
4472
|
+
if (!expanded) { host.innerHTML = ""; return; }
|
|
4473
|
+
host.innerHTML = '<div class="muted-note">Loading tools…</div>';
|
|
4474
|
+
loadTool("mcp_imported_tool_list", { alias: alias }).then(function (r) {
|
|
4475
|
+
if (!r.ok) { host.innerHTML = '<div class="muted-note">mcp_imported_tool_list: ' + escHtml(r.message) + '</div>'; return; }
|
|
4476
|
+
var tools = (r.data && r.data.tools) || [];
|
|
4477
|
+
if (tools.length === 0) { host.innerHTML = '<div class="empty">No tools (server may not be connected yet).</div>'; return; }
|
|
4478
|
+
var h = '<div class="muted-note">' + tools.length + ' tool(s):</div><ul>';
|
|
4479
|
+
for (var t = 0; t < tools.length; t++) {
|
|
4480
|
+
h += '<li><code>' + escHtml(tools[t].name) + '</code>' + (tools[t].description ? " — " + escHtml(tools[t].description) : "") + '</li>';
|
|
4481
|
+
}
|
|
4482
|
+
h += '</ul>';
|
|
4483
|
+
host.innerHTML = h;
|
|
4484
|
+
});
|
|
4485
|
+
});
|
|
4486
|
+
})(toolBtns[i]);
|
|
4487
|
+
}
|
|
4488
|
+
|
|
4489
|
+
var removeBtns = container.querySelectorAll("[data-cap-import-remove]");
|
|
4490
|
+
for (var r3 = 0; r3 < removeBtns.length; r3++) {
|
|
4491
|
+
(function (btn) {
|
|
4492
|
+
var id = btn.getAttribute("data-cap-import-remove");
|
|
4493
|
+
btn.addEventListener("click", function () {
|
|
4494
|
+
confirmClick("cap-import-remove-" + id, btn, function () {
|
|
4495
|
+
loadTool("mcp_imported_remove", { id: id }).then(function (res) {
|
|
4496
|
+
if (!res.ok) { toast(res.message, true); return; }
|
|
4497
|
+
toast("Removed.", false);
|
|
4498
|
+
loadCapabilities();
|
|
4499
|
+
});
|
|
4500
|
+
});
|
|
4501
|
+
});
|
|
4502
|
+
})(removeBtns[r3]);
|
|
4503
|
+
}
|
|
4504
|
+
|
|
4505
|
+
var importBtns = container.querySelectorAll("[data-cap-import]");
|
|
4506
|
+
for (var im = 0; im < importBtns.length; im++) {
|
|
4507
|
+
(function (btn) {
|
|
4508
|
+
var id = btn.getAttribute("data-cap-import");
|
|
4509
|
+
btn.addEventListener("click", function () {
|
|
4510
|
+
confirmClick("cap-import-" + id, btn, function () {
|
|
4511
|
+
loadTool("mcp_import", { sourceMcpId: id }).then(function (res) {
|
|
4512
|
+
if (!res.ok) { toast(res.message, true); return; }
|
|
4513
|
+
toast("Imported.", false);
|
|
4514
|
+
loadCapabilities();
|
|
4515
|
+
});
|
|
4516
|
+
});
|
|
4517
|
+
});
|
|
4518
|
+
})(importBtns[im]);
|
|
4519
|
+
}
|
|
4520
|
+
}
|
|
4521
|
+
|
|
4522
|
+
function capPackHasSkill(packs, name) {
|
|
4523
|
+
for (var i = 0; i < packs.length; i++) {
|
|
4524
|
+
if ((packs[i].skills || []).indexOf(name) !== -1) return true;
|
|
4525
|
+
}
|
|
4526
|
+
return false;
|
|
4527
|
+
}
|
|
4528
|
+
|
|
4529
|
+
function renderSkillsTabHtml(skills) {
|
|
4530
|
+
var harnesses = skills.byHarness || [];
|
|
4531
|
+
var packs = skills.packs || [];
|
|
4532
|
+
var defaults = skills.defaults || { global: [], byAdapter: {} };
|
|
4533
|
+
var html = "";
|
|
4534
|
+
if (skills.error) html += '<div class="muted-note">skills: ' + escHtml(skills.error) + '</div>';
|
|
4535
|
+
|
|
4536
|
+
html += '<div class="sect-h">Skills by harness</div>';
|
|
4537
|
+
if (harnesses.length === 0) {
|
|
4538
|
+
html += '<div class="empty">No adapters installed.</div>';
|
|
4539
|
+
return html;
|
|
4540
|
+
}
|
|
4541
|
+
|
|
4542
|
+
var skillNames = {};
|
|
4543
|
+
for (var p = 0; p < packs.length; p++) {
|
|
4544
|
+
for (var s = 0; s < (packs[p].skills || []).length; s++) skillNames[packs[p].skills[s]] = true;
|
|
4545
|
+
}
|
|
4546
|
+
for (var h = 0; h < harnesses.length; h++) {
|
|
4547
|
+
for (var i2 = 0; i2 < (harnesses[h].installed || []).length; i2++) skillNames[harnesses[h].installed[i2]] = true;
|
|
4548
|
+
for (var n = 0; n < (harnesses[h].native || []).length; n++) skillNames[harnesses[h].native[n]] = true;
|
|
4549
|
+
}
|
|
4550
|
+
var names = Object.keys(skillNames).sort();
|
|
4551
|
+
|
|
4552
|
+
html += '<div class="card"><div class="body" style="overflow-x:auto"><table><thead><tr><th>Skill</th>';
|
|
4553
|
+
for (var c = 0; c < harnesses.length; c++) {
|
|
4554
|
+
var target = harnesses[c].target;
|
|
4555
|
+
html += '<th data-card-id="' + escHtml(harnesses[c].adapter) + '">' + escHtml(harnesses[c].adapter)
|
|
4556
|
+
+ '<div class="cfg-help">' + (target ? escHtml(target.dir || "") : "unsupported") + '</div>'
|
|
4557
|
+
+ (harnesses[c].spawnOption ? '<div class="cfg-help">skills spawn option</div>' : '')
|
|
4558
|
+
+ '</th>';
|
|
4559
|
+
}
|
|
4560
|
+
html += '</tr></thead><tbody>';
|
|
4561
|
+
|
|
4562
|
+
html += '<tr><td><em>defaults</em></td>';
|
|
4563
|
+
for (var d = 0; d < harnesses.length; d++) {
|
|
4564
|
+
var adapterDefaults = defaults.byAdapter[harnesses[d].adapter] || [];
|
|
4565
|
+
var all = defaults.global.concat(adapterDefaults);
|
|
4566
|
+
html += '<td>' + (all.length > 0 ? escHtml(all.join(", ")) : "–") + '</td>';
|
|
4567
|
+
}
|
|
4568
|
+
html += '</tr>';
|
|
4569
|
+
|
|
4570
|
+
if (names.length === 0) {
|
|
4571
|
+
html += '<tr><td colspan="' + (harnesses.length + 1) + '">No skills found in any installed pack.</td></tr>';
|
|
4572
|
+
}
|
|
4573
|
+
for (var nm = 0; nm < names.length; nm++) {
|
|
4574
|
+
html += '<tr><td>' + escHtml(names[nm]) + '</td>';
|
|
4575
|
+
for (var hc = 0; hc < harnesses.length; hc++) {
|
|
4576
|
+
var row = harnesses[hc];
|
|
4577
|
+
var cell;
|
|
4578
|
+
if (!row.target) {
|
|
4579
|
+
cell = '<span class="tag">unsupported</span>';
|
|
4580
|
+
} else if ((row.installed || []).indexOf(names[nm]) !== -1) {
|
|
4581
|
+
cell = '<span class="tag ok">installed</span>';
|
|
4582
|
+
} else if ((row.native || []).indexOf(names[nm]) !== -1) {
|
|
4583
|
+
cell = '<span class="tag ok">native</span>';
|
|
4584
|
+
} else if (capPackHasSkill(packs, names[nm])) {
|
|
4585
|
+
cell = '<span class="tag warn-tag">available</span><div class="cfg-help"><code>agentproto install skill/' + escHtml(names[nm]) + '</code></div>';
|
|
4586
|
+
} else {
|
|
4587
|
+
cell = '<span class="tag">–</span>';
|
|
4588
|
+
}
|
|
4589
|
+
html += '<td>' + cell + '</td>';
|
|
4590
|
+
}
|
|
4591
|
+
html += '</tr>';
|
|
4592
|
+
}
|
|
4593
|
+
html += '</tbody></table></div></div>';
|
|
4594
|
+
|
|
4595
|
+
html += '<div class="sect-h">Packs</div>';
|
|
4596
|
+
if (packs.length === 0) {
|
|
4597
|
+
html += '<div class="empty">No skill packs found under ~/.agentproto/packs.</div>';
|
|
4598
|
+
} else {
|
|
4599
|
+
html += '<div class="card"><div class="body"><table><thead><tr><th>Pack</th><th>Version</th><th>Skills</th></tr></thead><tbody>';
|
|
4600
|
+
for (var pk = 0; pk < packs.length; pk++) {
|
|
4601
|
+
html += '<tr data-card-id="' + escHtml(packs[pk].name) + '"><td>' + escHtml(packs[pk].name) + '</td><td>' + escHtml(packs[pk].version || "") + '</td><td>' + escHtml((packs[pk].skills || []).join(", ")) + '</td></tr>';
|
|
4602
|
+
}
|
|
4603
|
+
html += '</tbody></table></div></div>';
|
|
4604
|
+
}
|
|
4605
|
+
return html;
|
|
4606
|
+
}
|
|
4607
|
+
|
|
4311
4608
|
// ============================================================
|
|
4312
4609
|
// Defaults & messaging
|
|
4313
4610
|
// ============================================================
|