Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions apps/codex-claw/src/routeTree.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { Route as ApiSendRouteImport } from './routes/api/send'
import { Route as ApiRepoContextRouteImport } from './routes/api/repo-context'
import { Route as ApiPingRouteImport } from './routes/api/ping'
import { Route as ApiPathsRouteImport } from './routes/api/paths'
import { Route as ApiMcpHealthRouteImport } from './routes/api/mcp-health'
import { Route as ApiHistoryRouteImport } from './routes/api/history'
import { Route as ApiGitReviewRouteImport } from './routes/api/git-review'

Expand Down Expand Up @@ -78,6 +79,11 @@ const ApiPathsRoute = ApiPathsRouteImport.update({
path: '/api/paths',
getParentRoute: () => rootRouteImport,
} as any)
const ApiMcpHealthRoute = ApiMcpHealthRouteImport.update({
id: '/api/mcp-health',
path: '/api/mcp-health',
getParentRoute: () => rootRouteImport,
} as any)
const ApiHistoryRoute = ApiHistoryRouteImport.update({
id: '/api/history',
path: '/api/history',
Expand All @@ -95,6 +101,7 @@ export interface FileRoutesByFullPath {
'/new': typeof NewRoute
'/api/git-review': typeof ApiGitReviewRoute
'/api/history': typeof ApiHistoryRoute
'/api/mcp-health': typeof ApiMcpHealthRoute
'/api/paths': typeof ApiPathsRoute
'/api/ping': typeof ApiPingRoute
'/api/repo-context': typeof ApiRepoContextRoute
Expand All @@ -110,6 +117,7 @@ export interface FileRoutesByTo {
'/new': typeof NewRoute
'/api/git-review': typeof ApiGitReviewRoute
'/api/history': typeof ApiHistoryRoute
'/api/mcp-health': typeof ApiMcpHealthRoute
'/api/paths': typeof ApiPathsRoute
'/api/ping': typeof ApiPingRoute
'/api/repo-context': typeof ApiRepoContextRoute
Expand All @@ -126,6 +134,7 @@ export interface FileRoutesById {
'/new': typeof NewRoute
'/api/git-review': typeof ApiGitReviewRoute
'/api/history': typeof ApiHistoryRoute
'/api/mcp-health': typeof ApiMcpHealthRoute
'/api/paths': typeof ApiPathsRoute
'/api/ping': typeof ApiPingRoute
'/api/repo-context': typeof ApiRepoContextRoute
Expand All @@ -143,6 +152,7 @@ export interface FileRouteTypes {
| '/new'
| '/api/git-review'
| '/api/history'
| '/api/mcp-health'
| '/api/paths'
| '/api/ping'
| '/api/repo-context'
Expand All @@ -158,6 +168,7 @@ export interface FileRouteTypes {
| '/new'
| '/api/git-review'
| '/api/history'
| '/api/mcp-health'
| '/api/paths'
| '/api/ping'
| '/api/repo-context'
Expand All @@ -173,6 +184,7 @@ export interface FileRouteTypes {
| '/new'
| '/api/git-review'
| '/api/history'
| '/api/mcp-health'
| '/api/paths'
| '/api/ping'
| '/api/repo-context'
Expand All @@ -189,6 +201,7 @@ export interface RootRouteChildren {
NewRoute: typeof NewRoute
ApiGitReviewRoute: typeof ApiGitReviewRoute
ApiHistoryRoute: typeof ApiHistoryRoute
ApiMcpHealthRoute: typeof ApiMcpHealthRoute
ApiPathsRoute: typeof ApiPathsRoute
ApiPingRoute: typeof ApiPingRoute
ApiRepoContextRoute: typeof ApiRepoContextRoute
Expand Down Expand Up @@ -278,6 +291,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof ApiPathsRouteImport
parentRoute: typeof rootRouteImport
}
'/api/mcp-health': {
id: '/api/mcp-health'
path: '/api/mcp-health'
fullPath: '/api/mcp-health'
preLoaderRoute: typeof ApiMcpHealthRouteImport
parentRoute: typeof rootRouteImport
}
'/api/history': {
id: '/api/history'
path: '/api/history'
Expand All @@ -301,6 +321,7 @@ const rootRouteChildren: RootRouteChildren = {
NewRoute: NewRoute,
ApiGitReviewRoute: ApiGitReviewRoute,
ApiHistoryRoute: ApiHistoryRoute,
ApiMcpHealthRoute: ApiMcpHealthRoute,
ApiPathsRoute: ApiPathsRoute,
ApiPingRoute: ApiPingRoute,
ApiRepoContextRoute: ApiRepoContextRoute,
Expand Down
24 changes: 24 additions & 0 deletions apps/codex-claw/src/routes/api/mcp-health.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { createFileRoute } from '@tanstack/react-router'
import { json } from '@tanstack/react-start'

import { getMcpHealthPayload } from '../../server/mcp-health'

export const Route = createFileRoute('/api/mcp-health')({
server: {
handlers: {
GET: () => {
try {
return json(getMcpHealthPayload())
} catch (err) {
return json(
{
ok: false,
error: err instanceof Error ? err.message : String(err),
},
{ status: 500 },
)
}
},
},
},
})
7 changes: 7 additions & 0 deletions apps/codex-claw/src/screens/chat/chat-queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
GatewayMessage,
GitReviewPayload,
HistoryResponse,
McpHealthPayload,
RepoContextPayload,
RepoContextSelection,
SessionListResponse,
Expand Down Expand Up @@ -134,6 +135,12 @@ export async function fetchGitReview(): Promise<GitReviewPayload> {
return (await res.json()) as GitReviewPayload
}

export async function fetchMcpHealth(): Promise<McpHealthPayload> {
const res = await fetch('/api/mcp-health')
if (!res.ok) throw new Error(await readError(res))
return (await res.json()) as McpHealthPayload
}

export async function stageGitReviewFiles(
paths: Array<string>,
): Promise<GitReviewPayload> {
Expand Down
8 changes: 8 additions & 0 deletions apps/codex-claw/src/screens/chat/chat-screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { ChatHeader } from './components/chat-header'
import { ChatMessageList } from './components/chat-message-list'
import { ChatComposer } from './components/chat-composer'
import { GitReviewPanel } from './components/git-review-panel'
import { McpHealthPanel } from './components/mcp-health-panel'
import { GatewayStatusMessage } from './components/gateway-status-message'
import {
hasPendingGeneration,
Expand Down Expand Up @@ -71,6 +72,7 @@ export function ChatScreen({
const [creatingSession, setCreatingSession] = useState(false)
const [isRedirecting, setIsRedirecting] = useState(false)
const [gitReviewOpen, setGitReviewOpen] = useState(false)
const [mcpHealthOpen, setMcpHealthOpen] = useState(false)
const { headerRef, composerRef, mainRef, pinGroupMinHeight, headerHeight } =
useChatMeasurements()
const [waitingForResponse, setWaitingForResponse] = useState(
Expand Down Expand Up @@ -629,6 +631,12 @@ export function ChatScreen({
maxTokens={activeSession?.contextTokens}
gitReviewOpen={gitReviewOpen}
onToggleGitReview={() => setGitReviewOpen((current) => !current)}
mcpHealthOpen={mcpHealthOpen}
onToggleMcpHealth={() => setMcpHealthOpen((current) => !current)}
/>
<McpHealthPanel
open={mcpHealthOpen}
onClose={() => setMcpHealthOpen(false)}
/>
<GitReviewPanel
open={gitReviewOpen}
Expand Down
25 changes: 22 additions & 3 deletions apps/codex-claw/src/screens/chat/components/chat-header.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { memo } from 'react'
import { HugeiconsIcon } from '@hugeicons/react'
import { GitBranchIcon, Menu01Icon } from '@hugeicons/core-free-icons'
import {
GitBranchIcon,
Menu01Icon,
Settings01Icon,
} from '@hugeicons/core-free-icons'
import { ContextMeter } from './context-meter'
import { Button } from '@/components/ui/button'
import { ExportMenu } from '@/components/export-menu'
Expand All @@ -19,6 +23,8 @@ type ChatHeaderProps = {
showExport?: boolean
gitReviewOpen?: boolean
onToggleGitReview?: () => void
mcpHealthOpen?: boolean
onToggleMcpHealth?: () => void
}

function ChatHeaderComponent({
Expand All @@ -33,6 +39,8 @@ function ChatHeaderComponent({
showExport = true,
gitReviewOpen = false,
onToggleGitReview,
mcpHealthOpen = false,
onToggleMcpHealth,
}: ChatHeaderProps) {
return (
<div
Expand All @@ -47,7 +55,7 @@ function ChatHeaderComponent({
className="mr-2 text-primary-800 hover:bg-primary-100"
aria-label="Open sidebar"
>
<HugeiconsIcon icon={Menu01Icon} size={18} strokeWidth={1.6} />
<HugeiconsIcon icon={Menu01Icon} size={20} strokeWidth={1.5} />
</Button>
) : null}
<div className="flex-1 min-w-0 text-sm font-medium truncate">
Expand All @@ -62,7 +70,18 @@ function ChatHeaderComponent({
className={gitReviewOpen ? 'bg-primary-100' : undefined}
aria-label="Review local changes"
>
<HugeiconsIcon icon={GitBranchIcon} size={18} strokeWidth={1.5} />
<HugeiconsIcon icon={GitBranchIcon} size={20} strokeWidth={1.5} />
</Button>
) : null}
{onToggleMcpHealth ? (
<Button
size="icon-sm"
variant="ghost"
onClick={onToggleMcpHealth}
className={mcpHealthOpen ? 'bg-primary-100' : undefined}
aria-label="Inspect MCP tools"
>
<HugeiconsIcon icon={Settings01Icon} size={20} strokeWidth={1.5} />
</Button>
) : null}
{showExport ? (
Expand Down
Loading
Loading