chore: test deploy snapshot
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,312 @@
|
||||
import { db } from '../db/client.js';
|
||||
import {
|
||||
CHAT_CONVERSATION_TABLE,
|
||||
ensureChatConversationTables,
|
||||
} from './chat-room-service.js';
|
||||
|
||||
const CHAT_SHARE_TOKEN_ROOM_MAP_TABLE = 'chat_share_token_room_maps';
|
||||
|
||||
export type ChatShareTokenRoomMapItem = {
|
||||
tokenId: string;
|
||||
sessionId: string;
|
||||
rootRequestId: string;
|
||||
isDefault: boolean;
|
||||
sortOrder: number;
|
||||
createdByClientId: string | null;
|
||||
title: string;
|
||||
requestBadgeLabel: string | null;
|
||||
chatTypeId: string | null;
|
||||
lastChatTypeId: string | null;
|
||||
contextLabel: string | null;
|
||||
contextDescription: string | null;
|
||||
notifyOffline: boolean;
|
||||
createdAt: string | null;
|
||||
updatedAt: string | null;
|
||||
conversationUpdatedAt: string | null;
|
||||
};
|
||||
|
||||
function normalizeOptionalText(value: unknown) {
|
||||
if (typeof value !== 'string') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const normalized = value.trim();
|
||||
return normalized || null;
|
||||
}
|
||||
|
||||
function normalizeRequiredText(value: unknown) {
|
||||
if (typeof value !== 'string') {
|
||||
return '';
|
||||
}
|
||||
|
||||
return value.trim();
|
||||
}
|
||||
|
||||
function normalizeBoolean(value: unknown) {
|
||||
return value === true;
|
||||
}
|
||||
|
||||
function normalizeInteger(value: unknown, fallback = 0) {
|
||||
const parsed = Number(value);
|
||||
if (!Number.isFinite(parsed)) {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
return Math.trunc(parsed);
|
||||
}
|
||||
|
||||
function normalizeDateTime(value: unknown) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (value instanceof Date) {
|
||||
return Number.isNaN(value.getTime()) ? null : value.toISOString();
|
||||
}
|
||||
|
||||
if (typeof value === 'string') {
|
||||
const normalized = value.trim();
|
||||
return normalized || null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function mapChatShareTokenRoomRow(row: Record<string, unknown>): ChatShareTokenRoomMapItem {
|
||||
return {
|
||||
tokenId: normalizeRequiredText(row.shared_resource_token_id),
|
||||
sessionId: normalizeRequiredText(row.session_id),
|
||||
rootRequestId: normalizeRequiredText(row.root_request_id),
|
||||
isDefault: normalizeBoolean(row.is_default),
|
||||
sortOrder: normalizeInteger(row.sort_order),
|
||||
createdByClientId: normalizeOptionalText(row.created_by_client_id),
|
||||
title: normalizeRequiredText(row.title) || '공유 채팅방',
|
||||
requestBadgeLabel: normalizeOptionalText(row.request_badge_label),
|
||||
chatTypeId: normalizeOptionalText(row.chat_type_id),
|
||||
lastChatTypeId: normalizeOptionalText(row.last_chat_type_id),
|
||||
contextLabel: normalizeOptionalText(row.context_label),
|
||||
contextDescription: normalizeOptionalText(row.context_description),
|
||||
notifyOffline: normalizeBoolean(row.notify_offline),
|
||||
createdAt: normalizeDateTime(row.created_at),
|
||||
updatedAt: normalizeDateTime(row.updated_at),
|
||||
conversationUpdatedAt: normalizeDateTime(row.conversation_updated_at),
|
||||
};
|
||||
}
|
||||
|
||||
export async function ensureChatShareTokenRoomMapTable() {
|
||||
await ensureChatConversationTables();
|
||||
|
||||
const hasTable = await db.schema.hasTable(CHAT_SHARE_TOKEN_ROOM_MAP_TABLE);
|
||||
|
||||
if (!hasTable) {
|
||||
await db.schema.createTable(CHAT_SHARE_TOKEN_ROOM_MAP_TABLE, (table) => {
|
||||
table.increments('id').primary();
|
||||
table.string('shared_resource_token_id', 120).notNullable().index();
|
||||
table.string('session_id', 120).notNullable().index();
|
||||
table.string('root_request_id', 120).notNullable();
|
||||
table.boolean('is_default').notNullable().defaultTo(false);
|
||||
table.integer('sort_order').notNullable().defaultTo(0);
|
||||
table.string('created_by_client_id', 120).nullable();
|
||||
table.timestamp('archived_at', { useTz: true }).nullable().index();
|
||||
table.timestamp('created_at', { useTz: true }).notNullable().defaultTo(db.fn.now());
|
||||
table.timestamp('updated_at', { useTz: true }).notNullable().defaultTo(db.fn.now());
|
||||
table.unique(['shared_resource_token_id', 'session_id']);
|
||||
});
|
||||
}
|
||||
|
||||
const requiredColumns: Array<[string, (table: any) => void]> = [
|
||||
['shared_resource_token_id', (table) => table.string('shared_resource_token_id', 120).notNullable().index()],
|
||||
['session_id', (table) => table.string('session_id', 120).notNullable().index()],
|
||||
['root_request_id', (table) => table.string('root_request_id', 120).notNullable().defaultTo('')],
|
||||
['is_default', (table) => table.boolean('is_default').notNullable().defaultTo(false)],
|
||||
['sort_order', (table) => table.integer('sort_order').notNullable().defaultTo(0)],
|
||||
['created_by_client_id', (table) => table.string('created_by_client_id', 120).nullable()],
|
||||
['archived_at', (table) => table.timestamp('archived_at', { useTz: true }).nullable().index()],
|
||||
['created_at', (table) => table.timestamp('created_at', { useTz: true }).notNullable().defaultTo(db.fn.now())],
|
||||
['updated_at', (table) => table.timestamp('updated_at', { useTz: true }).notNullable().defaultTo(db.fn.now())],
|
||||
];
|
||||
|
||||
for (const [columnName, createColumn] of requiredColumns) {
|
||||
const hasColumn = await db.schema.hasColumn(CHAT_SHARE_TOKEN_ROOM_MAP_TABLE, columnName);
|
||||
|
||||
if (!hasColumn) {
|
||||
await db.schema.alterTable(CHAT_SHARE_TOKEN_ROOM_MAP_TABLE, (table) => {
|
||||
createColumn(table);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function listChatShareTokenRoomMaps(tokenId: string) {
|
||||
const normalizedTokenId = tokenId.trim();
|
||||
|
||||
if (!normalizedTokenId) {
|
||||
return [] as ChatShareTokenRoomMapItem[];
|
||||
}
|
||||
|
||||
await ensureChatShareTokenRoomMapTable();
|
||||
|
||||
const rows = await db(`${CHAT_SHARE_TOKEN_ROOM_MAP_TABLE} as room_map`)
|
||||
.leftJoin(`${CHAT_CONVERSATION_TABLE} as conversation`, 'conversation.session_id', 'room_map.session_id')
|
||||
.select(
|
||||
'room_map.shared_resource_token_id',
|
||||
'room_map.session_id',
|
||||
'room_map.root_request_id',
|
||||
'room_map.is_default',
|
||||
'room_map.sort_order',
|
||||
'room_map.created_by_client_id',
|
||||
'room_map.created_at',
|
||||
'room_map.updated_at',
|
||||
'conversation.title',
|
||||
'conversation.request_badge_label',
|
||||
'conversation.chat_type_id',
|
||||
'conversation.last_chat_type_id',
|
||||
'conversation.context_label',
|
||||
'conversation.context_description',
|
||||
'conversation.notify_offline',
|
||||
'conversation.updated_at as conversation_updated_at',
|
||||
)
|
||||
.where({ 'room_map.shared_resource_token_id': normalizedTokenId })
|
||||
.whereNull('room_map.archived_at')
|
||||
.orderBy('room_map.is_default', 'desc')
|
||||
.orderBy('room_map.sort_order', 'asc')
|
||||
.orderBy('room_map.created_at', 'asc');
|
||||
|
||||
return rows.map((row) => mapChatShareTokenRoomRow(row));
|
||||
}
|
||||
|
||||
export async function getChatShareTokenRoomMap(tokenId: string, sessionId: string) {
|
||||
const normalizedTokenId = tokenId.trim();
|
||||
const normalizedSessionId = sessionId.trim();
|
||||
|
||||
if (!normalizedTokenId || !normalizedSessionId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const rooms = await listChatShareTokenRoomMaps(normalizedTokenId);
|
||||
return rooms.find((item) => item.sessionId === normalizedSessionId) ?? null;
|
||||
}
|
||||
|
||||
export async function upsertChatShareTokenRoomMap(args: {
|
||||
tokenId: string;
|
||||
sessionId: string;
|
||||
rootRequestId: string;
|
||||
isDefault?: boolean;
|
||||
sortOrder?: number | null;
|
||||
createdByClientId?: string | null;
|
||||
}) {
|
||||
const normalizedTokenId = args.tokenId.trim();
|
||||
const normalizedSessionId = args.sessionId.trim();
|
||||
const normalizedRootRequestId = args.rootRequestId.trim();
|
||||
|
||||
if (!normalizedTokenId || !normalizedSessionId || !normalizedRootRequestId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
await ensureChatShareTokenRoomMapTable();
|
||||
|
||||
await db.transaction(async (trx) => {
|
||||
const current = await trx(CHAT_SHARE_TOKEN_ROOM_MAP_TABLE)
|
||||
.where({
|
||||
shared_resource_token_id: normalizedTokenId,
|
||||
session_id: normalizedSessionId,
|
||||
})
|
||||
.whereNull('archived_at')
|
||||
.first();
|
||||
|
||||
const maxSortOrderRow = await trx(CHAT_SHARE_TOKEN_ROOM_MAP_TABLE)
|
||||
.where({ shared_resource_token_id: normalizedTokenId })
|
||||
.whereNull('archived_at')
|
||||
.max<{ max_sort_order?: number | string | null }>('sort_order as max_sort_order')
|
||||
.first();
|
||||
const nextSortOrder = args.sortOrder != null
|
||||
? Math.max(0, Math.trunc(Number(args.sortOrder) || 0))
|
||||
: Math.max(0, normalizeInteger(maxSortOrderRow?.max_sort_order) + (current ? 0 : 1));
|
||||
|
||||
if (args.isDefault === true) {
|
||||
await trx(CHAT_SHARE_TOKEN_ROOM_MAP_TABLE)
|
||||
.where({ shared_resource_token_id: normalizedTokenId })
|
||||
.whereNull('archived_at')
|
||||
.update({
|
||||
is_default: false,
|
||||
updated_at: db.fn.now(),
|
||||
});
|
||||
}
|
||||
|
||||
const payload = {
|
||||
shared_resource_token_id: normalizedTokenId,
|
||||
session_id: normalizedSessionId,
|
||||
root_request_id: normalizedRootRequestId,
|
||||
is_default: args.isDefault === true,
|
||||
sort_order: nextSortOrder,
|
||||
created_by_client_id: normalizeOptionalText(args.createdByClientId),
|
||||
archived_at: null,
|
||||
updated_at: db.fn.now(),
|
||||
};
|
||||
|
||||
if (current) {
|
||||
await trx(CHAT_SHARE_TOKEN_ROOM_MAP_TABLE)
|
||||
.where({
|
||||
shared_resource_token_id: normalizedTokenId,
|
||||
session_id: normalizedSessionId,
|
||||
})
|
||||
.update(payload);
|
||||
return;
|
||||
}
|
||||
|
||||
await trx(CHAT_SHARE_TOKEN_ROOM_MAP_TABLE).insert({
|
||||
...payload,
|
||||
created_at: db.fn.now(),
|
||||
});
|
||||
});
|
||||
|
||||
return getChatShareTokenRoomMap(normalizedTokenId, normalizedSessionId);
|
||||
}
|
||||
|
||||
export async function ensureDefaultChatShareTokenRoomMap(args: {
|
||||
tokenId: string;
|
||||
sessionId: string;
|
||||
rootRequestId: string;
|
||||
createdByClientId?: string | null;
|
||||
}) {
|
||||
const normalizedTokenId = args.tokenId.trim();
|
||||
const normalizedSessionId = args.sessionId.trim();
|
||||
const normalizedRootRequestId = args.rootRequestId.trim();
|
||||
|
||||
if (!normalizedTokenId || !normalizedSessionId || !normalizedRootRequestId) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const existing = await getChatShareTokenRoomMap(normalizedTokenId, normalizedSessionId);
|
||||
|
||||
if (!existing) {
|
||||
await upsertChatShareTokenRoomMap({
|
||||
tokenId: normalizedTokenId,
|
||||
sessionId: normalizedSessionId,
|
||||
rootRequestId: normalizedRootRequestId,
|
||||
isDefault: true,
|
||||
createdByClientId: args.createdByClientId ?? null,
|
||||
});
|
||||
}
|
||||
|
||||
const rooms = await listChatShareTokenRoomMaps(normalizedTokenId);
|
||||
|
||||
if (rooms.some((item) => item.isDefault)) {
|
||||
return rooms;
|
||||
}
|
||||
|
||||
await upsertChatShareTokenRoomMap({
|
||||
tokenId: normalizedTokenId,
|
||||
sessionId: normalizedSessionId,
|
||||
rootRequestId: normalizedRootRequestId,
|
||||
isDefault: true,
|
||||
createdByClientId: args.createdByClientId ?? null,
|
||||
});
|
||||
|
||||
return listChatShareTokenRoomMaps(normalizedTokenId);
|
||||
}
|
||||
|
||||
export async function resolveChatShareTokenRoomSessionIds(tokenId: string) {
|
||||
const rooms = await listChatShareTokenRoomMaps(tokenId);
|
||||
return rooms.map((item) => item.sessionId).filter(Boolean);
|
||||
}
|
||||
@@ -1901,6 +1901,54 @@ export async function fetchChatRuntimeSnapshot() {
|
||||
return response.item;
|
||||
}
|
||||
|
||||
export async function fetchChatShareRuntimeSnapshot(
|
||||
token: string,
|
||||
options?: {
|
||||
sessionId?: string | null;
|
||||
sharePin?: string | null;
|
||||
},
|
||||
) {
|
||||
const query = new URLSearchParams();
|
||||
const normalizedSessionId = options?.sessionId?.trim() || '';
|
||||
|
||||
if (normalizedSessionId) {
|
||||
query.set('sessionId', normalizedSessionId);
|
||||
}
|
||||
|
||||
const response = await requestChatApi<{ ok: boolean; item: ChatRuntimeSnapshot }>(
|
||||
`/shares/${encodeURIComponent(token)}/runtime${query.size > 0 ? `?${query.toString()}` : ''}`,
|
||||
undefined,
|
||||
{
|
||||
allowUnauthenticated: true,
|
||||
sharePin: options?.sharePin,
|
||||
timeoutMs: 20000,
|
||||
},
|
||||
);
|
||||
return response.item;
|
||||
}
|
||||
|
||||
export async function cancelChatShareRuntimeRequest(
|
||||
token: string,
|
||||
payload: {
|
||||
requestId: string;
|
||||
sessionId?: string | null;
|
||||
},
|
||||
) {
|
||||
const response = await requestChatApi<{ ok: boolean; action: 'cancelled' | 'removed' }>(
|
||||
`/shares/${encodeURIComponent(token)}/runtime-requests/${encodeURIComponent(payload.requestId)}/cancel`,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
sessionId: payload.sessionId?.trim() || undefined,
|
||||
}),
|
||||
},
|
||||
{
|
||||
allowUnauthenticated: true,
|
||||
},
|
||||
);
|
||||
return response.action;
|
||||
}
|
||||
|
||||
export async function fetchChatSourceChanges(limit = 300) {
|
||||
const query = new URLSearchParams();
|
||||
query.set('limit', String(Math.max(1, Math.min(500, Math.round(limit)))));
|
||||
@@ -2268,11 +2316,14 @@ export async function clearChatConversationRoom(sessionId: string) {
|
||||
};
|
||||
}
|
||||
|
||||
export async function clearChatShareConversationRoom(token: string) {
|
||||
export async function clearChatShareConversationRoom(token: string, sessionId?: string | null) {
|
||||
const response = await requestChatApi<{ ok: boolean; item: ChatConversationSummary }>(
|
||||
`/shares/${encodeURIComponent(token)}/clear`,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
sessionId: sessionId?.trim() || undefined,
|
||||
}),
|
||||
},
|
||||
{
|
||||
allowUnauthenticated: true,
|
||||
@@ -2282,6 +2333,44 @@ export async function clearChatShareConversationRoom(token: string) {
|
||||
return response.item;
|
||||
}
|
||||
|
||||
export async function createChatShareRoom(
|
||||
token: string,
|
||||
payload: {
|
||||
chatTypeId: string;
|
||||
chatTypeLabel: string;
|
||||
title: string;
|
||||
requestBadgeLabel?: string | null;
|
||||
seedMessage: string;
|
||||
},
|
||||
) {
|
||||
const response = await requestChatApi<{ ok: boolean; room: ChatShareRoomSummary }>(
|
||||
`/shares/${encodeURIComponent(token)}/rooms`,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
},
|
||||
{
|
||||
allowUnauthenticated: true,
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
sessionId: normalizeRequiredText(response.room.sessionId),
|
||||
requestId: normalizeRequiredText(response.room.requestId),
|
||||
isDefault: response.room.isDefault === true,
|
||||
sortOrder: Number.isFinite(response.room.sortOrder) ? Number(response.room.sortOrder) : 0,
|
||||
title: normalizeRequiredText(response.room.title) || '공유 채팅방',
|
||||
requestBadgeLabel: normalizeOptionalText(response.room.requestBadgeLabel),
|
||||
chatTypeId: normalizeOptionalText(response.room.chatTypeId),
|
||||
lastChatTypeId: normalizeOptionalText(response.room.lastChatTypeId),
|
||||
contextLabel: normalizeOptionalText(response.room.contextLabel),
|
||||
contextDescription: normalizeOptionalText(response.room.contextDescription),
|
||||
notifyOffline: response.room.notifyOffline === true,
|
||||
createdAt: normalizeOptionalText(response.room.createdAt),
|
||||
updatedAt: normalizeOptionalText(response.room.updatedAt),
|
||||
} satisfies ChatShareRoomSummary;
|
||||
}
|
||||
|
||||
export async function deleteChatConversationRequest(sessionId: string, requestId: string) {
|
||||
const response = await requestChatApi<{ ok: boolean; deleted: boolean; sessionId: string; requestId: string }>(
|
||||
`/conversations/${encodeURIComponent(sessionId)}/requests/${encodeURIComponent(requestId)}`,
|
||||
@@ -2313,6 +2402,7 @@ export async function persistChatPromptSelection(
|
||||
sessionId: string,
|
||||
payload: {
|
||||
parentRequestId: string;
|
||||
sessionId?: string | null;
|
||||
promptIndex: number;
|
||||
promptTitle: string;
|
||||
promptSignature: string;
|
||||
@@ -2391,6 +2481,22 @@ export async function submitChatPromptSelection(
|
||||
|
||||
export type ChatShareKind = 'request-bundle' | 'inquiry-message' | 'prompt';
|
||||
|
||||
export type ChatShareRoomSummary = {
|
||||
sessionId: string;
|
||||
requestId: string;
|
||||
isDefault: boolean;
|
||||
sortOrder: number;
|
||||
title: string;
|
||||
requestBadgeLabel?: string | null;
|
||||
chatTypeId?: string | null;
|
||||
lastChatTypeId?: string | null;
|
||||
contextLabel?: string | null;
|
||||
contextDescription?: string | null;
|
||||
notifyOffline?: boolean;
|
||||
createdAt?: string | null;
|
||||
updatedAt?: string | null;
|
||||
};
|
||||
|
||||
export type ChatShareSnapshot = {
|
||||
share: {
|
||||
kind: ChatShareKind;
|
||||
@@ -2432,6 +2538,8 @@ export type ChatShareSnapshot = {
|
||||
requests: ChatConversationRequest[];
|
||||
messages: ChatMessage[];
|
||||
activityLogs: ChatConversationActivityLog[];
|
||||
rooms: ChatShareRoomSummary[];
|
||||
activeSessionId?: string | null;
|
||||
roomRequestCounts?: {
|
||||
processingCount: number;
|
||||
unansweredCount: number;
|
||||
@@ -2565,6 +2673,7 @@ export async function createManagedChatShareRoom(payload: ManagedChatShareRoomDr
|
||||
export async function saveChatShareRoomSettings(
|
||||
token: string,
|
||||
input: {
|
||||
sessionId?: string | null;
|
||||
accessPin?: string | null;
|
||||
accessPinPromptTtlMinutes?: number | null;
|
||||
chatTypeId?: string | null;
|
||||
@@ -2592,6 +2701,7 @@ export async function saveChatShareRoomSettings(
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
sessionId: input.sessionId,
|
||||
accessPin: input.accessPin,
|
||||
accessPinPromptTtlMinutes: input.accessPinPromptTtlMinutes,
|
||||
chatTypeId: input.chatTypeId,
|
||||
@@ -2626,7 +2736,7 @@ export async function saveChatShareRoomSettings(
|
||||
};
|
||||
}
|
||||
|
||||
export async function fetchChatShareSnapshot(token: string, options?: { sharePin?: string | null }) {
|
||||
export async function fetchChatShareSnapshot(token: string, options?: { sharePin?: string | null; sessionId?: string | null }) {
|
||||
const response = await requestChatApi<{
|
||||
ok: boolean;
|
||||
share: ChatShareSnapshot['share'];
|
||||
@@ -2636,11 +2746,13 @@ export async function fetchChatShareSnapshot(token: string, options?: { sharePin
|
||||
requests: ChatConversationRequest[];
|
||||
messages: ChatMessage[];
|
||||
activityLogs: ChatConversationActivityLog[];
|
||||
rooms?: ChatShareRoomSummary[];
|
||||
activeSessionId?: string | null;
|
||||
roomRequestCounts?: ChatShareSnapshot['roomRequestCounts'];
|
||||
promptTarget?: ChatShareSnapshot['promptTarget'];
|
||||
refreshedAt: string;
|
||||
}>(
|
||||
`/shares/${encodeURIComponent(token)}`,
|
||||
`/shares/${encodeURIComponent(token)}${options?.sessionId?.trim() ? `?sessionId=${encodeURIComponent(options.sessionId.trim())}` : ''}`,
|
||||
undefined,
|
||||
{
|
||||
allowUnauthenticated: true,
|
||||
@@ -2707,6 +2819,24 @@ export async function fetchChatShareSnapshot(token: string, options?: { sharePin
|
||||
? response.messages.map((message, index) => normalizeChatMessage(message, index))
|
||||
: [],
|
||||
activityLogs: Array.isArray(response.activityLogs) ? response.activityLogs : [],
|
||||
rooms: Array.isArray(response.rooms)
|
||||
? response.rooms.map((item) => ({
|
||||
sessionId: normalizeRequiredText(item.sessionId),
|
||||
requestId: normalizeRequiredText(item.requestId),
|
||||
isDefault: item.isDefault === true,
|
||||
sortOrder: Number.isFinite(item.sortOrder) ? Number(item.sortOrder) : 0,
|
||||
title: normalizeRequiredText(item.title) || '공유 채팅방',
|
||||
requestBadgeLabel: normalizeOptionalText(item.requestBadgeLabel),
|
||||
chatTypeId: normalizeOptionalText(item.chatTypeId),
|
||||
lastChatTypeId: normalizeOptionalText(item.lastChatTypeId),
|
||||
contextLabel: normalizeOptionalText(item.contextLabel),
|
||||
contextDescription: normalizeOptionalText(item.contextDescription),
|
||||
notifyOffline: item.notifyOffline === true,
|
||||
createdAt: normalizeOptionalText(item.createdAt),
|
||||
updatedAt: normalizeOptionalText(item.updatedAt),
|
||||
}))
|
||||
: [],
|
||||
activeSessionId: normalizeOptionalText(response.activeSessionId),
|
||||
roomRequestCounts: response.roomRequestCounts
|
||||
? {
|
||||
processingCount: Number.isFinite(response.roomRequestCounts.processingCount) ? response.roomRequestCounts.processingCount : 0,
|
||||
@@ -2722,6 +2852,7 @@ export async function submitChatShareMessage(
|
||||
token: string,
|
||||
text: string,
|
||||
options?: {
|
||||
sessionId?: string | null;
|
||||
mode?: 'queue' | 'direct';
|
||||
parentRequestId?: string | null;
|
||||
},
|
||||
@@ -2732,6 +2863,7 @@ export async function submitChatShareMessage(
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
text,
|
||||
sessionId: options?.sessionId?.trim() || undefined,
|
||||
mode: options?.mode === 'direct' ? 'direct' : 'queue',
|
||||
parentRequestId: options?.parentRequestId?.trim() || undefined,
|
||||
}),
|
||||
@@ -2790,6 +2922,7 @@ export async function completeChatShareManualBadge(
|
||||
token: string,
|
||||
payload: {
|
||||
parentRequestId: string;
|
||||
sessionId?: string | null;
|
||||
type: 'prompt' | 'verification';
|
||||
},
|
||||
) {
|
||||
@@ -2811,6 +2944,7 @@ export async function cancelChatShareRequest(
|
||||
token: string,
|
||||
payload: {
|
||||
parentRequestId: string;
|
||||
sessionId?: string | null;
|
||||
},
|
||||
) {
|
||||
const response = await requestChatApi<{ ok: boolean; item: ChatConversationRequest }>(
|
||||
@@ -2831,6 +2965,7 @@ export async function retryChatShareRequest(
|
||||
token: string,
|
||||
payload: {
|
||||
parentRequestId: string;
|
||||
sessionId?: string | null;
|
||||
},
|
||||
) {
|
||||
return requestChatApi<{ ok: boolean; queuedRequestId: string }>(
|
||||
|
||||
@@ -210,6 +210,71 @@
|
||||
box-shadow: inset 0 0 0 1px rgba(219, 226, 236, 0.82);
|
||||
}
|
||||
|
||||
.chat-share-page__room-list-panel {
|
||||
padding: 10px;
|
||||
border-radius: 14px;
|
||||
background: rgba(248, 250, 252, 0.94);
|
||||
box-shadow: inset 0 0 0 1px rgba(219, 226, 236, 0.82);
|
||||
}
|
||||
|
||||
.chat-share-page__room-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr));
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.chat-share-page__room-card {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
padding: 12px;
|
||||
border: 0;
|
||||
border-radius: 14px;
|
||||
background: linear-gradient(180deg, #f8fbff 0%, #eef4fb 100%);
|
||||
box-shadow:
|
||||
inset 0 0 0 1px rgba(191, 204, 220, 0.82),
|
||||
0 6px 18px rgba(148, 163, 184, 0.08);
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.chat-share-page__room-card--active {
|
||||
background: linear-gradient(180deg, #dbeafe 0%, #d7ecff 100%);
|
||||
box-shadow:
|
||||
inset 0 0 0 1px rgba(59, 130, 246, 0.38),
|
||||
0 10px 24px rgba(59, 130, 246, 0.16);
|
||||
}
|
||||
|
||||
.chat-share-page__room-card-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.chat-share-page__room-card-title {
|
||||
min-width: 0;
|
||||
color: #0f172a;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.chat-share-page__room-card-meta {
|
||||
color: #64748b;
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.chat-share-page__create-room-form {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.chat-share-page__create-room-field {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.chat-share-page__message-list {
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
@@ -222,6 +287,26 @@
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.chat-share-page__conversation-loading-block {
|
||||
display: grid;
|
||||
flex: 1 1 auto;
|
||||
align-content: center;
|
||||
justify-items: center;
|
||||
gap: 10px;
|
||||
min-height: 240px;
|
||||
padding: 24px 12px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.chat-share-page__composer-loading-block {
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 132px;
|
||||
padding: 16px 0;
|
||||
}
|
||||
|
||||
.chat-share-page__search-modal {
|
||||
top: 16px;
|
||||
padding-bottom: 16px;
|
||||
@@ -947,24 +1032,50 @@
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
min-height: calc(100vh - 48px);
|
||||
min-width: 0;
|
||||
padding: 14px 16px 18px;
|
||||
}
|
||||
|
||||
.chat-share-page__room-settings-tabs {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.chat-share-page__room-settings-tabs .ant-tabs-nav {
|
||||
margin-bottom: 12px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.chat-share-page__room-settings-tabs .ant-tabs-nav-wrap {
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
.chat-share-page__room-settings-tabs .ant-tabs-nav-list {
|
||||
min-width: max-content;
|
||||
}
|
||||
|
||||
.chat-share-page__room-settings-tabs .ant-tabs-tab {
|
||||
flex: 0 0 auto;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.chat-share-page__room-settings-tabs .ant-tabs-content-holder {
|
||||
min-width: 0;
|
||||
min-height: calc(100vh - 140px);
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.chat-share-page__room-settings-tabs .ant-tabs-content,
|
||||
.chat-share-page__room-settings-tabs .ant-tabs-tabpane {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.chat-share-page__room-settings-panel {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
min-width: 0;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.chat-share-page__room-settings-panel-head {
|
||||
@@ -999,6 +1110,29 @@
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.chat-share-page__room-settings-runtime-list {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.chat-share-page__room-settings-runtime-card {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
padding: 14px 16px;
|
||||
border: 1px solid rgba(191, 219, 254, 0.9);
|
||||
border-radius: 18px;
|
||||
background: rgba(248, 250, 252, 0.96);
|
||||
box-shadow: 0 10px 24px rgba(148, 163, 184, 0.08);
|
||||
}
|
||||
|
||||
.chat-share-page__room-settings-runtime-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.chat-share-page__room-settings-checkbox-group {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
@@ -1586,19 +1720,49 @@
|
||||
max-width: min(82%, 920px);
|
||||
border: 1px solid #dbe2ec;
|
||||
border-radius: 14px;
|
||||
padding: 10px 12px 9px;
|
||||
padding: 12px 12px 9px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.chat-share-page__message-tone-label {
|
||||
position: absolute;
|
||||
top: -9px;
|
||||
.chat-share-page__message-tone-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.chat-share-page__message-tone-meta {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.chat-share-page__message-actions {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 6px;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.chat-share-page__message-tone-label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 20px;
|
||||
padding: 0 6px;
|
||||
color: #64748b;
|
||||
font-size: 11px;
|
||||
line-height: 1.4;
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.chat-share-page__message-tone-time {
|
||||
color: #94a3b8;
|
||||
font-size: 11px;
|
||||
line-height: 1.4;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.chat-share-page__message-tone--question {
|
||||
@@ -1610,7 +1774,7 @@
|
||||
}
|
||||
|
||||
.chat-share-page__message-tone--question .chat-share-page__message-tone-label {
|
||||
right: 12px;
|
||||
margin-left: auto;
|
||||
background: #e7f1ff;
|
||||
}
|
||||
|
||||
@@ -1622,10 +1786,24 @@
|
||||
}
|
||||
|
||||
.chat-share-page__message-tone--answer .chat-share-page__message-tone-label {
|
||||
left: 12px;
|
||||
background: #e7f7ee;
|
||||
}
|
||||
|
||||
.chat-share-page__message-action-button.ant-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 28px;
|
||||
min-width: 28px;
|
||||
height: 28px;
|
||||
padding: 0;
|
||||
color: #475569;
|
||||
}
|
||||
|
||||
.chat-share-page__message-action-button.ant-btn.ant-btn-dangerous {
|
||||
color: #dc2626;
|
||||
}
|
||||
|
||||
|
||||
.chat-share-page__response-block {
|
||||
display: grid;
|
||||
@@ -2034,21 +2212,6 @@
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.chat-share-page__composer-send-mode {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.chat-share-page__composer-send-mode-text.ant-typography {
|
||||
margin-bottom: 0;
|
||||
font-size: 12px;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.chat-share-page__reply-reference {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -2222,16 +2385,6 @@
|
||||
padding: 0 6px 6px;
|
||||
}
|
||||
|
||||
.chat-share-page__request-block > .chat-share-page__message-time {
|
||||
justify-self: end;
|
||||
padding: 0 0 0 6px;
|
||||
}
|
||||
|
||||
.chat-share-page__response-block > .chat-share-page__message-time {
|
||||
justify-self: start;
|
||||
padding: 0 6px 0 0;
|
||||
}
|
||||
|
||||
.chat-share-page__section-head--compact {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user