Install child-friendly replies by default through signed Marketplace delivery

This commit is contained in:
2026-09-28 23:00:54 +08:00
parent efff238a75
commit e70b6eab91
8 changed files with 276 additions and 18 deletions

View File

@@ -0,0 +1,54 @@
import type { AccountBinding, MarketplaceLibrarySnapshot } from './account-plugin-cache';
import { MarketplaceClientError, type MarketplaceClient } from './marketplace-client';
import type { PluginPackageStore } from './package-store';
import { isMakeLoreVersionCompatible } from './release-descriptor';
export const DEFAULT_CHILD_REPLIES_PLUGIN_ID = 'makelore.child-friendly-replies';
/** Defaults use the normal signed Artifact flow and the account's removal receipt. */
export async function installDefaultChildReplies(options: {
marketplace: MarketplaceClient;
packageStore: PluginPackageStore;
clientVersion: string;
binding: AccountBinding | null;
library: MarketplaceLibrarySnapshot;
onInstalled(): Promise<void>;
}): Promise<MarketplaceLibrarySnapshot> {
let library = options.library;
const binding = options.binding;
if (!binding || library.stale) return library;
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');
}
};
const pluginId = DEFAULT_CHILD_REPLIES_PLUGIN_ID;
const entry = library.items.find((item) => item.pluginId === pluginId);
if (entry?.removedAt || entry?.runtimeStatus === 'suspended' || entry?.catalogStatus === 'retired') return library;
try {
assertAccount();
if (entry && await options.packageStore.getInstalled(pluginId)) return library;
const detail = await options.marketplace.readDetail(pluginId);
assertAccount();
const release = detail.stableRelease;
if (detail.stale || detail.runtimeStatus !== 'enabled' || detail.acquisition !== 'free'
|| release?.deliveryKind !== 'artifact' || !release.signingKeyId || !release.descriptorSignature
|| !isMakeLoreVersionCompatible(options.clientVersion, release.minMakeloreVersion, release.maxMakeloreVersion)) return library;
if (!entry) {
library = await options.marketplace.acquire(pluginId);
assertAccount();
}
await options.packageStore.resolveAndInstall({
pluginId, makeloreVersion: options.clientVersion, channel: 'stable',
});
assertAccount();
await options.onInstalled();
} catch (error) {
assertAccount();
if (error instanceof MarketplaceClientError && error.code === 'marketplace_account_changed') throw error;
// An unavailable default must not hide the rest of the Library. A later
// session/list refresh retries; no local success or removal receipt is invented.
}
return library;
}