Merge remote-tracking branch 'origin/master' into dev-jenken

# Conflicts:
#	.hermes/shared-memory/pitfalls.md
#	server-rs/crates/api-server/src/modules/jump_hop.rs
#	src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx
#	src/services/jump-hop/jumpHopClient.test.ts
This commit is contained in:
2026-06-05 23:59:40 +08:00
67 changed files with 8713 additions and 2537 deletions

View File

@@ -5,6 +5,7 @@ import type {
JumpHopGalleryCardResponse,
JumpHopGalleryDetailResponse,
JumpHopGalleryResponse,
JumpHopLeaderboardResponse,
JumpHopRunResponse,
JumpHopRuntimeRunSnapshotResponse,
JumpHopSessionResponse,
@@ -12,8 +13,8 @@ import type {
JumpHopWorkDetailResponse,
JumpHopWorkMutationResponse,
JumpHopWorkProfileResponse,
JumpHopWorksResponse,
JumpHopWorkspaceCreateRequest,
JumpHopWorksResponse,
JumpHopWorkSummaryResponse,
} from '../../../packages/shared/src/contracts/jumpHop';
import {
@@ -30,12 +31,23 @@ import {
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';
// 中文注释跳一跳创作会等待背景图、25 格图集、切片和 OSS 写入,不能沿用共创会话默认 15 秒超时。
const JUMP_HOP_GENERATION_TIMEOUT_MS = 20 * 60 * 1000;
const JUMP_HOP_RUNTIME_READ_RETRY: ApiRetryOptions = {
maxRetries: 1,
baseDelayMs: 120,
maxDelayMs: 360,
};
type JumpHopRuntimeRequestOptions = RuntimeGuestRequestOptions;
export type JumpHopRuntimeRequestOptions = RuntimeGuestRequestOptions;
type JumpHopRuntimeMode = 'draft' | 'published';
type JumpHopStartRunOptions = JumpHopRuntimeRequestOptions & {
runtimeMode?: JumpHopRuntimeMode;
};
type JumpHopJumpPayload = {
dragDistance: number;
dragVectorX?: number;
dragVectorY?: number;
};
export type {
JumpHopActionRequest,
@@ -44,6 +56,7 @@ export type {
JumpHopGalleryCardResponse,
JumpHopGalleryDetailResponse,
JumpHopGalleryResponse,
JumpHopLeaderboardResponse,
JumpHopRunResponse,
JumpHopRuntimeRunSnapshotResponse,
JumpHopSessionResponse,
@@ -51,16 +64,10 @@ export type {
JumpHopWorkDetailResponse,
JumpHopWorkMutationResponse,
JumpHopWorkProfileResponse,
JumpHopWorksResponse,
JumpHopWorkspaceCreateRequest,
JumpHopWorksResponse,
};
export type CreateJumpHopSessionRequest = {
themeText: string;
characterDescription: string;
tileStyle: string;
difficulty: string;
rhythmPreference: string;
};
export type CreateJumpHopSessionRequest = JumpHopWorkspaceCreateRequest;
export type ExecuteJumpHopActionRequest = JumpHopActionRequest;
export type JumpHopSessionSnapshot = JumpHopSessionSnapshotResponse;
@@ -82,6 +89,8 @@ const jumpHopCreationClient = createCreationAgentClient<
streamIncomplete: '跳一跳共创消息流式结果不完整',
executeAction: '执行跳一跳共创操作失败',
},
createSessionTimeoutMs: JUMP_HOP_GENERATION_TIMEOUT_MS,
executeActionTimeoutMs: JUMP_HOP_GENERATION_TIMEOUT_MS,
});
type FlattenedJumpHopWorkProfileResponse = Omit<
@@ -104,6 +113,7 @@ function normalizeJumpHopWorkProfile(
profileId: flattened.profileId,
ownerUserId: flattened.ownerUserId,
sourceSessionId: flattened.sourceSessionId ?? null,
themeText: flattened.themeText || flattened.workTitle,
workTitle: flattened.workTitle,
workDescription: flattened.workDescription,
themeTags: flattened.themeTags,
@@ -122,9 +132,12 @@ function normalizeJumpHopWorkProfile(
summary,
draft: flattened.draft,
path: flattened.path,
defaultCharacter: flattened.defaultCharacter ?? flattened.draft?.defaultCharacter,
characterAsset: flattened.characterAsset,
tileAtlasAsset: flattened.tileAtlasAsset,
tileAssets: flattened.tileAssets,
backButtonAsset:
flattened.backButtonAsset ?? flattened.draft?.backButtonAsset ?? null,
};
}
@@ -240,9 +253,10 @@ export async function deleteJumpHopWork(profileId: string) {
export async function startJumpHopRuntimeRun(
profileId: string,
options: JumpHopRuntimeRequestOptions = {},
options: JumpHopStartRunOptions = {},
) {
const requestOptions = buildRuntimeGuestAuthOptions(options);
const runtimeMode = options.runtimeMode ?? 'published';
return requestJson<JumpHopRunResponse>(
`${JUMP_HOP_RUNTIME_API_BASE}/runs`,
{
@@ -251,7 +265,7 @@ export async function startJumpHopRuntimeRun(
'content-type': 'application/json',
...buildRuntimeGuestHeaders(options),
},
body: JSON.stringify({ profileId }),
body: JSON.stringify({ profileId, runtimeMode }),
},
'启动跳一跳运行态失败',
{
@@ -262,12 +276,14 @@ export async function startJumpHopRuntimeRun(
export async function submitJumpHopJump(
runId: string,
payload: { chargeMs: number },
payload: JumpHopJumpPayload,
options: JumpHopRuntimeRequestOptions = {},
) {
const requestOptions = buildRuntimeGuestAuthOptions(options);
const requestPayload = {
chargeMs: payload.chargeMs,
dragDistance: payload.dragDistance,
dragVectorX: payload.dragVectorX,
dragVectorY: payload.dragVectorY,
clientEventId: `jump-${runId}-${Date.now()}`,
};
@@ -286,6 +302,22 @@ export async function submitJumpHopJump(
);
}
export async function getJumpHopLeaderboard(
profileId: string,
options: JumpHopRuntimeRequestOptions = {},
) {
const requestOptions = buildRuntimeGuestAuthOptions(options);
return requestJson<JumpHopLeaderboardResponse>(
`${JUMP_HOP_RUNTIME_API_BASE}/works/${encodeURIComponent(profileId)}/leaderboard`,
{
method: 'GET',
headers: buildRuntimeGuestHeaders(options),
},
'读取跳一跳排行榜失败',
requestOptions,
);
}
export async function restartJumpHopRuntimeRun(
runId: string,
options: JumpHopRuntimeRequestOptions = {},
@@ -318,6 +350,7 @@ export const jumpHopClient = {
listGallery: listJumpHopGallery,
listWorks: listJumpHopWorks,
publishWork: publishJumpHopWork,
getLeaderboard: getJumpHopLeaderboard,
restartRun: restartJumpHopRuntimeRun,
startRun: startJumpHopRuntimeRun,
submitJump: submitJumpHopJump,