@floless/app 0.25.1 → 0.25.2
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/floless-server.cjs +22 -4
- package/dist/web/aware.js +44 -22
- package/package.json +1 -1
package/dist/floless-server.cjs
CHANGED
|
@@ -52777,7 +52777,7 @@ function appVersion() {
|
|
|
52777
52777
|
return resolveVersion({
|
|
52778
52778
|
isSea: isSea2(),
|
|
52779
52779
|
sqVersionXml: readSqVersionXml(),
|
|
52780
|
-
define: true ? "0.25.
|
|
52780
|
+
define: true ? "0.25.2" : void 0,
|
|
52781
52781
|
pkgVersion: readPkgVersion()
|
|
52782
52782
|
});
|
|
52783
52783
|
}
|
|
@@ -52787,7 +52787,7 @@ function resolveChannel(s) {
|
|
|
52787
52787
|
return "dev";
|
|
52788
52788
|
}
|
|
52789
52789
|
function appChannel() {
|
|
52790
|
-
return resolveChannel({ isSea: isSea2(), define: true ? "0.25.
|
|
52790
|
+
return resolveChannel({ isSea: isSea2(), define: true ? "0.25.2" : void 0 });
|
|
52791
52791
|
}
|
|
52792
52792
|
|
|
52793
52793
|
// oauth-presets.ts
|
|
@@ -57665,11 +57665,29 @@ async function startServer() {
|
|
|
57665
57665
|
throw err;
|
|
57666
57666
|
}
|
|
57667
57667
|
});
|
|
57668
|
+
const installingAgents = /* @__PURE__ */ new Set();
|
|
57669
|
+
let installQueue = Promise.resolve();
|
|
57668
57670
|
app.post("/api/agents/install", async (req, reply) => {
|
|
57669
57671
|
const id = req.body?.id;
|
|
57670
57672
|
if (!id || typeof id !== "string") return reply.status(400).send({ ok: false, error: "id is required" });
|
|
57671
|
-
|
|
57672
|
-
|
|
57673
|
+
if (installingAgents.has(id)) return reply.status(202).send({ ok: true, started: true });
|
|
57674
|
+
installingAgents.add(id);
|
|
57675
|
+
installQueue = installQueue.then(async () => {
|
|
57676
|
+
let result;
|
|
57677
|
+
try {
|
|
57678
|
+
const res = await aware.ensureAgentInstalled(id);
|
|
57679
|
+
result = { type: "agent-install-result", id, ok: true, installed: res.installed ?? id };
|
|
57680
|
+
} catch (err) {
|
|
57681
|
+
result = { type: "agent-install-result", id, ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
57682
|
+
} finally {
|
|
57683
|
+
installingAgents.delete(id);
|
|
57684
|
+
}
|
|
57685
|
+
try {
|
|
57686
|
+
broadcast(result);
|
|
57687
|
+
} catch {
|
|
57688
|
+
}
|
|
57689
|
+
});
|
|
57690
|
+
return reply.status(202).send({ ok: true, started: true });
|
|
57673
57691
|
});
|
|
57674
57692
|
app.get("/api/integrations", async () => {
|
|
57675
57693
|
let integrations = listIntegrations();
|
package/dist/web/aware.js
CHANGED
|
@@ -3292,6 +3292,23 @@
|
|
|
3292
3292
|
loadAgentCatalog().then(() => {
|
|
3293
3293
|
if ($libModal && $libModal.classList.contains('show')) renderLibrary();
|
|
3294
3294
|
}).catch(() => {});
|
|
3295
|
+
} else if (m.type === 'agent-install-result') {
|
|
3296
|
+
// A background `aware agent install` (from the Available tab) finished. Clear
|
|
3297
|
+
// its in-flight state, then on success refresh so it drops out of Available and
|
|
3298
|
+
// appears under Installed; on failure restore its Install button + surface why.
|
|
3299
|
+
installingIds.delete(m.id);
|
|
3300
|
+
if (m.ok) {
|
|
3301
|
+
const a = availableCatalog.find((x) => x.id === m.id);
|
|
3302
|
+
showToast(`Installed “${a && a.display_name ? a.display_name : m.id}” — find it in Installed`, 'ok');
|
|
3303
|
+
loadAgentCatalog().then(() => {
|
|
3304
|
+
if (!($libModal && $libModal.classList.contains('show'))) return;
|
|
3305
|
+
renderAvailable();
|
|
3306
|
+
if (libTab === 'installed') renderLibrary();
|
|
3307
|
+
}).catch(() => {});
|
|
3308
|
+
} else {
|
|
3309
|
+
showToast(`Install failed: ${String(m.error || '').slice(0, 80)}`, 'err');
|
|
3310
|
+
if ($libModal && $libModal.classList.contains('show')) renderAvailable();
|
|
3311
|
+
}
|
|
3295
3312
|
} else if (m.type === 'request-added' || m.type === 'requests-changed') {
|
|
3296
3313
|
loadRequests();
|
|
3297
3314
|
if (window.flolessPanels) window.flolessPanels.refreshPending(); // composer's "queued" line
|
|
@@ -3796,6 +3813,7 @@
|
|
|
3796
3813
|
let availableLoading = false; // a fetch is in flight (prevents a double-fetch race)
|
|
3797
3814
|
let availableUnsupported = false; // CLI too old to know `agent catalog`
|
|
3798
3815
|
let libTab = 'installed';
|
|
3816
|
+
const installingIds = new Set(); // ids with an install in flight (server runs it async)
|
|
3799
3817
|
|
|
3800
3818
|
async function loadAvailableAgents() {
|
|
3801
3819
|
const { agents, unsupported } = await api('/api/agents/available');
|
|
@@ -3817,6 +3835,11 @@
|
|
|
3817
3835
|
// renders "undefined command". (Numbers, so no escaping needed.)
|
|
3818
3836
|
const cmds = Number(a.commands) || 0;
|
|
3819
3837
|
const skills = Number(a.skills) || 0;
|
|
3838
|
+
// The install runs server-side and can take a minute; the button persists its
|
|
3839
|
+
// "Installing…" state across re-renders (search/tab-switch) via installingIds.
|
|
3840
|
+
const installBtn = installingIds.has(a.id)
|
|
3841
|
+
? `<button class="lib-install" aria-busy="true" aria-label="Installing ${escapeAttr(a.display_name || a.id)}…" data-tip="Downloading from the registry — this can take a minute"><span class="rtn-spinner"></span></button>`
|
|
3842
|
+
: `<button class="lib-install" data-install="${escapeAttr(a.id)}" aria-label="Install ${escapeAttr(a.display_name || a.id)}">Install</button>`;
|
|
3820
3843
|
return `
|
|
3821
3844
|
<div class="lib-card" data-agent="${escapeAttr(a.id)}">
|
|
3822
3845
|
<div class="lib-item">
|
|
@@ -3825,7 +3848,7 @@
|
|
|
3825
3848
|
<div class="meta">${cmds} command${cmds === 1 ? '' : 's'} · ${skills} skill${skills === 1 ? '' : 's'}</div>
|
|
3826
3849
|
${blurb}
|
|
3827
3850
|
</div>
|
|
3828
|
-
|
|
3851
|
+
${installBtn}
|
|
3829
3852
|
</div>
|
|
3830
3853
|
</div>`;
|
|
3831
3854
|
}
|
|
@@ -3896,29 +3919,28 @@
|
|
|
3896
3919
|
});
|
|
3897
3920
|
}
|
|
3898
3921
|
|
|
3899
|
-
|
|
3900
|
-
|
|
3922
|
+
// Kick off an install. The server runs `aware agent install` asynchronously (it can
|
|
3923
|
+
// take a minute — it downloads from the registry) and reports completion over SSE
|
|
3924
|
+
// (`agent-install-result`), so we DON'T await it here — that's what made the button
|
|
3925
|
+
// look hung. We flip the card to "Installing…" and let the SSE handler finish it.
|
|
3926
|
+
function installAgent(id, btn) {
|
|
3927
|
+
if (installingIds.has(id)) return; // already in flight (server dedupes too)
|
|
3928
|
+
installingIds.add(id);
|
|
3901
3929
|
const a = availableCatalog.find((x) => x.id === id);
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
btn.removeAttribute('aria-busy');
|
|
3909
|
-
btn.setAttribute('aria-label', label);
|
|
3910
|
-
btn.textContent = 'Install';
|
|
3911
|
-
reportErr(e);
|
|
3912
|
-
return;
|
|
3930
|
+
const nice = a && a.display_name ? a.display_name : id;
|
|
3931
|
+
if (btn) { // immediate feedback before the next render
|
|
3932
|
+
btn.setAttribute('aria-busy', 'true');
|
|
3933
|
+
btn.setAttribute('aria-label', `Installing ${nice}…`);
|
|
3934
|
+
btn.removeAttribute('data-install'); // a stray re-wire can't re-trigger it
|
|
3935
|
+
btn.innerHTML = '<span class="rtn-spinner"></span>';
|
|
3913
3936
|
}
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
if (libTab === 'installed') renderLibrary();
|
|
3937
|
+
showToast(`Installing “${nice}” — this can take a minute or two`, 'info');
|
|
3938
|
+
api('/api/agents/install', { method: 'POST', body: JSON.stringify({ id }) })
|
|
3939
|
+
.catch((e) => { // the START failed (bad id / server) — completion errors arrive via SSE
|
|
3940
|
+
installingIds.delete(id);
|
|
3941
|
+
if ($libModal && $libModal.classList.contains('show')) renderAvailable();
|
|
3942
|
+
reportErr(e);
|
|
3943
|
+
});
|
|
3922
3944
|
}
|
|
3923
3945
|
|
|
3924
3946
|
function switchLibTab(tab) {
|