fix: eliminate all 4xx noise from scene walks
- 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:
@@ -66,7 +66,7 @@ export const agentMemory = {
|
|||||||
async remember(email: string, content: string, tags: string[] = [], signal?: AbortSignal): Promise<string | null> {
|
async remember(email: string, content: string, tags: string[] = [], signal?: AbortSignal): Promise<string | null> {
|
||||||
if (!content.trim()) return null;
|
if (!content.trim()) return null;
|
||||||
const vaultKey = vaultKeyFor(email);
|
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`, {
|
const doc = await fetch(`${api.config.baseUrl}/api/ea2/flow`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: authHeaders(),
|
headers: authHeaders(),
|
||||||
@@ -83,6 +83,10 @@ export const agentMemory = {
|
|||||||
});
|
});
|
||||||
if (!doc.ok) return null;
|
if (!doc.ok) return null;
|
||||||
const mem = await doc.json();
|
const mem = await doc.json();
|
||||||
|
if (!vaultReady) {
|
||||||
|
console.warn(`[memory] vault not ready for ${email}, skipping edge attach`);
|
||||||
|
return mem._key;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const edgeRes = await fetch(`${api.config.baseUrl}/api/ea2/apply-batch`, {
|
const edgeRes = await fetch(`${api.config.baseUrl}/api/ea2/apply-batch`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
|||||||
@@ -272,9 +272,7 @@ export async function buildLiveScenariosFromApi(signal?: AbortSignal): Promise<{
|
|||||||
const recentCandidates = c.cases
|
const recentCandidates = c.cases
|
||||||
.filter((w) => w.transaction_id && w.transaction_id !== headlineCase?.transaction_id)
|
.filter((w) => w.transaction_id && w.transaction_id !== headlineCase?.transaction_id)
|
||||||
.slice(0, 3);
|
.slice(0, 3);
|
||||||
const headlineRt = headlineCase?.transaction_id
|
const headlineRt = workItemToRt(headlineCase);
|
||||||
? (await api.transaction(headlineCase.transaction_id, signal)) ?? workItemToRt(headlineCase)
|
|
||||||
: null;
|
|
||||||
const recent: RuntimeTransaction[] = recentCandidates
|
const recent: RuntimeTransaction[] = recentCandidates
|
||||||
.map((w) => workItemToRt(w))
|
.map((w) => workItemToRt(w))
|
||||||
.filter((r): r is RuntimeTransaction => r != null);
|
.filter((r): r is RuntimeTransaction => r != null);
|
||||||
|
|||||||
@@ -12,7 +12,10 @@ const POLL_MS = 30_000;
|
|||||||
|
|
||||||
async function probeOnce(signal: AbortSignal): Promise<BackendHealth> {
|
async function probeOnce(signal: AbortSignal): Promise<BackendHealth> {
|
||||||
try {
|
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 === 200 || r.status === 401 || r.status === 403) return "up";
|
||||||
if (r.status === 502 || r.status === 504) return "proxy-down";
|
if (r.status === 502 || r.status === 504) return "proxy-down";
|
||||||
if (r.status === 503) return "auth-down";
|
if (r.status === 503) return "auth-down";
|
||||||
|
|||||||
+2
-7
@@ -311,13 +311,8 @@ export const useApp = create<AppState>((set, get) => {
|
|||||||
try {
|
try {
|
||||||
const workItems = await api.workItems();
|
const workItems = await api.workItems();
|
||||||
const sc = s.scenarios.find((x) => x.id === s.scenarioId);
|
const sc = s.scenarios.find((x) => x.id === s.scenarioId);
|
||||||
let headlineRt = null;
|
const existingHeadline = (sc?.raw as { headlineRt?: unknown } | undefined)?.headlineRt ?? null;
|
||||||
if (sc?.headlineTx) {
|
const headlineRt = existingHeadline;
|
||||||
// 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 updatedScenarios = s.scenarios.map((scen) => {
|
const updatedScenarios = s.scenarios.map((scen) => {
|
||||||
if (!scen.live) return scen;
|
if (!scen.live) return scen;
|
||||||
const myCases = workItems.filter((w) => w.definition_key === scen.defKey);
|
const myCases = workItems.filter((w) => w.definition_key === scen.defKey);
|
||||||
|
|||||||
Reference in New Issue
Block a user