loopengine 0.1.42 → 0.1.43
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/ability-manager.d.ts +14 -0
- package/dist/bin/ability-manager.js +33 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/web/agents-config-page.js +17 -6
- package/package.json +1 -1
|
@@ -84,6 +84,20 @@ export interface InstalledAbilityRecord {
|
|
|
84
84
|
export declare function listInstalledAbilities(agentName: string): Array<{
|
|
85
85
|
name: string;
|
|
86
86
|
} & InstalledAbilityRecord>;
|
|
87
|
+
/** `record.dependencies` is only ever absent for an ability installed or
|
|
88
|
+
* last upgraded before that field existed (see InstalledAbilityRecord's
|
|
89
|
+
* own doc comment) — this re-derives it once by refetching the ability's
|
|
90
|
+
* own manifest (same technique upgradeAbility already uses for its own
|
|
91
|
+
* three-way merge base) and persists the result into provenance, so this
|
|
92
|
+
* only ever runs once per such ability rather than on every read. A
|
|
93
|
+
* record that already has `dependencies` — even a real empty array,
|
|
94
|
+
* meaning the ability genuinely declares none — is returned unchanged,
|
|
95
|
+
* never refetched. Best-effort: a spec that no longer resolves (private
|
|
96
|
+
* registry auth expired, a git ref that's gone, ...) leaves
|
|
97
|
+
* `dependencies` unset rather than throwing, since the Admin UI's own
|
|
98
|
+
* caller (handleAbilitiesGet) would rather show "can't tell" than fail
|
|
99
|
+
* the whole abilities list over one ability's stale record. */
|
|
100
|
+
export declare function backfillDependencies(agentName: string, abilityName: string, options?: FetchOptions): Promise<string[] | undefined>;
|
|
87
101
|
/** `npm pack <spec>` + tar extract — generalized from
|
|
88
102
|
* create-loopengine's own `fetchPublishedTemplateDir` (that function
|
|
89
103
|
* only ever fetches the hardcoded `create-loopengine@<version>`; this
|
|
@@ -166,6 +166,39 @@ export function listInstalledAbilities(agentName) {
|
|
|
166
166
|
function writeProvenance(agentName, data) {
|
|
167
167
|
writeFileSync(provenancePath(agentName), JSON.stringify(data, null, 2) + '\n');
|
|
168
168
|
}
|
|
169
|
+
/** `record.dependencies` is only ever absent for an ability installed or
|
|
170
|
+
* last upgraded before that field existed (see InstalledAbilityRecord's
|
|
171
|
+
* own doc comment) — this re-derives it once by refetching the ability's
|
|
172
|
+
* own manifest (same technique upgradeAbility already uses for its own
|
|
173
|
+
* three-way merge base) and persists the result into provenance, so this
|
|
174
|
+
* only ever runs once per such ability rather than on every read. A
|
|
175
|
+
* record that already has `dependencies` — even a real empty array,
|
|
176
|
+
* meaning the ability genuinely declares none — is returned unchanged,
|
|
177
|
+
* never refetched. Best-effort: a spec that no longer resolves (private
|
|
178
|
+
* registry auth expired, a git ref that's gone, ...) leaves
|
|
179
|
+
* `dependencies` unset rather than throwing, since the Admin UI's own
|
|
180
|
+
* caller (handleAbilitiesGet) would rather show "can't tell" than fail
|
|
181
|
+
* the whole abilities list over one ability's stale record. */
|
|
182
|
+
export async function backfillDependencies(agentName, abilityName, options = {}) {
|
|
183
|
+
const provenance = readProvenance(agentName);
|
|
184
|
+
const record = provenance[abilityName];
|
|
185
|
+
if (!record)
|
|
186
|
+
return undefined;
|
|
187
|
+
if (record.dependencies !== undefined)
|
|
188
|
+
return record.dependencies;
|
|
189
|
+
const fetch = options.fetchAbilityDir ?? fetchAbilityDir;
|
|
190
|
+
try {
|
|
191
|
+
const dir = fetch(record.spec ?? abilityName);
|
|
192
|
+
const manifest = readManifest(dir);
|
|
193
|
+
record.dependencies = manifest.dependencies ?? [];
|
|
194
|
+
provenance[abilityName] = record;
|
|
195
|
+
writeProvenance(agentName, provenance);
|
|
196
|
+
return record.dependencies;
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
return undefined;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
169
202
|
function sha256(content) {
|
|
170
203
|
return createHash('sha256').update(content).digest('hex');
|
|
171
204
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -57,7 +57,7 @@ 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, upgradeAbility, listInstalledAbilities, AbilityManifestError, AbilityVersionError, AbilityCollisionError, AbilityAlreadyInstalledError, AbilityNotInstalledError, } from './bin/ability-manager.js';
|
|
60
|
+
export { installAbility, upgradeAbility, listInstalledAbilities, backfillDependencies, AbilityManifestError, AbilityVersionError, AbilityCollisionError, AbilityAlreadyInstalledError, AbilityNotInstalledError, } from './bin/ability-manager.js';
|
|
61
61
|
export type { InstalledAbilityRecord, AbilityEnvDecl, UpgradeFileResult } from './bin/ability-manager.js';
|
|
62
62
|
export { searchPublicAbilities, fetchLatestAbilityVersion } from './web/abilities-admin.js';
|
|
63
63
|
export type { PublicAbilitySearchResult } from './web/abilities-admin.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, upgradeAbility, listInstalledAbilities, AbilityManifestError, AbilityVersionError, AbilityCollisionError, AbilityAlreadyInstalledError, AbilityNotInstalledError, } from './bin/ability-manager.js';
|
|
54
|
+
export { installAbility, upgradeAbility, listInstalledAbilities, backfillDependencies, AbilityManifestError, AbilityVersionError, AbilityCollisionError, AbilityAlreadyInstalledError, AbilityNotInstalledError, } from './bin/ability-manager.js';
|
|
55
55
|
export { searchPublicAbilities, fetchLatestAbilityVersion } 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';
|
|
@@ -75,15 +75,18 @@ export const agentsConfigPageHtml = `<!doctype html>
|
|
|
75
75
|
flex-direction: column;
|
|
76
76
|
}
|
|
77
77
|
#agentList { list-style: none; margin: 0; padding: 6px; flex: 1; }
|
|
78
|
-
#agentList li {
|
|
78
|
+
#agentList li { border-radius: 6px; }
|
|
79
|
+
#agentList li a {
|
|
80
|
+
display: block;
|
|
79
81
|
padding: 8px 10px;
|
|
80
82
|
border-radius: 6px;
|
|
81
|
-
cursor: pointer;
|
|
82
83
|
font-size: 13px;
|
|
83
84
|
font-family: ui-monospace, monospace;
|
|
85
|
+
color: inherit;
|
|
86
|
+
text-decoration: none;
|
|
84
87
|
}
|
|
85
|
-
#agentList li:hover { background: light-dark(#eee, #26262b); }
|
|
86
|
-
#agentList li.active { background: light-dark(#dbeafe, #1e3a5f); font-weight: 600; }
|
|
88
|
+
#agentList li a:hover { background: light-dark(#eee, #26262b); }
|
|
89
|
+
#agentList li.active a { background: light-dark(#dbeafe, #1e3a5f); font-weight: 600; }
|
|
87
90
|
main {
|
|
88
91
|
flex: 1;
|
|
89
92
|
overflow-y: auto;
|
|
@@ -2512,9 +2515,17 @@ export const agentsConfigPageHtml = `<!doctype html>
|
|
|
2512
2515
|
for (var i = 0; i < agents.length; i++) {
|
|
2513
2516
|
(function (name) {
|
|
2514
2517
|
var li = document.createElement('li');
|
|
2515
|
-
li.textContent = name;
|
|
2516
2518
|
li.dataset.name = name;
|
|
2517
|
-
|
|
2519
|
+
// A real <a href>, not a click handler calling selectAgent —
|
|
2520
|
+
// switching agents is a full navigation to this same page with
|
|
2521
|
+
// a different ?agent=, so the URL, browser back/forward, and
|
|
2522
|
+
// bookmarking all reflect which agent is open, instead of the
|
|
2523
|
+
// URL staying frozen at whatever it was on first load while
|
|
2524
|
+
// the panel silently swaps underneath it via fetch.
|
|
2525
|
+
var a = document.createElement('a');
|
|
2526
|
+
a.href = '/agents/config?agent=' + encodeURIComponent(name);
|
|
2527
|
+
a.textContent = name;
|
|
2528
|
+
li.appendChild(a);
|
|
2518
2529
|
agentList.appendChild(li);
|
|
2519
2530
|
})(agents[i].name);
|
|
2520
2531
|
}
|