chore: exclude local resource artifacts from main sync

This commit is contained in:
2026-05-15 10:16:45 +09:00
parent 442879313f
commit d38d022872
504 changed files with 17074 additions and 3642 deletions

View File

@@ -4,15 +4,9 @@ import { useEffect, useMemo, useState, type ReactNode } from 'react';
import { useNavigate } from 'react-router-dom';
import { canUseChatType, resolveCurrentChatPermissionRoles, useChatTypeRegistry } from '../../../app/main/chatTypeAccess';
import { createChatConversationRoom, fetchChatConversations } from '../../../app/main/mainChatPanel';
import {
LAYOUT_EDITOR_GUIDED_CHAT_TYPE_DESCRIPTION,
LAYOUT_EDITOR_GUIDED_CHAT_TYPE_ID,
LAYOUT_EDITOR_GUIDED_CHAT_TYPE_NAME,
} from '../../../app/main/chatTypeDefaults';
import { buildChatPath } from '../../../app/main/routes';
import { useTokenAccess } from '../../../app/main/tokenAccess';
import { SelectUI, type SelectOptionItem } from '../../../components/inputs/select';
import { resolvePreferredLayoutCodexChatType } from '../../../views/play/layoutCodexChatType';
import { listSavedLayouts, saveLayout, type SavedLayoutRecord } from '../../../views/play/layoutStorage';
import { isReusableLayoutConversation, resolveLayoutCodexRequestSocketUrl, resolveLayoutConversationTitle } from './featureMenu.chat';
import type { FeatureMenuTabKey, LayoutInteractionRule } from './featureMenu.types';
@@ -40,21 +34,17 @@ export function FeatureMenuLayoutPage({ layoutId, savedLayouts, onSavedLayoutsCh
const [draftBody, setDraftBody] = useState('');
const [isSaving, setIsSaving] = useState(false);
const [isSending, setIsSending] = useState(false);
const [selectedChatTypeId, setSelectedChatTypeId] = useState<string | null>(null);
const chatPermissionRoles = useMemo(() => resolveCurrentChatPermissionRoles(hasAccess), [hasAccess]);
const availableChatTypes = useMemo(
() => chatTypes.filter((item) => canUseChatType(item, chatPermissionRoles)),
[chatPermissionRoles, chatTypes],
);
const preferredCodexChatType = useMemo(
() => resolvePreferredLayoutCodexChatType(availableChatTypes),
[availableChatTypes],
const selectedChatType = useMemo(
() => availableChatTypes.find((item) => item.id === selectedChatTypeId) ?? availableChatTypes[0] ?? null,
[availableChatTypes, selectedChatTypeId],
);
const targetChatType = preferredCodexChatType ?? {
id: LAYOUT_EDITOR_GUIDED_CHAT_TYPE_ID,
name: LAYOUT_EDITOR_GUIDED_CHAT_TYPE_NAME,
description: LAYOUT_EDITOR_GUIDED_CHAT_TYPE_DESCRIPTION,
};
const layoutOptions = useMemo<SelectOptionItem[]>(
() =>
@@ -91,6 +81,19 @@ export function FeatureMenuLayoutPage({ layoutId, savedLayouts, onSavedLayoutsCh
setSelectedLayoutId(fallback?.id ?? null);
}, [layoutId, savedLayouts, selectedLayoutId]);
useEffect(() => {
if (availableChatTypes.length === 0) {
setSelectedChatTypeId(null);
return;
}
if (selectedChatTypeId && availableChatTypes.some((item) => item.id === selectedChatTypeId)) {
return;
}
setSelectedChatTypeId(availableChatTypes[0]?.id ?? null);
}, [availableChatTypes, selectedChatTypeId]);
const selectedLayout = selectedLayoutId ? savedLayouts.find((item) => item.id === selectedLayoutId) ?? null : null;
const selectedLayoutInteractions = useMemo<LayoutInteractionRule[]>(
() => normalizeLayoutInteractions(selectedLayout?.tree ?? null),
@@ -276,7 +279,10 @@ export function FeatureMenuLayoutPage({ layoutId, savedLayouts, onSavedLayoutsCh
};
const handleCodexExecute = async () => {
if (!selectedLayout) {
if (!selectedLayout || !selectedChatType) {
if (!selectedChatType) {
void messageApi.error('사용 가능한 채팅유형이 없어 Codex 실행을 보낼 수 없습니다.');
}
return;
}
@@ -289,7 +295,7 @@ export function FeatureMenuLayoutPage({ layoutId, savedLayouts, onSavedLayoutsCh
try {
const conversations = await fetchChatConversations();
const matchedConversation = conversations.find((item) =>
isReusableLayoutConversation(item, conversationTitle, targetChatType.id),
isReusableLayoutConversation(item, conversationTitle, selectedChatType.id),
);
const shouldCreateConversation = !matchedConversation;
const targetSessionId =
@@ -302,10 +308,10 @@ export function FeatureMenuLayoutPage({ layoutId, savedLayouts, onSavedLayoutsCh
await createChatConversationRoom({
sessionId: targetSessionId,
title: conversationTitle,
chatTypeId: targetChatType.id,
lastChatTypeId: targetChatType.id,
contextLabel: targetChatType.name,
contextDescription: targetChatType.description,
chatTypeId: selectedChatType.id,
lastChatTypeId: selectedChatType.id,
contextLabel: selectedChatType.name,
contextDescription: selectedChatType.description,
notifyOffline: true,
});
}
@@ -326,9 +332,9 @@ export function FeatureMenuLayoutPage({ layoutId, savedLayouts, onSavedLayoutsCh
type: 'message:send',
payload: {
text: prompt,
chatTypeId: targetChatType.id,
chatTypeLabel: targetChatType.name,
chatTypeDescription: targetChatType.description,
chatTypeId: selectedChatType.id,
chatTypeLabel: selectedChatType.name,
chatTypeDescription: selectedChatType.description,
requestId,
mode: 'queue',
},
@@ -434,13 +440,29 @@ export function FeatureMenuLayoutPage({ layoutId, savedLayouts, onSavedLayoutsCh
}}
/>
</div>
<div className="feature-menu-layout-page__field">
<Text className="feature-menu-layout-page__field-label">Codex </Text>
<SelectUI
data={availableChatTypes.map((item) => ({
code: item.id,
value: item.name,
}))}
value={selectedChatType?.id ?? undefined}
allowClear={false}
disabled={availableChatTypes.length === 0}
className="feature-menu-layout-page__select"
onChange={(nextCode) => {
setSelectedChatTypeId(nextCode ?? null);
}}
/>
</div>
<Tooltip title="Codex 실행">
<Button
type="primary"
size="large"
icon={<PlayCircleOutlined />}
className="feature-menu-layout-page__run-button"
disabled={!selectedLayout}
disabled={!selectedLayout || !selectedChatType}
loading={isSending}
aria-label="Codex 실행"
onClick={() => {