修正GameAgent灵感区数据接入
Project CI / Repository checks (push) Successful in 1m24s
Project CI / Frontend tests (push) Successful in 3m31s
Project CI / Backend tests (push) Successful in 4m22s
Project CI / Native shell tests (push) Successful in 15m18s

保留灵感推荐空态展示

移除主站精选接口与素材类型接入

补充无数据状态回归测试与产品边界文档
This commit is contained in:
2026-08-12 14:17:47 +08:00
parent e3d28c50af
commit 4c3c0e9cd4
5 changed files with 21 additions and 96 deletions
@@ -12,26 +12,6 @@ import { fetchClientHttp } from './clientHttp';
const ACCESS_TOKEN_STORAGE_KEY = 'genarrative.auth.access-token.v1';
export type EditorShowcaseResource = {
resourceId: string;
showcaseId?: string | null;
label?: string | null;
imageSrc: string;
width?: number;
height?: number;
prompt?: string | null;
actualPrompt?: string | null;
assetKind?: string | null;
authorDisplayName?: string | null;
authorPublicUserCode?: string | null;
likeCount?: number | null;
};
type EditorShowcaseResourceListResponse = {
resources: EditorShowcaseResource[];
nextCursor?: string | null;
};
export class ClientAuthRequestError extends Error {
readonly status: number | null;
readonly networkError: boolean;
@@ -159,12 +139,3 @@ export function getClientProfileWalletLedger() {
'读取泥点账单失败',
);
}
export function listClientShowcaseResources() {
return requestClientApi<EditorShowcaseResourceListResponse>(
'/api/editor/showcase/resources',
{ method: 'GET' },
'读取灵感推荐失败',
{ skipAuth: true },
);
}
@@ -21,7 +21,6 @@ import {
type HomeDraft,
useLauncherHomeDraftStore,
} from './useHomeDraftStore';
import { useHomeShowcase } from './useHomeShowcase';
export type {
HomeAgentMode,
@@ -73,8 +72,6 @@ export default function HomeView({
(state) => state.setRichText,
);
const [homeCreationBusy, setHomeCreationBusy] = useState(false);
const { resources: showcaseResources, status: showcaseStatus } =
useHomeShowcase();
const activeHomeMode =
homeAgentModeItems.find((item) => item.mode === homeAgentMode) ??
homeAgentModeItems[0];
@@ -278,38 +275,13 @@ export default function HomeView({
/>
</span>
<p className="mb-0 mt-1 text-[12px] text-(--platform-text-soft)">
{showcaseStatus}
</p>
</div>
</header>
{showcaseResources.length > 0 ? (
<div className="grid grid-cols-6 gap-3 max-[760px]:grid-cols-1">
{showcaseResources.map((resource) => (
<article
className="grid gap-1.75 overflow-hidden rounded-lg border border-(--platform-surface-border) bg-(image:--platform-subpanel-fill) pb-2.5 shadow-(--platform-panel-shadow)"
key={resource.showcaseId ?? resource.resourceId}
>
<img
className="aspect-square w-full object-cover bg-(--platform-warm-bg)"
src={resource.imageSrc}
alt={resource.label || resource.prompt || '灵感素材'}
/>
<strong className="min-w-0 overflow-hidden text-ellipsis whitespace-nowrap px-2.25 text-[12px] text-(--platform-text-strong)">
{resource.label || '未命名素材'}
</strong>
<small className="min-w-0 overflow-hidden text-ellipsis whitespace-nowrap px-2.25 text-[11px] text-(--platform-text-soft)">
{resource.authorDisplayName ||
resource.authorPublicUserCode ||
'陶泥儿精选'}
</small>
</article>
))}
</div>
) : (
<div className="grid min-h-24 place-items-center overflow-hidden rounded-lg border border-(--platform-surface-border) bg-(image:--platform-subpanel-fill) text-[11px] text-(--platform-text-soft)">
{showcaseStatus}
</div>
)}
<div className="grid min-h-24 place-items-center overflow-hidden rounded-lg border border-(--platform-surface-border) bg-(image:--platform-subpanel-fill) text-[11px] text-(--platform-text-soft)">
</div>
</section>
</div>
);
@@ -1,35 +0,0 @@
import { useEffect, useState } from 'react';
import {
type EditorShowcaseResource,
listClientShowcaseResources,
} from '../../services/clientApi';
export function useHomeShowcase() {
const [resources, setResources] = useState<EditorShowcaseResource[]>([]);
const [status, setStatus] = useState('正在读取灵感');
useEffect(() => {
let disposed = false;
void listClientShowcaseResources()
.then((response) => {
if (disposed) {
return;
}
setResources(response.resources.slice(0, 6));
setStatus(response.resources.length > 0 ? '已读取灵感' : '暂无灵感');
})
.catch((error) => {
if (disposed) {
return;
}
setResources([]);
setStatus(error instanceof Error ? error.message : '灵感读取失败');
});
return () => {
disposed = true;
};
}, []);
return { resources, status };
}
@@ -25,6 +25,22 @@ import {
} from './harness';
export function registerClientHomeTests() {
it('keeps the empty inspiration section without reading the main-site showcase', async () => {
const fetchSpy = vi.spyOn(globalThis, 'fetch');
renderLauncherAt('/?launcher');
const inspirationSection = screen.getByLabelText('灵感推荐');
expect(within(inspirationSection).getAllByText('暂无灵感')).toHaveLength(2);
await act(async () => {
await Promise.resolve();
});
expect(
fetchSpy.mock.calls.some(
([input]) => String(input) === '/api/editor/showcase/resources',
),
).toBe(false);
});
it('projects Supervisor manifest updates into the open workbench without reopening the project', async () => {
const projectPath = '/tmp/live-manifest-workbench';
const initialManifest = createGameCreationAppManifest(
@@ -566,6 +566,7 @@ game-project/
- Agent 状态列表从 `.agent/manifest.json` 的任务 / 角色清单、`.agent/run.latest.json` / `.agent/runs/<runId>.json` 的 step、taskGraph、passPlans、lifecycleStatus,以及 `read_game_creator_agent_runtimes` 批量读取的 `.agent/runtime/agents/<taskId>.json` 和最近任务派生;v1 不新增独立状态数据库,也不承诺完整后台 runner。
- App 启动先检查平台登录态;登录后进入同一个客户端首页,不再有面向用户的启动器 / 主窗口切换概念。首页按 `做游戏` / `做素材` / `做方案` 保存 `game` / `art` / `doc` 初始意图,输入状态按文字与附件 token 的顺序保存,附件以文件名 token 内嵌在输入框中而非堆叠在下方;提交时才将 token 转为 LLM 可读的 `{1st attachment}` 引用。发送时弹出原生目录选择,目标目录存在且非空时必须二次确认;确认后调用 `init_local_game_project` 初始化本地项目、`upload_local_asset` 导入附件,再把首条需求直接投递给 active `project-supervisor` Session 的后台 Runtime,写入最近项目并切到项目开发页。缺少 active Session 时先创建并激活;成功后清空首页草稿,取消或创建失败时在首页回显状态,首页响应式断点与应用外壳统一为 `760px`。本流程不调用 `generate_local_game_draft``generate_platform_art_asset`、一次性 `chat_with_game_creator_agent` 或 legacy 项目对话 append。
- 首页发送、项目组目录选择和本地文件选择必须使用 Tauri 非阻塞原生 picker,并把选择器绑定到当前 `client` 窗口;禁止在同步 command 中调用 `blocking_pick_folder` / `blocking_pick_file` 阻塞 WebView 事件循环。选择器打开期间保留首页草稿可编辑,取消后恢复“开启创作”按钮并回显“已取消”。
- 当前尚未定义 GameAgent 独立的灵感数据源;首页保留“灵感推荐”区块并显示无数据状态,但不得展示或请求主站 `/creation` 的陶泥儿精选 `/api/editor/showcase/resources`。后续接入前必须先明确独立数据契约和交互验收。
- debug 构建启动后在用户 `client` 窗口之外额外打开 `developer` 窗口;该窗口用于开发者单独选择 Agent、管理对应 active/archived Session 并读取历史,用户消息和真实 Agent 回复只持久化到 `.agent/conversations/agents/<agentId>/` 下的规范 Session。普通用户窗口不得出现 `Agent 聊天` 导航、picker 或工具台入口。
- 首页最近项目只展示最近 3 个有效项目;项目组页在同一窗口管理最近项目、打开项目、新建项目和显示目录。打开项目只读取已初始化项目并切到项目开发页,不打开第二窗口;新建项目仍沿用非空目录确认,不自动重建无效历史路径。
- 项目开发页保留左侧栏和顶部栏,顶部展示项目名、路径和最近 run 状态;中间只挂载 active `project-supervisor` Session 的正式对话面、Runtime 状态、确认/Needs input 和专业 Agent 协作只读状态,底部保留附件导入结果。真正的项目开发画布仍未落地;专业 Agent picker、完整计划和工具台继续留在开发入口。