建立 AGC 稳定版生命周期基础合同 (#348)
## 变更内容 这是基于 PR #346 的稳定版生命周期基础切换,承接已完成的 HTTP body timeout、Runner blocking worker、最近项目逐项刷新和首页跨页防重: - 新增统一 `ClientOperation` 合同,固定 operationId、requestId、phase、deadline、scope、cancellable 和 stale 判定; - 认证 refresh 投影 `auth-refresh` operation;登录、401 refresh、退出共用平台 session generation,并由 `auth-transition` 投影 Runner phase/成功/失败/不确定状态; - 首页自动创建记录 draft、startMode、phase 和建项后的 project scope,页面卸载不会释放 operation; - `.app/dev-stack.json` 增加 instanceId、repoRoot、服务级 dataDir/instanceId,AGC Vite marker 增加 repoRoot/processId/port;缺身份的旧状态拒绝 AGC 后端复用; - 新增稳定版生命周期主规范、开发运维口径和 shared pitfalls。 ## 验证 - `npm --prefix apps/ai-game-creator-shell run typecheck` - `npm --prefix apps/ai-game-creator-shell exec -- vitest run tests/clientOperation.test.ts tests/clientApi.test.ts tests/clientHttp.test.ts tests/recentProjectsModel.test.ts tests/start-dev-stack.test.ts tests/dev-port.test.ts --reporter=dot`(61 passed,2 skipped) - `npm --prefix apps/ai-game-creator-shell exec -- vitest run tests/appSurface.test.ts --reporter=dot`(423/423 passed) - `node --check scripts/dev.mjs` - `node --check apps/ai-game-creator-shell/scripts/start-dev-stack.mjs` - `npm run check:doc-index` - `npm run check:encoding` - `git diff --check` `scripts/dev.test.ts` 全量仍有 1 个 Windows 文件权限相关既有失败:bootstrap secret 测试在 Windows 上无法通过 chmod 模拟 0600;本变更未触及该逻辑。 Reviewed-on: #348
This commit was merged in pull request #348.
This commit is contained in:
@@ -425,6 +425,7 @@ function buildDevStackSnapshot(runner, updatedAt = new Date().toISOString()) {
|
||||
|
||||
return {
|
||||
schemaVersion: 2,
|
||||
instanceId: runner.instanceId,
|
||||
command: runner.command ?? 'all',
|
||||
repoRoot,
|
||||
database: runner.options.database,
|
||||
@@ -450,6 +451,12 @@ function buildDevStackServiceSnapshot(runner, serviceName, updatedAt) {
|
||||
: null;
|
||||
|
||||
return {
|
||||
repoRoot,
|
||||
instanceId: runner.instanceId,
|
||||
dataDir:
|
||||
serviceName === 'spacetime'
|
||||
? resolve(runner.options.spacetimeDataDir)
|
||||
: null,
|
||||
status,
|
||||
pid:
|
||||
childPid ??
|
||||
@@ -1198,6 +1205,9 @@ class DevRunner {
|
||||
constructor(options, baseEnv = process.env, explicitOptions = new Set()) {
|
||||
this.options = options;
|
||||
this.baseEnv = { ...baseEnv };
|
||||
this.instanceId = `dev-${process.pid}-${randomBytes(12).toString('hex')}`;
|
||||
this.baseEnv.GENARRATIVE_DEV_STACK_INSTANCE_ID = this.instanceId;
|
||||
this.baseEnv.GENARRATIVE_DEV_STACK_REPO_ROOT = repoRoot;
|
||||
this.spacetimeApiToken = String(
|
||||
this.baseEnv.GENARRATIVE_SPACETIME_TOKEN ?? '',
|
||||
).trim();
|
||||
|
||||
@@ -723,6 +723,7 @@ describe('dev scheduler stack state file', () => {
|
||||
test('状态快照记录服务 pid、端口、URL 和当前命令', () => {
|
||||
const updatedAt = '2026-05-29T00:00:00.000Z';
|
||||
const runner = {
|
||||
instanceId: 'test-instance',
|
||||
command: 'web',
|
||||
options: {
|
||||
apiHost: '127.0.0.1',
|
||||
@@ -770,12 +771,16 @@ describe('dev scheduler stack state file', () => {
|
||||
const snapshot = buildDevStackSnapshot(runner, updatedAt);
|
||||
|
||||
expect(snapshot.schemaVersion).toBe(2);
|
||||
expect(snapshot.instanceId).toBe('test-instance');
|
||||
expect(snapshot.command).toBe('web');
|
||||
expect(snapshot.database).toBe('genarrative-test');
|
||||
expect(snapshot.spacetimeDataDir).toBe(
|
||||
resolve('server-rs/.spacetimedb/local/data'),
|
||||
);
|
||||
expect(snapshot.services.web).toMatchObject({
|
||||
repoRoot: resolve('.'),
|
||||
instanceId: 'test-instance',
|
||||
dataDir: null,
|
||||
status: 'running',
|
||||
pid: 4321,
|
||||
host: '0.0.0.0',
|
||||
|
||||
Reference in New Issue
Block a user