Compare commits
2 Commits
91c134c309
...
cfd064aad5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cfd064aad5 | ||
|
|
9ce6bfc08f |
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
**Upstream version:** v0.51.118
|
**Upstream version:** v0.51.118
|
||||||
**Plugin version:** 0.5.0
|
**Plugin version:** 0.5.0
|
||||||
**Total dependencies:** 33 (24 public API · 0 forced internal · 9 frontend)
|
**Total dependencies:** 32 (23 public API · 0 forced internal · 9 frontend)
|
||||||
|
|
||||||
> **Auto-generated by `scripts/ast-connection-map.py`. Do not hand-edit.**
|
> **Auto-generated by `scripts/ast-connection-map.py`. Do not hand-edit.**
|
||||||
> To change a justification, edit the `# CONNECTION:` comment above the
|
> To change a justification, edit the `# CONNECTION:` comment above the
|
||||||
@ -32,10 +32,9 @@
|
|||||||
| `routes/transcribe.py:37` | `api.logger` | `log = api.logger("svrnty.routes.transcribe")` |
|
| `routes/transcribe.py:37` | `api.logger` | `log = api.logger("svrnty.routes.transcribe")` |
|
||||||
| `routes/transcribe.py:38` | `api.register_route` | `api.register_route("/api/transcribe", "POST", _handle_transcribe)` |
|
| `routes/transcribe.py:38` | `api.register_route` | `api.register_route("/api/transcribe", "POST", _handle_transcribe)` |
|
||||||
| `routes/transcribe.py:39` | `api.register_audio_attachment_processor` | `api.register_audio_attachment_processor(_transcribe_audio_attachments)` |
|
| `routes/transcribe.py:39` | `api.register_audio_attachment_processor` | `api.register_audio_attachment_processor(_transcribe_audio_attachments)` |
|
||||||
| `routes/umbrella.py:30` | `api.logger` | `log = api.logger("svrnty.routes.umbrella")` |
|
| `routes/umbrella.py:37` | `api.logger` | `log = api.logger("svrnty.routes.umbrella")` |
|
||||||
| `routes/umbrella.py:31` | `api.register_route` | `api.register_route("/umbrella", "GET", _handle_panel_html)` |
|
| `routes/umbrella.py:38` | `api.register_route` | `api.register_route("/api/umbrella", "GET", _handle_graph_json)` |
|
||||||
| `routes/umbrella.py:32` | `api.register_route` | `api.register_route("/api/umbrella", "GET", _handle_graph_json)` |
|
| `routes/umbrella.py:39` | `api.register_route` | `api.register_route("/api/umbrella/doc", "GET", _handle_doc_body)` |
|
||||||
| `routes/umbrella.py:33` | `api.register_route` | `api.register_route("/api/umbrella/doc", "GET", _handle_doc_body)` |
|
|
||||||
| `routes/vault_status.py:19` | `api.logger` | `log = api.logger("svrnty.routes.vault_status")` |
|
| `routes/vault_status.py:19` | `api.logger` | `log = api.logger("svrnty.routes.vault_status")` |
|
||||||
| `routes/vault_status.py:20` | `api.register_route` | `api.register_route("/api/vault/status", "GET", _handle_vault_status)` |
|
| `routes/vault_status.py:20` | `api.register_route` | `api.register_route("/api/vault/status", "GET", _handle_vault_status)` |
|
||||||
|
|
||||||
@ -57,9 +56,9 @@ _None. Plugin uses only the public API._ ✓
|
|||||||
| `static/bte.js` | 360 | `/api/query/assetDtos` |
|
| `static/bte.js` | 360 | `/api/query/assetDtos` |
|
||||||
| `static/bte.js` | 372 | `/api/assets/` |
|
| `static/bte.js` | 372 | `/api/assets/` |
|
||||||
| `static/bte.js` | 481 | `/api/command/rateAsset` |
|
| `static/bte.js` | 481 | `/api/command/rateAsset` |
|
||||||
| `static/adwright.js` | 168 | `/api/profile/switch` |
|
| `static/adwright.js` | 175 | `/api/profile/switch` |
|
||||||
| `static/adwright.js` | 189 | `/api/profile/active` |
|
| `static/adwright.js` | 196 | `/api/profile/active` |
|
||||||
| `static/adwright.js` | 539 | `/api/adwright/provision-creds` |
|
| `static/adwright.js` | 583 | `/api/adwright/provision-creds` |
|
||||||
| `static/umbrella.js` | 41 | `/api/umbrella` |
|
| `static/umbrella.js` | 41 | `/api/umbrella` |
|
||||||
| `static/app.js` | 165 | `/api/vault/status` |
|
| `static/app.js` | 165 | `/api/vault/status` |
|
||||||
|
|
||||||
|
|||||||
@ -314,7 +314,7 @@
|
|||||||
'<div class="svrnty-aw-timeline-time">' + _esc(c.started_at || "") + '</div>' +
|
'<div class="svrnty-aw-timeline-time">' + _esc(c.started_at || "") + '</div>' +
|
||||||
'<div class="svrnty-aw-timeline-text">' +
|
'<div class="svrnty-aw-timeline-text">' +
|
||||||
_esc(c.title || ("Cycle #" + (c.id || "?"))) +
|
_esc(c.title || ("Cycle #" + (c.id || "?"))) +
|
||||||
' — <span style="color:var(--muted)">' + _esc(c.status || "") + '</span>' +
|
' — <span style="color:var(--muted)">' + _esc(_humanStatus(c.status)) + '</span>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'</div>'
|
'</div>'
|
||||||
).join("") +
|
).join("") +
|
||||||
@ -329,6 +329,23 @@
|
|||||||
function _cycleSpend(x) {
|
function _cycleSpend(x) {
|
||||||
return parseFloat(x.spend || 0) || 0;
|
return parseFloat(x.spend || 0) || 0;
|
||||||
}
|
}
|
||||||
|
// Backend serializes enum as canonical proto string ("CYCLE_STATUS_PREVIEW_READY",
|
||||||
|
// "VARIANT_STATUS_ACTIVE", etc.). Drop the prefix + title-case the rest.
|
||||||
|
const _STATUS_LABELS = {
|
||||||
|
"CYCLE_STATUS_ANALYZING": "Analyzing",
|
||||||
|
"CYCLE_STATUS_PREVIEW_READY": "Preview ready",
|
||||||
|
"CYCLE_STATUS_RUNNING": "Running",
|
||||||
|
"CYCLE_STATUS_COMPLETE": "Complete",
|
||||||
|
"CYCLE_STATUS_FAILED": "Failed",
|
||||||
|
"VARIANT_STATUS_PREVIEW_READY": "Preview ready",
|
||||||
|
"VARIANT_STATUS_ACTIVE": "Active",
|
||||||
|
"VARIANT_STATUS_PAUSED": "Paused",
|
||||||
|
"VARIANT_STATUS_COMPLETE": "Complete",
|
||||||
|
};
|
||||||
|
function _humanStatus(s) {
|
||||||
|
if (!s) return "";
|
||||||
|
return _STATUS_LABELS[s] || s;
|
||||||
|
}
|
||||||
function _deriveKpis(cycles, recipes) {
|
function _deriveKpis(cycles, recipes) {
|
||||||
const c = cycles || [];
|
const c = cycles || [];
|
||||||
const r = recipes || [];
|
const r = recipes || [];
|
||||||
@ -381,7 +398,7 @@
|
|||||||
'<div class="svrnty-aw-row" data-svrnty-aw-cycle="' + _attr(c.id) + '">' +
|
'<div class="svrnty-aw-row" data-svrnty-aw-cycle="' + _attr(c.id) + '">' +
|
||||||
'<div class="svrnty-aw-row-main">' +
|
'<div class="svrnty-aw-row-main">' +
|
||||||
'<div class="svrnty-aw-row-title">' + _esc(c.title || ("Cycle #" + c.id)) + '</div>' +
|
'<div class="svrnty-aw-row-title">' + _esc(c.title || ("Cycle #" + c.id)) + '</div>' +
|
||||||
'<div class="svrnty-aw-row-sub">' + _esc(c.status || "") + ' · started ' + _esc(c.started_at || "") + '</div>' +
|
'<div class="svrnty-aw-row-sub">' + _esc(_humanStatus(c.status)) + ' · started ' + _esc(c.started_at || "") + '</div>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'<div class="svrnty-aw-row-meta">$' + _fmt(_cycleSpend(c)) + ' / $' + _fmt(_cycleBudget(c)) + '</div>' +
|
'<div class="svrnty-aw-row-meta">$' + _fmt(_cycleSpend(c)) + ' / $' + _fmt(_cycleBudget(c)) + '</div>' +
|
||||||
'</div>'
|
'</div>'
|
||||||
@ -412,7 +429,7 @@
|
|||||||
variants.map((v) =>
|
variants.map((v) =>
|
||||||
'<div style="display:flex;justify-content:space-between;font-size:12px">' +
|
'<div style="display:flex;justify-content:space-between;font-size:12px">' +
|
||||||
'<span>' + _esc(v.name || v.id || "variant") + '</span>' +
|
'<span>' + _esc(v.name || v.id || "variant") + '</span>' +
|
||||||
'<span style="color:var(--muted)">' + _esc(v.status || "") + ' · imp ' + _fmt(v.impressions || 0) + '</span>' +
|
'<span style="color:var(--muted)">' + _esc(_humanStatus(v.status)) + ' · imp ' + _fmt(v.impressions || 0) + '</span>' +
|
||||||
'</div>'
|
'</div>'
|
||||||
).join("") +
|
).join("") +
|
||||||
'</div>';
|
'</div>';
|
||||||
@ -612,12 +629,34 @@
|
|||||||
}
|
}
|
||||||
_fireAction(action);
|
_fireAction(action);
|
||||||
}
|
}
|
||||||
|
// User-facing label for each action — shown via our toast so the user sees
|
||||||
|
// "Refreshing Overview" rather than the raw `/adwright refresh-cycles` slash
|
||||||
|
// command that hermes-webui's native Queued banner displays underneath.
|
||||||
|
const _ACTION_LABELS = {
|
||||||
|
"refresh-overview": "Refreshing Overview…",
|
||||||
|
"refresh-cycles": "Refreshing cycles…",
|
||||||
|
"get-cycle": "Loading cycle…",
|
||||||
|
"list-segments": "Loading segments…",
|
||||||
|
"list-recipes": "Loading recipes…",
|
||||||
|
"connections-status": "Checking connections…",
|
||||||
|
};
|
||||||
|
// Compound actions — one user gesture, multiple underlying tool calls.
|
||||||
|
// Overview KPIs need both cycles (for Cycles count + Spend + timeline)
|
||||||
|
// AND recipes (for Recipes count). Fire both so KPIs stay coherent.
|
||||||
|
const _COMPOUND_ACTIONS = {
|
||||||
|
"refresh-overview": ["refresh-cycles", "list-recipes"],
|
||||||
|
};
|
||||||
function _fireAction(action, args) {
|
function _fireAction(action, args) {
|
||||||
if (!_isCmoActive()) {
|
if (!_isCmoActive()) {
|
||||||
_toast("Switch to CMO profile to run /adwright commands.", "error");
|
_toast("Switch to CMO profile to run /adwright commands.", "error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
args = args || {};
|
args = args || {};
|
||||||
|
if (_COMPOUND_ACTIONS[action]) {
|
||||||
|
if (_ACTION_LABELS[action]) _toast(_ACTION_LABELS[action]);
|
||||||
|
_COMPOUND_ACTIONS[action].forEach((sub) => _fireAction(sub, args));
|
||||||
|
return;
|
||||||
|
}
|
||||||
const cmd = _commandFor(action, args);
|
const cmd = _commandFor(action, args);
|
||||||
if (!cmd) return;
|
if (!cmd) return;
|
||||||
// Dispatch event for any external listeners (audit / tests).
|
// Dispatch event for any external listeners (audit / tests).
|
||||||
@ -630,6 +669,7 @@
|
|||||||
_toast("Couldn't post to chat — is a session open?", "error");
|
_toast("Couldn't post to chat — is a session open?", "error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (_ACTION_LABELS[action]) _toast(_ACTION_LABELS[action]);
|
||||||
_startPolling();
|
_startPolling();
|
||||||
}
|
}
|
||||||
function _commandFor(action, args) {
|
function _commandFor(action, args) {
|
||||||
@ -670,8 +710,12 @@
|
|||||||
|
|
||||||
// ── Polling: /api/adwright/last-panel-update ──────────────────────────
|
// ── Polling: /api/adwright/last-panel-update ──────────────────────────
|
||||||
function _startPolling() {
|
function _startPolling() {
|
||||||
if (NS.state.pollTimer) return;
|
// Reset deadline on every call so back-to-back sub-actions (compound
|
||||||
|
// refresh-overview = refresh-cycles + list-recipes) each get a fresh
|
||||||
|
// POLL_MAX_MS window — CMO processes chat messages sequentially and
|
||||||
|
// each tool can take ~25s.
|
||||||
NS.state.pollStartedAt = Date.now();
|
NS.state.pollStartedAt = Date.now();
|
||||||
|
if (NS.state.pollTimer) return;
|
||||||
NS.state.pollTimer = setInterval(_pollOnce, POLL_INTERVAL_MS);
|
NS.state.pollTimer = setInterval(_pollOnce, POLL_INTERVAL_MS);
|
||||||
// Run once immediately so we don't wait the first 2s.
|
// Run once immediately so we don't wait the first 2s.
|
||||||
_pollOnce();
|
_pollOnce();
|
||||||
@ -699,9 +743,16 @@
|
|||||||
const u = r.update;
|
const u = r.update;
|
||||||
if (u.ts && u.ts <= NS.state.lastSeenTs) return;
|
if (u.ts && u.ts <= NS.state.lastSeenTs) return;
|
||||||
NS.state.lastSeenTs = u.ts || Date.now();
|
NS.state.lastSeenTs = u.ts || Date.now();
|
||||||
|
// Sign of life — reset deadline. Lets compound actions (two CMO
|
||||||
|
// calls back-to-back, ~50s total) finish even when each sub-action
|
||||||
|
// shares one POLL_MAX_MS window with its sibling.
|
||||||
|
NS.state.pollStartedAt = Date.now();
|
||||||
_ingestUpdate(u);
|
_ingestUpdate(u);
|
||||||
// Got our update — stop polling, render.
|
// Got our update — stop polling only when the response matches the
|
||||||
if (u.tool === tool || !tool) {
|
// CURRENT pendingTool. Compound actions overwrite pendingTool after
|
||||||
|
// sub1's fetch is already in flight; if sub1's response arrives we
|
||||||
|
// ingest it but keep polling for sub2.
|
||||||
|
if (NS.state.pendingTool && u.tool === NS.state.pendingTool) {
|
||||||
NS.state.pendingTool = null;
|
NS.state.pendingTool = null;
|
||||||
_stopPolling();
|
_stopPolling();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,10 +10,10 @@
|
|||||||
============================================================================ */
|
============================================================================ */
|
||||||
|
|
||||||
/* ── Montserrat (self-hosted, sovereign — no external CDN; font-src 'self') ── */
|
/* ── Montserrat (self-hosted, sovereign — no external CDN; font-src 'self') ── */
|
||||||
@font-face{font-family:"Montserrat";font-style:normal;font-weight:400;font-display:swap;src:url("/extensions/fonts/montserrat-400.woff2") format("woff2");}
|
@font-face{font-family:"Montserrat";font-style:normal;font-weight:400;font-display:swap;src:url("/plugins/svrnty/fonts/montserrat-400.woff2") format("woff2");}
|
||||||
@font-face{font-family:"Montserrat";font-style:normal;font-weight:500;font-display:swap;src:url("/extensions/fonts/montserrat-500.woff2") format("woff2");}
|
@font-face{font-family:"Montserrat";font-style:normal;font-weight:500;font-display:swap;src:url("/plugins/svrnty/fonts/montserrat-500.woff2") format("woff2");}
|
||||||
@font-face{font-family:"Montserrat";font-style:normal;font-weight:600;font-display:swap;src:url("/extensions/fonts/montserrat-600.woff2") format("woff2");}
|
@font-face{font-family:"Montserrat";font-style:normal;font-weight:600;font-display:swap;src:url("/plugins/svrnty/fonts/montserrat-600.woff2") format("woff2");}
|
||||||
@font-face{font-family:"Montserrat";font-style:normal;font-weight:700;font-display:swap;src:url("/extensions/fonts/montserrat-700.woff2") format("woff2");}
|
@font-face{font-family:"Montserrat";font-style:normal;font-weight:700;font-display:swap;src:url("/plugins/svrnty/fonts/montserrat-700.woff2") format("woff2");}
|
||||||
|
|
||||||
/* ── Light (svrnty *.light) ─────────────────────────────────────────────── */
|
/* ── Light (svrnty *.light) ─────────────────────────────────────────────── */
|
||||||
:root {
|
:root {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user