diff --git a/apps/ai-game-creator-shell/src/app/appMetadata.ts b/apps/ai-game-creator-shell/src/app/appMetadata.ts new file mode 100644 index 000000000..8ba27e8e9 --- /dev/null +++ b/apps/ai-game-creator-shell/src/app/appMetadata.ts @@ -0,0 +1,5 @@ +import appPackage from '../../package.json'; + +/** Product metadata shared by the client UI and release bundle. */ +export const APP_NAME = 'Genarrative AI Game Creator'; +export const APP_VERSION = appPackage.version; diff --git a/apps/ai-game-creator-shell/src/features/runtime-config/RuntimeConfigDialog.tsx b/apps/ai-game-creator-shell/src/features/runtime-config/RuntimeConfigDialog.tsx index 320b5acc8..386c6d2cf 100644 --- a/apps/ai-game-creator-shell/src/features/runtime-config/RuntimeConfigDialog.tsx +++ b/apps/ai-game-creator-shell/src/features/runtime-config/RuntimeConfigDialog.tsx @@ -3,6 +3,7 @@ import { Cable, CheckCircle2, CircleAlert, + Info, LoaderCircle, RotateCcw, Save, @@ -13,6 +14,8 @@ import { import { type FormEvent, useEffect, useRef, useState } from 'react'; import { createGameCreationAppSeedTasks } from '../../../../../packages/shared/src/contracts/gameCreationApp'; +import BRAND_ICON from '../../../../../packages/shared/src/icons/taonier-product-ip.png'; +import { APP_NAME, APP_VERSION } from '../../app/appMetadata'; import { closeDialogOnBackdropMouseDown, closeDialogOnEscape, @@ -79,7 +82,12 @@ const defaultRuntimeConfigDraft: GameCreatorAppConfig = { }, }; -type RuntimeSettingsSection = 'general' | 'agents' | 'connections' | 'advanced'; +type RuntimeSettingsSection = + | 'general' + | 'agents' + | 'connections' + | 'advanced' + | 'about'; type RuntimeConfigToast = { tone: 'success' | 'error'; @@ -111,6 +119,12 @@ const runtimeSettingsSections = [ description: '上下文、超时与重试', icon: SlidersHorizontal, }, + { + id: 'about', + label: '关于', + description: '客户端信息', + icon: Info, + }, ] as const satisfies ReadonlyArray<{ id: RuntimeSettingsSection; label: string; @@ -1258,6 +1272,44 @@ export function RuntimeConfigDialog({ ) : null} ) : null} + {activeSection === 'about' ? ( +
+
+ +
+ + GENARRATIVE + +

{APP_NAME}

+

面向游戏创作者的智能创作客户端

+
+
+
+
+
客户端版本
+
+ v{APP_VERSION} +
+
+
+
运行环境
+
桌面客户端
+
+
+
+ ) : null} diff --git a/apps/ai-game-creator-shell/src/styles.css b/apps/ai-game-creator-shell/src/styles.css index cad79fb6d..cd7f24a7f 100644 --- a/apps/ai-game-creator-shell/src/styles.css +++ b/apps/ai-game-creator-shell/src/styles.css @@ -3212,6 +3212,101 @@ h2 { box-shadow: 0 0 0 3px var(--platform-input-focus-ring); } +.runtime-settings-about { + grid-column: 1 / -1; + display: grid; + gap: 14px; + max-width: 680px; +} + +.runtime-settings-about-hero { + display: flex; + align-items: center; + gap: 18px; + min-height: 158px; + padding: 24px; + border: 1px solid var(--platform-subpanel-border); + border-radius: 16px; + background: var(--runtime-settings-subpanel-fill); +} + +.runtime-settings-about-mark { + display: grid; + flex: 0 0 auto; + width: 72px; + height: 72px; + border: 1px solid var(--platform-nav-active-border); + border-radius: 20px; + background: var(--platform-nav-active-fill); + color: var(--platform-accent); + font-size: 32px; + font-weight: 900; + letter-spacing: -0.08em; + place-items: center; + box-shadow: var(--platform-nav-active-shadow); +} + +.runtime-settings-about-mark img { + width: 100%; + height: 100%; + object-fit: contain; + transform: scale(1.35); +} + +.runtime-settings-about-hero > div:last-child { + display: grid; + gap: 5px; + min-width: 0; +} + +.runtime-settings-about-kicker { + color: var(--platform-accent); + font-size: 10px; + font-weight: 900; + letter-spacing: 0.16em; +} + +.runtime-settings-about-hero h4 { + margin: 0; + color: var(--platform-text-strong); + font-size: 20px; + letter-spacing: -0.03em; +} + +.runtime-settings-about-hero p { + margin: 0; + color: var(--platform-text-soft); + font-size: 12px; +} + +.runtime-settings-about-meta { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 10px; + margin: 0; +} + +.runtime-settings-about-meta > div { + display: grid; + gap: 7px; + padding: 14px; + border: 1px solid var(--platform-subpanel-border); + border-radius: 12px; + background: var(--runtime-settings-subpanel-fill); +} + +.runtime-settings-about-meta dt { + color: var(--platform-text-soft); + font-size: 10px; +} + +.runtime-settings-about-meta dd { + margin: 0; + color: var(--platform-text-strong); + font-size: 14px; + font-weight: 800; +} + .runtime-agent-list { grid-column: 1 / -1; display: grid; @@ -4034,6 +4129,16 @@ iframe.preview-frame { grid-template-columns: 1fr; } + .runtime-settings-about-hero { + align-items: flex-start; + flex-direction: column; + min-height: 0; + } + + .runtime-settings-about-meta { + grid-template-columns: 1fr; + } + .runtime-agent-card-summary > span:last-child { max-width: 48%; text-align: right; diff --git a/apps/ai-game-creator-shell/src/view/home/InspirationGallery.tsx b/apps/ai-game-creator-shell/src/view/home/InspirationGallery.tsx new file mode 100644 index 000000000..dc15824e9 --- /dev/null +++ b/apps/ai-game-creator-shell/src/view/home/InspirationGallery.tsx @@ -0,0 +1,81 @@ +import { useEffect, useState } from 'react'; +import { createPortal } from 'react-dom'; + +// TODO: 后续改为由服务器下发灵感资源;届时保留此组件的展示与预览交互,移除本地目录扫描。 +const INSPIRATION_IMAGES = Object.entries( + import.meta.glob('./assets/inspiration/*.{webp,png,jpg,jpeg}', { + eager: true, + import: 'default', + query: '?url', + }), +) + .sort(([left], [right]) => + left.localeCompare(right, undefined, { numeric: true }), + ) + .map(([, image]) => image as string); + +export default function InspirationGallery() { + const [selectedImage, setSelectedImage] = useState(null); + + useEffect(() => { + if (!selectedImage) { + return; + } + const previousOverflow = document.body.style.overflow; + document.body.style.overflow = 'hidden'; + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === 'Escape') { + setSelectedImage(null); + } + }; + window.addEventListener('keydown', handleKeyDown); + return () => { + document.body.style.overflow = previousOverflow; + window.removeEventListener('keydown', handleKeyDown); + }; + }, [selectedImage]); + + return ( + <> +
+ {INSPIRATION_IMAGES.map((image, index) => ( + + ))} +
+ + {selectedImage + ? createPortal( +
setSelectedImage(null)} + > + 放大的灵感图片 event.stopPropagation()} + /> +
, + document.body, + ) + : null} + + ); +} diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-01.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-01.webp new file mode 100644 index 000000000..25821e804 Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-01.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-02.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-02.webp new file mode 100644 index 000000000..ce26591db Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-02.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-03.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-03.webp new file mode 100644 index 000000000..90287a674 Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-03.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-04.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-04.webp new file mode 100644 index 000000000..8fa04357a Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-04.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-05.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-05.webp new file mode 100644 index 000000000..cc657f1ef Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-05.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-06.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-06.webp new file mode 100644 index 000000000..bf922e8d3 Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-06.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-07.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-07.webp new file mode 100644 index 000000000..67048cfb9 Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-07.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-08.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-08.webp new file mode 100644 index 000000000..13f642612 Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-08.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-09.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-09.webp new file mode 100644 index 000000000..d98a01ec7 Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-09.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-10.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-10.webp new file mode 100644 index 000000000..4ed427e84 Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-10.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-11.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-11.webp new file mode 100644 index 000000000..b147b8ff7 Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-11.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-12.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-12.webp new file mode 100644 index 000000000..084ed36bb Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-12.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-13.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-13.webp new file mode 100644 index 000000000..7da22fa4f Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-13.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-14.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-14.webp new file mode 100644 index 000000000..88dcc70cb Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-14.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-15.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-15.webp new file mode 100644 index 000000000..13315c560 Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-15.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-16.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-16.webp new file mode 100644 index 000000000..4af52bbda Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-16.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-17.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-17.webp new file mode 100644 index 000000000..87c1ebe09 Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-17.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-18.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-18.webp new file mode 100644 index 000000000..cc4bcb6c5 Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-18.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-19.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-19.webp new file mode 100644 index 000000000..413fff72b Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-19.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-20.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-20.webp new file mode 100644 index 000000000..b55594bba Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-20.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-21.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-21.webp new file mode 100644 index 000000000..31db46017 Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-21.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-22.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-22.webp new file mode 100644 index 000000000..5d2e1fa4e Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-22.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-23.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-23.webp new file mode 100644 index 000000000..f34cd2398 Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-23.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-24.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-24.webp new file mode 100644 index 000000000..b23f5e8d1 Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-24.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-25.webp b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-25.webp new file mode 100644 index 000000000..e008db1fc Binary files /dev/null and b/apps/ai-game-creator-shell/src/view/home/assets/inspiration/inspiration-25.webp differ diff --git a/apps/ai-game-creator-shell/src/view/home/index.tsx b/apps/ai-game-creator-shell/src/view/home/index.tsx index 8d077a76e..b76dfec30 100644 --- a/apps/ai-game-creator-shell/src/view/home/index.tsx +++ b/apps/ai-game-creator-shell/src/view/home/index.tsx @@ -18,6 +18,7 @@ import { richTextToAttachments, richTextToPrompt, } from './components/RichInputArea/richTextToPrompt'; +import InspirationGallery from './InspirationGallery'; import { type HomeCreationType, type HomeDraft, @@ -171,7 +172,11 @@ export default function HomeView({ } return ( -
+
-
+
); diff --git a/apps/ai-game-creator-shell/tests/appSurface/home.suite.ts b/apps/ai-game-creator-shell/tests/appSurface/home.suite.ts index e6ccb2fd3..6be9b73a8 100644 --- a/apps/ai-game-creator-shell/tests/appSurface/home.suite.ts +++ b/apps/ai-game-creator-shell/tests/appSurface/home.suite.ts @@ -28,12 +28,25 @@ import { } from './harness'; export function registerClientHomeTests() { - it('keeps the empty inspiration module without requesting the retired feed', async () => { + it('shows the built-in inspiration masonry gallery and opens a dismissible preview without requesting the retired feed', async () => { const fetchSpy = vi.spyOn(globalThis, 'fetch'); renderLauncherAt('/?launcher'); - expect(screen.getByLabelText('灵感推荐')).not.toBeNull(); + const inspiration = screen.getByLabelText('灵感推荐'); + const inspirationImages = within(inspiration).getAllByRole('button', { + name: /查看灵感图片/, + }); + expect(inspirationImages).toHaveLength(23); + expect(inspiration.closest('.overflow-y-auto')).not.toBeNull(); expect(screen.queryByText('暂无灵感')).toBeNull(); + + fireEvent.click(inspirationImages[0]!); + const preview = screen.getByRole('dialog', { name: '查看灵感图片' }); + fireEvent.click(screen.getByAltText('放大的灵感图片')); + expect(screen.getByRole('dialog', { name: '查看灵感图片' })).not.toBeNull(); + fireEvent.click(preview); + expect(screen.queryByRole('dialog', { name: '查看灵感图片' })).toBeNull(); + await act(async () => { await Promise.resolve(); }); diff --git a/apps/ai-game-creator-shell/tests/appSurface/runtime-settings.suite.ts b/apps/ai-game-creator-shell/tests/appSurface/runtime-settings.suite.ts index e013037c3..9916904e2 100644 --- a/apps/ai-game-creator-shell/tests/appSurface/runtime-settings.suite.ts +++ b/apps/ai-game-creator-shell/tests/appSurface/runtime-settings.suite.ts @@ -1,3 +1,4 @@ +import { APP_VERSION } from '../../src/app/appMetadata'; import { act, createGameCreationAppManifest, @@ -234,6 +235,58 @@ export function registerAgentStatusDerivationTests() { } export function registerRuntimeSettingsTests() { + it('shows the client version on the About settings page', async () => { + const invoke = vi.fn(async (command: string) => { + if (command === 'read_game_creator_app_config') { + return { + path: '/home/test/AppData/game-creator.config.json', + config: { + agentMode: 'codex_app_server', + llm: { + apiKey: '', + baseUrl: 'https://llm.example.test/v1', + model: 'gpt-about', + apiKind: 'openai_responses', + reasoningEffort: 'high', + stream: true, + webSearchEnabled: false, + contextWindowTokens: 128000, + autoCompactTokenLimit: 64000, + toolOutputTokenLimit: 12000, + requestTimeoutMs: 180000, + maxRetries: 2, + retryBackoffMs: 500, + }, + agentLlm: {}, + editorApi: { + baseUrl: 'http://127.0.0.1:8082', + apiKey: '', + }, + }, + }; + } + throw new Error(`unexpected invoke ${command}`); + }); + window.__TAURI__ = { core: { invoke } }; + renderLauncherAt('/?launcher'); + + fireEvent.click(screen.getByRole('button', { name: '配置' })); + expect( + await screen.findByRole('dialog', { name: '运行时配置' }), + ).not.toBeNull(); + + fireEvent.click(screen.getByRole('button', { name: /关于/ })); + + expect(screen.getByText('Genarrative AI Game Creator')).not.toBeNull(); + expect( + screen.getByTestId('runtime-settings-app-logo').getAttribute('src'), + ).toContain('taonier-product-ip.png'); + expect(screen.getByTestId('runtime-settings-app-version').textContent).toBe( + `v${APP_VERSION}`, + ); + expect(screen.getByText('桌面客户端')).not.toBeNull(); + }); + it('keeps the Agent mode fixed to app-server and preserves its LLM config', async () => { const invoke = vi.fn( async (command: string, args?: Record) => { diff --git a/apps/ai-game-creator-shell/tsconfig.json b/apps/ai-game-creator-shell/tsconfig.json index b0cd676a5..894821755 100644 --- a/apps/ai-game-creator-shell/tsconfig.json +++ b/apps/ai-game-creator-shell/tsconfig.json @@ -6,6 +6,7 @@ "lib": ["ES2022", "DOM", "DOM.Iterable"], "skipLibCheck": true, "moduleResolution": "bundler", + "resolveJsonModule": true, "isolatedModules": true, "moduleDetection": "force", "allowJs": false, diff --git a/docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md b/docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md index 8beef2c9a..f6ef11e15 100644 --- a/docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md +++ b/docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md @@ -137,7 +137,7 @@ Supervisor 认领该回执后,由父 run 自己为每个原 delivery 逐一创 ## 目标 -在 Genarrative 内建设独立桌面 App:普通用户通过项目开发工作台中的陶泥儿对话、资源画布、运行状态和确认操作,让平台生成保存在本地的可运行 Web 游戏原型,并通过本地 HTTP server 预览;主窗口提供运行时配置入口,用于保存发布版 AppData / Tauri 配置目录里的 LLM 配置及受控开发者 External Editor 配置。普通客户素材画布使用平台登录态调用内部编辑器 API,不展示或要求填写画板 Base URL / API Key。任务明细、原始文件、命令日志和专业 Agent 调试控制只通过显式开发调试入口查看,不随普通客户端启动额外打开窗口。v1 的生成闭环仍以 Web 小游戏为主,同时允许用户打开已有 Godot 项目:用户选择的目录始终作为工作区根,`.agent/`、Session、Runtime、文件工具和外围资料都留在该根;客户端检查根目录及一层直接子目录中的普通文件 `project.godot`,将唯一命中的实际目录以工作区相对 `godotProjectRoot` 记录到 manifest。Agent 使用标准运行档继续修改,不创建 `game/`、`assets/`、`memory/`、`exports/` 平行目录;本期不扩展 Unity、Godot 内嵌预览、云同步或插件市场。 +在 Genarrative 内建设独立桌面 App:普通用户通过项目开发工作台中的陶泥儿对话、资源画布、运行状态和确认操作,让平台生成保存在本地的可运行 Web 游戏原型,并通过本地 HTTP server 预览;主窗口提供运行时配置入口,用于保存发布版 AppData / Tauri 配置目录里的 LLM 配置及受控开发者 External Editor 配置,设置弹窗同时提供独立“关于”页并显示从客户端构建版本注入的版本号。普通客户素材画布使用平台登录态调用内部编辑器 API,不展示或要求填写画板 Base URL / API Key。任务明细、原始文件、命令日志和专业 Agent 调试控制只通过显式开发调试入口查看,不随普通客户端启动额外打开窗口。v1 的生成闭环仍以 Web 小游戏为主,同时允许用户打开已有 Godot 项目:用户选择的目录始终作为工作区根,`.agent/`、Session、Runtime、文件工具和外围资料都留在该根;客户端检查根目录及一层直接子目录中的普通文件 `project.godot`,将唯一命中的实际目录以工作区相对 `godotProjectRoot` 记录到 manifest。Agent 使用标准运行档继续修改,不创建 `game/`、`assets/`、`memory/`、`exports/` 平行目录;本期不扩展 Unity、Godot 内嵌预览、云同步或插件市场。 ## 技术选择 @@ -683,7 +683,7 @@ game-project/ - 结构化对话记录按授权本地项目路径追加 JSONL;正式聊天读取 Supervisor active Session 与只读 legacy 项目历史,开发单 Agent 对话读取对应 Agent Session。开发入口已支持本地 Session 新建、切换、归档和分叉,但不提供云端同步。 - Agent 状态列表从 `.agent/manifest.json` 的任务 / 角色清单、`.agent/run.latest.json` / `.agent/runs/.json` 的 step、taskGraph、passPlans、lifecycleStatus,以及 `read_game_creator_agent_runtimes` 批量读取的 `.agent/runtime/agents/.json` 和最近任务派生;v1 不新增独立状态数据库,也不承诺完整后台 runner。 - 首页发送、项目组目录选择和本地文件选择必须使用 Tauri 非阻塞原生 picker,并把选择器绑定到当前 `client` 窗口;禁止在同步 command 中调用 `blocking_pick_folder` / `blocking_pick_file` 阻塞 WebView 事件循环。选择器打开期间保留首页草稿可编辑,取消后恢复“开启创作”按钮并回显“已取消”。 -- 当前尚未定义 GameAgent 独立的灵感数据源;首页保留“灵感推荐”模块及空白内容容器,但不显示无数据文案,也不得展示或请求主站 `/creation` 的陶泥儿精选 `/api/editor/showcase/resources`。后续接入前必须先明确独立数据契约和交互验收。 +- GameAgent 首页“灵感推荐”当前使用客户端随包发布的内置图片素材,不请求主站 `/creation` 的陶泥儿精选 `/api/editor/showcase/resources`,也不引入远端灵感数据源。图片按原始宽高比组成响应式瀑布流,首页内容区域允许纵向滚动;点击图片只打开全屏原图预览,点击图片外遮罩或按 Escape 关闭,不展示标题或其它业务动作。后续改接远端数据前仍须先明确独立数据契约和交互验收。 - 首页正式桌面版以约 `814px` 的居中内容栏组织品牌区、创作类型、输入框、最近项目与灵感推荐;品牌区和类型按钮在内容栏左缘对齐,输入框和下方模块仍保持整体居中。标题使用深色暖橙层级,固定副标题为“你的游戏创作管家”;选中的创作类型使用实心暖橙按钮,未选中项使用浅色描边,输入框使用更舒展的单行创作起始比例。 - 最近项目固定展示至多三个横向信息卡:左侧为本地渐变封面占位,右侧只投影项目名称、项目类型、目录真实修改时间和已有最近运行状态。目录检查通过 `modifiedAt` 提供修改时间;没有封面资产时不得假装读取了项目封面,也不新增封面持久化字段。 - debug 构建启动后在用户 `client` 窗口之外额外打开 `developer` 窗口;该窗口用于开发者单独选择 Agent、管理对应 active/archived Session 并读取历史,用户消息和真实 Agent 回复只持久化到 `.agent/conversations/agents//` 下的规范 Session。普通用户窗口不得出现 `Agent 聊天` 导航、picker 或工具台入口。