@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 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) : "&#8211;") + '</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&hellip;</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 ? " &mdash; " + 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(", ")) : "&#8211;") + '</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">&#8211;</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
  // ============================================================