diff --git a/apps/ai-game-creator-shell/package.json b/apps/ai-game-creator-shell/package.json index e8918f0fe..1f87e5b8c 100644 --- a/apps/ai-game-creator-shell/package.json +++ b/apps/ai-game-creator-shell/package.json @@ -1,13 +1,16 @@ { "name": "@genarrative/ai-game-creator-shell", "private": true, - "version": "0.1.9", + "version": "0.1.10", "type": "module", "scripts": { "dev": "node scripts/start-tauri-dev.mjs", "dev-server": "node scripts/start-dev-server.mjs", "dev-stack": "node scripts/start-dev-stack.mjs", "build": "npm --prefix ../.. exec tauri -- build", + "skill-pack:check": "node scripts/check-skill-pack.mjs", + "skill-pack:sync": "node scripts/check-skill-pack.mjs --write", + "skill-pack:test": "node --test scripts/check-skill-pack.test.mjs", "llm-status": "node scripts/run-cli-with-config.mjs --llm-status", "agent-task": "node scripts/run-cli-with-config.mjs --agent-task", "chat": "node scripts/run-cli-with-config.mjs --swarm-chat", @@ -31,7 +34,7 @@ "agent-runtime:supervisor-swarm-tool-plan-handoff-runner-kill-real-e2e": "node scripts/agent-runtime-real-e2e.mjs --suite supervisor-swarm-tool-plan-handoff-runner-kill", "agent-runtime:steer-real-e2e": "node scripts/agent-runtime-steer-real-e2e.mjs", "agent-runtime:steer-runner-kill-real-e2e": "node scripts/agent-runtime-real-e2e.mjs --suite steer-runner-kill", - "typecheck": "tsc -p tsconfig.json --noEmit && node scripts/check-config.mjs" + "typecheck": "tsc -p tsconfig.json --noEmit && npm run skill-pack:check && node scripts/check-config.mjs" }, "dependencies": { "@cubone/react-file-manager": "^1.35.0", diff --git a/apps/ai-game-creator-shell/scripts/check-config.mjs b/apps/ai-game-creator-shell/scripts/check-config.mjs index 162950bd8..4f0d64715 100644 --- a/apps/ai-game-creator-shell/scripts/check-config.mjs +++ b/apps/ai-game-creator-shell/scripts/check-config.mjs @@ -1533,11 +1533,13 @@ if ( } if ( - tauriConfig.version !== '0.1.9' || - packageConfig.version !== '0.1.9' || - cargoPackageVersion !== '0.1.9' + tauriConfig.version !== '0.1.10' || + packageConfig.version !== '0.1.10' || + cargoPackageVersion !== '0.1.10' ) { - throw new Error('AI game creator standard release must remain version 0.1.9'); + throw new Error( + 'AI game creator standard release must remain version 0.1.10', + ); } const devServerSource = fs.readFileSync( diff --git a/apps/ai-game-creator-shell/scripts/check-skill-pack.mjs b/apps/ai-game-creator-shell/scripts/check-skill-pack.mjs new file mode 100644 index 000000000..c317981f9 --- /dev/null +++ b/apps/ai-game-creator-shell/scripts/check-skill-pack.mjs @@ -0,0 +1,48 @@ +import process from 'node:process'; + +import { + inspectSkillPack, + syncSkillPackManifest, +} from './skill-pack-manifest.mjs'; + +const argumentsList = process.argv.slice(2); +const writeMode = argumentsList.length === 1 && argumentsList[0] === '--write'; +if ( + argumentsList.length > 1 || + (argumentsList.length === 1 && argumentsList[0] !== '--write') +) { + console.error('用法:node scripts/check-skill-pack.mjs [--write]'); + process.exit(1); +} + +try { + if (writeMode) { + const result = syncSkillPackManifest(); + if (!result.changed) { + console.log(`[skill-pack] 已是最新(version=${result.version})`); + } else { + console.log( + `[skill-pack] 已同步 ${result.mismatches.map((item) => item.name).join('、')}(version=${result.version})`, + ); + } + } else { + const result = inspectSkillPack(); + if (result.mismatches.length > 0) { + console.error('[skill-pack] 内容指纹与 manifest 不一致:'); + for (const mismatch of result.mismatches) { + console.error( + `- ${mismatch.name}: manifest=${mismatch.expected} actual=${mismatch.actual}`, + ); + } + console.error('[skill-pack] 内容变更后运行:npm run agc:skill-pack:sync'); + process.exitCode = 1; + } else { + console.log(`[skill-pack] OK(version=${result.manifest.version})`); + } + } +} catch (error) { + console.error( + `[skill-pack] ${error instanceof Error ? error.message : String(error)}`, + ); + process.exitCode = 1; +} diff --git a/apps/ai-game-creator-shell/scripts/check-skill-pack.test.mjs b/apps/ai-game-creator-shell/scripts/check-skill-pack.test.mjs new file mode 100644 index 000000000..b92b38e7c --- /dev/null +++ b/apps/ai-game-creator-shell/scripts/check-skill-pack.test.mjs @@ -0,0 +1,49 @@ +import assert from 'node:assert/strict'; +import { spawnSync } from 'node:child_process'; +import fs from 'node:fs'; +import os from 'node:os'; +import path from 'node:path'; +import test from 'node:test'; +import { fileURLToPath } from 'node:url'; + +import { + computeSkillContentFingerprint, + inspectSkillPack, +} from './skill-pack-manifest.mjs'; + +test('bundled skill pack manifest is synchronized', () => { + const result = inspectSkillPack(); + assert.deepEqual(result.mismatches, []); +}); + +test('skill content fingerprint canonicalizes CRLF', () => { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'agc-skill-pack-')); + try { + fs.mkdirSync(path.join(root, 'demo'), { recursive: true }); + const entry = { + name: 'demo', + files: ['SKILL.md'], + }; + fs.writeFileSync(path.join(root, 'demo', 'SKILL.md'), 'line 1\nline 2\n'); + const lf = computeSkillContentFingerprint(root, entry); + fs.writeFileSync( + path.join(root, 'demo', 'SKILL.md'), + 'line 1\r\nline 2\r\n', + ); + assert.equal(computeSkillContentFingerprint(root, entry), lf); + } finally { + fs.rmSync(root, { recursive: true, force: true }); + } +}); + +test('check command without arguments remains read-only', () => { + const scriptPath = path.join( + path.dirname(fileURLToPath(import.meta.url)), + 'check-skill-pack.mjs', + ); + const result = spawnSync(process.execPath, [scriptPath], { + encoding: 'utf8', + }); + assert.equal(result.status, 0, result.stderr); + assert.match(result.stdout, /\[skill-pack\] OK/u); +}); diff --git a/apps/ai-game-creator-shell/scripts/skill-pack-manifest.mjs b/apps/ai-game-creator-shell/scripts/skill-pack-manifest.mjs new file mode 100644 index 000000000..d660c2a70 --- /dev/null +++ b/apps/ai-game-creator-shell/scripts/skill-pack-manifest.mjs @@ -0,0 +1,213 @@ +import crypto from 'node:crypto'; +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { TextDecoder } from 'node:util'; + +export const SKILL_PACK_SCHEMA_VERSION = 'agc-skill-pack.v1'; +export const EXPECTED_SKILL_NAMES = Object.freeze([ + 'agc-browser-playtest', + 'agc-client-projection', + 'agc-project-structure', + 'agc-web-game-development', + 'taonier-art-assets', +]); + +const utf8Decoder = new TextDecoder('utf-8', { fatal: true }); +const defaultRoot = path.resolve( + path.dirname(fileURLToPath(import.meta.url)), + '../src-tauri/resources/agc-skills', +); + +function canonicalTextBytes(filePath) { + const decoded = utf8Decoder.decode(fs.readFileSync(filePath)); + return Buffer.from(decoded.replaceAll('\r\n', '\n'), 'utf8'); +} + +export function isSafeSkillRelativePath(value) { + if ( + typeof value !== 'string' || + value.length === 0 || + value.includes('\\') || + value.includes(':') || + value.startsWith('/') + ) { + return false; + } + return value + .split('/') + .every( + (segment) => segment.length > 0 && segment !== '.' && segment !== '..', + ); +} + +function skillFilePath(rootDir, skillName, relativePath) { + if (!isSafeSkillRelativePath(relativePath)) { + throw new Error(`Skill ${skillName} 包含不安全相对路径: ${relativePath}`); + } + const target = path.resolve(rootDir, skillName, ...relativePath.split('/')); + const skillRoot = path.resolve(rootDir, skillName); + const prefix = `${skillRoot}${path.sep}`; + if (!target.startsWith(prefix)) { + throw new Error(`Skill ${skillName} 路径越过审核根目录: ${relativePath}`); + } + return target; +} + +export function computeSkillContentFingerprint(rootDir, entry) { + const digest = crypto.createHash('sha256'); + for (const relativePath of [...entry.files].sort()) { + const filePath = skillFilePath(rootDir, entry.name, relativePath); + const bytes = canonicalTextBytes(filePath); + digest.update(relativePath, 'utf8'); + digest.update(Buffer.from([0])); + digest.update(bytes); + digest.update(Buffer.from([0])); + } + return digest.digest('hex'); +} + +function collectBundledFiles(rootDir) { + const files = []; + const walk = (directory, prefix) => { + for (const entry of fs.readdirSync(directory, { withFileTypes: true })) { + const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name; + const absolutePath = path.join(directory, entry.name); + if (entry.isSymbolicLink()) { + throw new Error(`内置 AGC Skill 不允许符号链接: ${relativePath}`); + } + if (entry.isDirectory()) { + walk(absolutePath, relativePath); + } else if (entry.isFile()) { + files.push(relativePath.replaceAll('\\', '/')); + } else { + throw new Error(`内置 AGC Skill 文件类型不受支持: ${relativePath}`); + } + } + }; + walk(rootDir, ''); + return files.filter((file) => file !== 'manifest.json').sort(); +} + +function readManifest(rootDir) { + const manifestPath = path.join(rootDir, 'manifest.json'); + return { + manifestPath, + manifest: JSON.parse(fs.readFileSync(manifestPath, 'utf8')), + }; +} + +function validateManifestShape(rootDir, manifest) { + if (manifest?.schemaVersion !== SKILL_PACK_SCHEMA_VERSION) { + throw new Error('内置 AGC Skill 清单 schemaVersion 不受支持'); + } + if (typeof manifest.version !== 'string' || manifest.version.trim() === '') { + throw new Error('内置 AGC Skill 清单缺少版本'); + } + if (!Array.isArray(manifest.skills)) { + throw new Error('内置 AGC Skill 清单缺少 skills 数组'); + } + const names = manifest.skills.map((entry) => entry?.name); + if ( + names.length !== EXPECTED_SKILL_NAMES.length || + [...names].sort().join('\n') !== [...EXPECTED_SKILL_NAMES].sort().join('\n') + ) { + throw new Error('内置 AGC Skill 清单不等于审核白名单'); + } + + const declaredFiles = new Set(); + const mismatches = []; + for (const entry of manifest.skills) { + if ( + typeof entry.name !== 'string' || + !Array.isArray(entry.files) || + entry.files.length === 0 || + !entry.files.includes('SKILL.md') || + new Set(entry.files).size !== entry.files.length + ) { + throw new Error( + `内置 AGC Skill ${entry.name ?? ''} 元数据不完整`, + ); + } + for (const relativePath of entry.files) { + if (!isSafeSkillRelativePath(relativePath)) { + throw new Error( + `内置 AGC Skill ${entry.name} 包含不安全相对路径: ${relativePath}`, + ); + } + declaredFiles.add(`${entry.name}/${relativePath}`); + } + const actual = computeSkillContentFingerprint(rootDir, entry); + if (actual !== entry.sha256) { + mismatches.push({ + name: entry.name, + expected: entry.sha256, + actual, + }); + } + } + + const bundledFiles = collectBundledFiles(rootDir); + if ( + declaredFiles.size !== bundledFiles.length || + [...declaredFiles].sort().join('\n') !== bundledFiles.join('\n') + ) { + throw new Error('内置 AGC Skill 文件集合与审核清单不一致'); + } + return { mismatches }; +} + +export function inspectSkillPack(rootDir = defaultRoot) { + const resolvedRoot = path.resolve(rootDir); + const { manifestPath, manifest } = readManifest(resolvedRoot); + const { mismatches } = validateManifestShape(resolvedRoot, manifest); + return { manifestPath, manifest, mismatches }; +} + +function incrementPackVersion(version) { + const match = /^(\d{4}-\d{2}-\d{2})\.(\d+)$/u.exec(version); + if (!match) { + throw new Error( + `无法自动递增 Skill pack 版本 ${version},请使用 YYYY-MM-DD.N 格式`, + ); + } + return `${match[1]}.${Number(match[2]) + 1}`; +} + +export function syncSkillPackManifest(rootDir = defaultRoot) { + const inspection = inspectSkillPack(rootDir); + if (inspection.mismatches.length === 0) { + return { + changed: false, + version: inspection.manifest.version, + mismatches: [], + }; + } + + const mismatchByName = new Map( + inspection.mismatches.map((mismatch) => [mismatch.name, mismatch.actual]), + ); + const nextManifest = { + ...inspection.manifest, + version: incrementPackVersion(inspection.manifest.version), + skills: inspection.manifest.skills.map((entry) => + mismatchByName.has(entry.name) + ? { ...entry, sha256: mismatchByName.get(entry.name) } + : entry, + ), + }; + fs.writeFileSync( + inspection.manifestPath, + `${JSON.stringify(nextManifest, null, 2)}\n`, + 'utf8', + ); + const verified = inspectSkillPack(rootDir); + if (verified.mismatches.length > 0) { + throw new Error('Skill pack manifest 同步后仍存在内容指纹不匹配'); + } + return { + changed: true, + version: nextManifest.version, + mismatches: inspection.mismatches, + }; +} diff --git a/apps/ai-game-creator-shell/src-tauri/Cargo.lock b/apps/ai-game-creator-shell/src-tauri/Cargo.lock index f815af2ec..161613e5a 100644 --- a/apps/ai-game-creator-shell/src-tauri/Cargo.lock +++ b/apps/ai-game-creator-shell/src-tauri/Cargo.lock @@ -1695,7 +1695,7 @@ dependencies = [ [[package]] name = "genarrative-ai-game-creator-shell" -version = "0.1.9" +version = "0.1.10" dependencies = [ "agent-runtime-core", "axum", diff --git a/apps/ai-game-creator-shell/src-tauri/Cargo.toml b/apps/ai-game-creator-shell/src-tauri/Cargo.toml index 98c7a1a9e..85baf1f63 100644 --- a/apps/ai-game-creator-shell/src-tauri/Cargo.toml +++ b/apps/ai-game-creator-shell/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "genarrative-ai-game-creator-shell" -version = "0.1.9" +version = "0.1.10" edition = "2021" publish = false 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 2a3066fc6..90b1a5893 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.2", + "version": "2026-08-26.3", "skills": [ { "name": "agc-project-structure", @@ -104,7 +104,7 @@ "agents/openai.yaml", "references/projection-contract.md" ], - "sha256": "790d0788a8b1585e95b7d2181b0d09af611b2c673596a56e46a853bea736a4da" + "sha256": "2e11baf232bd1a786cc3189a9183e3a687b846c4e0816393e5b5687551a5eeb7" } ] } 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 e21b7901a..53a6ad506 100644 --- a/apps/ai-game-creator-shell/src-tauri/tauri.conf.json +++ b/apps/ai-game-creator-shell/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "Genarrative AI Game Creator", - "version": "0.1.9", + "version": "0.1.10", "identifier": "world.genarrative.ai-game-creator", "build": { "beforeDevCommand": "npm --prefix ../.. run agc:serve", diff --git a/apps/ai-game-creator-shell/src/view/home/components/RichInputArea/index.tsx b/apps/ai-game-creator-shell/src/view/home/components/RichInputArea/index.tsx index 4c45a8d75..1d627d7dc 100644 --- a/apps/ai-game-creator-shell/src/view/home/components/RichInputArea/index.tsx +++ b/apps/ai-game-creator-shell/src/view/home/components/RichInputArea/index.tsx @@ -239,7 +239,7 @@ export default function RichInputArea(props: RichInputAreaProps) { }, }} > -
+
} placeholder={ - + {props.placeholder} } 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 db356ee08..6ab9c7a13 100644 --- a/apps/ai-game-creator-shell/tests/appSurface/home.suite.ts +++ b/apps/ai-game-creator-shell/tests/appSurface/home.suite.ts @@ -28,6 +28,17 @@ import { } from './harness'; export function registerClientHomeTests() { + it('anchors the empty home input placeholder to the editor while the page scrolls', () => { + renderLauncherAt('/?launcher'); + + const placeholder = screen.getByText('今天想把什么灵感做成游戏'); + expect(placeholder.classList.contains('absolute')).toBe(true); + expect(placeholder.classList.contains('top-0')).toBe(true); + expect(placeholder.parentElement?.classList.contains('relative')).toBe( + true, + ); + }); + 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'); diff --git a/docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md b/docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md index 05a4e833d..56c4d8e77 100644 --- a/docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md +++ b/docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md @@ -1178,7 +1178,7 @@ game-project/ - 普通项目对话只由一个 project-bound Codex app-server thread 执行。客户端系统提示词只放最小工程合同、当前游戏源码有界快照、项目 prompts 和审核 Skill 索引;不再批量读取项目 `.codex/.agents/.hermes` Skill 正文,也不恢复 Supervisor、专业 Agent 或 harness。 - 首页恢复“做游戏 / 做素材 / 做方案”三个创作类型,默认“做游戏”。该选择与设置页的 Agent Runtime 模式无关;每次首页提交仍只自动创建一个新项目并进入项目工作台。用户正文原样进入项目对话,`game|art|doc` 仅作为受限结构化首轮上下文传给同一 Codex thread,不拼接“初始意图”文案、不产生首页对话、不切换 Provider 或恢复旧 Runtime 编排。 -- `agc-skill-pack.v1` 只包含项目结构、陶泥儿美术、Web 游戏实现、真实浏览器试玩、客户端资源投影五项 Skill。清单记录用途、触发条件、所需工具、版本和内容 SHA-256;审核文本按 UTF-8 读取并将 CRLF 规范为 LF 后计算指纹和安装,避免混合换行造成 Windows / Linux 构建结果漂移,语义内容变化时必须同步重算对应清单指纹并提升版本。客户端把审核文件安装到隔离目录后通过 app-server `skills/extraRoots/set + skills/list` 注册并复核,完整正文由 Codex 原生 Skill 机制按意图加载,一层引用只能经 `agc_read_skill_resource` 读取清单内 Markdown。引用路径按平台无关规则拒绝反斜杠、盘符、UNC、绝对路径和 `..`,不能依赖当前宿主的 `std::path` 语义判断其它平台路径。 +- `agc-skill-pack.v1` 只包含项目结构、陶泥儿美术、Web 游戏实现、真实浏览器试玩、客户端资源投影五项 Skill。清单记录用途、触发条件、所需工具、版本和内容 SHA-256;审核文本按 UTF-8 读取并将 CRLF 规范为 LF 后计算指纹和安装,避免混合换行造成 Windows / Linux 构建结果漂移,语义内容变化时必须同步重算对应清单指纹并提升版本。同步统一运行 `npm run agc:skill-pack:sync`,只读校验由 AGC `typecheck` 和 release build 自动执行,发现漂移时直接列出 Skill 与实际摘要,不让失配内容进入构建产物。客户端把审核文件安装到隔离目录后通过 app-server `skills/extraRoots/set + skills/list` 注册并复核,完整正文由 Codex 原生 Skill 机制按意图加载,一层引用只能经 `agc_read_skill_resource` 读取清单内 Markdown。引用路径按平台无关规则拒绝反斜杠、盘符、UNC、绝对路径和 `..`,不能依赖当前宿主的 `std::path` 语义判断其它平台路径。 - DirectProject 只连接客户端内置的 `agc_tools` STDIO MCP,工具固定为审核引用读取、标准陶泥儿美术准备、已登记资源有界查询、视频 / 角色动画 / 音效 / BGM 的 create-or-derive 语义生成、已登记图片去背景和 desktop/mobile 浏览器试玩。MCP 进程只做协议;真实浏览器与付费 External v1 调用通过随机 loopback 地址回到客户端主进程,因此不复制 GUI 登录态、开发者 Key、项目路径、revision、operation 或幂等键到模型上下文。已登记工具固定自动批准,但付费资源工具仍由客户端绑定稳定回合身份、限制单回合请求数、串行执行并优先恢复匹配账本;通用 shell、Codex 原生 webSearch、任意网络、多 Agent、插件和外部 MCP 继续关闭。`codex_app_server` 模式要求 `llm.webSearchEnabled=false`。 - 陶泥儿生成继续复用持久幂等账本、operation 恢复、来源/下载/PNG 解码和 manifest 登记;普通客户端优先使用当前 AGC 登录会话及账号路由,只有受控的 ExternalDeveloper 发布模式才在客户端内部使用按服务器 origin 隔离的私有 Key。用户和模型都不需要提供或配置 API Key;凭据失效、来源不明或结果未知时失败关闭,不能自动换 Key 或重新扣费。 - 自定义 LLM API Key 路由只在 DirectHome/DirectProject 经 loopback `/responses` 流式代理转发。代理不注入 Key,只要求请求自带 Bearer,并剥离开发网关错误携带的 `X-Codex-*` ChatGPT 账户额度头,防止隔离 app-server 把 API Provider 误判为余额 0;旧 ToolHost 保持原 Provider 行为。 diff --git a/package-lock.json b/package-lock.json index 7ef88a9ff..92c3036fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -93,7 +93,7 @@ }, "apps/ai-game-creator-shell": { "name": "@genarrative/ai-game-creator-shell", - "version": "0.1.9", + "version": "0.1.10", "dependencies": { "@cubone/react-file-manager": "^1.35.0", "@genarrative/image-canvas-core": "0.1.0", diff --git a/package.json b/package.json index a3bec46ba..0b8ce8f38 100644 --- a/package.json +++ b/package.json @@ -158,6 +158,8 @@ "agc:backend": "node scripts/dev.mjs backend", "agc:config": "npm --prefix apps/ai-game-creator-shell run config --", "agc:build": "npm --prefix apps/ai-game-creator-shell run build --", + "agc:skill-pack:check": "npm --prefix apps/ai-game-creator-shell run skill-pack:check", + "agc:skill-pack:sync": "npm --prefix apps/ai-game-creator-shell run skill-pack:sync", "agc:check": "npm run ai-game-creator-shell:check", "agc:typecheck": "npm --prefix apps/ai-game-creator-shell run typecheck", "agc:test": "npm --prefix apps/ai-game-creator-shell run agent-runtime:supervisor-autonomous-playable-lane-defense-deterministic-e2e --", diff --git a/scripts/check-npm-workspaces.mjs b/scripts/check-npm-workspaces.mjs index a2cab468b..6a91ba9d0 100644 --- a/scripts/check-npm-workspaces.mjs +++ b/scripts/check-npm-workspaces.mjs @@ -174,7 +174,7 @@ export function collectNpmWorkspaceErrors(rootDir) { ); } const expectedWorkspaceVersion = - workspacePath === 'apps/ai-game-creator-shell' ? '0.1.9' : '0.1.0'; + workspacePath === 'apps/ai-game-creator-shell' ? '0.1.10' : '0.1.0'; if (manifest.version !== expectedWorkspaceVersion) { errors.push( `${manifestPath}: workspace version must be ${expectedWorkspaceVersion}`, diff --git a/scripts/check-npm-workspaces.test.mjs b/scripts/check-npm-workspaces.test.mjs index 0aa027b15..74e87b4ea 100644 --- a/scripts/check-npm-workspaces.test.mjs +++ b/scripts/check-npm-workspaces.test.mjs @@ -79,7 +79,7 @@ function createValidFixture() { name: workspaceNames[workspacePath], private: true, version: - workspacePath === 'apps/ai-game-creator-shell' ? '0.1.9' : '0.1.0', + workspacePath === 'apps/ai-game-creator-shell' ? '0.1.10' : '0.1.0', dependencies: localDependencies[workspacePath], }; writeJson(rootDir, `${workspacePath}/package.json`, manifest);