fix(codex-config): close fix-round-1 parity gaps against CcConfig
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ĩ <vinnt@smartgift.vn>
This commit is contained in:
@@ -30,6 +30,10 @@ export type EditorState<TType extends string = CcArtifactType> =
|
||||
}
|
||||
| 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<TType extends string = CcArtifactType> {
|
||||
state: NonNullable<EditorState<TType>>;
|
||||
fetchContent: (filePath: string) => Promise<string>;
|
||||
@@ -41,6 +45,9 @@ interface EditorModalProps<TType extends string = CcArtifactType> {
|
||||
content: string;
|
||||
project?: string;
|
||||
}) => Promise<void>;
|
||||
/** 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<TType extends string = CcArtifactType>({
|
||||
@@ -48,9 +55,11 @@ export function EditorModal<TType extends string = CcArtifactType>({
|
||||
fetchContent,
|
||||
onClose,
|
||||
onSave,
|
||||
namelessTypes = DEFAULT_NAMELESS_TYPES,
|
||||
}: EditorModalProps<TType>) {
|
||||
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<string>(isCreate ? state.template : "");
|
||||
const [name, setName] = useState<string>("");
|
||||
@@ -91,7 +100,7 @@ export function EditorModal<TType extends string = CcArtifactType>({
|
||||
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<TType extends string = CcArtifactType>({
|
||||
// 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<TType extends string = CcArtifactType>({
|
||||
</div>
|
||||
|
||||
<div className="overflow-auto p-4 space-y-3">
|
||||
{isCreate && state.type !== "memory" && (
|
||||
{isCreate && !isNameless && (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label className="block text-[11px] font-semibold uppercase tracking-wider text-fg-muted mb-1">
|
||||
|
||||
Reference in New Issue
Block a user