diff --git a/apps/ai-game-creator-shell/scripts/check-config.mjs b/apps/ai-game-creator-shell/scripts/check-config.mjs index 3c333133f..e32dfb4b7 100644 --- a/apps/ai-game-creator-shell/scripts/check-config.mjs +++ b/apps/ai-game-creator-shell/scripts/check-config.mjs @@ -1295,7 +1295,7 @@ for (const requiredSource of [ } } -if (tauriConfig.productName !== 'Genarrative AI Game Creator') { +if (tauriConfig.productName !== '陶泥儿') { throw new Error('AI game creator shell productName drifted'); } @@ -1307,19 +1307,19 @@ const expectedBundledDesignAgentResources = { 'design-agent': 'design-agent', }; const expectedBundledWindowsResources = { - 'resources/codex/win-x64/bin/codex.exe': 'codex/win-x64/bin/codex.exe', + 'resources/codex/win-x64/bin/codex.exe': 'coding-agent/win-x64/bin/codex.exe', 'resources/codex/win-x64/bin/codex-code-mode-host.exe': - 'codex/win-x64/bin/codex-code-mode-host.exe', + 'coding-agent/win-x64/bin/codex-code-mode-host.exe', 'resources/codex/win-x64/codex-path/rg.exe': - 'codex/win-x64/codex-path/rg.exe', + 'coding-agent/win-x64/codex-path/rg.exe', 'resources/codex/win-x64/codex-resources/codex-command-runner.exe': - 'codex/win-x64/codex-resources/codex-command-runner.exe', + 'coding-agent/win-x64/codex-resources/codex-command-runner.exe', 'resources/codex/win-x64/codex-resources/codex-windows-sandbox-setup.exe': - 'codex/win-x64/codex-resources/codex-windows-sandbox-setup.exe', + 'coding-agent/win-x64/codex-resources/codex-windows-sandbox-setup.exe', 'resources/codex/win-x64/codex-package.json': - 'codex/win-x64/codex-package.json', - 'resources/codex/win-x64/NOTICE.md': 'codex/win-x64/NOTICE.md', - 'resources/codex/win-x64/manifest.json': 'codex/win-x64/manifest.json', + 'coding-agent/win-x64/codex-package.json', + 'resources/codex/win-x64/NOTICE.md': 'coding-agent/win-x64/NOTICE.md', + 'resources/codex/win-x64/manifest.json': 'coding-agent/win-x64/manifest.json', 'resources/plugins': 'plugins', }; assert.deepEqual( diff --git a/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/agc-game-production-workflow/SKILL.md b/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/agc-game-production-workflow/SKILL.md index f02b45374..82a42ddee 100644 --- a/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/agc-game-production-workflow/SKILL.md +++ b/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/agc-game-production-workflow/SKILL.md @@ -19,8 +19,14 @@ Use this Skill as the top-level SOP for a new game or a substantial game brief. ## Stage transitions -Advance only when the current stage has its output: brief → inventory; inventory → art decision; art decision → usable registered assets or an explicit no-art decision; implementation → source references to those assets; build → playable entry; playtest → evidence; delivery → truthful report. If a tool fails, preserve its error and stop or repair at that stage instead of silently substituting a later-stage placeholder. +Advance only when the current stage has its output: brief → inventory; inventory → art decision; art decision → usable registered assets or an explicit no-art decision; implementation → source references to those assets; build → playable entry; playtest → evidence; delivery → truthful report. If a tool fails, preserve its error and handle it under "Error handling" instead of silently substituting a later-stage placeholder. For a small edit to an existing game where the brief and suitable assets are unchanged, use the focused edit path and do not regenerate art. This exception does not apply to a new game or a substantial planning brief. +## Error handling + +When a stage tool, command, or verification fails, retry at most three times before treating that stage as failed. Keep the retries serial and scoped to the same stage and the same input: a retry must not open a parallel path, skip ahead to a later stage, or substitute a placeholder for the missing output. + +Only after the third attempt also fails, stop and tell the user the failure reason — which stage failed, which tool or command reported the error, what the error says, and what is still missing. A stage whose three attempts never succeeded is not complete, and its missing output cannot be reported as delivered. + Read the referenced specialist Skills for their detailed contracts: `agc-project-structure`, `taonier-art-assets`, `agc-web-game-development`, `agc-client-projection`, and `agc-browser-playtest`. diff --git a/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/manifest.json b/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/manifest.json index 72dbdf5fb..76de3bbc3 100644 --- a/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/manifest.json +++ b/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/manifest.json @@ -1,6 +1,6 @@ { "schemaVersion": "agc-skill-pack.v1", - "version": "2026-08-26.13", + "version": "2026-08-26.14", "skills": [ { "name": "agc-game-production-workflow", @@ -22,7 +22,7 @@ "agents/openai.yaml", "references/workflow-contract.md" ], - "sha256": "91082fdff4123f1e1fcf930af433cbea51a8c9d26991678b19028b344ea49f39" + "sha256": "d9d8e7e0a6bc512e0b463e0e4bd77edee1cc57f4a6965c9553e0920e38985d5c" }, { "name": "agc-project-structure", diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/codex_cli.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/codex_cli.rs index 23fd00fe9..863b8cdad 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/agent/codex_cli.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/agent/codex_cli.rs @@ -6,8 +6,9 @@ use sha2::{Digest, Sha256}; use tokio::io::{AsyncRead, AsyncReadExt, AsyncWriteExt}; const GAME_CREATOR_CODEX_CLI_EXECUTABLE: &str = "codex"; -const GAME_CREATOR_BUNDLED_CODEX_CLI_RELATIVE_PATH: &str = "codex/win-x64/bin/codex.exe"; -const GAME_CREATOR_BUNDLED_CODEX_CLI_MANIFEST_RELATIVE_PATH: &str = "codex/win-x64/manifest.json"; +const GAME_CREATOR_BUNDLED_CODEX_CLI_RELATIVE_PATH: &str = "coding-agent/win-x64/bin/codex.exe"; +const GAME_CREATOR_BUNDLED_CODEX_CLI_MANIFEST_RELATIVE_PATH: &str = + "coding-agent/win-x64/manifest.json"; const GAME_CREATOR_BUNDLED_CODEX_CLI_REQUIRED_FILES: [&str; 6] = [ "bin/codex.exe", "bin/codex-code-mode-host.exe", diff --git a/apps/ai-game-creator-shell/src-tauri/tauri.conf.json b/apps/ai-game-creator-shell/src-tauri/tauri.conf.json index 7fc0d7cf1..c5fa7f96b 100644 --- a/apps/ai-game-creator-shell/src-tauri/tauri.conf.json +++ b/apps/ai-game-creator-shell/src-tauri/tauri.conf.json @@ -1,6 +1,6 @@ { "$schema": "https://schema.tauri.app/config/2", - "productName": "Genarrative AI Game Creator", + "productName": "陶泥儿", "version": "0.1.29", "identifier": "world.genarrative.ai-game-creator", "build": { diff --git a/apps/ai-game-creator-shell/src-tauri/tauri.windows.conf.json b/apps/ai-game-creator-shell/src-tauri/tauri.windows.conf.json index 30c71cc2e..5fa3b1b35 100644 --- a/apps/ai-game-creator-shell/src-tauri/tauri.windows.conf.json +++ b/apps/ai-game-creator-shell/src-tauri/tauri.windows.conf.json @@ -4,14 +4,14 @@ "targets": ["nsis"], "useLocalToolsDir": true, "resources": { - "resources/codex/win-x64/bin/codex.exe": "codex/win-x64/bin/codex.exe", - "resources/codex/win-x64/bin/codex-code-mode-host.exe": "codex/win-x64/bin/codex-code-mode-host.exe", - "resources/codex/win-x64/codex-path/rg.exe": "codex/win-x64/codex-path/rg.exe", - "resources/codex/win-x64/codex-resources/codex-command-runner.exe": "codex/win-x64/codex-resources/codex-command-runner.exe", - "resources/codex/win-x64/codex-resources/codex-windows-sandbox-setup.exe": "codex/win-x64/codex-resources/codex-windows-sandbox-setup.exe", - "resources/codex/win-x64/codex-package.json": "codex/win-x64/codex-package.json", - "resources/codex/win-x64/NOTICE.md": "codex/win-x64/NOTICE.md", - "resources/codex/win-x64/manifest.json": "codex/win-x64/manifest.json", + "resources/codex/win-x64/bin/codex.exe": "coding-agent/win-x64/bin/codex.exe", + "resources/codex/win-x64/bin/codex-code-mode-host.exe": "coding-agent/win-x64/bin/codex-code-mode-host.exe", + "resources/codex/win-x64/codex-path/rg.exe": "coding-agent/win-x64/codex-path/rg.exe", + "resources/codex/win-x64/codex-resources/codex-command-runner.exe": "coding-agent/win-x64/codex-resources/codex-command-runner.exe", + "resources/codex/win-x64/codex-resources/codex-windows-sandbox-setup.exe": "coding-agent/win-x64/codex-resources/codex-windows-sandbox-setup.exe", + "resources/codex/win-x64/codex-package.json": "coding-agent/win-x64/codex-package.json", + "resources/codex/win-x64/NOTICE.md": "coding-agent/win-x64/NOTICE.md", + "resources/codex/win-x64/manifest.json": "coding-agent/win-x64/manifest.json", "resources/plugins": "plugins" } } diff --git a/apps/ai-game-creator-shell/src/features/project-workspace/ConversationModelSelect.tsx b/apps/ai-game-creator-shell/src/features/project-workspace/ConversationModelSelect.tsx index 1bc4c9ea4..324f83aad 100644 --- a/apps/ai-game-creator-shell/src/features/project-workspace/ConversationModelSelect.tsx +++ b/apps/ai-game-creator-shell/src/features/project-workspace/ConversationModelSelect.tsx @@ -14,6 +14,8 @@ import type { ClientLlmModel, ClientLlmModelCatalog, } from '../../services/clientApi'; +import { ClientAuthRequestError } from '../../services/clientApi'; +import { ClientHttpTimeoutError } from '../../services/clientHttp'; import { cachedLlmModelCatalog, refreshLlmModelCatalog, @@ -27,6 +29,14 @@ export type ConversationModelSelectHandle = { /** 客户端配置读取/写回失败:与「模型目录加载失败」区分,避免误导提示。 */ class ModelSelectionConfigError extends Error {} +function modelCatalogErrorMessage(error: unknown) { + if (error instanceof ClientHttpTimeoutError) + return '模型列表请求超时,请重试'; + if (error instanceof ClientAuthRequestError && error.status) + return `模型列表加载失败(HTTP ${error.status})`; + return '模型列表加载失败'; +} + export function ConversationModelSelect({ className, disabled, @@ -51,6 +61,7 @@ export function ConversationModelSelect({ const [busy, setBusy] = useState(!initialCatalog); const [error, setError] = useState(''); const [notice, setNotice] = useState(''); + const [manualRefreshBusy, setManualRefreshBusy] = useState(false); const [open, setOpen] = useState(false); const containerRef = useRef(null); const appliedRevisionRef = useRef( @@ -180,7 +191,11 @@ export function ConversationModelSelect({ ); const syncCatalog = useCallback( - async (showBusy: boolean) => { + async (showBusy: boolean, manualRefresh = false) => { + if (manualRefresh && mountedRef.current) { + setManualRefreshBusy(true); + setNotice('正在刷新模型列表'); + } const busyToken = showBusy ? ++busyTokenRef.current : busyTokenRef.current; @@ -195,12 +210,17 @@ export function ConversationModelSelect({ try { let catalog: ClientLlmModelCatalog; let usingCachedCatalog = false; + let catalogError: unknown = null; try { catalog = await refreshLlmModelCatalog(); - } catch { + } catch (error) { + catalogError = error; const cached = cachedLlmModelCatalog(); if (!cached) { - if (mountedRef.current) setError('模型列表加载失败'); + if (mountedRef.current) { + setError(modelCatalogErrorMessage(error)); + setNotice(''); + } markReady(false); return false; } @@ -209,10 +229,14 @@ export function ConversationModelSelect({ } const ready = await applyCatalog(catalog, showBusy, epochAtRequest); if (usingCachedCatalog && mountedRef.current) - setError('模型列表加载失败'); + setError(modelCatalogErrorMessage(catalogError)); + if (manualRefresh && mountedRef.current) { + setNotice(usingCachedCatalog ? '' : '模型列表已刷新'); + } return ready; } catch (error) { if (mountedRef.current) { + setNotice(''); setError( error instanceof ModelSelectionConfigError ? error.message @@ -230,6 +254,7 @@ export function ConversationModelSelect({ ) { setBusy(false); } + if (manualRefresh && mountedRef.current) setManualRefreshBusy(false); } }, [applyCatalog, markReady], @@ -375,11 +400,12 @@ export function ConversationModelSelect({ type="button" className="conversation-model-menu-refresh" aria-label="刷新模型列表" - disabled={disabled || busy} - onClick={() => void syncCatalog(true)} + disabled={disabled || busy || manualRefreshBusy} + aria-busy={manualRefreshBusy} + onClick={() => void syncCatalog(true, true)} >