Refine desktop setup and remove bundled app center apps

This commit is contained in:
inman
2026-06-04 09:58:58 +08:00
parent 6153579b90
commit 84128dbe23
73 changed files with 3888 additions and 2024 deletions

View File

@@ -65,6 +65,12 @@ vi.mock('@electron/shared/providers/registry', () => ({
import { ProviderService } from '@electron/services/providers/provider-service';
import type { ProviderAccount } from '@electron/shared/providers/types';
import {
YINIAN_MODEL_DEFAULT_BASE_URL,
YINIAN_MODEL_REF,
} from '../../shared/yinian-model';
const MINIMAX_DEFAULT_MODEL_ID = 'MiniMax-M3';
function makeAccount(overrides: Partial<ProviderAccount> = {}): ProviderAccount {
return {
@@ -90,7 +96,7 @@ function setupDefaultKeyMapping() {
);
}
describe('ProviderService.listAccounts (openclaw.json as sole source of truth)', () => {
describe('ProviderService.listAccounts', () => {
let service: ProviderService;
beforeEach(() => {
@@ -104,7 +110,7 @@ describe('ProviderService.listAccounts (openclaw.json as sole source of truth)',
service = new ProviderService();
});
it('returns empty when activeProviders is empty', async () => {
it('keeps stored accounts when runtime providers are empty', async () => {
mocks.listProviderAccounts.mockResolvedValue([
makeAccount({ id: 'moonshot-1', vendorId: 'moonshot' as ProviderAccount['vendorId'] }),
]);
@@ -112,10 +118,11 @@ describe('ProviderService.listAccounts (openclaw.json as sole source of truth)',
const result = await service.listAccounts();
expect(result).toEqual([]);
expect(result).toHaveLength(1);
expect(result[0].id).toBe('moonshot-1');
});
it('returns only providers present in openclaw.json, ignoring extra store accounts', async () => {
it('keeps stored accounts even when openclaw.json is missing a runtime provider', async () => {
mocks.listProviderAccounts.mockResolvedValue([
makeAccount({ id: 'moonshot-1', vendorId: 'moonshot' as ProviderAccount['vendorId'] }),
makeAccount({ id: 'custom-orphan', vendorId: 'custom' as ProviderAccount['vendorId'] }),
@@ -129,8 +136,8 @@ describe('ProviderService.listAccounts (openclaw.json as sole source of truth)',
const result = await service.listAccounts();
expect(result).toHaveLength(1);
expect(result[0].id).toBe('moonshot-1');
expect(result).toHaveLength(2);
expect(result.map((account: ProviderAccount) => account.id)).toEqual(['moonshot-1', 'custom-orphan']);
});
it('seeds new account from openclaw.json when no store match exists', async () => {
@@ -150,6 +157,70 @@ describe('ProviderService.listAccounts (openclaw.json as sole source of truth)',
expect(result).toHaveLength(1);
});
it('does not re-seed the legacy placeholder yinian model provider', async () => {
mocks.listProviderAccounts.mockResolvedValue([]);
mocks.getActiveOpenClawProviders.mockResolvedValue(new Set(['yinian-model']));
mocks.getOpenClawProvidersConfig.mockResolvedValue({
providers: {
'yinian-model': {
baseUrl: YINIAN_MODEL_DEFAULT_BASE_URL,
api: 'openai-completions',
models: [{ id: 'custom-model', name: 'Custom Model' }],
},
},
defaultModel: YINIAN_MODEL_REF,
});
const result = await service.listAccounts();
expect(result).toEqual([]);
expect(mocks.saveProviderAccount).not.toHaveBeenCalled();
});
it('does not seed auth-only yinian model leftovers without a runtime baseUrl', async () => {
mocks.listProviderAccounts.mockResolvedValue([]);
mocks.getActiveOpenClawProviders.mockResolvedValue(new Set(['yinian-model']));
mocks.getOpenClawProvidersConfig.mockResolvedValue({
providers: {
'yinian-model': {},
},
defaultModel: 'minimax-portal/MiniMax-M3',
});
const result = await service.listAccounts();
expect(result).toEqual([]);
expect(mocks.saveProviderAccount).not.toHaveBeenCalled();
});
it('removes a previously seeded legacy placeholder yinian model account', async () => {
mocks.listProviderAccounts.mockResolvedValue([
makeAccount({
id: 'yinian-model',
vendorId: 'custom' as ProviderAccount['vendorId'],
baseUrl: YINIAN_MODEL_DEFAULT_BASE_URL,
model: YINIAN_MODEL_REF,
}),
makeAccount({ id: 'moonshot-1', vendorId: 'moonshot' as ProviderAccount['vendorId'] }),
]);
mocks.getActiveOpenClawProviders.mockResolvedValue(new Set(['yinian-model']));
mocks.getOpenClawProvidersConfig.mockResolvedValue({
providers: {
'yinian-model': {
baseUrl: YINIAN_MODEL_DEFAULT_BASE_URL,
models: [{ id: 'custom-model', name: 'Custom Model' }],
},
},
defaultModel: YINIAN_MODEL_REF,
});
const result = await service.listAccounts();
expect(result).toHaveLength(1);
expect(result[0].id).toBe('moonshot-1');
expect(mocks.deleteProviderAccount).toHaveBeenCalledWith('yinian-model');
});
it('uses store metadata when match exists (does not re-seed)', async () => {
mocks.listProviderAccounts.mockResolvedValue([
makeAccount({ id: 'moonshot', vendorId: 'moonshot' as ProviderAccount['vendorId'], label: 'My Moonshot' }),
@@ -306,7 +377,7 @@ describe('ProviderService.listAccounts (openclaw.json as sole source of truth)',
id: 'minimax-portal-cn',
name: 'MiniMax (CN)',
defaultAuthMode: 'oauth_device',
defaultModelId: 'MiniMax-M2.7',
defaultModelId: MINIMAX_DEFAULT_MODEL_ID,
providerConfig: {
baseUrl: 'https://api.minimaxi.com/anthropic',
api: 'anthropic-messages',