Repository navigation
Fix Agent Flow evidence schema fallback - #286
NomadDigita wants to merge 0 commit into
Conversation
|
Deployment failed for project tidelight with the following error: Learn More: https://vercel.com/tessera8?upgradeToPro=build-rate-limit |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
6f2f571 to
d75c711
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d22a27a304
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| return { ticker: snap.ticker, issuer: snap.issuer, summary: assessment.summary, stance: assessment.stance, confidence: assessment.confidence, confidenceCapped: assessment.confidenceCapped ?? false, citedUrls: assessment.citedUrls, supportingEvidence: assessment.supportingEvidence, counterEvidence: assessment.counterEvidence, risks: assessment.risks, nextCheck: assessment.nextCheck, tokenizedMarket: marketReview, markets: { spot: snap.spot, perp: snap.perp }, tradeGate: { tradeable: gate.tradeable, direction: gate.direction, reasons: gateReasons }, destinations, sources: snap.sources, researchRunId: run.id }; | ||
| }); | ||
| stage("Coordinator", "complete", "Review ready", assets.some(asset => asset.tradeable) ? "One or more scenarios may proceed to a separate trade review. Nothing was sent to Bitget or the paper ledger." : "Keep watching the evidence and market. No scenario passed every trade review gate."); | ||
| const result = { researchRunId: run.id, question, researchCoverage: { mode: "deep", lookbackDays: 30, queriesPerTicker: 8, collectedItems: snapshots.reduce((count, snap) => count + snap.sources.length, 0), publishers: [...new Set(snapshots.flatMap(snap => snap.sources.map(source => source.publisher)))].length, sourceDomains: [...new Set(snapshots.flatMap(snap => snap.sources.map(source => new URL(source.url).hostname)))].length, collectedAt: new Date().toISOString(), limitations: ["Headlines and snippets are discovery references, not full article reads.", "Public-feed coverage is bounded and cannot represent the entire internet."] }, assets, tradeable: assets.some(asset => asset.tradeable), trace, contextRunId, ...(workspaceContext ? { workspaceContext } : {}) }; | ||
| const { error: saveError } = await supabase.from("research_runs").update({ status: "complete", completed_at: new Date().toISOString(), summary: result }).eq("id", run.id); | ||
| if (saveError) { | ||
| stage("Coordinator", "blocked", "Private trace could not be saved", "No trade handoff was offered because the research record was not committed."); | ||
| throw new Error(`research-save-failed:${saveError.code}`); | ||
| } else push("result", result); | ||
| } catch (cause) { | ||
| console.error("agent-flow-failed", cause instanceof Error ? cause.message : "unknown"); | ||
| await supabase.from("research_runs").update({ status: "failed", completed_at: new Date().toISOString(), summary: { trace, error: "The market or research workflow did not complete." } }).eq("id", run.id); | ||
| push("error", { error: "The research workflow could not finish. No paper or live order was placed." }); | ||
| const summary = { question, collectedAt: new Date().toISOString(), agentTrace: trace, assets }; |
There was a problem hiding this comment.
Preserve the established Agent Flow result contract
On every successful run, this payload renames required fields (trace to agentTrace, market to markets, and tradeable/gateReasons/handoff to tradeGate/destinations) and omits top-level researchRunId and tradeable. Consequently, parseIntelligenceResult rejects every result in intelligence-provider.tsx, while the direct Agent Flow desk can crash when it dereferences asset.market; return the schema expected by the existing consumers rather than introducing an uncoordinated replacement.
Useful? React with 👍 / 👎.
| } catch (error) { | ||
| console.error("agent-flow-error", error); | ||
| stage("Coordinator", "blocked", "Research run failed", error instanceof Error ? error.message : "The research run could not complete."); | ||
| await supabase.from("research_runs").update({ status: "error", summary: { question, error: "The research run could not complete. Retry shortly.", agentTrace: trace } }).eq("id", run.id); |
There was a problem hiding this comment.
Store failed runs with an allowed status
When any source, persistence, or workflow exception reaches this handler, the update attempts to write status: "error", but the research_runs constraint in 20261004104708_initial_tidelight_research_schema.sql permits failed rather than error. Because the update error is ignored, affected records remain stuck in collecting or analyzing with no saved failure summary or completion timestamp.
Useful? React with 👍 / 👎.
| function jsonObject(raw: string): Record<string, unknown> | null { | ||
| try { | ||
| const clean = raw.trim().replace(/^```(?:json)?\s*/i, "").replace(/\s*```$/, ""); | ||
| const clean = raw.trim().replace(/^\`\`\`(?:json)?\\s*/i, "").replace(/\\s*\`\`\`$/, ""); |
There was a problem hiding this comment.
Restore whitespace matching around fenced JSON
If a provider returns valid JSON inside a conventional fenced block such as `````json\n{"ok":true}\n``` ``, these expressions now look for the literal characters \s instead of whitespace, so neither fence is removed and `JSON.parse` rejects the response. This unnecessarily triggers retries or provider fallback for otherwise valid model output.
Useful? React with 👍 / 👎.
| failures.push(`${provider.label}-invalid-response`); | ||
| // A well-formed but schema-invalid response can improve on retry; | ||
| // retries remain bounded by the same provider and route deadlines. | ||
| if (attempt === 0 && timeoutMs > 9000) continue; |
There was a problem hiding this comment.
Allow schema-invalid responses to retry under the default budget
With both providers configured and the default 20-second budget, the primary provider receives roughly one third of the remaining budget (about 6.7 seconds), making timeoutMs > 9000 false even when its first response is immediately schema-invalid. The newly added retry behavior therefore does not run for default callers, and the accompanying schema-invalid primary response is retried test fails with one Qwen call instead of two.
Useful? React with 👍 / 👎.
| }; | ||
| try { | ||
| const tokenizedMarketQuestion = /\br(?:[A-Z]{1,6})(?:usdt)?\b/i.test(question) || /\b(tokenized|tokenised|reality market|r-token|rtoken)\b/i.test(question); | ||
| const tokenizedMarketQuestion = /\\br(?:[A-Z]{1,6})(?:usdt)?\\b/i.test(question) || /\\b(tokenized|tokenised|reality market|r-token|rtoken)\\b/i.test(question); |
There was a problem hiding this comment.
Restore word boundaries in tokenized-market detection
For normal questions containing rNVDA, tokenized, reality market, or r-token, both expressions now search for literal \b text rather than regex word boundaries, so tokenizedMarketQuestion remains false. Those requests consequently receive the generic AI scope, the source-only fallback omits the rToken-specific limitations, and tokenizedMarketReview is skipped even though the user explicitly asked about the tokenized instrument.
Useful? React with 👍 / 👎.
| await supabase.from("research_runs").update({ status: "failed", completed_at: new Date().toISOString(), summary: { trace, error: "The market or research workflow did not complete." } }).eq("id", run.id); | ||
| push("error", { error: "The research workflow could not finish. No paper or live order was placed." }); | ||
| const summary = { question, collectedAt: new Date().toISOString(), agentTrace: trace, assets }; | ||
| const { error: saveError } = await supabase.from("research_runs").update({ status: "complete", summary }).eq("id", run.id); |
There was a problem hiding this comment.
Record the completion timestamp for successful runs
Successful runs are now marked complete without populating completed_at. This leaves completed records without lifecycle metadata and makes /api/research/replays substitute the later publication time for capturedAt, so a replay published hours or days afterward misstates when its market snapshot and research were captured.
Useful? React with 👍 / 👎.
Summary
textand exactcitedUrls, matching the existing validator.Context
Production logs showed Gemini returning complete JSON, but Agent Flow rejected the response shape. The prompt named evidence fields without the per-point
textkey. Qwen also timed out on the observed batch.Verification