fix: eliminate all 4xx noise from scene walks
build-and-publish / test (push) Has been cancelled
build-and-publish / image (push) Has been cancelled

- buildScenarios: drop the /api/runtime/transactions/{id} headline GET
  entirely. Synthesize the RuntimeTransaction shape from the work-item
  data. Backend's per-id endpoint is broken (500 on valid IDs, 404 on
  work-item IDs); we already have all the display fields we need.
- store.ts pollLiveTick: don't refetch headline transaction; reuse
  the existing scenario.raw.headlineRt synthesized at build time.
- useBackendHealth: pass the bearer token if present so the probe
  returns 200 instead of 401 for authenticated users. The probe still
  treats 401 as 'up' for unauthenticated landing page.
- agentMemory.remember: track ensureVault result. Skip the edge attach
  apply-batch entirely if the vault didn't materialize, so we don't
  fire a guaranteed-422 create_edge against a missing from-doc.
This commit is contained in:
canvas-bot
2026-06-16 21:16:31 +04:00
parent b0127c24eb
commit f3a3794e54
4 changed files with 12 additions and 12 deletions
+5 -1
View File
@@ -66,7 +66,7 @@ export const agentMemory = {
async remember(email: string, content: string, tags: string[] = [], signal?: AbortSignal): Promise<string | null> {
if (!content.trim()) return null;
const vaultKey = vaultKeyFor(email);
await ensureVault(vaultKey, email, signal);
const vaultReady = await ensureVault(vaultKey, email, signal);
const doc = await fetch(`${api.config.baseUrl}/api/ea2/flow`, {
method: "POST",
headers: authHeaders(),
@@ -83,6 +83,10 @@ export const agentMemory = {
});
if (!doc.ok) return null;
const mem = await doc.json();
if (!vaultReady) {
console.warn(`[memory] vault not ready for ${email}, skipping edge attach`);
return mem._key;
}
try {
const edgeRes = await fetch(`${api.config.baseUrl}/api/ea2/apply-batch`, {
method: "POST",
+1 -3
View File
@@ -272,9 +272,7 @@ export async function buildLiveScenariosFromApi(signal?: AbortSignal): Promise<{
const recentCandidates = c.cases
.filter((w) => w.transaction_id && w.transaction_id !== headlineCase?.transaction_id)
.slice(0, 3);
const headlineRt = headlineCase?.transaction_id
? (await api.transaction(headlineCase.transaction_id, signal)) ?? workItemToRt(headlineCase)
: null;
const headlineRt = workItemToRt(headlineCase);
const recent: RuntimeTransaction[] = recentCandidates
.map((w) => workItemToRt(w))
.filter((r): r is RuntimeTransaction => r != null);
+4 -1
View File
@@ -12,7 +12,10 @@ const POLL_MS = 30_000;
async function probeOnce(signal: AbortSignal): Promise<BackendHealth> {
try {
const r = await fetch("/api/v1/auth/me", { method: "GET", signal });
const token = typeof sessionStorage !== "undefined" ? sessionStorage.getItem("fm.mc.token.v1") || "" : "";
const headers: Record<string, string> = { "Accept": "application/json" };
if (token) headers.Authorization = `Bearer ${token}`;
const r = await fetch("/api/v1/auth/me", { method: "GET", headers, signal });
if (r.status === 200 || r.status === 401 || r.status === 403) return "up";
if (r.status === 502 || r.status === 504) return "proxy-down";
if (r.status === 503) return "auth-down";
+2 -7
View File
@@ -311,13 +311,8 @@ export const useApp = create<AppState>((set, get) => {
try {
const workItems = await api.workItems();
const sc = s.scenarios.find((x) => x.id === s.scenarioId);
let headlineRt = null;
if (sc?.headlineTx) {
// Best-effort: the per-transaction endpoint can 500/404 when the
// runtime DB is unreachable. Don't surface that as a polling error —
// existing headlineRt in scenario.raw is still valid for display.
headlineRt = await api.transaction(sc.headlineTx).catch(() => null);
}
const existingHeadline = (sc?.raw as { headlineRt?: unknown } | undefined)?.headlineRt ?? null;
const headlineRt = existingHeadline;
const updatedScenarios = s.scenarios.map((scen) => {
if (!scen.live) return scen;
const myCases = workItems.filter((w) => w.definition_key === scen.defKey);