[codex] add multi-agent command center#19
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d951e04fba
ℹ️ 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".
| const score = latest.seo.health_score ?? latest.seo.score ?? latest.seo.performance_score; | ||
| if (score == null) return 0; | ||
| return score < 0.9 ? 1 : 0; |
There was a problem hiding this comment.
Compare SEO health score on the correct scale
latest.seo.health_score is a 0–100 metric (see how get_latest_scans returns seo_health_score directly), but this gate compares it to 0.9, so almost every scanned project is treated as having zero SEO fixes even when health is very poor (e.g., 45). This makes the SEO agent row under-report actionable work and misstates project status in the new command-center queue.
Useful? React with 👍 / 👎.
| if result: | ||
| return result |
There was a problem hiding this comment.
Return empty MCP search results instead of treating as failure
When MCP search succeeds but returns zero matches, result is an empty list and this truthy check falls through as if Tavily were unavailable. In MCP-only deployments (no TAVILY_API_KEY), that converts a valid empty response into None, which downstream code interprets as provider failure (for example, SERP tracking emits Tavily unavailable and triggers fallback behavior). Empty results should be returned as [], not dropped.
Useful? React with 👍 / 👎.
| if (latestMonitoring?.status === "pending" || latestMonitoring?.status === "running") return "running"; | ||
| if (pendingApprovals > 0) return "needsReview"; | ||
| return "completed"; |
There was a problem hiding this comment.
Report failed monitoring runs instead of completed
The new status resolver never handles latestMonitoring.status === "failed", so a failed run is shown as Completed whenever the project is not paused and has no pending approvals. This hides operational failures in the command-center header and can cause teams to miss broken monitoring until they inspect deeper pages.
Useful? React with 👍 / 👎.
| for line in text.splitlines(): | ||
| if not line.startswith("data: "): | ||
| continue | ||
| payload = line[6:].strip() | ||
| if not payload or payload == "[DONE]": | ||
| continue | ||
| return json.loads(payload) | ||
| return json.loads(text) |
There was a problem hiding this comment.
Parse full SSE event payload before JSON decoding
This decoder returns on the first data: line, but SSE events can legally contain multiple data: lines that must be concatenated before parsing. With a compliant MCP server that splits JSON across lines, this will try to decode a partial payload and fail every MCP call, silently forcing fallback behavior (or total Tavily unavailability in MCP-only setups).
Useful? React with 👍 / 👎.
d951e04 to
799467c
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 799467c1a6
ℹ️ 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".
| const geoActions = countFeedMatches(feedItems, "geo") || (latest.geo ? 1 : 0); | ||
| const communityActions = countFeedMatches(feedItems, "community") || communityHits; | ||
| const redditApprovals = countApprovalMatches(feedItems, "reddit"); | ||
| const redditOpportunities = Math.max(countFeedMatches(feedItems, "reddit"), redditApprovals, communityHits); |
There was a problem hiding this comment.
Scope Reddit opportunity count to Reddit signals
The Reddit row currently uses Math.max(..., communityHits), but communityHits is the total across all community platforms, not Reddit-specific activity. That means projects with only non-Reddit hits (e.g., YouTube or Twitter mentions) still show Reddit opportunities as ready, which misroutes users to Reddit actions and inflates channel-specific workload in the new command-center queue.
Useful? React with 👍 / 👎.
| if not line.startswith("data: "): | ||
| continue |
There was a problem hiding this comment.
Parse SSE data lines with optional whitespace
_decode_mcp_response only accepts lines starting with "data: "; if an MCP/SSE server emits data: without a space, the loop skips the payload and falls back to json.loads(text) on the full event frame (event: + data:), which raises and causes the MCP call to be treated as failed. This creates avoidable Tavily fallback/unavailability in otherwise valid SSE responses.
Useful? React with 👍 / 👎.
| <ChatContainer | ||
| messages={messages} | ||
| isStreaming={isStreaming} | ||
| currentAgent={currentAgent} | ||
| sendMessage={sendMessage} | ||
| hasMessages={messages.length > 0} | ||
| projectId={activeProjectId} | ||
| projectContext={chatContext ?? null} |
There was a problem hiding this comment.
Block sending chat until active project context is switched
This panel renders immediately with the new project's title/context but still wires ChatContainer to activeProjectId from useChat; during route changes between /projects/:id, that state is updated in a later effect, so users can send a prompt that is posted to the previous project's chat session while viewing the new project. This can contaminate the wrong project's conversation/history and trigger actions against the wrong project.
Useful? React with 👍 / 👎.
| reddit: ["reddit", "subreddit"], | ||
| twitter: ["twitter", "tweet", "x agent", "x/twitter"], | ||
| linkedin: ["linkedin"], | ||
| hackerNews: ["hacker news", "hackernews", "hn"], |
There was a problem hiding this comment.
Remove ambiguous HN token from channel matcher
Using "hn" as a Hacker News matcher causes broad substring collisions (for example words like launching contain hn), so unrelated feed items can be counted as Hacker News opportunities. This inflates the HN row status/count and can send users down the wrong channel workflow in the command-center queue.
Useful? React with 👍 / 👎.
What changed
Validation