311 lines
8.5 KiB
TypeScript
311 lines
8.5 KiB
TypeScript
import type {
|
|
JumpHopActionRequest,
|
|
JumpHopActionResponse,
|
|
JumpHopDraftResponse,
|
|
JumpHopGalleryCardResponse,
|
|
JumpHopGalleryDetailResponse,
|
|
JumpHopGalleryResponse,
|
|
JumpHopRunResponse,
|
|
JumpHopRuntimeRunSnapshotResponse,
|
|
JumpHopSessionResponse,
|
|
JumpHopSessionSnapshotResponse,
|
|
JumpHopWorkDetailResponse,
|
|
JumpHopWorkMutationResponse,
|
|
JumpHopWorkProfileResponse,
|
|
JumpHopWorksResponse,
|
|
JumpHopWorkspaceCreateRequest,
|
|
JumpHopWorkSummaryResponse,
|
|
} from '../../../packages/shared/src/contracts/jumpHop';
|
|
import {
|
|
type ApiRequestOptions,
|
|
type ApiRetryOptions,
|
|
requestJson,
|
|
} from '../apiClient';
|
|
import { createCreationAgentClient } from '../creation-agent';
|
|
|
|
const JUMP_HOP_API_BASE = '/api/creation/jump-hop/sessions';
|
|
const JUMP_HOP_WORKS_API_BASE = '/api/creation/jump-hop/works';
|
|
const JUMP_HOP_RUNTIME_API_BASE = '/api/runtime/jump-hop';
|
|
const JUMP_HOP_RUNTIME_READ_RETRY: ApiRetryOptions = {
|
|
maxRetries: 1,
|
|
baseDelayMs: 120,
|
|
maxDelayMs: 360,
|
|
};
|
|
type JumpHopRuntimeRequestOptions = Pick<
|
|
ApiRequestOptions,
|
|
| 'authImpact'
|
|
| 'skipAuth'
|
|
| 'skipRefresh'
|
|
| 'notifyAuthStateChange'
|
|
| 'clearAuthOnUnauthorized'
|
|
>;
|
|
|
|
export type {
|
|
JumpHopActionRequest,
|
|
JumpHopActionResponse,
|
|
JumpHopDraftResponse,
|
|
JumpHopGalleryCardResponse,
|
|
JumpHopGalleryDetailResponse,
|
|
JumpHopGalleryResponse,
|
|
JumpHopRunResponse,
|
|
JumpHopRuntimeRunSnapshotResponse,
|
|
JumpHopSessionResponse,
|
|
JumpHopSessionSnapshotResponse,
|
|
JumpHopWorkDetailResponse,
|
|
JumpHopWorkMutationResponse,
|
|
JumpHopWorkProfileResponse,
|
|
JumpHopWorksResponse,
|
|
JumpHopWorkspaceCreateRequest,
|
|
};
|
|
export type CreateJumpHopSessionRequest = {
|
|
themeText: string;
|
|
characterDescription: string;
|
|
tileStyle: string;
|
|
difficulty: string;
|
|
rhythmPreference: string;
|
|
};
|
|
export type ExecuteJumpHopActionRequest = JumpHopActionRequest;
|
|
export type JumpHopSessionSnapshot = JumpHopSessionSnapshotResponse;
|
|
|
|
const jumpHopCreationClient = createCreationAgentClient<
|
|
JumpHopWorkspaceCreateRequest,
|
|
JumpHopSessionResponse,
|
|
JumpHopSessionResponse,
|
|
JumpHopSessionSnapshotResponse,
|
|
never,
|
|
never,
|
|
JumpHopActionRequest,
|
|
JumpHopActionResponse
|
|
>({
|
|
apiBase: JUMP_HOP_API_BASE,
|
|
messages: {
|
|
createSession: '创建跳一跳共创会话失败',
|
|
getSession: '读取跳一跳共创会话失败',
|
|
sendMessage: '发送跳一跳共创消息失败',
|
|
streamIncomplete: '跳一跳共创消息流式结果不完整',
|
|
executeAction: '执行跳一跳共创操作失败',
|
|
},
|
|
});
|
|
|
|
type FlattenedJumpHopWorkProfileResponse = Omit<
|
|
JumpHopWorkProfileResponse,
|
|
'summary'
|
|
> &
|
|
JumpHopWorkSummaryResponse;
|
|
|
|
function normalizeJumpHopWorkProfile(
|
|
work: JumpHopWorkProfileResponse | FlattenedJumpHopWorkProfileResponse,
|
|
): JumpHopWorkProfileResponse {
|
|
if ('summary' in work && work.summary) {
|
|
return work;
|
|
}
|
|
|
|
const flattened = work as FlattenedJumpHopWorkProfileResponse;
|
|
const summary: JumpHopWorkProfileResponse['summary'] = {
|
|
runtimeKind: flattened.runtimeKind,
|
|
workId: flattened.workId,
|
|
profileId: flattened.profileId,
|
|
ownerUserId: flattened.ownerUserId,
|
|
sourceSessionId: flattened.sourceSessionId ?? null,
|
|
workTitle: flattened.workTitle,
|
|
workDescription: flattened.workDescription,
|
|
themeTags: flattened.themeTags,
|
|
difficulty: flattened.difficulty,
|
|
stylePreset: flattened.stylePreset,
|
|
coverImageSrc: flattened.coverImageSrc ?? null,
|
|
publicationStatus: flattened.publicationStatus,
|
|
playCount: flattened.playCount,
|
|
updatedAt: flattened.updatedAt,
|
|
publishedAt: flattened.publishedAt ?? null,
|
|
publishReady: flattened.publishReady,
|
|
generationStatus: flattened.generationStatus,
|
|
};
|
|
|
|
return {
|
|
summary,
|
|
draft: flattened.draft,
|
|
path: flattened.path,
|
|
characterAsset: flattened.characterAsset,
|
|
tileAtlasAsset: flattened.tileAtlasAsset,
|
|
tileAssets: flattened.tileAssets,
|
|
};
|
|
}
|
|
|
|
function normalizeJumpHopActionResponse(
|
|
response: JumpHopActionResponse,
|
|
): JumpHopActionResponse {
|
|
return {
|
|
...response,
|
|
work: response.work ? normalizeJumpHopWorkProfile(response.work) : null,
|
|
};
|
|
}
|
|
|
|
function normalizeJumpHopWorkDetailResponse(
|
|
response: JumpHopWorkDetailResponse,
|
|
): JumpHopWorkDetailResponse {
|
|
return {
|
|
...response,
|
|
item: normalizeJumpHopWorkProfile(response.item),
|
|
};
|
|
}
|
|
|
|
function normalizeJumpHopWorkMutationResponse(
|
|
response: JumpHopWorkMutationResponse,
|
|
): JumpHopWorkMutationResponse {
|
|
return {
|
|
...response,
|
|
item: normalizeJumpHopWorkProfile(response.item),
|
|
};
|
|
}
|
|
|
|
export function createJumpHopCreationSession(
|
|
payload: JumpHopWorkspaceCreateRequest,
|
|
) {
|
|
return jumpHopCreationClient.createSession(payload);
|
|
}
|
|
|
|
export function getJumpHopCreationSession(sessionId: string) {
|
|
return jumpHopCreationClient.getSession(sessionId);
|
|
}
|
|
|
|
export function executeJumpHopCreationAction(
|
|
sessionId: string,
|
|
payload: JumpHopActionRequest,
|
|
) {
|
|
return jumpHopCreationClient
|
|
.executeAction(sessionId, payload)
|
|
.then(normalizeJumpHopActionResponse);
|
|
}
|
|
|
|
export async function getJumpHopWorkDetail(profileId: string) {
|
|
const response = await requestJson<JumpHopWorkDetailResponse>(
|
|
`${JUMP_HOP_RUNTIME_API_BASE}/works/${encodeURIComponent(profileId)}`,
|
|
{ method: 'GET' },
|
|
'读取跳一跳作品详情失败',
|
|
);
|
|
return normalizeJumpHopWorkDetailResponse(response);
|
|
}
|
|
|
|
export async function listJumpHopGallery() {
|
|
return requestJson<JumpHopGalleryResponse>(
|
|
`${JUMP_HOP_RUNTIME_API_BASE}/gallery`,
|
|
{ method: 'GET' },
|
|
'读取跳一跳广场失败',
|
|
{
|
|
retry: JUMP_HOP_RUNTIME_READ_RETRY,
|
|
skipAuth: true,
|
|
skipRefresh: true,
|
|
},
|
|
);
|
|
}
|
|
|
|
export async function getJumpHopGalleryDetail(publicWorkCode: string) {
|
|
const response = await requestJson<JumpHopGalleryDetailResponse>(
|
|
`${JUMP_HOP_RUNTIME_API_BASE}/gallery/${encodeURIComponent(publicWorkCode)}`,
|
|
{ method: 'GET' },
|
|
'读取跳一跳广场详情失败',
|
|
{
|
|
retry: JUMP_HOP_RUNTIME_READ_RETRY,
|
|
skipAuth: true,
|
|
skipRefresh: true,
|
|
},
|
|
);
|
|
return normalizeJumpHopWorkDetailResponse(response);
|
|
}
|
|
|
|
export async function listJumpHopWorks() {
|
|
return requestJson<JumpHopWorksResponse>(
|
|
JUMP_HOP_WORKS_API_BASE,
|
|
{ method: 'GET' },
|
|
'读取跳一跳作品列表失败',
|
|
{
|
|
retry: JUMP_HOP_RUNTIME_READ_RETRY,
|
|
},
|
|
);
|
|
}
|
|
|
|
export async function publishJumpHopWork(profileId: string) {
|
|
const response = await requestJson<JumpHopWorkMutationResponse>(
|
|
`${JUMP_HOP_WORKS_API_BASE}/${encodeURIComponent(profileId)}/publish`,
|
|
{ method: 'POST' },
|
|
'发布跳一跳作品失败',
|
|
);
|
|
return normalizeJumpHopWorkMutationResponse(response);
|
|
}
|
|
|
|
export async function startJumpHopRuntimeRun(
|
|
profileId: string,
|
|
options: JumpHopRuntimeRequestOptions = {},
|
|
) {
|
|
return requestJson<JumpHopRunResponse>(
|
|
`${JUMP_HOP_RUNTIME_API_BASE}/runs`,
|
|
{
|
|
method: 'POST',
|
|
headers: {
|
|
'content-type': 'application/json',
|
|
},
|
|
body: JSON.stringify({ profileId }),
|
|
},
|
|
'启动跳一跳运行态失败',
|
|
{
|
|
authImpact: options.authImpact,
|
|
skipAuth: options.skipAuth,
|
|
skipRefresh: options.skipRefresh,
|
|
notifyAuthStateChange: options.notifyAuthStateChange,
|
|
clearAuthOnUnauthorized: options.clearAuthOnUnauthorized,
|
|
},
|
|
);
|
|
}
|
|
|
|
export async function submitJumpHopJump(
|
|
runId: string,
|
|
payload: { chargeMs: number },
|
|
) {
|
|
const requestPayload = {
|
|
chargeMs: payload.chargeMs,
|
|
clientEventId: `jump-${runId}-${Date.now()}`,
|
|
};
|
|
|
|
return requestJson<JumpHopRunResponse>(
|
|
`${JUMP_HOP_RUNTIME_API_BASE}/runs/${encodeURIComponent(runId)}/jump`,
|
|
{
|
|
method: 'POST',
|
|
headers: {
|
|
'content-type': 'application/json',
|
|
},
|
|
body: JSON.stringify(requestPayload),
|
|
},
|
|
'提交跳一跳起跳失败',
|
|
);
|
|
}
|
|
|
|
export async function restartJumpHopRuntimeRun(runId: string) {
|
|
return requestJson<JumpHopRunResponse>(
|
|
`${JUMP_HOP_RUNTIME_API_BASE}/runs/${encodeURIComponent(runId)}/restart`,
|
|
{
|
|
method: 'POST',
|
|
headers: {
|
|
'content-type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
clientActionId: `restart-${runId}-${Date.now()}`,
|
|
}),
|
|
},
|
|
'重新开始跳一跳失败',
|
|
);
|
|
}
|
|
|
|
export const jumpHopClient = {
|
|
createSession: createJumpHopCreationSession,
|
|
getSession: getJumpHopCreationSession,
|
|
executeAction: executeJumpHopCreationAction,
|
|
getGalleryDetail: getJumpHopGalleryDetail,
|
|
getWorkDetail: getJumpHopWorkDetail,
|
|
listGallery: listJumpHopGallery,
|
|
listWorks: listJumpHopWorks,
|
|
publishWork: publishJumpHopWork,
|
|
restartRun: restartJumpHopRuntimeRun,
|
|
startRun: startJumpHopRuntimeRun,
|
|
submitJump: submitJumpHopJump,
|
|
};
|