feat: enhance Codex agent connection handling with automatic thread recovery and improved error logging

This commit is contained in:
HouYunFei
2026-07-05 23:40:54 +08:00
parent 6113986637
commit 3080d6da10
9 changed files with 154 additions and 37 deletions
+34 -1
View File
@@ -1,4 +1,5 @@
import { Menu } from "lucide-react";
import { Button, Tooltip } from "antd";
import { Link, useLocation } from "react-router-dom";
import { navigationTools, type NavigationToolSlug } from "@/constant/navigation-tools";
@@ -6,15 +7,28 @@ import { AppConfigModal } from "@/components/layout/app-config-modal";
import { MobileNavDrawer } from "@/components/layout/mobile-nav-drawer";
import { UserStatusActions } from "@/components/layout/user-status-actions";
import { cn } from "@/lib/utils";
import { useState } from "react";
import { useEffect, useRef, useState } from "react";
import { useCanvasAgentStore } from "@/stores/canvas/use-canvas-agent-store";
import { useConfigStore } from "@/stores/use-config-store";
export function AppTopNav() {
const { pathname } = useLocation();
const [mobileNavOpen, setMobileNavOpen] = useState(false);
const autoConnectRef = useRef(false);
const agentToken = useCanvasAgentStore((state) => state.token);
const agentEnabled = useCanvasAgentStore((state) => state.enabled);
const agentConnected = useCanvasAgentStore((state) => state.connected);
const connectAgent = useCanvasAgentStore((state) => state.connectAgent);
const hideHeader = /^\/canvas\/[^/]+/.test(pathname);
const slug = pathname.split("/").filter(Boolean)[0];
const activeToolSlug = navigationTools.some((tool) => tool.slug === slug) ? (slug as NavigationToolSlug) : undefined;
useEffect(() => {
if (autoConnectRef.current || agentEnabled || agentConnected || !agentToken.trim()) return;
autoConnectRef.current = true;
connectAgent();
}, [agentConnected, agentEnabled, agentToken, connectAgent]);
return (
<>
{!hideHeader ? (
@@ -66,6 +80,7 @@ export function AppTopNav() {
</div>
<div className="my-auto flex h-9 min-w-0 items-center justify-end gap-2 justify-self-end whitespace-nowrap">
<CodexStatusButton />
<UserStatusActions />
</div>
</div>
@@ -77,3 +92,21 @@ export function AppTopNav() {
</>
);
}
function CodexStatusButton() {
const connected = useCanvasAgentStore((state) => state.connected);
const enabled = useCanvasAgentStore((state) => state.enabled);
const activity = useCanvasAgentStore((state) => state.activity);
const connectError = useCanvasAgentStore((state) => state.connectError);
const openConfigDialog = useConfigStore((state) => state.openConfigDialog);
const color = connectError ? "#dc2626" : connected ? "#16a34a" : enabled ? "#d97706" : "currentColor";
const title = connectError || (connected ? activity || "Codex 已连接" : enabled ? "Codex 连接中" : "Codex 未连接");
return (
<Tooltip title={title}>
<Button type="text" shape="circle" className="relative !h-8 !w-8 !min-w-8" onClick={() => openConfigDialog(false, "codex")} aria-label="Codex 连接状态">
<span className="mx-auto block size-4" style={{ background: color, WebkitMask: "url(/icons/openai.svg) center / contain no-repeat", mask: "url(/icons/openai.svg) center / contain no-repeat" }} />
<span className="absolute right-1 top-1 size-2 rounded-full border border-background" style={{ background: color }} />
</Button>
</Tooltip>
);
}