feat: add official game audio generation client

This commit is contained in:
2026-09-21 12:17:32 +08:00
parent d222d17500
commit 09e0ce5cf3
28 changed files with 1835 additions and 31 deletions

View File

@@ -48,6 +48,10 @@ import {
import { createDataServicePluginAdapter } from '../coding-plugins/adapters/data-service';
import { createGameResourcePluginAdapter } from '../coding-plugins/adapters/game-resource';
import { GameResourceClient } from '../services/game-resource-client';
import { GameAudioClient } from '../services/game-audio-client';
import { GameAudioDeliveryCoordinator, GameAudioReceiptStore } from '../services/game-audio-delivery';
import { GameAudioPluginAdapter } from '../coding-plugins/adapters/game-audio';
import { MarketplaceHostedAdmissionResolver } from '../coding-plugins/hosted-admission';
import {
GameResourceDeliveryCoordinator,
GameResourceDeliveryReceiptStore,
@@ -339,6 +343,27 @@ export function createCodingComposition(
bundledReleases: CODE_OWNED_OPTIONAL_BUNDLED_RELEASES,
});
const policyClient = options.policyClient ?? new PluginPolicyClient();
const gameAudioClient = new GameAudioClient();
const gameAudioDelivery = new GameAudioDeliveryCoordinator({
client: gameAudioClient,
receipts: new GameAudioReceiptStore(path.join(options.paths.userDataDir, 'coding-runtime', 'game-audio', 'receipts.json')),
leases: projectWriteLeases,
recordTouchedPaths: (conversationId, runId, paths) => productTools.recordTouchedPaths(conversationId, runId, paths),
...(options.acquireBackgroundLease ? { acquireBackgroundLease: options.acquireBackgroundLease } : {}),
});
const gameAudioAdapter = new GameAudioPluginAdapter({
client: gameAudioClient,
delivery: gameAudioDelivery,
admission: new MarketplaceHostedAdmissionResolver({
marketplace: marketplaceClient, packageStore,
makeloreVersion: options.clientVersion ?? '2.0.1',
bundledReleases: CODE_OWNED_OPTIONAL_BUNDLED_RELEASES,
}),
getPricingVersion: () => {
const state = policyClient.getState();
return state.status === 'current' ? state.catalog?.pricing_version?.version_id ?? null : null;
},
});
const knownPluginIds = new Set(pluginDefinitions.map(({ id }) => id));
// Existing user Releases are discovered from the device index at startup;
// unlike the bundled catalog they cannot be enumerated synchronously. Keep
@@ -373,7 +398,7 @@ export function createCodingComposition(
const capabilityRegistry = createCodingCapabilityRegistry({
policyClient,
projectPlugins,
adapters: [dataServiceAdapter, gameResourceAdapter],
adapters: [dataServiceAdapter, gameResourceAdapter, gameAudioAdapter],
definitions: pluginDefinitions,
effectiveResolver,
getDurableProjectId: async (projectPath, localProjectId) => {
@@ -389,7 +414,7 @@ export function createCodingComposition(
projects,
projectPlugins,
policyClient,
adapters: [dataServiceAdapter, gameResourceAdapter],
adapters: [dataServiceAdapter, gameResourceAdapter, gameAudioAdapter],
definitions: pluginDefinitions,
effectiveResolver,
getDefinitions: async () => {
@@ -505,9 +530,11 @@ export function createCodingComposition(
},
});
void gameResourceDelivery.resumePending().catch(() => undefined);
void gameAudioDelivery.resumePending().catch(() => undefined);
const unsubscribeMarketplaceSession = subscribeWorksSquareSession(() => {
void invalidateManagedResources();
void gameResourceDelivery.resumePending().catch(() => undefined);
void gameAudioDelivery.resumePending().catch(() => undefined);
});
const host = createCodingProductHost({
projects,
@@ -526,6 +553,7 @@ export function createCodingComposition(
})
: () => undefined;
return {
gameAudio: gameAudioDelivery,
attachments,
dataService,
devicePackages: devicePackageManager,
@@ -557,6 +585,7 @@ export function createCodingComposition(
async shutdown() {
conversations.dispose();
gameResourceDelivery.dispose();
gameAudioDelivery.dispose();
previewDataSession?.dispose();
if (typeof options.browser.configurePreviewDataSession === 'function') {
options.browser.configurePreviewDataSession(undefined);