From f6973d24d66f69176971766627e2fa35354bb579 Mon Sep 17 00:00:00 2001 From: nntrivi2001 Date: Tue, 8 Sep 2026 20:48:58 +0700 Subject: [PATCH] refactor(config): make EditorState/ConfirmDeleteState generic over the artifact type Review feedback: string widening dropped the compile-time guard at the write/delete boundary right where the Codex panel (the next task) starts writing into this state. Threading through EditorState/EditorModal and ConfirmDeleteState/ConfirmDeleteModal keeps CcConfig.tsx's write/delete calls checked against CcArtifactType by default while still letting a Codex-typed caller instantiate its own union later, removing the two `as CcArtifactType` casts. --- .../components/config/ConfirmDeleteModal.tsx | 15 +++++++++----- client/src/components/config/EditorModal.tsx | 20 ++++++++++++------- client/src/pages/CcConfig.tsx | 6 +++--- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/client/src/components/config/ConfirmDeleteModal.tsx b/client/src/components/config/ConfirmDeleteModal.tsx index 43786f62..5df74986 100644 --- a/client/src/components/config/ConfirmDeleteModal.tsx +++ b/client/src/components/config/ConfirmDeleteModal.tsx @@ -9,22 +9,27 @@ import { useCallback, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { ShieldAlert, Trash2 } from "lucide-react"; +import type { CcArtifactType } from "../../lib/api"; -export type ConfirmDeleteState = { - type: string; +export type ConfirmDeleteState = { + type: TType; scope: "user" | "project" | "auto-memory"; name?: string; path: string; project?: string; // set for type === "auto-memory" } | null; -interface ConfirmDeleteModalProps { - state: NonNullable; +interface ConfirmDeleteModalProps { + state: NonNullable>; onCancel: () => void; onConfirm: () => Promise; } -export function ConfirmDeleteModal({ state, onCancel, onConfirm }: ConfirmDeleteModalProps) { +export function ConfirmDeleteModal({ + state, + onCancel, + onConfirm, +}: ConfirmDeleteModalProps) { const { t } = useTranslation("ccConfig"); const [busy, setBusy] = useState(false); diff --git a/client/src/components/config/EditorModal.tsx b/client/src/components/config/EditorModal.tsx index 7ea3305c..8f5ac1f5 100644 --- a/client/src/components/config/EditorModal.tsx +++ b/client/src/components/config/EditorModal.tsx @@ -10,18 +10,19 @@ import { useCallback, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { Pencil, X, Save, AlertCircle } from "lucide-react"; +import type { CcArtifactType } from "../../lib/api"; -export type EditorState = +export type EditorState = | { mode: "create"; - type: string; + type: TType; defaultScope: "user" | "project"; template: string; project?: string; // set for type === "auto-memory" } | { mode: "edit"; - type: string; + type: TType; scope: "user" | "project" | "auto-memory"; name: string; filePath: string; @@ -29,12 +30,12 @@ export type EditorState = } | null; -interface EditorModalProps { - state: NonNullable; +interface EditorModalProps { + state: NonNullable>; fetchContent: (filePath: string) => Promise; onClose: () => void; onSave: (args: { - type: string; + type: TType; targetScope: "user" | "project" | "auto-memory"; name: string | undefined; content: string; @@ -42,7 +43,12 @@ interface EditorModalProps { }) => Promise; } -export function EditorModal({ state, fetchContent, onClose, onSave }: EditorModalProps) { +export function EditorModal({ + state, + fetchContent, + onClose, + onSave, +}: EditorModalProps) { const { t } = useTranslation("ccConfig"); const isCreate = state.mode === "create"; const isAutoMemory = state.type === "auto-memory"; diff --git a/client/src/pages/CcConfig.tsx b/client/src/pages/CcConfig.tsx index 8def56b9..935e21d6 100644 --- a/client/src/pages/CcConfig.tsx +++ b/client/src/pages/CcConfig.tsx @@ -426,7 +426,7 @@ export function CcConfig() { const handleSave = useCallback( async (args: { - type: string; + type: CcArtifactType; targetScope: "user" | "project" | "auto-memory"; name: string | undefined; content: string; @@ -434,7 +434,7 @@ export function CcConfig() { }) => { const result: CcMutationResult = await api.ccConfig.write({ scope: args.targetScope, - type: args.type as CcArtifactType, + type: args.type, name: args.name, content: args.content, project: args.project, @@ -456,7 +456,7 @@ export function CcConfig() { try { const result = await api.ccConfig.delete({ scope: confirmDelete.scope, - type: confirmDelete.type as CcArtifactType, + type: confirmDelete.type, name: confirmDelete.name, project: confirmDelete.project, });