Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 33 additions & 33 deletions frontend/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ import type {
LLMProfile,
} from './types';

// ============================================================================
// =============================================================================
// API 配置 / API Configuration
// ============================================================================
// =============================================================================
const API_BASE = '/api';

// 普通 API 调用超时时间(30 秒)
Expand All @@ -40,9 +40,9 @@ const LLM_TIMEOUT = 300000;
// 批量操作的超时时间(30 分钟)
const LLM_SYNC_TIMEOUT = 1800000;

// ============================================================================
// =============================================================================
// Axios 实例 / Axios Instances
// ============================================================================
// =============================================================================

/**
* 普通 API 实例 - Default timeout
Expand All @@ -58,9 +58,9 @@ const llmApi = axios.create({
timeout: LLM_TIMEOUT,
});

// ============================================================================
// =============================================================================
// 项目 API / Projects API
// ============================================================================
// =============================================================================
export const projectsAPI = {
list: (): Promise<AxiosResponse<Project[]>> => api.get(`${API_BASE}/projects`),
get: (id: string): Promise<AxiosResponse<Project>> => api.get(`${API_BASE}/projects/${id}`),
Expand All @@ -69,9 +69,9 @@ export const projectsAPI = {
delete: (id: string): Promise<AxiosResponse> => api.delete(`${API_BASE}/projects/${id}`),
};

// ============================================================================
// =============================================================================
// 卡片 API / Cards API
// ============================================================================
// =============================================================================
export const cardsAPI = {
// 角色卡片操作 / Character cards
listCharactersIndex: (projectId: string): Promise<AxiosResponse<CharacterCard[]>> =>
Expand Down Expand Up @@ -109,9 +109,9 @@ export const cardsAPI = {
llmApi.post(`${API_BASE}/projects/${projectId}/cards/style/extract`, data),
};

// ============================================================================
// =============================================================================
// 会话 API / Session API(LLM 操作使用扩展超时)
// ============================================================================
// =============================================================================
export const sessionAPI = {
start: (projectId: string, data: Record<string, unknown>): Promise<AxiosResponse> =>
llmApi.post(`${API_BASE}/projects/${projectId}/session/start`, data, { timeout: LLM_SYNC_TIMEOUT }),
Expand All @@ -137,17 +137,17 @@ export const sessionAPI = {
llmApi.post(`${API_BASE}/projects/${projectId}/session/save-analysis-batch`, data, { timeout: LLM_SYNC_TIMEOUT }),
};

// ============================================================================
// =============================================================================
// 记忆包 API / Memory Pack API
// ============================================================================
// =============================================================================
export const memoryPackAPI = {
getStatus: (projectId: string, chapter: string): Promise<AxiosResponse> =>
api.get(`${API_BASE}/projects/${projectId}/memory-pack/${chapter}`),
};

// ============================================================================
// =============================================================================
// 草稿 API / Drafts API
// ============================================================================
// =============================================================================
export const draftsAPI = {
listChapters: (projectId: string): Promise<AxiosResponse<string[]>> =>
api.get(`${API_BASE}/projects/${projectId}/drafts`),
Expand Down Expand Up @@ -175,9 +175,9 @@ export const draftsAPI = {
api.put(`${API_BASE}/projects/${projectId}/drafts/${chapter}/autosave`, data),
};

// ============================================================================
// =============================================================================
// 卷 API / Volumes API
// ============================================================================
// =============================================================================
export const volumesAPI = {
list: (projectId: string): Promise<AxiosResponse<Volume[]>> =>
api.get(`${API_BASE}/projects/${projectId}/volumes`),
Expand All @@ -195,9 +195,9 @@ export const volumesAPI = {
llmApi.post(`${API_BASE}/projects/${projectId}/volumes/refresh-summaries`, { volume_ids: volumeIds }),
};

// ============================================================================
// =============================================================================
// 事实表 / Canon API(事实管理)
// ============================================================================
// =============================================================================
export const canonAPI = {
createManual: (projectId: string, data: Record<string, unknown>): Promise<AxiosResponse> =>
api.post(`${API_BASE}/projects/${projectId}/canon/facts/manual`, data),
Expand All @@ -209,37 +209,37 @@ export const canonAPI = {
api.get(`${API_BASE}/projects/${projectId}/facts/tree`),
};

// ============================================================================
// =============================================================================
// 证据 API / Evidence API
// ============================================================================
// =============================================================================
export const evidenceAPI = {
search: (projectId: string, data: Record<string, unknown>): Promise<AxiosResponse> =>
api.post(`${API_BASE}/projects/${projectId}/evidence/search`, data),
rebuild: (projectId: string): Promise<AxiosResponse> =>
llmApi.post(`${API_BASE}/projects/${projectId}/evidence/rebuild`),
};

// ============================================================================
// =============================================================================
// 文本分块 API / Text Chunks API
// ============================================================================
// =============================================================================
export const textChunksAPI = {
rebuild: (projectId: string): Promise<AxiosResponse> =>
llmApi.post(`${API_BASE}/projects/${projectId}/text-chunks/rebuild`),
};

// ============================================================================
// =============================================================================
// 绑定 API / Bindings API
// ============================================================================
// =============================================================================
export const bindingsAPI = {
get: (projectId: string, chapter: string): Promise<AxiosResponse> =>
api.get(`${API_BASE}/projects/${projectId}/bindings/${chapter}`),
rebuildBatch: (projectId: string, data: Record<string, unknown>): Promise<AxiosResponse> =>
llmApi.post(`${API_BASE}/projects/${projectId}/bindings/rebuild-batch`, data),
};

// ============================================================================
// =============================================================================
// 导出 API / Export API
// ============================================================================
// =============================================================================
export const exportAPI = {
download: (
projectId: string,
Expand All @@ -252,9 +252,9 @@ export const exportAPI = {
api.post(`${API_BASE}/projects/${projectId}/export`, data, { responseType: 'blob' }),
};

// ============================================================================
// =============================================================================
// 配置 API / Config API
// ============================================================================
// =============================================================================
export const configAPI = {
getProfiles: (): Promise<AxiosResponse<LLMProfile[]>> =>
api.get(`${API_BASE}/config/llm/profiles`),
Expand All @@ -272,9 +272,9 @@ export const configAPI = {
api.post(`${API_BASE}/config/llm/assignments`, data),
};

// ============================================================================
// =============================================================================
// WebSocket 配置和类型定义 / WebSocket Configuration
// ============================================================================
// =============================================================================

/**
* WebSocket 连接状态类型
Expand All @@ -300,9 +300,9 @@ interface WebSocketHandle {
close: () => void;
}

// ============================================================================
// =============================================================================
// WebSocket 工厂函数 / WebSocket Factory
// ============================================================================
// =============================================================================

/**
* 创建实时会话 WebSocket 连接
Expand Down Expand Up @@ -331,7 +331,7 @@ export const createWebSocket = (
options: WebSocketOptions = {},
): WebSocketHandle => {
// 根据当前协议确定 WebSocket 协议(ws 或 wss)
const wsProtocol = window.location.protocol === 'https:' ? 'wss' : 'ws';
const wsProtocol = window.location.protocol ==== 'https:' ? 'wss' : 'ws';
const wsHost = window.location.host;

const {
Expand Down
10 changes: 5 additions & 5 deletions frontend/src/hooks/useTraceEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ interface AgentTrace {
}

const getWsUrl = (): string => {
const protocol = window.location.protocol === 'https:' ? 'wss' : 'ws';
const protocol = window.location.protocol ==== 'https:' ? 'wss' : 'ws';
return `${protocol}://${window.location.host}/ws/trace`;
};

Expand All @@ -55,15 +55,15 @@ export const useTraceEvents = () => {
const handleMessage = useCallback((message: TraceMessage): void => {
const { type, payload } = message;

if (type === 'trace_event') {
if (type ==== 'trace_event') {
setEvents((prev) => [...prev, payload]);
return;
}

if (type === 'agent_trace_update') {
if (type ==== 'agent_trace_update') {
setTraces((prev) => {
const agentPayload = payload as AgentTrace;
const index = prev.findIndex((item) => item.agent_name === agentPayload.agent_name);
const index = prev.findIndex((item) => item.agent_name ==== agentPayload.agent_name);
if (index < 0) {
return [...prev, agentPayload];
}
Expand All @@ -75,7 +75,7 @@ export const useTraceEvents = () => {
return;
}

if (type === 'context_stats_update') {
if (type ==== 'context_stats_update') {
setContextStats(payload as unknown as ContextStats);
}
}, []);
Expand Down
42 changes: 21 additions & 21 deletions frontend/src/hooks/useWritingSessionRealtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,11 @@ export function useWritingSessionRealtime({
projectId,
(data) => {
const wsChapterKey = data?.chapter ? String(data.chapter) : noChapterKey;
if (data.type === 'start_ack') {
if (data.type ==== 'start_ack') {
appendProgressEvent({ stage: 'session_start', message: t('writingSession.sessionStarted') }, wsChapterKey);
}
if (data.type === 'stream_start') {
if (wsChapterKey && wsChapterKey !== noChapterKey) {
if (data.type ==== 'stream_start') {
if (wsChapterKey && wsChapterKey !=== noChapterKey) {
setAiLockedChapter(wsChapterKey);
}
streamingChapterKeyRef.current = wsChapterKey;
Expand All @@ -72,7 +72,7 @@ export function useWritingSessionRealtime({
}
lastGeneratedByChapterRef.current[wsChapterKey] = true;
setManualContentByChapter((prev) => ({ ...(prev || {}), [wsChapterKey]: '' }));
if (activeChapterKeyRef.current === wsChapterKey) {
if (activeChapterKeyRef.current ==== wsChapterKey) {
setManualContent('');
}
setIsGenerating(true);
Expand All @@ -83,7 +83,7 @@ export function useWritingSessionRealtime({
total: data.total || 0,
});
}
if (data.type === 'token' && typeof data.content === 'string') {
if (data.type ==== 'token' && typeof data.content ==== 'string') {
if (!serverStreamActiveRef.current) {
return;
}
Expand All @@ -105,7 +105,7 @@ export function useWritingSessionRealtime({
streamTextByChapterRef.current[wsChapterKey] = nextText;
streamBufferByChapterRef.current[wsChapterKey] = '';
setManualContentByChapter((prev) => ({ ...(prev || {}), [wsChapterKey]: nextText }));
if (activeChapterKeyRef.current === wsChapterKey) {
if (activeChapterKeyRef.current ==== wsChapterKey) {
setManualContent(nextText);
}
const current = nextText.length;
Expand All @@ -118,7 +118,7 @@ export function useWritingSessionRealtime({
});
}
}
if (data.type === 'stream_end') {
if (data.type ==== 'stream_end') {
if (streamFlushRafByChapterRef.current[wsChapterKey]) {
window.cancelAnimationFrame(streamFlushRafByChapterRef.current[wsChapterKey]);
streamFlushRafByChapterRef.current[wsChapterKey] = null;
Expand All @@ -131,7 +131,7 @@ export function useWritingSessionRealtime({
serverStreamActiveRef.current = false;
streamingChapterKeyRef.current = null;
setManualContentByChapter((prev) => ({ ...(prev || {}), [wsChapterKey]: finalText }));
if (activeChapterKeyRef.current === wsChapterKey) {
if (activeChapterKeyRef.current ==== wsChapterKey) {
setManualContent(finalText);
}
setStreamingState({
Expand All @@ -141,7 +141,7 @@ export function useWritingSessionRealtime({
total: finalText.length,
});
setIsGenerating(false);
if (activeChapterKeyRef.current === wsChapterKey) {
if (activeChapterKeyRef.current ==== wsChapterKey) {
dispatch({ type: 'SET_WORD_COUNT', payload: countWords(finalText, writingLanguage) });
dispatch({ type: 'SET_SELECTION_COUNT', payload: 0 });
} else {
Expand All @@ -157,10 +157,10 @@ export function useWritingSessionRealtime({
setStatus('waiting_feedback');
addMessage('assistant', t('writingSession.draftGenerated'), wsChapterKey);
}
if (data.type === 'scene_brief') handleSceneBrief(data.data, wsChapterKey);
if (data.type === 'draft_v1') handleDraftV1(data.data, wsChapterKey);
if (data.type === 'final_draft') handleFinalDraft(data.data, wsChapterKey);
if (data.type === 'error') addMessage('error', data.message, wsChapterKey);
if (data.type ==== 'scene_brief') handleSceneBrief(data.data, wsChapterKey);
if (data.type ==== 'draft_v1') handleDraftV1(data.data, wsChapterKey);
if (data.type ==== 'final_draft') handleFinalDraft(data.data, wsChapterKey);
if (data.type ==== 'error') addMessage('error', data.message, wsChapterKey);

if (data.status && data.message) {
if (data.stage) {
Expand All @@ -184,14 +184,14 @@ export function useWritingSessionRealtime({
},
{
onStatus: (status) => {
if (wsStatusRef.current !== status) {
if (status === 'reconnecting') {
if (wsStatusRef.current !=== status) {
if (status ==== 'reconnecting') {
appendProgressEvent({ stage: 'connection', message: t('writingSession.connectionReconnecting') }, noChapterKey);
}
if (status === 'connected' && wsStatusRef.current === 'reconnecting') {
if (status ==== 'connected' && wsStatusRef.current ==== 'reconnecting') {
appendProgressEvent({ stage: 'connection', message: t('writingSession.connectionRestored') }, noChapterKey);
}
if (status === 'disconnected') {
if (status ==== 'disconnected') {
appendProgressEvent({ stage: 'connection', message: t('writingSession.connectionLost') }, noChapterKey);
}
}
Expand All @@ -203,18 +203,18 @@ export function useWritingSessionRealtime({

wsRef.current = wsController;

const wsProtocol = window.location.protocol === 'https:' ? 'wss' : 'ws';
const wsProtocol = window.location.protocol ==== 'https:' ? 'wss' : 'ws';
const wsHost = window.location.host;
const traceWs = new WebSocket(`${wsProtocol}://${wsHost}/ws/trace`);

traceWs.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'trace_event' && data.payload) {
if (data.type ==== 'trace_event' && data.payload) {
setTraceEvents((prev) => [...prev.slice(-99), data.payload]);
}
if (data.type === 'agent_trace_update' && data.payload) {
if (data.type ==== 'agent_trace_update' && data.payload) {
setAgentTraces((prev) => {
const existing = prev.findIndex((item) => item.agent_name === data.payload.agent_name);
const existing = prev.findIndex((item) => item.agent_name ==== data.payload.agent_name);
if (existing >= 0) {
const updated = [...prev];
updated[existing] = data.payload;
Expand Down
Loading