Files
Mutual_Fund/frontend/lib/assistant-api.ts
T

155 lines
4.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { apiFetch, readSSE, type SSESummary } from "@/lib/api";
import type { Page } from "@/lib/admin-api";
/**
* 投顾 Agent(/api/advisor-agent/*)适配层。
* 该系列接口的成功码是 0 而不是 200(agent_success),已在 lib/api.ts 统一兼容。
*/
export interface AgentMessage {
role?: string;
content?: string;
[key: string]: unknown;
}
export interface AgentDraft {
draft_id?: string;
id?: string;
title?: string | null;
content?: string | null;
intent?: string | null;
status?: string | null;
customer_id?: number | null;
create_time?: string | null;
update_time?: string | null;
structured_data?: Record<string, unknown> | null;
[key: string]: unknown;
}
export interface DataQueryResult {
query_id?: string;
answer?: string;
summary?: string;
columns?: string[];
rows?: Record<string, unknown>[];
total?: number;
page?: number;
page_size?: number;
[key: string]: unknown;
}
export interface FundAnalysisResult {
analysis_text?: string;
items?: Record<string, unknown>[];
[key: string]: unknown;
}
export interface TalkScriptResult {
script?: string;
content?: string;
scene?: string;
[key: string]: unknown;
}
/** 会话上下文:scope=customer 时必须带 customer_id,否则后端会尝试从问题文本里猜客户。 */
export interface ChatScope {
sessionId?: string;
customerId?: number | null;
scope?: "customer" | "advisor";
}
function qs(params: Record<string, string | number | undefined | null>) {
const search = new URLSearchParams();
for (const [key, value] of Object.entries(params)) {
if (value !== undefined && value !== null && value !== "") search.set(key, String(value));
}
const text = search.toString();
return text ? `?${text}` : "";
}
export const assistantApi = {
/** GET /session/{session_id}/history —— 读取本人短期 Agent 会话记录。 */
sessionHistory: (sessionId: string) =>
apiFetch<AgentMessage[]>(`/advisor-agent/session/${encodeURIComponent(sessionId)}/history`),
/**
* POST /chat/stream —— 响应是 text/event-stream,但后端整包输出,
* 因此读完整条响应后一次性返回聚合结果(非流式渲染)。
*/
chatOnce(
body: {
query: string;
session_id?: string;
scope?: "customer" | "advisor";
customer_id?: number | null;
},
signal?: AbortSignal
): Promise<SSESummary> {
return readSSE("/advisor-agent/chat/stream", body, signal);
},
/** POST /data-query —— 自然语言查客户数据(非流式)。 */
dataQuery: (body: {
query: string;
session_id?: string;
max_rows?: number;
page?: number;
page_size?: number;
}) =>
apiFetch<DataQueryResult>("/advisor-agent/data-query", {
method: "POST",
body: JSON.stringify(body),
}),
/** GET /draft/list */
drafts: (params: { customer_id?: number; status?: string; page?: number; page_size?: number } = {}) =>
apiFetch<Page<AgentDraft> & { items?: AgentDraft[] }>(`/advisor-agent/draft/list${qs(params)}`),
/** GET /draft/{draft_id} */
draft: (draftId: string) =>
apiFetch<AgentDraft>(`/advisor-agent/draft/${encodeURIComponent(draftId)}`),
/** PUT /draft/{draft_id}/save */
saveDraft: (
draftId: string,
body: { title?: string; content?: string; structured_data?: Record<string, unknown> }
) =>
apiFetch<AgentDraft>(`/advisor-agent/draft/${encodeURIComponent(draftId)}/save`, {
method: "PUT",
body: JSON.stringify(body),
}),
/** POST /draft/{draft_id}/operate —— 后端目前仅支持 operation=discard。 */
operateDraft: (draftId: string, operation: "discard") =>
apiFetch<AgentDraft>(`/advisor-agent/draft/${encodeURIComponent(draftId)}/operate`, {
method: "POST",
body: JSON.stringify({ operation }),
}),
/** POST /rebalance/run —— 异步受理,返回 accepted/queued,草稿稍后生成。 */
runRebalance: (query: string) =>
apiFetch<{ accepted?: boolean; status?: string }>("/advisor-agent/rebalance/run", {
method: "POST",
body: JSON.stringify({ query }),
}),
/** POST /fund-analysis —— query 里需包含基金代码,如「分析 000001」。 */
fundAnalysis: (query: string) =>
apiFetch<FundAnalysisResult>("/advisor-agent/fund-analysis", {
method: "POST",
body: JSON.stringify({ query }),
}),
/** POST /generate-talk-script */
generateTalkScript: (query: string) =>
apiFetch<TalkScriptResult>("/advisor-agent/generate-talk-script", {
method: "POST",
body: JSON.stringify({ query }),
}),
};
/** 生成本地会话 ID(后端 session_id 为空时自动创建,这里只是前端约定的稳定键)。 */
export function newSessionId(): string {
return `advisor-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
}