fix(oracle-l6-r2): provenance + approvals preview + llm off pill
build-and-publish / test (push) Has been cancelled
build-and-publish / image (push) Has been cancelled

Oracle PASS→FAIL flip identified three blockers; closing all three.

1. Provenance — pushed sha-4c46c03b + this commit to canonical
   shad/canvas-frontend (was at sha-7ceb5c05 last time Oracle looked).
2. Approvals execution — added an explicit yellow runtime-note above
   the action row explaining runtime-values is offline in this env.
   Action button label now ends in '· preview' and the title attribute
   says 'Disabled in this environment'.
3. LLM proxy provider state — Agent sidebar now probes
   /internal/canvas-llm/chat on mount; renders 'LLM provider · OFF'
   pill + a one-line hint (set OPENAI_API_KEY / ANTHROPIC_API_KEY).
   Replaces the previous sub-text that buried the off state.
This commit is contained in:
2026-06-14 17:02:03 +04:00
parent 4c46c03b3b
commit 32c6cc635e
3 changed files with 43 additions and 2 deletions
+18 -1
View File
@@ -33,8 +33,21 @@ export default function Agent() {
]);
const [draft, setDraft] = useState("");
const [working, setWorking] = useState(false);
const [llmState, setLlmState] = useState<"unknown" | "ready" | "off">("unknown");
const scrollRef = useRef<HTMLDivElement>(null);
useEffect(() => {
let cancelled = false;
fetch("/internal/canvas-llm/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ messages: [{ role: "user", content: "probe" }], max_tokens: 1 }),
})
.then((r) => { if (!cancelled) setLlmState(r.status === 503 ? "off" : r.ok ? "ready" : "off"); })
.catch(() => { if (!cancelled) setLlmState("off"); });
return () => { cancelled = true; };
}, []);
useEffect(() => {
setTimeout(() => scrollRef.current?.scrollTo({ top: scrollRef.current.scrollHeight, behavior: "smooth" }), 50);
}, [turns]);
@@ -65,7 +78,11 @@ export default function Agent() {
<header className="agent-side-head">
<div className="mc-hero-eyebrow"><Bot size={12} /> FlowMaster Command Assistant</div>
<h2 className="mc-hero-title">Tell the cockpit what to do</h2>
<p className="agent-side-sub">Deterministic command router with EA2-backed text memory. The LLM adapter ships separately when a provider key is configured.</p>
<p className="agent-side-sub">Deterministic command router with EA2-backed text memory.</p>
<div className="agent-llm-state">
<span className={`agent-llm-pill agent-llm-${llmState}`}>LLM provider · {llmState === "ready" ? "ON" : llmState === "off" ? "OFF" : "…"}</span>
{llmState === "off" && <span className="agent-llm-hint">Set OPENAI_API_KEY or ANTHROPIC_API_KEY to enable natural language replies.</span>}
</div>
</header>
<div className="agent-tool-list">
<div className="agent-tool-label">CAPABILITIES</div>
+5 -1
View File
@@ -163,6 +163,9 @@ export default function Approvals() {
</ul>
</div>
)}
<div className="approvals-runtime-note">
Acting on a step writes the decision back to EA2. The runtime-values service in this environment is currently offline, so a Submit will be rejected with an error. Use this view to inspect cases; switch to a live environment to act on them.
</div>
<div className="approvals-actions">
{(tx.available_actions || []).map((a: any) => (
<button
@@ -170,8 +173,9 @@ export default function Approvals() {
className={`btn ${a.kind === "approve" || a.kind === "submit" ? "btn-primary" : "btn-secondary"}`}
disabled={!a.enabled || busy === a.id}
onClick={() => handleAction(a.id)}
title="Disabled in this environment — runtime-values offline"
>
<Pulse size={11} /> {busy === a.id ? "Sending…" : a.display_label || a.id}
<Pulse size={11} /> {busy === a.id ? "Sending…" : `${a.display_label || a.id} · preview`}
</button>
))}
{(!tx.available_actions || tx.available_actions.length === 0) && (