Install child-friendly replies by default through signed Marketplace delivery

This commit is contained in:
brother7 committed 2026-09-28 23:00:54 +08:00
1 parent efff238a75
commit e70b6eab91
8 files changed
+276 -18

No files matched your search

+2
View File
@@ -545,8 +545,10 @@ export function createCodingComposition(
});
void gameResourceDelivery.resumePending().catch(() => undefined);
void gameAudioDelivery.resumePending().catch(() => undefined);
void pluginMarketplace.readLibrary().catch(() => undefined);
const unsubscribeMarketplaceSession = subscribeWorksSquareSession(() => {
void invalidateManagedResources();
void pluginMarketplace.readLibrary().catch(() => undefined);
void gameResourceDelivery.resumePending().catch(() => undefined);
void gameAudioDelivery.resumePending().catch(() => undefined);
});
+38 -9
View File
@@ -28,6 +28,8 @@ import type {
PluginBackendProjection,
} from '../coding-plugins/registry';
import type { ProjectPluginService } from '../coding-plugins/project-service';
import { DEFAULT_CHILD_REPLIES_PLUGIN_ID, installDefaultChildReplies } from '../coding-plugins/default-installation';
import { MarketplaceClientError } from '../coding-plugins/marketplace-client';
import type {
PluginBillingPolicy,
PluginCatalogOperation,
@@ -170,6 +172,25 @@ async function publicLibrary(
export function createCodingPluginMarketplaceService(
options: CreateCodingPluginMarketplaceServiceOptions,
): CodingPluginMarketplaceService {
// Order automatic installation and explicit removal so the user's later action wins.
let pending: Promise<unknown> = Promise.resolve();
const forAccount = <T>(action: () => Promise<T>): Promise<T> => {
const binding = options.marketplace.getCurrentAccountBinding();
const run = pending.then(async () => {
const assertAccount = () => {
const current = options.marketplace.getCurrentAccountBinding();
if (current?.accountKey !== binding?.accountKey || current?.epoch !== binding?.epoch) {
throw new MarketplaceClientError('marketplace_account_changed', 409, 'Marketplace account changed');
}
};
assertAccount();
const result = await action();
assertAccount();
return result;
});
pending = run.catch(() => undefined);
return run;
};
const install = async (pluginId: string, kind: 'install' | 'update'): Promise<PublicPluginInstallation> => {
const snapshot = await options.packageStore.resolveAndInstall({
pluginId,
@@ -190,6 +211,7 @@ export function createCodingPluginMarketplaceService(
return publicInstallation(snapshot);
};
const uninstall = async (pluginId: string): Promise<PublicPluginInstallation> => {
if (pluginId === DEFAULT_CHILD_REPLIES_PLUGIN_ID) await options.marketplace.remove(pluginId);
const snapshot = await options.packageStore.uninstall(pluginId);
await options.onChanged?.({ pluginId, kind: 'uninstall' });
return publicInstallation(snapshot);
@@ -197,21 +219,28 @@ export function createCodingPluginMarketplaceService(
return {
readCatalog: (input = {}) => options.marketplace.readCatalog(input),
readDetail: (pluginId) => options.marketplace.readDetail(pluginId),
readLibrary: async () => publicLibrary(await options.marketplace.readLibrary(), options.packageStore),
acquire: async (pluginId) => {
readLibrary: () => forAccount(async () => {
const binding = options.marketplace.getCurrentAccountBinding();
const library = await installDefaultChildReplies({
...options, binding, library: await options.marketplace.readLibrary(),
onInstalled: async () => { await options.onChanged?.({ pluginId: DEFAULT_CHILD_REPLIES_PLUGIN_ID, kind: 'install' }); },
});
return publicLibrary(library, options.packageStore);
}),
acquire: (pluginId) => forAccount(async () => {
const snapshot = await options.marketplace.acquire(pluginId);
await options.onChanged?.({ pluginId, kind: 'acquire' });
return publicLibrary(snapshot, options.packageStore);
},
remove: async (pluginId) => {
}),
remove: (pluginId) => forAccount(async () => {
const snapshot = await options.marketplace.remove(pluginId);
await options.onChanged?.({ pluginId, kind: 'remove' });
return publicLibrary(snapshot, options.packageStore);
},
install: (pluginId) => install(pluginId, 'install'),
installBeta,
update: (pluginId) => install(pluginId, 'update'),
uninstall,
}),
install: (pluginId) => forAccount(() => install(pluginId, 'install')),
installBeta: (pluginId) => forAccount(() => installBeta(pluginId)),
update: (pluginId) => forAccount(() => install(pluginId, 'update')),
uninstall: (pluginId) => forAccount(() => uninstall(pluginId)),
};
}