feat(mindspace): 0630004 空间 UI、聊天连接、微信分享与 Agent 能力
含 MindSpace 三列布局与统计修复、聊天加载态与连接降级、平台页脚标记与 og:site_name 微信卡片、勾选资料删除 Agent 接口及内部话术过滤。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+70
-29
@@ -61,6 +61,7 @@ import { normalizeConversationMessages, normalizeUserMessageForApi } from '../ut
|
||||
|
||||
const API = '/api';
|
||||
const DEFAULT_API_TIMEOUT_MS = 20_000;
|
||||
const AGENT_CONNECT_TIMEOUT_MS = 60_000;
|
||||
const AGENT_RUNS_PATH = '/agent/runs';
|
||||
|
||||
export type AgentRun = {
|
||||
@@ -184,10 +185,14 @@ function notifyUnauthorized() {
|
||||
unauthorizedHandler();
|
||||
}
|
||||
|
||||
async function fetchWithTimeout(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {
|
||||
async function fetchWithTimeout(
|
||||
input: RequestInfo | URL,
|
||||
init?: RequestInit,
|
||||
timeoutMs = DEFAULT_API_TIMEOUT_MS,
|
||||
): Promise<Response> {
|
||||
const controller = new AbortController();
|
||||
const upstreamSignal = init?.signal;
|
||||
const timeout = window.setTimeout(() => controller.abort(), DEFAULT_API_TIMEOUT_MS);
|
||||
const timeout = window.setTimeout(() => controller.abort(), timeoutMs);
|
||||
|
||||
const abortFromUpstream = () => controller.abort();
|
||||
if (upstreamSignal) {
|
||||
@@ -267,16 +272,24 @@ function sanitizeSessionEvent(event: SessionEvent): SessionEvent {
|
||||
return { ...event, error: sanitizeUserFacingErrorMessage(event.error) };
|
||||
}
|
||||
|
||||
async function apiFetch<T>(path: string, init?: RequestInit): Promise<T> {
|
||||
async function apiFetch<T>(
|
||||
path: string,
|
||||
init?: RequestInit,
|
||||
options?: { timeoutMs?: number },
|
||||
): Promise<T> {
|
||||
let res: Response;
|
||||
try {
|
||||
res = await fetchWithTimeout(`${API}${path}`, {
|
||||
...init,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...init?.headers,
|
||||
res = await fetchWithTimeout(
|
||||
`${API}${path}`,
|
||||
{
|
||||
...init,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...init?.headers,
|
||||
},
|
||||
},
|
||||
});
|
||||
options?.timeoutMs,
|
||||
);
|
||||
} catch (err) {
|
||||
throw new ApiError(0, formatNetworkError(err));
|
||||
}
|
||||
@@ -313,10 +326,14 @@ async function apiFetch<T>(path: string, init?: RequestInit): Promise<T> {
|
||||
}
|
||||
|
||||
export async function startSession(): Promise<Session> {
|
||||
return apiFetch<Session>('/agent/start', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({}),
|
||||
});
|
||||
return apiFetch<Session>(
|
||||
'/agent/start',
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify({}),
|
||||
},
|
||||
{ timeoutMs: AGENT_CONNECT_TIMEOUT_MS },
|
||||
);
|
||||
}
|
||||
|
||||
export async function bootstrapProjectMemory(
|
||||
@@ -929,6 +946,7 @@ export async function saveChatMessageAsPage(input: {
|
||||
selectedLinkIndex?: number;
|
||||
acknowledgedFindingIds?: string[];
|
||||
replacePageId?: string;
|
||||
saveAsNew?: boolean;
|
||||
}): Promise<ChatSaveResult> {
|
||||
const result = await apiFetch<{ data: ChatSaveResult }>(
|
||||
'/mindspace/v1/pages/save-from-chat',
|
||||
@@ -945,6 +963,7 @@ export async function saveChatMessageAsPage(input: {
|
||||
acknowledged_finding_ids: input.acknowledgedFindingIds,
|
||||
page_type: input.templateId === 'report' ? 'report' : 'article',
|
||||
replace_page_id: input.replacePageId,
|
||||
save_as_new: input.saveAsNew ?? false,
|
||||
}),
|
||||
},
|
||||
);
|
||||
@@ -1018,6 +1037,20 @@ export async function updateMindSpacePage(
|
||||
return result.data;
|
||||
}
|
||||
|
||||
export async function rewriteMindSpacePageDownloadLinks(
|
||||
pageId: string,
|
||||
content: string,
|
||||
): Promise<string> {
|
||||
const result = await apiFetch<{ data: { html: string } }>(
|
||||
`/mindspace/v1/pages/${encodeURIComponent(pageId)}/rewrite-download-links`,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ content }),
|
||||
},
|
||||
);
|
||||
return result.data.html;
|
||||
}
|
||||
|
||||
export async function fetchMindSpacePageDraftPreview(
|
||||
pageId: string,
|
||||
input: {
|
||||
@@ -2112,14 +2145,18 @@ export async function resumeSession(
|
||||
sessionId: string,
|
||||
options?: { skipReconcile?: boolean },
|
||||
): Promise<Session> {
|
||||
const result = await apiFetch<{ session: Session }>('/agent/resume', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
session_id: sessionId,
|
||||
load_model_and_extensions: true,
|
||||
...(options?.skipReconcile ? { skip_reconcile: true } : {}),
|
||||
}),
|
||||
});
|
||||
const result = await apiFetch<{ session: Session }>(
|
||||
'/agent/resume',
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
session_id: sessionId,
|
||||
load_model_and_extensions: true,
|
||||
...(options?.skipReconcile ? { skip_reconcile: true } : {}),
|
||||
}),
|
||||
},
|
||||
{ timeoutMs: AGENT_CONNECT_TIMEOUT_MS },
|
||||
);
|
||||
return result.session;
|
||||
}
|
||||
|
||||
@@ -2211,14 +2248,18 @@ export async function createAgentRun(
|
||||
requestId: string,
|
||||
userMessage: Message,
|
||||
): Promise<AgentRun> {
|
||||
const result = await apiFetch<{ run: AgentRun }>(AGENT_RUNS_PATH, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
session_id: sessionId,
|
||||
request_id: requestId,
|
||||
user_message: normalizeUserMessageForApi(userMessage),
|
||||
}),
|
||||
});
|
||||
const result = await apiFetch<{ run: AgentRun }>(
|
||||
AGENT_RUNS_PATH,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
session_id: sessionId,
|
||||
request_id: requestId,
|
||||
user_message: normalizeUserMessageForApi(userMessage),
|
||||
}),
|
||||
},
|
||||
{ timeoutMs: AGENT_CONNECT_TIMEOUT_MS },
|
||||
);
|
||||
return result.run;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user