Merge branch 'master' of http://82.157.175.59:3000/GenarrativeAI/Genarrative
Some checks failed
CI / verify (push) Has been cancelled
Some checks failed
CI / verify (push) Has been cancelled
This commit is contained in:
29
src/services/big-fish-gallery/bigFishGalleryClient.ts
Normal file
29
src/services/big-fish-gallery/bigFishGalleryClient.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import type { BigFishWorksResponse } from '../../../packages/shared/src/contracts/bigFishWorkSummary';
|
||||
import { type ApiRetryOptions, requestJson } from '../apiClient';
|
||||
|
||||
const BIG_FISH_GALLERY_API_BASE = '/api/runtime/big-fish/gallery';
|
||||
const BIG_FISH_GALLERY_READ_RETRY: ApiRetryOptions = {
|
||||
maxRetries: 1,
|
||||
baseDelayMs: 120,
|
||||
maxDelayMs: 360,
|
||||
};
|
||||
|
||||
/**
|
||||
* 读取大鱼吃小鱼公开广场列表。
|
||||
*/
|
||||
export async function listBigFishGallery() {
|
||||
return requestJson<BigFishWorksResponse>(
|
||||
BIG_FISH_GALLERY_API_BASE,
|
||||
{
|
||||
method: 'GET',
|
||||
},
|
||||
'读取大鱼吃小鱼广场失败',
|
||||
{
|
||||
retry: BIG_FISH_GALLERY_READ_RETRY,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export const bigFishGalleryClient = {
|
||||
list: listBigFishGallery,
|
||||
};
|
||||
4
src/services/big-fish-gallery/index.ts
Normal file
4
src/services/big-fish-gallery/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export {
|
||||
bigFishGalleryClient,
|
||||
listBigFishGallery,
|
||||
} from './bigFishGalleryClient';
|
||||
@@ -3,6 +3,7 @@ import { expect, test } from 'vitest';
|
||||
import {
|
||||
clearCustomWorldAgentUiState,
|
||||
readCustomWorldAgentUiState,
|
||||
shouldRestoreCustomWorldAgentUiState,
|
||||
writeCustomWorldAgentUiState,
|
||||
} from './customWorldAgentUiState';
|
||||
|
||||
@@ -73,3 +74,49 @@ test('custom world agent ui state reads from query first and persists to session
|
||||
clearCustomWorldAgentUiState(env);
|
||||
expect(readCustomWorldAgentUiState(env)).toEqual({});
|
||||
});
|
||||
|
||||
test('custom world agent ui state only auto restores stored pointers on RPG creation paths', () => {
|
||||
const sessionStorage = createMemoryStorage();
|
||||
sessionStorage.setItem(
|
||||
'genarrative.custom-world-agent-ui.v1',
|
||||
JSON.stringify({
|
||||
activeSessionId: 'session-1',
|
||||
ownerUserId: 'user-1',
|
||||
}),
|
||||
);
|
||||
|
||||
expect(
|
||||
shouldRestoreCustomWorldAgentUiState({
|
||||
location: {
|
||||
pathname: '/',
|
||||
search: '',
|
||||
},
|
||||
history: null,
|
||||
sessionStorage,
|
||||
}),
|
||||
).toBe(false);
|
||||
|
||||
expect(
|
||||
shouldRestoreCustomWorldAgentUiState({
|
||||
location: {
|
||||
pathname: '/creation/rpg/agent',
|
||||
search: '',
|
||||
},
|
||||
history: null,
|
||||
sessionStorage,
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test('custom world agent ui state restores explicit query pointers on any main path', () => {
|
||||
expect(
|
||||
shouldRestoreCustomWorldAgentUiState({
|
||||
location: {
|
||||
pathname: '/',
|
||||
search: '?customWorldSessionId=session-1',
|
||||
},
|
||||
history: null,
|
||||
sessionStorage: createMemoryStorage(),
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
@@ -56,6 +56,49 @@ function normalizeGenerationSource(value: unknown) {
|
||||
return value === 'agent-draft-foundation' ? value : null;
|
||||
}
|
||||
|
||||
function hasExplicitAgentUiStateQuery(
|
||||
params: URLSearchParams,
|
||||
) {
|
||||
return (
|
||||
params.has(CUSTOM_WORLD_AGENT_SESSION_QUERY_KEY) ||
|
||||
params.has(CUSTOM_WORLD_AGENT_OPERATION_QUERY_KEY) ||
|
||||
params.has(CUSTOM_WORLD_GENERATION_SOURCE_QUERY_KEY)
|
||||
);
|
||||
}
|
||||
|
||||
function normalizePathname(value: string | undefined) {
|
||||
const pathname = value?.trim().toLowerCase() ?? '';
|
||||
if (!pathname || pathname === '/') {
|
||||
return '/';
|
||||
}
|
||||
|
||||
return pathname.replace(/\/+$/u, '');
|
||||
}
|
||||
|
||||
function isRpgCreationRestorePath(pathname: string | undefined) {
|
||||
const normalizedPathname = normalizePathname(pathname);
|
||||
return (
|
||||
normalizedPathname === '/creation/rpg' ||
|
||||
normalizedPathname.startsWith('/creation/rpg/')
|
||||
);
|
||||
}
|
||||
|
||||
export function shouldRestoreCustomWorldAgentUiState(
|
||||
env?: CustomWorldAgentUiEnvironment,
|
||||
) {
|
||||
const resolved = resolveEnvironment(env);
|
||||
const params = new URLSearchParams(resolved.location?.search ?? '');
|
||||
|
||||
// URL 显式恢复参数优先于当前路径,用于支持外部分享或登录回跳后的深链恢复。
|
||||
if (hasExplicitAgentUiStateQuery(params)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// sessionStorage 里的残留指针只能在 RPG 创作页面生效,
|
||||
// 避免刷新平台首页时被旧工作区状态强制带到 Agent 页面。
|
||||
return isRpgCreationRestorePath(resolved.location?.pathname);
|
||||
}
|
||||
|
||||
export function readCustomWorldAgentUiState(
|
||||
env?: CustomWorldAgentUiEnvironment,
|
||||
): CustomWorldAgentUiState {
|
||||
|
||||
@@ -13,6 +13,14 @@ export function buildPuzzlePublicWorkCode(profileId: string) {
|
||||
return `PZ-${suffix}`;
|
||||
}
|
||||
|
||||
export function buildBigFishPublicWorkCode(sessionId: string) {
|
||||
const normalized = normalizePublicCodeText(sessionId);
|
||||
const fallback = normalized || '00000000';
|
||||
const suffix = fallback.slice(-8).padStart(8, '0');
|
||||
|
||||
return `BF-${suffix}`;
|
||||
}
|
||||
|
||||
export function isSamePuzzlePublicWorkCode(keyword: string, profileId: string) {
|
||||
const normalizedKeyword = normalizePublicCodeText(keyword);
|
||||
|
||||
@@ -22,3 +30,16 @@ export function isSamePuzzlePublicWorkCode(keyword: string, profileId: string) {
|
||||
normalizedKeyword === normalizePublicCodeText(profileId)
|
||||
);
|
||||
}
|
||||
|
||||
export function isSameBigFishPublicWorkCode(
|
||||
keyword: string,
|
||||
sessionId: string,
|
||||
) {
|
||||
const normalizedKeyword = normalizePublicCodeText(keyword);
|
||||
|
||||
return (
|
||||
normalizedKeyword ===
|
||||
normalizePublicCodeText(buildBigFishPublicWorkCode(sessionId)) ||
|
||||
normalizedKeyword === normalizePublicCodeText(sessionId)
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user