收紧story与custom world迁移能力边界
This commit is contained in:
@@ -2,7 +2,6 @@ import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
|
||||
import type { CustomWorldSessionRecord } from '../../../packages/shared/src/contracts/runtime.js';
|
||||
import type { RuntimeRepositoryPort } from '../repositories/runtimeRepository.js';
|
||||
import {
|
||||
buildPendingClarifications,
|
||||
evaluateCreatorIntentReadiness,
|
||||
@@ -15,8 +14,13 @@ import { CustomWorldAgentOrchestrator } from './customWorldAgentOrchestrator.js'
|
||||
import { CustomWorldAgentSessionStore } from './customWorldAgentSessionStore.js';
|
||||
import { createTestCustomWorldAgentSingleTurnLlmClient } from './customWorldAgentTestHelpers.js';
|
||||
import { listCustomWorldWorkSummaries } from './customWorldWorkSummaryService.js';
|
||||
import type {
|
||||
CustomWorldSessionCapability,
|
||||
CustomWorldWorkSummaryCapability,
|
||||
} from './runtimeCapabilities.js';
|
||||
|
||||
function createRuntimeRepositoryStub(): RuntimeRepositoryPort {
|
||||
function createRuntimeRepositoryStub(): CustomWorldSessionCapability &
|
||||
CustomWorldWorkSummaryCapability {
|
||||
const sessionsByUser = new Map<
|
||||
string,
|
||||
Map<string, CustomWorldSessionRecord>
|
||||
@@ -35,51 +39,9 @@ function createRuntimeRepositoryStub(): RuntimeRepositoryPort {
|
||||
};
|
||||
|
||||
return {
|
||||
async getSnapshot(_userId) {
|
||||
return null;
|
||||
},
|
||||
async putSnapshot(_userId, _payload) {
|
||||
throw new Error('not implemented');
|
||||
},
|
||||
async deleteSnapshot(_userId) {
|
||||
return undefined;
|
||||
},
|
||||
async getSettings() {
|
||||
return {
|
||||
musicVolume: 0.42,
|
||||
platformTheme: 'light',
|
||||
};
|
||||
},
|
||||
async putSettings(_userId, settings) {
|
||||
return settings;
|
||||
},
|
||||
async listCustomWorldProfiles(userId) {
|
||||
return [...(profilesByUser.get(userId) ?? [])];
|
||||
},
|
||||
async upsertCustomWorldProfile(userId, profileId, profile) {
|
||||
const current = [...(profilesByUser.get(userId) ?? [])].filter(
|
||||
(item) => String(item.id ?? '') !== profileId,
|
||||
);
|
||||
current.unshift({
|
||||
...profile,
|
||||
id: profileId,
|
||||
});
|
||||
profilesByUser.set(userId, current);
|
||||
return current;
|
||||
},
|
||||
async deleteCustomWorldProfile(userId, profileId) {
|
||||
const current = [...(profilesByUser.get(userId) ?? [])].filter(
|
||||
(item) => String(item.id ?? '') !== profileId,
|
||||
);
|
||||
profilesByUser.set(userId, current);
|
||||
return current;
|
||||
},
|
||||
async listProfileSaveArchives() {
|
||||
return [];
|
||||
},
|
||||
async resumeProfileSaveArchive() {
|
||||
return null;
|
||||
},
|
||||
async listCustomWorldSessions(userId) {
|
||||
return [...getSessionBucket(userId).values()];
|
||||
},
|
||||
|
||||
@@ -2,13 +2,17 @@ import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
|
||||
import type { CustomWorldSessionRecord } from '../../../packages/shared/src/contracts/runtime.js';
|
||||
import type { RuntimeRepositoryPort } from '../repositories/runtimeRepository.js';
|
||||
import { CustomWorldAgentOrchestrator } from './customWorldAgentOrchestrator.js';
|
||||
import { CustomWorldAgentSessionStore } from './customWorldAgentSessionStore.js';
|
||||
import { createTestCustomWorldAgentSingleTurnLlmClient } from './customWorldAgentTestHelpers.js';
|
||||
import { listCustomWorldWorkSummaries } from './customWorldWorkSummaryService.js';
|
||||
import type {
|
||||
CustomWorldSessionCapability,
|
||||
CustomWorldWorkSummaryCapability,
|
||||
} from './runtimeCapabilities.js';
|
||||
|
||||
function createRuntimeRepositoryStub(): RuntimeRepositoryPort {
|
||||
function createRuntimeRepositoryStub(): CustomWorldSessionCapability &
|
||||
CustomWorldWorkSummaryCapability {
|
||||
const sessionsByUser = new Map<
|
||||
string,
|
||||
Map<string, CustomWorldSessionRecord>
|
||||
@@ -27,51 +31,9 @@ function createRuntimeRepositoryStub(): RuntimeRepositoryPort {
|
||||
};
|
||||
|
||||
return {
|
||||
async getSnapshot(_userId) {
|
||||
return null;
|
||||
},
|
||||
async putSnapshot(_userId, _payload) {
|
||||
throw new Error('not implemented');
|
||||
},
|
||||
async deleteSnapshot(_userId) {
|
||||
return undefined;
|
||||
},
|
||||
async getSettings() {
|
||||
return {
|
||||
musicVolume: 0.42,
|
||||
platformTheme: 'light',
|
||||
};
|
||||
},
|
||||
async putSettings(_userId, settings) {
|
||||
return settings;
|
||||
},
|
||||
async listCustomWorldProfiles(userId) {
|
||||
return [...(profilesByUser.get(userId) ?? [])];
|
||||
},
|
||||
async upsertCustomWorldProfile(userId, profileId, profile) {
|
||||
const current = [...(profilesByUser.get(userId) ?? [])].filter(
|
||||
(item) => String(item.id ?? '') !== profileId,
|
||||
);
|
||||
current.unshift({
|
||||
...profile,
|
||||
id: profileId,
|
||||
});
|
||||
profilesByUser.set(userId, current);
|
||||
return current;
|
||||
},
|
||||
async deleteCustomWorldProfile(userId, profileId) {
|
||||
const current = [...(profilesByUser.get(userId) ?? [])].filter(
|
||||
(item) => String(item.id ?? '') !== profileId,
|
||||
);
|
||||
profilesByUser.set(userId, current);
|
||||
return current;
|
||||
},
|
||||
async listProfileSaveArchives() {
|
||||
return [];
|
||||
},
|
||||
async resumeProfileSaveArchive() {
|
||||
return null;
|
||||
},
|
||||
async listCustomWorldSessions(userId) {
|
||||
return [...getSessionBucket(userId).values()];
|
||||
},
|
||||
|
||||
@@ -2,14 +2,18 @@ import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
|
||||
import type { CustomWorldSessionRecord } from '../../../packages/shared/src/contracts/runtime.js';
|
||||
import type { RuntimeRepositoryPort } from '../repositories/runtimeRepository.js';
|
||||
import { normalizeFoundationDraftProfile } from './customWorldAgentDraftCompiler.js';
|
||||
import { CustomWorldAgentOrchestrator } from './customWorldAgentOrchestrator.js';
|
||||
import { CustomWorldAgentSessionStore } from './customWorldAgentSessionStore.js';
|
||||
import { createTestCustomWorldAgentSingleTurnLlmClient } from './customWorldAgentTestHelpers.js';
|
||||
import { listCustomWorldWorkSummaries } from './customWorldWorkSummaryService.js';
|
||||
import type {
|
||||
CustomWorldSessionCapability,
|
||||
CustomWorldWorkSummaryCapability,
|
||||
} from './runtimeCapabilities.js';
|
||||
|
||||
function createRuntimeRepositoryStub(): RuntimeRepositoryPort {
|
||||
function createRuntimeRepositoryStub(): CustomWorldSessionCapability &
|
||||
CustomWorldWorkSummaryCapability {
|
||||
const sessionsByUser = new Map<
|
||||
string,
|
||||
Map<string, CustomWorldSessionRecord>
|
||||
@@ -28,51 +32,9 @@ function createRuntimeRepositoryStub(): RuntimeRepositoryPort {
|
||||
};
|
||||
|
||||
return {
|
||||
async getSnapshot(_userId) {
|
||||
return null;
|
||||
},
|
||||
async putSnapshot(_userId, _payload) {
|
||||
throw new Error('not implemented');
|
||||
},
|
||||
async deleteSnapshot(_userId) {
|
||||
return undefined;
|
||||
},
|
||||
async getSettings() {
|
||||
return {
|
||||
musicVolume: 0.42,
|
||||
platformTheme: 'light',
|
||||
};
|
||||
},
|
||||
async putSettings(_userId, settings) {
|
||||
return settings;
|
||||
},
|
||||
async listCustomWorldProfiles(userId) {
|
||||
return [...(profilesByUser.get(userId) ?? [])];
|
||||
},
|
||||
async upsertCustomWorldProfile(userId, profileId, profile) {
|
||||
const current = [...(profilesByUser.get(userId) ?? [])].filter(
|
||||
(item) => String(item.id ?? '') !== profileId,
|
||||
);
|
||||
current.unshift({
|
||||
...profile,
|
||||
id: profileId,
|
||||
});
|
||||
profilesByUser.set(userId, current);
|
||||
return current;
|
||||
},
|
||||
async deleteCustomWorldProfile(userId, profileId) {
|
||||
const current = [...(profilesByUser.get(userId) ?? [])].filter(
|
||||
(item) => String(item.id ?? '') !== profileId,
|
||||
);
|
||||
profilesByUser.set(userId, current);
|
||||
return current;
|
||||
},
|
||||
async listProfileSaveArchives() {
|
||||
return [];
|
||||
},
|
||||
async resumeProfileSaveArchive() {
|
||||
return null;
|
||||
},
|
||||
async listCustomWorldSessions(userId) {
|
||||
return [...getSessionBucket(userId).values()];
|
||||
},
|
||||
|
||||
@@ -2,18 +2,17 @@ import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
|
||||
import type { CustomWorldSessionRecord } from '../../../packages/shared/src/contracts/runtime.js';
|
||||
import type { RuntimeRepositoryPort } from '../repositories/runtimeRepository.js';
|
||||
import { normalizeFoundationDraftProfile } from './customWorldAgentDraftCompiler.js';
|
||||
import { CustomWorldAgentOrchestrator } from './customWorldAgentOrchestrator.js';
|
||||
import { CustomWorldAgentSessionStore } from './customWorldAgentSessionStore.js';
|
||||
import { createTestCustomWorldAgentSingleTurnLlmClient } from './customWorldAgentTestHelpers.js';
|
||||
import type { CustomWorldSessionCapability } from './runtimeCapabilities.js';
|
||||
|
||||
function createRuntimeRepositoryStub(): RuntimeRepositoryPort {
|
||||
function createRuntimeRepositoryStub(): CustomWorldSessionCapability {
|
||||
const sessionsByUser = new Map<
|
||||
string,
|
||||
Map<string, CustomWorldSessionRecord>
|
||||
>();
|
||||
const profilesByUser = new Map<string, Record<string, unknown>[]>();
|
||||
|
||||
const getSessionBucket = (userId: string) => {
|
||||
const existing = sessionsByUser.get(userId);
|
||||
@@ -27,51 +26,6 @@ function createRuntimeRepositoryStub(): RuntimeRepositoryPort {
|
||||
};
|
||||
|
||||
return {
|
||||
async getSnapshot() {
|
||||
return null;
|
||||
},
|
||||
async putSnapshot(_userId, payload) {
|
||||
return payload;
|
||||
},
|
||||
async deleteSnapshot() {
|
||||
return undefined;
|
||||
},
|
||||
async getSettings() {
|
||||
return {
|
||||
musicVolume: 0.42,
|
||||
platformTheme: 'light',
|
||||
};
|
||||
},
|
||||
async putSettings(_userId, settings) {
|
||||
return settings;
|
||||
},
|
||||
async listCustomWorldProfiles(userId) {
|
||||
return [...(profilesByUser.get(userId) ?? [])];
|
||||
},
|
||||
async upsertCustomWorldProfile(userId, profileId, profile) {
|
||||
const current = [...(profilesByUser.get(userId) ?? [])].filter(
|
||||
(item) => String(item.id ?? '') !== profileId,
|
||||
);
|
||||
current.unshift({
|
||||
...profile,
|
||||
id: profileId,
|
||||
});
|
||||
profilesByUser.set(userId, current);
|
||||
return current;
|
||||
},
|
||||
async deleteCustomWorldProfile(userId, profileId) {
|
||||
const current = [...(profilesByUser.get(userId) ?? [])].filter(
|
||||
(item) => String(item.id ?? '') !== profileId,
|
||||
);
|
||||
profilesByUser.set(userId, current);
|
||||
return current;
|
||||
},
|
||||
async listProfileSaveArchives() {
|
||||
return [];
|
||||
},
|
||||
async resumeProfileSaveArchive() {
|
||||
return null;
|
||||
},
|
||||
async listCustomWorldSessions(userId) {
|
||||
return [...getSessionBucket(userId).values()];
|
||||
},
|
||||
|
||||
@@ -13,7 +13,6 @@ import type {
|
||||
EightAnchorContent,
|
||||
} from '../../../packages/shared/src/contracts/customWorldAgent.js';
|
||||
import type { CustomWorldSessionRecord as LegacyCustomWorldSessionRecord } from '../../../packages/shared/src/contracts/runtime.js';
|
||||
import type { RuntimeRepositoryPort } from '../repositories/runtimeRepository.js';
|
||||
import {
|
||||
buildPendingClarifications,
|
||||
evaluateCreatorIntentReadiness,
|
||||
@@ -33,6 +32,7 @@ import {
|
||||
estimateProgressPercentFromAnchorContent,
|
||||
normalizeEightAnchorContent,
|
||||
} from './eightAnchorCompatibilityService.js';
|
||||
import type { CustomWorldSessionCapability } from './runtimeCapabilities.js';
|
||||
|
||||
export const CUSTOM_WORLD_AGENT_SESSION_ID_PREFIX =
|
||||
'custom-world-agent-session-';
|
||||
@@ -565,7 +565,7 @@ function toSnapshot(
|
||||
}
|
||||
|
||||
export class CustomWorldAgentSessionStore {
|
||||
constructor(private readonly runtimeRepository: RuntimeRepositoryPort) {}
|
||||
constructor(private readonly runtimeRepository: CustomWorldSessionCapability) {}
|
||||
|
||||
private async persist(record: CustomWorldAgentSessionRecord) {
|
||||
await this.runtimeRepository.upsertCustomWorldSession(
|
||||
|
||||
@@ -7,7 +7,7 @@ import type {
|
||||
CustomWorldSessionRecord,
|
||||
CustomWorldSessionStatus,
|
||||
} from '../../../packages/shared/src/contracts/runtime.js';
|
||||
import type { RuntimeRepositoryPort } from '../repositories/runtimeRepository.js';
|
||||
import type { CustomWorldSessionCapability } from './runtimeCapabilities.js';
|
||||
|
||||
export type CustomWorldSession = {
|
||||
sessionId: string;
|
||||
@@ -111,7 +111,7 @@ function buildClarificationQuestions(
|
||||
|
||||
export class CustomWorldSessionStore {
|
||||
constructor(
|
||||
private readonly runtimeRepository: RuntimeRepositoryPort,
|
||||
private readonly runtimeRepository: CustomWorldSessionCapability,
|
||||
) {}
|
||||
|
||||
async create(
|
||||
|
||||
@@ -6,7 +6,6 @@ import type {
|
||||
CustomWorldLibraryEntry,
|
||||
CustomWorldProfileRecord,
|
||||
} from '../../../packages/shared/src/contracts/runtime.js';
|
||||
import type { RuntimeRepositoryPort } from '../repositories/runtimeRepository.js';
|
||||
import { resolveCustomWorldCoverPresentation } from '../repositories/customWorldLibraryMetadata.js';
|
||||
import { normalizeFoundationDraftProfile } from './customWorldAgentDraftCompiler.js';
|
||||
import {
|
||||
@@ -26,6 +25,7 @@ import {
|
||||
buildDraftSummaryFromEightAnchorContent,
|
||||
buildDraftTitleFromEightAnchorContent,
|
||||
} from './eightAnchorCompatibilityService.js';
|
||||
import type { CustomWorldWorkSummaryCapability } from './runtimeCapabilities.js';
|
||||
|
||||
function toText(value: unknown) {
|
||||
return typeof value === 'string' ? value.trim() : '';
|
||||
@@ -171,7 +171,7 @@ function isLibraryEntry(
|
||||
export async function listCustomWorldWorkSummaries(
|
||||
userId: string,
|
||||
dependencies: {
|
||||
runtimeRepository: RuntimeRepositoryPort;
|
||||
runtimeRepository: CustomWorldWorkSummaryCapability;
|
||||
customWorldAgentSessions: CustomWorldAgentSessionStore;
|
||||
},
|
||||
) {
|
||||
|
||||
53
server-node/src/services/runtimeCapabilities.ts
Normal file
53
server-node/src/services/runtimeCapabilities.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import type { CustomWorldProfileRecord, CustomWorldSessionRecord } from '../../../packages/shared/src/contracts/runtime.js';
|
||||
import type {
|
||||
RuntimeRepositoryPort,
|
||||
SavedSnapshot,
|
||||
} from '../repositories/runtimeRepository.js';
|
||||
|
||||
export type RuntimeSnapshotCapability = Pick<
|
||||
RuntimeRepositoryPort,
|
||||
'getSnapshot' | 'putSnapshot'
|
||||
>;
|
||||
|
||||
export type CustomWorldProfileCapability = Pick<
|
||||
RuntimeRepositoryPort,
|
||||
'listCustomWorldProfiles'
|
||||
>;
|
||||
|
||||
export type CustomWorldSessionCapability = {
|
||||
listCustomWorldSessions(userId: string): Promise<CustomWorldSessionRecord[]>;
|
||||
getCustomWorldSession(
|
||||
userId: string,
|
||||
sessionId: string,
|
||||
): Promise<CustomWorldSessionRecord | null>;
|
||||
upsertCustomWorldSession(
|
||||
userId: string,
|
||||
sessionId: string,
|
||||
session: CustomWorldSessionRecord,
|
||||
): Promise<CustomWorldSessionRecord>;
|
||||
};
|
||||
|
||||
export type RuntimeStoryCapability = RuntimeSnapshotCapability;
|
||||
|
||||
export type CustomWorldWorkSummaryCapability = CustomWorldProfileCapability;
|
||||
|
||||
export function createRuntimeSnapshotCapability(
|
||||
runtimeRepository: RuntimeRepositoryPort,
|
||||
): RuntimeSnapshotCapability {
|
||||
return runtimeRepository;
|
||||
}
|
||||
|
||||
export function createCustomWorldSessionCapability(
|
||||
runtimeRepository: RuntimeRepositoryPort,
|
||||
): CustomWorldSessionCapability {
|
||||
return runtimeRepository;
|
||||
}
|
||||
|
||||
export function createCustomWorldProfileCapability(
|
||||
runtimeRepository: RuntimeRepositoryPort,
|
||||
): CustomWorldProfileCapability {
|
||||
return runtimeRepository;
|
||||
}
|
||||
|
||||
export type RuntimeStorySnapshot = SavedSnapshot;
|
||||
export type RuntimeCustomWorldProfile = CustomWorldProfileRecord;
|
||||
Reference in New Issue
Block a user