chore: test deploy snapshot

This commit is contained in:
2026-05-28 16:11:33 +09:00
parent b1bec9cb6f
commit a97d933cff
2 changed files with 163 additions and 128 deletions

View File

@@ -2463,11 +2463,57 @@
.app-chat-preview-card--prompt .app-chat-preview-card__actions { .app-chat-preview-card--prompt .app-chat-preview-card__actions {
flex: 0 0 auto; flex: 0 0 auto;
min-width: fit-content; min-width: 0;
max-width: 100%;
flex-wrap: nowrap; flex-wrap: nowrap;
margin-left: auto; margin-left: auto;
} }
@media (max-width: 720px) {
.app-chat-preview-card--prompt .app-chat-preview-card__header {
align-items: flex-start;
flex-wrap: wrap;
}
.app-chat-preview-card--prompt .app-chat-preview-card__actions {
width: 100%;
flex: 1 1 100%;
justify-content: flex-start;
flex-wrap: wrap;
gap: 6px;
margin-left: 0;
}
.app-chat-prompt-card__submitted {
max-width: 100%;
white-space: normal;
overflow-wrap: anywhere;
word-break: break-word;
}
.app-chat-prompt-card__selection-pill {
max-width: 100%;
white-space: normal;
overflow-wrap: anywhere;
word-break: break-word;
}
.app-chat-prompt-card__step-header {
flex-wrap: wrap;
}
.app-chat-prompt-card__preview-toolbar {
flex-wrap: wrap;
align-items: flex-start;
justify-content: flex-start;
min-height: 0;
}
.app-chat-prompt-card__preview-title.ant-typography {
flex: 1 1 100%;
}
}
.app-chat-prompt-card__preview-modal.ant-modal { .app-chat-prompt-card__preview-modal.ant-modal {
background: background:
linear-gradient(180deg, rgba(248, 250, 252, 0.98), rgba(226, 232, 240, 0.98)), linear-gradient(180deg, rgba(248, 250, 252, 0.98), rgba(226, 232, 240, 0.98)),

View File

@@ -173,6 +173,9 @@ type ShareSearchResult = {
value: string; value: string;
}; };
}; };
type ShareSearchIndexedResult = ShareSearchResult & {
searchText: string;
};
type ShareSearchPanelMode = 'all' | 'apps'; type ShareSearchPanelMode = 'all' | 'apps';
type ShareWorkServerVersionStatus = 'latest' | 'unknown' | 'update-available' | 'build-required'; type ShareWorkServerVersionStatus = 'latest' | 'unknown' | 'update-available' | 'build-required';
type ClientNotificationPermissionState = 'unsupported' | 'default' | 'granted' | 'denied'; type ClientNotificationPermissionState = 'unsupported' | 'default' | 'granted' | 'denied';
@@ -1923,6 +1926,10 @@ function matchesSearchKeyword(keyword: string, ...values: Array<string | null |
return values.some((value) => normalizeSearchKeyword(value ?? '').includes(keyword)); return values.some((value) => normalizeSearchKeyword(value ?? '').includes(keyword));
} }
function buildSearchKeywordText(...values: Array<string | null | undefined>) {
return normalizeSearchKeyword(values.filter(Boolean).join(' '));
}
function buildSharePromptSelectionKey(parentRequestId: string, sourceMessageId: number, promptIndex: number, promptTitle: string, promptSignature: string) { function buildSharePromptSelectionKey(parentRequestId: string, sourceMessageId: number, promptIndex: number, promptTitle: string, promptSignature: string) {
return [parentRequestId.trim(), sourceMessageId, promptIndex, promptTitle.trim(), promptSignature.trim()].join('::'); return [parentRequestId.trim(), sourceMessageId, promptIndex, promptTitle.trim(), promptSignature.trim()].join('::');
} }
@@ -8379,110 +8386,26 @@ export function ChatSharePage() {
? renderEmbeddedSharePlayApp(programTarget.appId, closeProgramTarget, normalizedToken) ? renderEmbeddedSharePlayApp(programTarget.appId, closeProgramTarget, normalizedToken)
: null; : null;
const isServerCommandDrawerOpen = programTarget?.appId === 'server-command'; const isServerCommandDrawerOpen = programTarget?.appId === 'server-command';
const searchResults = useMemo<ShareSearchResult[]>(() => { const indexedContentSearchResults = useMemo<ShareSearchIndexedResult[]>(() => {
const keyword = normalizeSearchKeyword(searchKeyword); const results: ShareSearchIndexedResult[] = [];
const results: ShareSearchResult[] = [];
if (searchPanelMode === 'apps') {
const photoprismLauncher = buildPhotoPrismProgramTarget();
if (
matchesSearchKeyword(
keyword,
currentShareChatTarget.label,
currentShareChatTarget.appId,
'공유채팅',
'현재 토큰',
'현재 공유토큰 열기',
...APPS_LAUNCHER_SEARCH_TERMS,
)
) {
results.push({
key: `management-app:${SHARE_CURRENT_CHAT_APP_ID}`,
title: currentShareChatTarget.label,
description: `현재 공유토큰을 ${selectedAppEnvironment} 환경에서 다시 엽니다.`,
category: 'resource',
icon: <CommentOutlined />,
usageBadge: resolveShareAppUsageBadge(appLaunchUsage[SHARE_CURRENT_CHAT_APP_ID]),
resource: currentShareChatTarget,
});
}
sortedAllowedManagementApps.forEach((item) => {
if (!matchesSearchKeyword(keyword, item.value, item.label, item.description, ...APPS_LAUNCHER_SEARCH_TERMS)) {
return;
}
results.push({
key: `management-app:${item.value}`,
title: item.label,
description: item.description,
category: 'resource',
icon: item.icon,
usageBadge: resolveShareAppUsageBadge(appLaunchUsage[item.value]),
resource: buildShareManagementProgramTarget(item.value, item.label),
});
});
sortedAllowedPlayAppEntries.forEach((entry) => {
if (
!matchesSearchKeyword(
keyword,
entry.id,
entry.name,
entry.searchDescription,
...APPS_LAUNCHER_SEARCH_TERMS,
...(entry.searchKeywords ?? []),
)
) {
return;
}
results.push({
key: `app:${entry.id}`,
title: entry.name,
description: resolveSupportedEnvironmentSummary(entry),
category: 'resource',
icon: entry.icon,
usageBadge: resolveShareAppUsageBadge(appLaunchUsage[entry.id]),
appEntry: entry,
resource:
entry.id === 'photoprism'
? photoprismLauncher
: buildPlayAppProgramTarget(entry.id, entry.name),
});
});
return results;
}
if (!keyword) {
return results;
}
sortedRequests.forEach((request) => { sortedRequests.forEach((request) => {
const requestText = buildShareVisibleText(request.userText); const requestText = buildShareVisibleText(request.userText);
if (matchesSearchKeyword(keyword, requestText, request.statusMessage, request.requestId)) { results.push({
results.push({ key: `request:${request.requestId}`,
key: `request:${request.requestId}`, title: requestText || '질문',
title: requestText || '질문', description: `질문 · ${formatTimeLabel(request.createdAt)}`,
description: `질문 · ${formatTimeLabel(request.createdAt)}`, category: 'request',
category: 'request', requestId: request.requestId,
requestId: request.requestId, scrollTarget: {
scrollTarget: { type: 'request',
type: 'request', value: request.requestId,
value: request.requestId, },
}, searchText: buildSearchKeywordText(requestText, request.statusMessage, request.requestId),
}); });
}
buildSharePreviewItemsFromText(request.userText, normalizedToken).forEach((item) => { buildSharePreviewItemsFromText(request.userText, normalizedToken).forEach((item) => {
if (!matchesSearchKeyword(keyword, item.label, item.url, item.kind)) {
return;
}
const scopedUrl = resolveShareScopedResourceUrl(item.url, normalizedToken);
results.push({ results.push({
key: `request-resource:${request.requestId}:${item.id}`, key: `request-resource:${request.requestId}:${item.id}`,
title: item.label, title: item.label,
@@ -8492,7 +8415,7 @@ export function ChatSharePage() {
resource: { resource: {
key: `request-resource:${request.requestId}:${item.id}`, key: `request-resource:${request.requestId}:${item.id}`,
label: item.label, label: item.label,
url: scopedUrl, url: item.url,
kind: item.kind, kind: item.kind,
meta: `${item.kind} resource`, meta: `${item.kind} resource`,
}, },
@@ -8500,6 +8423,7 @@ export function ChatSharePage() {
type: 'request', type: 'request',
value: request.requestId, value: request.requestId,
}, },
searchText: buildSearchKeywordText(item.label, item.url, item.kind),
}); });
}); });
}); });
@@ -8509,25 +8433,20 @@ export function ChatSharePage() {
const visibleText = buildVisibleMessageText(entry, payload); const visibleText = buildVisibleMessageText(entry, payload);
const requestId = entry.clientRequestId?.trim() || snapshot?.rootRequestId?.trim() || ''; const requestId = entry.clientRequestId?.trim() || snapshot?.rootRequestId?.trim() || '';
if (matchesSearchKeyword(keyword, visibleText, entry.author, requestId)) { results.push({
results.push({ key: `response:${entry.id}`,
key: `response:${entry.id}`, title: visibleText || '응답',
title: visibleText || '응답', description: `${entry.author === 'user' ? '질문 메시지' : '응답'} · ${formatTimeLabel(entry.timestamp)}`,
description: `${entry.author === 'user' ? '질문 메시지' : '응답'} · ${formatTimeLabel(entry.timestamp)}`, category: 'response',
category: 'response', requestId: requestId || undefined,
requestId: requestId || undefined, scrollTarget: {
scrollTarget: { type: 'response',
type: 'response', value: String(entry.id),
value: String(entry.id), },
}, searchText: buildSearchKeywordText(visibleText, entry.author, requestId),
}); });
}
(payload?.promptParts ?? []).forEach((prompt, promptIndex) => { (payload?.promptParts ?? []).forEach((prompt, promptIndex) => {
if (!matchesSearchKeyword(keyword, buildSharePromptSearchText(prompt), requestId, entry.id)) {
return;
}
results.push({ results.push({
key: `prompt:${entry.id}:${promptIndex}`, key: `prompt:${entry.id}:${promptIndex}`,
title: prompt.title || 'prompt', title: prompt.title || 'prompt',
@@ -8538,15 +8457,15 @@ export function ChatSharePage() {
type: 'prompt', type: 'prompt',
value: buildSharePromptAnchorKey(entry.id, promptIndex), value: buildSharePromptAnchorKey(entry.id, promptIndex),
}, },
searchText: buildSearchKeywordText(buildSharePromptSearchText(prompt), requestId, String(entry.id)),
}); });
}); });
(payload?.previewItems ?? []).forEach((item) => { (payload?.previewItems ?? []).forEach((item) => {
if (!requestId || !matchesSearchKeyword(keyword, item.label, item.url, item.kind)) { if (!requestId) {
return; return;
} }
const scopedUrl = resolveShareScopedResourceUrl(item.url, normalizedToken);
results.push({ results.push({
key: `response-resource:${entry.id}:${item.id}`, key: `response-resource:${entry.id}:${item.id}`,
title: item.label, title: item.label,
@@ -8556,7 +8475,7 @@ export function ChatSharePage() {
resource: { resource: {
key: `response-resource:${entry.id}:${item.id}`, key: `response-resource:${entry.id}:${item.id}`,
label: item.label, label: item.label,
url: scopedUrl, url: resolveShareScopedResourceUrl(item.url, normalizedToken),
kind: item.kind, kind: item.kind,
meta: `${item.kind} resource`, meta: `${item.kind} resource`,
}, },
@@ -8564,6 +8483,7 @@ export function ChatSharePage() {
type: 'response', type: 'response',
value: String(entry.id), value: String(entry.id),
}, },
searchText: buildSearchKeywordText(item.label, item.url, item.kind),
}); });
}); });
}); });
@@ -8571,10 +8491,6 @@ export function ChatSharePage() {
(snapshot?.activityLogs ?? []).forEach((activity, index) => { (snapshot?.activityLogs ?? []).forEach((activity, index) => {
const summary = summarizeActivityLogLines(activity.lines ?? []).join(' '); const summary = summarizeActivityLogLines(activity.lines ?? []).join(' ');
if (!matchesSearchKeyword(keyword, activity.requestId, summary)) {
return;
}
results.push({ results.push({
key: `activity:${activity.requestId}:${index}`, key: `activity:${activity.requestId}:${index}`,
title: summary || `활동 로그 ${index + 1}`, title: summary || `활동 로그 ${index + 1}`,
@@ -8585,13 +8501,86 @@ export function ChatSharePage() {
type: 'activity', type: 'activity',
value: 'chat-share-activity-panel', value: 'chat-share-activity-panel',
}, },
searchText: buildSearchKeywordText(activity.requestId, summary),
}); });
}); });
return results return results.filter((item) => !item.scrollTarget || item.scrollTarget.value.trim());
.filter((item) => !item.scrollTarget || item.scrollTarget.value.trim()) }, [messageRenderPayloadById, normalizedToken, snapshot?.activityLogs, snapshot?.rootRequestId, sortedMessages, sortedRequests]);
.slice(0, 40); const indexedAppSearchResults = useMemo<ShareSearchIndexedResult[]>(() => {
}, [appLaunchUsage, currentShareChatTarget, messageRenderPayloadById, normalizedToken, searchKeyword, searchPanelMode, selectedAppEnvironment, snapshot?.activityLogs, snapshot?.rootRequestId, sortedAllowedManagementApps, sortedAllowedPlayAppEntries, sortedMessages, sortedRequests]); const results: ShareSearchIndexedResult[] = [];
const photoprismLauncher = buildPhotoPrismProgramTarget();
results.push({
key: `management-app:${SHARE_CURRENT_CHAT_APP_ID}`,
title: currentShareChatTarget.label,
description: `현재 공유토큰을 ${selectedAppEnvironment} 환경에서 다시 엽니다.`,
category: 'resource',
icon: <CommentOutlined />,
usageBadge: resolveShareAppUsageBadge(appLaunchUsage[SHARE_CURRENT_CHAT_APP_ID]),
resource: currentShareChatTarget,
searchText: buildSearchKeywordText(
currentShareChatTarget.label,
currentShareChatTarget.appId,
'공유채팅',
'현재 토큰',
'현재 공유토큰 열기',
...APPS_LAUNCHER_SEARCH_TERMS,
),
});
sortedAllowedManagementApps.forEach((item) => {
results.push({
key: `management-app:${item.value}`,
title: item.label,
description: item.description,
category: 'resource',
icon: item.icon,
usageBadge: resolveShareAppUsageBadge(appLaunchUsage[item.value]),
resource: buildShareManagementProgramTarget(item.value, item.label),
searchText: buildSearchKeywordText(item.value, item.label, item.description, ...APPS_LAUNCHER_SEARCH_TERMS),
});
});
sortedAllowedPlayAppEntries.forEach((entry) => {
results.push({
key: `app:${entry.id}`,
title: entry.name,
description: resolveSupportedEnvironmentSummary(entry),
category: 'resource',
icon: entry.icon,
usageBadge: resolveShareAppUsageBadge(appLaunchUsage[entry.id]),
appEntry: entry,
resource:
entry.id === 'photoprism'
? photoprismLauncher
: buildPlayAppProgramTarget(entry.id, entry.name),
searchText: buildSearchKeywordText(
entry.id,
entry.name,
entry.searchDescription,
...APPS_LAUNCHER_SEARCH_TERMS,
...(entry.searchKeywords ?? []),
),
});
});
return results;
}, [appLaunchUsage, currentShareChatTarget, selectedAppEnvironment, sortedAllowedManagementApps, sortedAllowedPlayAppEntries]);
const searchResults = useMemo<ShareSearchResult[]>(() => {
const keyword = normalizeSearchKeyword(searchKeyword);
const source = searchPanelMode === 'apps' ? indexedAppSearchResults : indexedContentSearchResults;
if (searchPanelMode !== 'apps' && !keyword) {
return [];
}
const filtered = keyword
? source.filter((item) => item.searchText.includes(keyword))
: source;
return filtered.slice(0, 40).map(({ searchText: _searchText, ...result }) => result);
}, [indexedAppSearchResults, indexedContentSearchResults, searchKeyword, searchPanelMode]);
const selectedTokenUsageSetting = shareTokenSetting; const selectedTokenUsageSetting = shareTokenSetting;
const tokenUsageSummaryByPeriod = useMemo( const tokenUsageSummaryByPeriod = useMemo(
() => () =>