Integrate role asset studio into custom world agent flow

This commit is contained in:
2026-04-14 20:16:41 +08:00
parent 0981d6ee1b
commit bc2999ffb9
118 changed files with 31211 additions and 1232 deletions

View File

@@ -1,14 +1,15 @@
import type { QueryResultRow } from 'pg';
import {
DEFAULT_MUSIC_VOLUME,
SAVE_SNAPSHOT_VERSION,
} from '../../../packages/shared/src/contracts/runtime.js';
import type {
CustomWorldProfileRecord,
RuntimeSettings,
SavedGameSnapshot,
} from '../../../packages/shared/src/contracts/runtime.js';
import {
type CustomWorldSessionRecord,
DEFAULT_MUSIC_VOLUME,
SAVE_SNAPSHOT_VERSION,
} from '../../../packages/shared/src/contracts/runtime.js';
import type { AppDatabase } from '../db.js';
const MAX_CUSTOM_WORLD_PROFILES = 12;
@@ -29,6 +30,13 @@ type SettingsRow = QueryResultRow & {
type ProfileRow = QueryResultRow & {
payload: CustomWorldProfileRecord;
updatedAt: string;
};
type SessionRow = QueryResultRow & {
payload: CustomWorldSessionRecord;
createdAt: string;
updatedAt: string;
};
export type RuntimeRepositoryPort = {
@@ -53,6 +61,16 @@ export type RuntimeRepositoryPort = {
userId: string,
profileId: string,
): Promise<CustomWorldProfileRecord[]>;
listCustomWorldSessions(userId: string): Promise<CustomWorldSessionRecord[]>;
getCustomWorldSession(
userId: string,
sessionId: string,
): Promise<CustomWorldSessionRecord | null>;
upsertCustomWorldSession(
userId: string,
sessionId: string,
session: CustomWorldSessionRecord,
): Promise<CustomWorldSessionRecord>;
};
export class RuntimeRepository implements RuntimeRepositoryPort {
@@ -175,7 +193,8 @@ export class RuntimeRepository implements RuntimeRepositoryPort {
async listCustomWorldProfiles(userId: string) {
const result = await this.db.query<ProfileRow>(
`SELECT payload_json AS payload
`SELECT payload_json AS payload,
updated_at AS "updatedAt"
FROM custom_world_profiles
WHERE user_id = $1
ORDER BY updated_at DESC
@@ -183,7 +202,10 @@ export class RuntimeRepository implements RuntimeRepositoryPort {
[userId, MAX_CUSTOM_WORLD_PROFILES],
);
return result.rows.map((row: ProfileRow) => row.payload);
return result.rows.map((row: ProfileRow) => ({
...row.payload,
updatedAt: row.updatedAt,
}));
}
async upsertCustomWorldProfile(
@@ -217,4 +239,75 @@ export class RuntimeRepository implements RuntimeRepositoryPort {
return this.listCustomWorldProfiles(userId);
}
async listCustomWorldSessions(userId: string) {
const result = await this.db.query<SessionRow>(
`SELECT payload_json AS payload,
created_at AS "createdAt",
updated_at AS "updatedAt"
FROM custom_world_sessions
WHERE user_id = $1
ORDER BY updated_at DESC`,
[userId],
);
return result.rows.map((row) => ({
...row.payload,
createdAt: row.createdAt,
updatedAt: row.updatedAt,
}));
}
async getCustomWorldSession(userId: string, sessionId: string) {
const result = await this.db.query<SessionRow>(
`SELECT payload_json AS payload,
created_at AS "createdAt",
updated_at AS "updatedAt"
FROM custom_world_sessions
WHERE user_id = $1 AND session_id = $2`,
[userId, sessionId],
);
const row = result.rows[0];
if (!row) {
return null;
}
return {
...row.payload,
createdAt: row.createdAt,
updatedAt: row.updatedAt,
};
}
async upsertCustomWorldSession(
userId: string,
sessionId: string,
session: CustomWorldSessionRecord,
) {
const payload = {
...session,
sessionId,
} satisfies CustomWorldSessionRecord;
await this.db.query(
`INSERT INTO custom_world_sessions (
user_id,
session_id,
payload_json,
created_at,
updated_at
) VALUES ($1, $2, $3, $4, $5)
ON CONFLICT (user_id, session_id) DO UPDATE SET
payload_json = EXCLUDED.payload_json,
updated_at = EXCLUDED.updated_at`,
[userId, sessionId, payload, session.createdAt, session.updatedAt],
);
return {
...payload,
createdAt: session.createdAt,
updatedAt: session.updatedAt,
};
}
}