mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-08 04:36:13 +08:00
feat(server): converge legacy compatibility (#15426)
#### PR Dependency Tree * **PR #15426** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added workspace BYOK profiles with provider/model catalogs, capability validation, connection probing, credential rotation, reordering, and secure local leases. * Added Copilot route options, selectable targets, managed tiers, explicit profile/model overrides, and improved streaming with tool callbacks and abort support. * Added Copilot availability controls to prevent access when the feature is disabled. * **Changes** * Simplified Copilot configuration and removed legacy provider-specific settings. * Removed obsolete model, token-cost, transcript strategy, and provider metadata fields from public responses. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -75,6 +75,25 @@ afterEach(async () => {
|
||||
});
|
||||
|
||||
describe('byok storage handlers', () => {
|
||||
const definition = {
|
||||
version: 1,
|
||||
endpoint: { kind: 'provider_default' },
|
||||
models: [
|
||||
{
|
||||
modelId: 'model-1',
|
||||
enabled: true,
|
||||
capabilities: [
|
||||
{
|
||||
input: ['text'],
|
||||
output: ['text'],
|
||||
features: [],
|
||||
attachmentKinds: [],
|
||||
attachmentSources: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
test('stores encrypted local keys and keeps lease providers sorted', async () => {
|
||||
const { byokStorageHandlers, disposeWorkspaceByokStorage: dispose } =
|
||||
await import('@affine/electron/main/byok-storage/handlers');
|
||||
@@ -85,14 +104,16 @@ describe('byok storage handlers', () => {
|
||||
id: 'local-openai',
|
||||
provider: 'openai',
|
||||
name: 'OpenAI',
|
||||
apiKey: 'sk-openai',
|
||||
credential: 'sk-openai',
|
||||
definition,
|
||||
sortOrder: 1,
|
||||
});
|
||||
await byokStorageHandlers.upsertWorkspaceKey(ipcEvent, 'workspace-1', {
|
||||
id: 'local-gemini',
|
||||
provider: 'gemini',
|
||||
name: 'Gemini',
|
||||
apiKey: 'sk-gemini',
|
||||
credential: 'sk-gemini',
|
||||
definition,
|
||||
sortOrder: 0,
|
||||
});
|
||||
|
||||
@@ -117,7 +138,7 @@ describe('byok storage handlers', () => {
|
||||
ipcEvent,
|
||||
'workspace-1'
|
||||
);
|
||||
expect(leaseProviders.map(key => key.apiKey)).toEqual([
|
||||
expect(leaseProviders.map(key => key.credential)).toEqual([
|
||||
'sk-openai',
|
||||
'sk-gemini',
|
||||
]);
|
||||
@@ -142,12 +163,60 @@ describe('byok storage handlers', () => {
|
||||
id: 'local-openai',
|
||||
provider: 'openai',
|
||||
name: 'OpenAI',
|
||||
apiKey: 'sk-openai',
|
||||
credential: 'sk-openai',
|
||||
definition,
|
||||
})
|
||||
).rejects.toThrow('Secure BYOK key storage is not available.');
|
||||
expect(electronMock.encryptString).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test.each([
|
||||
[
|
||||
'custom endpoint without URL',
|
||||
{ ...definition, endpoint: { kind: 'custom' } },
|
||||
],
|
||||
[
|
||||
'unsupported endpoint protocol',
|
||||
{ ...definition, endpoint: { kind: 'custom', url: 'file:///tmp/api' } },
|
||||
],
|
||||
[
|
||||
'malformed capability object',
|
||||
{
|
||||
...definition,
|
||||
models: [{ ...definition.models[0], capabilities: [{}] }],
|
||||
},
|
||||
],
|
||||
[
|
||||
'unknown capability value',
|
||||
{
|
||||
...definition,
|
||||
models: [
|
||||
{
|
||||
...definition.models[0],
|
||||
capabilities: [
|
||||
{ ...definition.models[0].capabilities[0], input: ['video'] },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
])('rejects %s from IPC input', async (_name, malformedDefinition) => {
|
||||
const { byokStorageHandlers, disposeWorkspaceByokStorage: dispose } =
|
||||
await import('@affine/electron/main/byok-storage/handlers');
|
||||
disposeWorkspaceByokStorage = dispose;
|
||||
|
||||
await expect(
|
||||
byokStorageHandlers.upsertWorkspaceKey(undefined, 'workspace-1', {
|
||||
id: 'local-openai',
|
||||
provider: 'openai',
|
||||
name: 'OpenAI',
|
||||
credential: 'sk-openai',
|
||||
definition: malformedDefinition as typeof definition,
|
||||
})
|
||||
).rejects.toThrow('Invalid BYOK key.');
|
||||
expect(electronMock.encryptString).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('preserves existing local key fields during partial updates', async () => {
|
||||
const { byokStorageHandlers, disposeWorkspaceByokStorage: dispose } =
|
||||
await import('@affine/electron/main/byok-storage/handlers');
|
||||
@@ -159,8 +228,11 @@ describe('byok storage handlers', () => {
|
||||
provider: 'openai',
|
||||
name: 'OpenAI',
|
||||
description: 'Primary key',
|
||||
apiKey: 'sk-openai',
|
||||
endpoint: 'https://api.openai.example/v1',
|
||||
credential: 'sk-openai',
|
||||
definition: {
|
||||
...definition,
|
||||
endpoint: { kind: 'custom', url: 'https://api.openai.example/v1' },
|
||||
},
|
||||
sortOrder: 4,
|
||||
enabled: false,
|
||||
});
|
||||
@@ -169,7 +241,7 @@ describe('byok storage handlers', () => {
|
||||
id: 'local-openai',
|
||||
provider: 'openai',
|
||||
name: 'OpenAI renamed',
|
||||
apiKey: 'sk-openai-next',
|
||||
credential: 'sk-openai-next',
|
||||
});
|
||||
|
||||
const [publicKey] = await byokStorageHandlers.listWorkspaceKeys(
|
||||
@@ -180,7 +252,10 @@ describe('byok storage handlers', () => {
|
||||
id: 'local-openai',
|
||||
name: 'OpenAI renamed',
|
||||
description: 'Primary key',
|
||||
endpoint: 'https://api.openai.example/v1',
|
||||
definition: {
|
||||
...definition,
|
||||
endpoint: { kind: 'custom', url: 'https://api.openai.example/v1' },
|
||||
},
|
||||
sortOrder: 4,
|
||||
enabled: false,
|
||||
});
|
||||
@@ -206,8 +281,11 @@ describe('byok storage handlers', () => {
|
||||
);
|
||||
expect(enabledLeaseProvider).toMatchObject({
|
||||
name: 'OpenAI renamed again',
|
||||
apiKey: 'sk-openai-next',
|
||||
endpoint: 'https://api.openai.example/v1',
|
||||
credential: 'sk-openai-next',
|
||||
definition: {
|
||||
...definition,
|
||||
endpoint: { kind: 'custom', url: 'https://api.openai.example/v1' },
|
||||
},
|
||||
sortOrder: 4,
|
||||
enabled: true,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user