feat: add CLI config preview API for Codex and Gemini

- Implemented `fetchCodexConfigPreview` and `fetchGeminiConfigPreview` functions in the API layer to retrieve masked configuration files.
- Added new interfaces `CodexConfigPreviewResponse` and `GeminiConfigPreviewResponse` to define the structure of the API responses.
- Created utility functions to read and mask sensitive values from `config.toml` and `auth.json` for Codex, and `settings.json` for Gemini.
- Updated CLI settings routes to handle new preview endpoints.
- Enhanced session content parser to support Claude JSONL format.
- Updated UI components to reflect changes in history page and navigation, including new tabs for observability.
- Localized changes for English and Chinese languages to reflect "CLI History" terminology.
This commit is contained in:
catlog22
2026-02-25 22:37:30 +08:00
parent c92754505a
commit b4d3426e6a
15 changed files with 1137 additions and 163 deletions

View File

@@ -3,7 +3,7 @@
// ========================================
// Unified page for issues, queue, and discovery with tab navigation
import { useState, useCallback } from 'react';
import { useState, useCallback, useEffect } from 'react';
import { useSearchParams } from 'react-router-dom';
import { useIntl } from 'react-intl';
import {
@@ -16,11 +16,12 @@ import {
} from 'lucide-react';
import { IssueHubHeader } from '@/components/issue/hub/IssueHubHeader';
import { IssueHubTabs, type IssueTab } from '@/components/issue/hub/IssueHubTabs';
const VALID_TABS: IssueTab[] = ['issues', 'board', 'queue', 'discovery', 'executions'];
import { IssuesPanel } from '@/components/issue/hub/IssuesPanel';
import { IssueBoardPanel } from '@/components/issue/hub/IssueBoardPanel';
import { QueuePanel } from '@/components/issue/hub/QueuePanel';
import { DiscoveryPanel } from '@/components/issue/hub/DiscoveryPanel';
import { ObservabilityPanel } from '@/components/issue/hub/ObservabilityPanel';
import { ExecutionPanel } from '@/components/issue/hub/ExecutionPanel';
import { Button } from '@/components/ui/Button';
import { Input } from '@/components/ui/Input';
@@ -285,7 +286,16 @@ function NewIssueDialog({ open, onOpenChange, onSubmit, isCreating }: {
export function IssueHubPage() {
const { formatMessage } = useIntl();
const [searchParams, setSearchParams] = useSearchParams();
const currentTab = (searchParams.get('tab') as IssueTab) || 'issues';
const rawTab = searchParams.get('tab') as IssueTab;
const currentTab = VALID_TABS.includes(rawTab) ? rawTab : 'issues';
// Redirect invalid tabs to 'issues'
useEffect(() => {
if (!VALID_TABS.includes(rawTab)) {
setSearchParams({ tab: 'issues' });
}
}, [rawTab, setSearchParams]);
const [isNewIssueOpen, setIsNewIssueOpen] = useState(false);
const [isGithubSyncing, setIsGithubSyncing] = useState(false);
@@ -387,11 +397,8 @@ export function IssueHubPage() {
case 'discovery':
return null; // Discovery panel has its own controls
case 'observability':
return null; // Observability panel has its own controls
case 'executions':
return null; // Execution panel has its own controls
return null; // Executions panel has its own controls
default:
return null;
@@ -436,7 +443,6 @@ export function IssueHubPage() {
{currentTab === 'board' && <IssueBoardPanel />}
{currentTab === 'queue' && <QueuePanel />}
{currentTab === 'discovery' && <DiscoveryPanel />}
{currentTab === 'observability' && <ObservabilityPanel />}
{currentTab === 'executions' && <ExecutionPanel />}
<NewIssueDialog open={isNewIssueOpen} onOpenChange={setIsNewIssueOpen} onSubmit={handleCreateIssue} isCreating={isCreating} />