Files
Genarrative/src/services/creative-agent/creativeAgentClient.ts
2026-05-08 11:44:42 +08:00

169 lines
4.7 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 type {
ConfirmCreativePuzzleTemplateRequest,
CreateCreativeAgentSessionRequest,
CreativeAgentSessionResponse,
CreativeAgentSessionSnapshot,
CreativeAgentSseEvent,
CreativeDraftEditStreamRequest,
StreamCreativeAgentMessageRequest,
} from '../../../packages/shared/src/contracts/creativeAgent';
import { parseApiErrorMessage } from '../../../packages/shared/src/http';
import type { TextStreamOptions } from '../aiTypes';
import { fetchWithApiAuth, requestJson } from '../apiClient';
import {
readCreativeAgentResultFromSse,
readCreativeAgentSessionFromSse,
} from './creativeAgentSse';
const CREATIVE_AGENT_API_BASE = '/api/runtime/creative-agent/sessions';
export type CreativeAgentStreamOptions = TextStreamOptions & {
onEvent?: (event: CreativeAgentSseEvent) => void;
};
function buildJsonPostInit(payload: unknown): RequestInit {
return {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
};
}
async function openCreativeAgentSsePost(
url: string,
payload: unknown,
fallbackMessage: string,
signal?: AbortSignal,
) {
const response = await fetchWithApiAuth(url, {
...buildJsonPostInit(payload),
signal,
});
if (!response.ok) {
const responseText = await response.text();
throw new Error(parseApiErrorMessage(responseText, fallbackMessage));
}
if (!response.body) {
throw new Error('streaming response body is unavailable');
}
return response;
}
export async function createCreativeAgentSession(
payload: CreateCreativeAgentSessionRequest = {},
) {
return requestJson<CreativeAgentSessionResponse>(
CREATIVE_AGENT_API_BASE,
buildJsonPostInit(payload),
'创建智能创作会话失败',
{
retry: {
maxRetries: 1,
baseDelayMs: 240,
maxDelayMs: 640,
retryUnsafeMethods: true,
},
timeoutMs: 15000,
},
);
}
export async function getCreativeAgentSession(sessionId: string) {
return requestJson<CreativeAgentSessionResponse>(
`${CREATIVE_AGENT_API_BASE}/${encodeURIComponent(sessionId)}`,
{ method: 'GET' },
'读取智能创作会话失败',
);
}
export async function streamCreativeAgentMessage(
sessionId: string,
payload: StreamCreativeAgentMessageRequest,
options: CreativeAgentStreamOptions = {},
) {
const response = await openCreativeAgentSsePost(
`${CREATIVE_AGENT_API_BASE}/${encodeURIComponent(sessionId)}/messages/stream`,
payload,
'发送智能创作消息失败',
options.signal,
);
return readCreativeAgentSessionFromSse(response, {
...options,
fallbackMessage: '发送智能创作消息失败',
incompleteMessage: '智能创作消息流式结果不完整',
});
}
export async function confirmCreativePuzzleTemplate(
sessionId: string,
payload: ConfirmCreativePuzzleTemplateRequest,
) {
return requestJson<CreativeAgentSessionResponse>(
`${CREATIVE_AGENT_API_BASE}/${encodeURIComponent(sessionId)}/confirm-template`,
buildJsonPostInit(payload),
'确认拼图模板失败',
{
retry: {
maxRetries: 1,
baseDelayMs: 240,
maxDelayMs: 640,
retryUnsafeMethods: true,
},
},
);
}
export async function streamCreativeDraftEdit(
sessionId: string,
payload: CreativeDraftEditStreamRequest,
options: CreativeAgentStreamOptions = {},
) {
const response = await openCreativeAgentSsePost(
`${CREATIVE_AGENT_API_BASE}/${encodeURIComponent(sessionId)}/draft-edits/stream`,
payload,
'修改拼图草稿失败',
options.signal,
);
return requestCreativeDraftEditResultFromSse(response, options);
}
export async function cancelCreativeAgentSession(sessionId: string) {
return requestJson<CreativeAgentSessionResponse>(
`${CREATIVE_AGENT_API_BASE}/${encodeURIComponent(sessionId)}/cancel`,
buildJsonPostInit({}),
'取消智能创作会话失败',
);
}
async function requestCreativeDraftEditResultFromSse(
response: Response,
options: CreativeAgentStreamOptions,
) {
const result = await readCreativeAgentResultFromSse(response, {
...options,
fallbackMessage: '修改拼图草稿失败',
incompleteMessage: '智能创作修改结果不完整',
});
if (result.draftEditResult) {
return result.draftEditResult;
}
// 中文注释:后端如果暂时只返回 session调用方仍能用 session 做保底收尾。
return result.session as CreativeAgentSessionSnapshot;
}
export const creativeAgentClient = {
createSession: createCreativeAgentSession,
getSession: getCreativeAgentSession,
streamMessage: streamCreativeAgentMessage,
confirmTemplate: confirmCreativePuzzleTemplate,
streamDraftEdit: streamCreativeDraftEdit,
cancelSession: cancelCreativeAgentSession,
};