diff --git a/apps/ai-game-creator-shell/src/services/gameDistributionPublish.ts b/apps/ai-game-creator-shell/src/services/gameDistributionPublish.ts index b5b5a5cfc..76c1f62ae 100644 --- a/apps/ai-game-creator-shell/src/services/gameDistributionPublish.ts +++ b/apps/ai-game-creator-shell/src/services/gameDistributionPublish.ts @@ -162,7 +162,7 @@ export type GameDistributionPublicationReadResult = * 发布面板打开时由原生恢复本地绑定与线上作品状态。 * * 原生按当前会话(账号 + origin)隔离绑定:切换账号/环境后不会接管他人作品;无本地绑定时 - * 按作者作品的 `localProjectId` 精确匹配做一次性恢复。网络/401/5xx 返回 `unavailable`, + * 按作者作品的 `projectKey` 精确匹配做一次性恢复。网络/401/5xx 返回 `unavailable`, * 调用方不得据此按首次发布继续。 */ export async function readGameDistributionPublication( @@ -235,10 +235,10 @@ function normalizeMetadata( function toCreateGameRequest( metadata: GameDistributionPublishMetadata, - localProjectId: string, + projectKey: string, ): GameDistributionCreateGameRequest { return { - localProjectId, + projectKey, title: metadata.title, summary: metadata.summary, description: metadata.description, @@ -305,8 +305,8 @@ export async function publishLocalProjectGame(args: { throw new Error('发布需要绑定本地项目'); } const metadata = normalizeMetadata(args.manifest, args.metadata); - const localProjectId = args.manifest.projectId.trim(); - if (!localProjectId) { + const projectKey = args.manifest.projectId.trim(); + if (!projectKey) { throw new Error('发布需要本地项目标识,请重新打开项目后再试'); } const gameId = args.gameId?.trim() ?? ''; @@ -334,7 +334,7 @@ export async function publishLocalProjectGame(args: { ) { throw new Error('缺少公开修订号,请重新打开发布面板后再试'); } - const gameMetadata = toCreateGameRequest(metadata, localProjectId); + const gameMetadata = toCreateGameRequest(metadata, projectKey); const rootKey = args.idempotencyKey?.trim() ?? ''; // 发布编排、认证、origin、分片续传与送审都在 Rust 完成;渲染进程只传递 // 已归一化的资料、面板给出的本地媒体路径、项目版本和本地项目标识,不接触 token、 diff --git a/apps/ai-game-creator-shell/tests/gameDistributionPublish.test.ts b/apps/ai-game-creator-shell/tests/gameDistributionPublish.test.ts index 6d1cc59fe..87164c5c5 100644 --- a/apps/ai-game-creator-shell/tests/gameDistributionPublish.test.ts +++ b/apps/ai-game-creator-shell/tests/gameDistributionPublish.test.ts @@ -86,7 +86,7 @@ describe('Rust 发布 facade', () => { coverPath: '', screenshotPaths: [], metadata: { - localProjectId: 'local-proj-1', + projectKey: 'local-proj-1', coverObjectKey: 'generated/cover.png', screenshots: ['generated/shot-1.png', 'generated/shot-2.png'], }, @@ -138,7 +138,7 @@ describe('Rust 发布 facade', () => { expect(calls[0]?.args).not.toHaveProperty('idempotencyKey'); expect(calls[0]?.args).toMatchObject({ projectPath: '/tmp/project', - metadata: { localProjectId: 'local-proj-1' }, + metadata: { projectKey: 'local-proj-1' }, }); }); diff --git a/apps/ai-game-creator-shell/tests/gameDistributionPublishLive.test.ts b/apps/ai-game-creator-shell/tests/gameDistributionPublishLive.test.ts index 1e4f61a3b..3c6c9edd8 100644 --- a/apps/ai-game-creator-shell/tests/gameDistributionPublishLive.test.ts +++ b/apps/ai-game-creator-shell/tests/gameDistributionPublishLive.test.ts @@ -7,7 +7,7 @@ * npx vitest run apps/ai-game-creator-shell/tests/gameDistributionPublishLive.test.ts * * 开启后测试会注册一个临时作者,并通过真实 HTTP(而不是 mock 请求层)验证 - * AGC 发布 facade 的请求合同,覆盖:创建游戏、同 `localProjectId` 复用游戏身份、 + * AGC 发布 facade 的请求合同,覆盖:创建游戏、同 `projectKey` 复用游戏身份、 * 真实分片上传、送审与版本回读。jsdom 只替代 Tauri command 的原生执行。 * * jsdom 里没有 Tauri 运行时,`upload_local_project_game_package` 由本测试按服务端 @@ -237,17 +237,17 @@ async function buildStagedPackage(): Promise<{ function createPublishAttemptLedger() { const attempts = new Map(); return { - resolve(localProjectId: string, packageSha256: string): string { - const key = `${localProjectId}:${packageSha256}`; + resolve(projectKey: string, packageSha256: string): string { + const key = `${projectKey}:${packageSha256}`; const existing = attempts.get(key); if (existing) return existing; const rootKey = `agc-publish-live-${randomUUID()}`; attempts.set(key, rootKey); return rootKey; }, - clear(localProjectId: string): void { + clear(projectKey: string): void { for (const key of [...attempts.keys()]) { - if (key.startsWith(`${localProjectId}:`)) attempts.delete(key); + if (key.startsWith(`${projectKey}:`)) attempts.delete(key); } }, }; @@ -435,7 +435,7 @@ liveTest( const rootKey = explicitKey || attempts.resolve( - String(metadata.localProjectId), + String(metadata.projectKey), staged.packageSha256, ); // 更新模式:带原 gameId 时跳过 create game,直接在原游戏上创建新版本。 @@ -483,7 +483,7 @@ liveTest( // 创建版本:整份版本声明放在 `metadata` 文本 part,封面字节随 `cover` part 重传; // 同样走被 stub 的全局 `fetch`,由桥生成 multipart boundary。 const versionRequest = { - localProjectId: metadata.localProjectId, + projectKey: metadata.projectKey, packageSha256: staged.packageSha256, packageBytes: staged.packageSizeBytes, packageFileCount: staged.packageFileCount, @@ -538,7 +538,7 @@ liveTest( ), ); // 送审成功即服务端收口:原生账本同样在这里清除本次尝试。 - attempts.clear(String(metadata.localProjectId)); + attempts.clear(String(metadata.projectKey)); return { gameId: game.id, versionId: version.versionId, @@ -624,7 +624,7 @@ liveTest( expect(readResult.version.frozenMetadata?.screenshots).toEqual([]); // 第二次发布:上一次已在送审成功时收口,账本清除,因此这里换新键——同 - // localProjectId 必须复用同一 gameId 并新增版本。 + // projectKey 必须复用同一 gameId 并新增版本。 const second = await publishLocalProjectGame({ invoke, projectPath: '/data/dsk/Genarrative/tmp-agc-live-project',