loopengine 0.1.38 → 0.1.39
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/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/web/agents-config-page.js +54 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -57,8 +57,8 @@ export { listDeclaredEnvVars, setEnvVar, EnvVarNameError } from './web/env-admin
|
|
|
57
57
|
export type { DeclaredEnvVar } from './web/env-admin.js';
|
|
58
58
|
export { readActauthConfig, addActauthRule, updateActauthRule, removeActauthRule, setDefaultDecision, ActauthRuleExistsError, ActauthRuleNotFoundError, } from './web/actauth-admin.js';
|
|
59
59
|
export type { ActauthRuleInput, ActauthConfigView } from './web/actauth-admin.js';
|
|
60
|
-
export { installAbility, listInstalledAbilities, AbilityManifestError, AbilityVersionError, AbilityCollisionError, AbilityAlreadyInstalledError, } from './bin/ability-manager.js';
|
|
61
|
-
export type { InstalledAbilityRecord, AbilityEnvDecl } from './bin/ability-manager.js';
|
|
60
|
+
export { installAbility, upgradeAbility, listInstalledAbilities, AbilityManifestError, AbilityVersionError, AbilityCollisionError, AbilityAlreadyInstalledError, AbilityNotInstalledError, } from './bin/ability-manager.js';
|
|
61
|
+
export type { InstalledAbilityRecord, AbilityEnvDecl, UpgradeFileResult } from './bin/ability-manager.js';
|
|
62
62
|
export { searchPublicAbilities } from './web/abilities-admin.js';
|
|
63
63
|
export type { PublicAbilitySearchResult } from './web/abilities-admin.js';
|
|
64
64
|
export { describeModelProviders, describeGateways } from './web/global-config.js';
|
package/dist/index.js
CHANGED
|
@@ -51,7 +51,7 @@ export { playgroundHtml } from './web/playground.js';
|
|
|
51
51
|
export { readSkill, writeSkill, deleteSkill, SkillInvalidIdError, SkillNotFoundError } from './web/skills-admin.js';
|
|
52
52
|
export { listDeclaredEnvVars, setEnvVar, EnvVarNameError } from './web/env-admin.js';
|
|
53
53
|
export { readActauthConfig, addActauthRule, updateActauthRule, removeActauthRule, setDefaultDecision, ActauthRuleExistsError, ActauthRuleNotFoundError, } from './web/actauth-admin.js';
|
|
54
|
-
export { installAbility, listInstalledAbilities, AbilityManifestError, AbilityVersionError, AbilityCollisionError, AbilityAlreadyInstalledError, } from './bin/ability-manager.js';
|
|
54
|
+
export { installAbility, upgradeAbility, listInstalledAbilities, AbilityManifestError, AbilityVersionError, AbilityCollisionError, AbilityAlreadyInstalledError, AbilityNotInstalledError, } from './bin/ability-manager.js';
|
|
55
55
|
export { searchPublicAbilities } from './web/abilities-admin.js';
|
|
56
56
|
export { describeModelProviders, describeGateways } from './web/global-config.js';
|
|
57
57
|
export { createTrackedApprover, listApprovals, decideApproval, findApproval } from './web/web-approver.js';
|
|
@@ -1292,6 +1292,7 @@ export const agentsConfigPageHtml = `<!doctype html>
|
|
|
1292
1292
|
'<td><code>' + escapeHtml(a.name) + '</code></td>' +
|
|
1293
1293
|
'<td>' + escapeHtml(a.version) + '</td>' +
|
|
1294
1294
|
'<td class="hint">' + escapeHtml((a.tools || []).join(', ')) + '</td>' +
|
|
1295
|
+
'<td><button type="button" class="ability-upgrade-btn" data-name="' + escapeHtml(a.name) + '">Upgrade</button></td>' +
|
|
1295
1296
|
'</tr>';
|
|
1296
1297
|
}
|
|
1297
1298
|
|
|
@@ -1306,7 +1307,8 @@ export const agentsConfigPageHtml = `<!doctype html>
|
|
|
1306
1307
|
function renderAbilitiesConfigHtml(data) {
|
|
1307
1308
|
var installed = data.abilities || [];
|
|
1308
1309
|
var installedHtml = installed.length
|
|
1309
|
-
? '<table><thead><tr><th>Name</th><th>Version</th><th>Tools</th></tr></thead><tbody>' + installed.map(renderInstalledAbilityRow).join('') + '</tbody></table>'
|
|
1310
|
+
? '<table><thead><tr><th>Name</th><th>Version</th><th>Tools</th><th></th></tr></thead><tbody>' + installed.map(renderInstalledAbilityRow).join('') + '</tbody></table>' +
|
|
1311
|
+
'<p id="abilityUpgradeStatus" class="hint"></p>'
|
|
1310
1312
|
: '<p class="hint">No abilities installed for this agent yet.</p>';
|
|
1311
1313
|
|
|
1312
1314
|
return '<h3>Installed</h3>' + installedHtml +
|
|
@@ -1371,6 +1373,48 @@ export const agentsConfigPageHtml = `<!doctype html>
|
|
|
1371
1373
|
});
|
|
1372
1374
|
}
|
|
1373
1375
|
|
|
1376
|
+
// Upgrades an already-installed ability to whatever it currently
|
|
1377
|
+
// resolves to — same endpoint upgradeAbility (bin/ability-manager.ts)
|
|
1378
|
+
// backs, which three-way merges tool/skill files instead of blindly
|
|
1379
|
+
// overwriting a hand-edited one, so a merge conflict is a real,
|
|
1380
|
+
// expected outcome here, not an error — surfaced distinctly from a
|
|
1381
|
+
// request actually failing.
|
|
1382
|
+
function upgradeAbility(name, abilityName, statusEl, btn) {
|
|
1383
|
+
if (btn) { btn.disabled = true; }
|
|
1384
|
+
statusEl.className = 'hint';
|
|
1385
|
+
statusEl.textContent = 'Upgrading ' + abilityName + '…';
|
|
1386
|
+
fetch('/agents/' + encodeURIComponent(name) + '/abilities/' + encodeURIComponent(abilityName) + '/upgrade', {
|
|
1387
|
+
method: 'POST',
|
|
1388
|
+
headers: { 'content-type': 'application/json' },
|
|
1389
|
+
body: JSON.stringify({}),
|
|
1390
|
+
})
|
|
1391
|
+
.then(function (r) { return r.json().then(function (j) { return { ok: r.ok, body: j }; }); })
|
|
1392
|
+
.then(function (result) {
|
|
1393
|
+
if (!result.ok) throw new Error(result.body.error || 'request failed');
|
|
1394
|
+
var files = result.body.files || [];
|
|
1395
|
+
var updated = files.filter(function (f) { return f.status === 'updated'; });
|
|
1396
|
+
var conflicts = files.filter(function (f) { return f.status === 'conflict'; });
|
|
1397
|
+
var message;
|
|
1398
|
+
if (!files.length || (!updated.length && !conflicts.length)) {
|
|
1399
|
+
message = escapeHtml(abilityName) + ' is already up to date.';
|
|
1400
|
+
} else {
|
|
1401
|
+
message = 'Upgraded ' + escapeHtml(abilityName) + ': ' + escapeHtml(updated.map(function (f) { return f.path; }).join(', ') || 'no files changed') +
|
|
1402
|
+
'. Already running under npx loopengine dev? It becomes active automatically. Running under serve (or nothing yet)? Restart the server to pick it up.';
|
|
1403
|
+
if (conflicts.length) {
|
|
1404
|
+
message += ' <strong>' + conflicts.length + ' file(s) need resolving by hand: ' + escapeHtml(conflicts.map(function (f) { return f.path; }).join(', ')) + '</strong> — a hand-edited file with upstream changes too, left alone rather than overwritten.';
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
statusEl.className = conflicts.length ? 'error' : 'hint';
|
|
1408
|
+
statusEl.innerHTML = message;
|
|
1409
|
+
loadAbilitiesTab(name);
|
|
1410
|
+
})
|
|
1411
|
+
.catch(function (err) {
|
|
1412
|
+
statusEl.className = 'error';
|
|
1413
|
+
statusEl.textContent = 'Could not upgrade: ' + err.message;
|
|
1414
|
+
if (btn) { btn.disabled = false; }
|
|
1415
|
+
});
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1374
1418
|
// Shared by the initial (empty-query) load right after the tab opens
|
|
1375
1419
|
// and the search form's own submit — the empty-query case is just
|
|
1376
1420
|
// "list every published ability" (the keyword filter alone, no extra
|
|
@@ -1403,6 +1447,15 @@ export const agentsConfigPageHtml = `<!doctype html>
|
|
|
1403
1447
|
var content = abilitiesContentEl();
|
|
1404
1448
|
if (!content) return;
|
|
1405
1449
|
|
|
1450
|
+
var upgradeStatusEl = content.querySelector('#abilityUpgradeStatus');
|
|
1451
|
+
var upgradeBtns = content.querySelectorAll('.ability-upgrade-btn');
|
|
1452
|
+
for (var u = 0; u < upgradeBtns.length; u++) {
|
|
1453
|
+
upgradeBtns[u].addEventListener('click', function (ev) {
|
|
1454
|
+
var btn = ev.currentTarget;
|
|
1455
|
+
upgradeAbility(name, btn.dataset.name, upgradeStatusEl, btn);
|
|
1456
|
+
});
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1406
1459
|
var searchForm = content.querySelector('#abilitySearchForm');
|
|
1407
1460
|
var resultsEl = content.querySelector('#abilitySearchResults');
|
|
1408
1461
|
if (searchForm && resultsEl) {
|