发布资料建议的项目上下文改为脱敏:素材只带文件名
Project CI / AI game creator shell Rust crates (push) Successful in 1m31s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m59s
Project CI / Backend tests (push) Successful in 4m24s
Project CI / Frontend tests (push) Successful in 2m17s
Project CI / Native shell tests (push) Successful in 6m27s
Project CI / AI game creator shell Rust lane 2/2 (push) Successful in 8m56s
Project CI / AI game creator shell Rust lane 1/2 (push) Successful in 9m24s
Project CI / AI game creator shell web tests (push) Has been cancelled
Project CI / Repository checks (push) Has been cancelled
Project CI / AI game creator shell Rust crates (push) Successful in 1m31s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m59s
Project CI / Backend tests (push) Successful in 4m24s
Project CI / Frontend tests (push) Successful in 2m17s
Project CI / Native shell tests (push) Successful in 6m27s
Project CI / AI game creator shell Rust lane 2/2 (push) Successful in 8m56s
Project CI / AI game creator shell Rust lane 1/2 (push) Successful in 9m24s
Project CI / AI game creator shell web tests (push) Has been cancelled
Project CI / Repository checks (push) Has been cancelled
- GameDistributionPublishPanel:buildPublishProjectContext 不再原样拼接 asset.localPath,新增 contextSafeAssetLabel(统一分隔符、取最后一段、限长 80),绝对路径(含用户目录)不再进入提示词;上下文整体仍截到 6,000 字符 - 新增用例「发布资料建议只带脱敏且有界的项目上下文」:40 个绝对路径素材 + 超长版本说明,断言长度在 5,000~6,000、含文件名、不含 C:\Users 与项目目录;13 tests passed - 变异验证:改回 `asset.localPath` 原样拼接后该用例立即以 expected ... to not include 'C:\Users' 变红 - 游戏分发里程碑第 C2 条补记该客户端侧口径与剩余边界(GUI 与真实 Provider 仍待验收)
This commit is contained in:
+14
-1
@@ -96,7 +96,7 @@ function buildPublishProjectContext(manifest: GameCreationAppManifest) {
|
||||
.join('、');
|
||||
const assetSummary = (manifest.assets ?? [])
|
||||
.slice(0, 24)
|
||||
.map((asset) => `${asset.kind}:${asset.localPath}`)
|
||||
.map((asset) => `${asset.kind}:${contextSafeAssetLabel(asset.localPath)}`)
|
||||
.join('、');
|
||||
const versionSummary = (manifest.versions ?? [])
|
||||
.slice(-3)
|
||||
@@ -116,6 +116,19 @@ function buildPublishProjectContext(manifest: GameCreationAppManifest) {
|
||||
.slice(0, 6_000);
|
||||
}
|
||||
|
||||
/**
|
||||
* 送进模型的项目上下文必须脱敏:素材只带文件名,不带目录片段。
|
||||
*
|
||||
* 素材清单里的 `localPath` 正常是项目内相对路径,但登记来源不受本地约束时也可能是
|
||||
* 绝对路径(含盘符或用户目录)——`C:\Users\<用户名>\...\assets\x.png` 这种一旦进提示词
|
||||
* 就等于把本地目录结构发给了平台模型。这里统一取最后一段并限长。
|
||||
*/
|
||||
function contextSafeAssetLabel(value: string) {
|
||||
const normalized = value.trim().replaceAll('\\', '/');
|
||||
const base = normalized.split('/').filter(Boolean).pop() ?? '';
|
||||
return base.slice(0, 80);
|
||||
}
|
||||
|
||||
function buildCoverGenerationPrompt(
|
||||
manifest: GameCreationAppManifest,
|
||||
summary: string,
|
||||
|
||||
@@ -176,6 +176,42 @@ describe('GameDistributionPublishPanel', () => {
|
||||
).not.toBeNull();
|
||||
});
|
||||
|
||||
test('发布资料建议只带脱敏且有界的项目上下文', async () => {
|
||||
const assets = Array.from({ length: 40 }, (_, index) => ({
|
||||
kind: 'image',
|
||||
localPath: `C:\\Users\\author\\secret-project\\assets\\shot-${index}.png`,
|
||||
name: `shot-${index}.png`,
|
||||
}));
|
||||
installTauriInvoke(async () => undefined);
|
||||
renderPanel({
|
||||
manifest: {
|
||||
...MANIFEST,
|
||||
assets,
|
||||
tasks: Array.from({ length: 24 }, (_, index) => ({
|
||||
title: `任务 ${index}`,
|
||||
status: 'completed',
|
||||
})),
|
||||
// 超长版本说明用于验证上下文真的被截到上限,而不是只在短样例里碰巧合规。
|
||||
versions: Array.from({ length: 6 }, () => ({
|
||||
editPrompt: '长'.repeat(3_000),
|
||||
})),
|
||||
} as unknown as GameCreationAppManifest,
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(suggestGameDistributionPublishMetadata).toHaveBeenCalled();
|
||||
});
|
||||
const [request] = vi.mocked(suggestGameDistributionPublishMetadata).mock
|
||||
.calls[0];
|
||||
const context = String(request.context ?? '');
|
||||
expect(context.length).toBeGreaterThanOrEqual(5_000);
|
||||
expect(context.length).toBeLessThanOrEqual(6_000);
|
||||
expect(context).toContain('shot-0.png');
|
||||
// 脱敏:绝对路径里的用户目录与项目目录不得进入提示词。
|
||||
expect(context).not.toContain('C:\\Users');
|
||||
expect(context).not.toContain('secret-project');
|
||||
});
|
||||
|
||||
test('确认后基于项目上下文生成封面并作为发布素材', async () => {
|
||||
vi.mocked(readGameCoverGenerationPrice).mockResolvedValueOnce(5);
|
||||
installTauriInvoke(async () => undefined);
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
### 行为与验收
|
||||
|
||||
- [ ] AGC 从已构建 dist 生成根入口为 `index.html` 的真实包,一次提交动作完成检查、资料确认、上传和送审;状态及失败原因与服务端回读一致。
|
||||
- [ ] AGC 发布面板隐藏发行包技术摘要;打开时基于有界、脱敏的项目上下文免费生成一句话简介与白名单分类,失败保留本地兜底且不阻断发布;作者始终可以直接编辑生成结果。
|
||||
- [ ] AGC 发布面板隐藏发行包技术摘要;打开时基于有界、脱敏的项目上下文免费生成一句话简介与白名单分类,失败保留本地兜底且不阻断发布;作者始终可以直接编辑生成结果。(2026-09-29 补客户端侧口径:「脱敏」此前只在服务端有界——`buildPublishProjectContext()` 会把素材的 `localPath` 原样写进提示词,登记来源不受本地约束时绝对路径(含用户目录)就会外发。现在素材只带**文件名**(`contextSafeAssetLabel` 取最后一段并限长 80),上下文整体仍截到 6,000 字符;`gameDistributionPublishPanel.test.tsx` 新增「发布资料建议只带脱敏且有界的项目上下文」并用 40 个绝对路径素材 + 超长版本说明验证。变异验证:把该处改回 `asset.localPath` 原样拼接后,用例立即以 `expected ... to not include 'C:\Users'` 变红。GUI 打开面板、真实 Provider 生成与失败兜底仍待客户端验收。)
|
||||
- [ ] AGC 发布封面支持基于项目上下文生成,复用现役图片生成与泥点扣费链路;生成结果登记为当前账号平台素材后自动作为 `coverAssetId`,不二次上传。
|
||||
- [x] 网页可选 ZIP、提交封面和必需资料,进入相同上传/校验/审核流程;任一客户端可以查看同账号游戏状态,更新沿用相同 `gameId`。
|
||||
- [x] 上传中断、双击、登录失效、窗口关闭后恢复原操作;换账号不能恢复前账号私有状态;待审不能显示为已发布。
|
||||
|
||||
Reference in New Issue
Block a user