fix(adwright panel): add 1-click Switch-to-CMO button + authoritative profile fetch
Some checks failed
plugin-tests / test (push) Failing after 5s
Some checks failed
plugin-tests / test (push) Failing after 5s
JP feedback: panel says "switch to cmo profile" but offers no way to do so.
Also window.S.activeProfile may be empty on /session/* pages before boot.js
finishes initializing, so the banner showed unnecessarily.
This patch:
- Replaces vague text with a [Switch to CMO] button that POSTs to
/api/profile/switch {name: "cmo-planb"} and reloads on success
- Adds _fetchActiveProfile() that reads /api/profile/active directly
(defense against window.S race); cached in NS.state._fetchedProfile
- Background poll every 5s catches profile switches made from the upstream
Profiles panel — no hard reload needed to clear the banner
- Disabled-state refresh fires once on mount + on each poll
Karpathy 4 rules: smallest possible change (one button + one fetch helper),
no abstraction layer, no fallback "smart" detection — authoritative API only.
This commit is contained in:
parent
c6d94462c4
commit
7dcda7669f
@ -44,7 +44,11 @@
|
||||
// ── Active-profile detection (PRD §3 visibility gating) ────────────────
|
||||
// hermes-webui exposes S.activeProfile (see static/ui.js line 1). We probe
|
||||
// it defensively — the panel always renders, but enables only for CMO.
|
||||
// Cache from a real /api/profile/active fetch since window.S may not be
|
||||
// populated yet on /session/* pages before boot.js runs.
|
||||
NS.state._fetchedProfile = null;
|
||||
function _activeProfile() {
|
||||
if (NS.state._fetchedProfile) return NS.state._fetchedProfile;
|
||||
try {
|
||||
return (window.S && window.S.activeProfile) || "default";
|
||||
} catch (_) { return "default"; }
|
||||
@ -90,6 +94,24 @@
|
||||
_wireConnections(panel);
|
||||
_refreshDisabledState();
|
||||
_renderTab(NS.state.activeTab);
|
||||
// Authoritative profile fetch (window.S may be empty on /session/* paths
|
||||
// before boot.js finishes). Update banner state once it arrives.
|
||||
_fetchActiveProfile().then((name) => {
|
||||
if (name) {
|
||||
NS.state._fetchedProfile = name;
|
||||
_refreshDisabledState();
|
||||
}
|
||||
});
|
||||
// Re-poll every 5s so a profile switch from the upstream Profiles panel
|
||||
// also lifts the banner without requiring a hard reload.
|
||||
setInterval(() => {
|
||||
_fetchActiveProfile().then((name) => {
|
||||
if (name && name !== NS.state._fetchedProfile) {
|
||||
NS.state._fetchedProfile = name;
|
||||
_refreshDisabledState();
|
||||
}
|
||||
});
|
||||
}, 5000);
|
||||
|
||||
NS.state.mounted = true;
|
||||
return true;
|
||||
@ -116,7 +138,8 @@
|
||||
'<nav class="svrnty-aw-nav">' + nav + '</nav>' +
|
||||
'<div class="svrnty-aw-content">' +
|
||||
'<div class="svrnty-aw-disabled-banner" id="svrntyAwDisabledBanner" style="display:none">' +
|
||||
'Adwright is read-only — switch to the <strong>cmo</strong> profile to run actions.' +
|
||||
'Adwright needs the <strong>cmo-planb</strong> profile active. ' +
|
||||
'<button class="svrnty-aw-btn svrnty-aw-btn-primary" id="svrntyAwSwitchCmo">Switch to CMO</button>' +
|
||||
'</div>' +
|
||||
tabs +
|
||||
'</div>' +
|
||||
@ -136,6 +159,38 @@
|
||||
if (bteBtn) bteBtn.addEventListener("click", () => {
|
||||
if (window.SvrntyBTE && window.SvrntyBTE.open) window.SvrntyBTE.open();
|
||||
});
|
||||
// One-click profile switch to cmo-planb.
|
||||
const switchBtn = panel.querySelector("#svrntyAwSwitchCmo");
|
||||
if (switchBtn) switchBtn.addEventListener("click", async () => {
|
||||
switchBtn.disabled = true;
|
||||
switchBtn.textContent = "Switching…";
|
||||
try {
|
||||
const res = await fetch("/api/profile/switch", {
|
||||
method: "POST",
|
||||
credentials: "same-origin",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ name: "cmo-planb" }),
|
||||
});
|
||||
if (!res.ok) throw new Error("HTTP " + res.status);
|
||||
// Reload to pick up new profile state across the whole webui.
|
||||
location.reload();
|
||||
} catch (e) {
|
||||
switchBtn.disabled = false;
|
||||
switchBtn.textContent = "Switch failed — retry";
|
||||
console.error("[svrnty-aw] profile switch failed", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Pull live active profile from server (don't rely on window.S which may
|
||||
// not be populated yet on /session/* pages before boot.js runs).
|
||||
async function _fetchActiveProfile() {
|
||||
try {
|
||||
const r = await fetch("/api/profile/active", { credentials: "same-origin" });
|
||||
if (!r.ok) return null;
|
||||
const d = await r.json();
|
||||
return (d && (d.name || d.profile)) || null;
|
||||
} catch (_) { return null; }
|
||||
}
|
||||
|
||||
function _activateTab(id) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user