From 56bf5bbf4d671ebb2da2961cf219ec198d78dbaa Mon Sep 17 00:00:00 2001 From: nntrivi2001 Date: Tue, 8 Sep 2026 21:34:06 +0700 Subject: [PATCH] fix(codex-config): close fix-round-1 parity gaps against CcConfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Isolate the codex-CLI-backed reads (mcp/plugins/marketplaces) from the file-backed ones in fetchAll via two independent Promise.all groups, so a missing `codex` binary degrades only the mcp/plugins tabs instead of leaving the whole panel stuck on skeletons. Generalize EditorModal's nameless-type detection behind a `namelessTypes` prop (defaulting to Claude's own ["memory"]) so Codex's config.toml can be created without a name. Port BackupsModal, disable the plugin/mcp Remove button when no stable identifier resolved, hide the inert search box on memory/config, drop a redundant empty state, and reword the delete-dialog copy to be tool-neutral. Co-authored-by: Nguyễn Ngọc Trí Vĩ --- client/src/components/config/EditorModal.tsx | 15 +- client/src/i18n/locales/en/ccConfig.json | 2 +- client/src/i18n/locales/en/codexConfig.json | 25 +- client/src/i18n/locales/vi/ccConfig.json | 2 +- client/src/i18n/locales/vi/codexConfig.json | 25 +- client/src/lib/types.ts | 7 +- client/src/pages/CodexConfig.tsx | 369 +++++++++++++++--- .../src/pages/__tests__/CodexConfig.test.tsx | 60 +++ 8 files changed, 432 insertions(+), 73 deletions(-) diff --git a/client/src/components/config/EditorModal.tsx b/client/src/components/config/EditorModal.tsx index 8f5ac1f5..75066ae0 100644 --- a/client/src/components/config/EditorModal.tsx +++ b/client/src/components/config/EditorModal.tsx @@ -30,6 +30,10 @@ export type EditorState = } | null; +/** Types that are a single fixed file per scope (e.g. Claude's CLAUDE.md, Codex's + * AGENTS.md / config.toml) - no `name` field, and no artifact name is ever sent. */ +const DEFAULT_NAMELESS_TYPES = ["memory"]; + interface EditorModalProps { state: NonNullable>; fetchContent: (filePath: string) => Promise; @@ -41,6 +45,9 @@ interface EditorModalProps { content: string; project?: string; }) => Promise; + /** Which `state.type` values are nameless singleton files. Defaults to + * Claude Code's own `["memory"]` so existing callers are unaffected. */ + namelessTypes?: readonly string[]; } export function EditorModal({ @@ -48,9 +55,11 @@ export function EditorModal({ fetchContent, onClose, onSave, + namelessTypes = DEFAULT_NAMELESS_TYPES, }: EditorModalProps) { const { t } = useTranslation("ccConfig"); const isCreate = state.mode === "create"; + const isNameless = namelessTypes.includes(state.type); const isAutoMemory = state.type === "auto-memory"; const [content, setContent] = useState(isCreate ? state.template : ""); const [name, setName] = useState(""); @@ -91,7 +100,7 @@ export function EditorModal({ setSaving(true); setError(null); try { - if (state.type !== "memory" && state.mode === "create" && !name) { + if (!isNameless && state.mode === "create" && !name) { setError(t("edit.nameLabel")); setSaving(false); return; @@ -99,7 +108,7 @@ export function EditorModal({ // For auto-memory creates, append a .md extension when the user omits it. const createName = isAutoMemory && !/\.md$/i.test(name) ? `${name}.md` : name; const effectiveName = - state.mode === "edit" ? state.name : state.type === "memory" ? undefined : createName; + state.mode === "edit" ? state.name : isNameless ? undefined : createName; await onSave({ type: state.type, targetScope: isAutoMemory ? "auto-memory" : targetScope, @@ -143,7 +152,7 @@ export function EditorModal({
- {isCreate && state.type !== "memory" && ( + {isCreate && !isNameless && (