mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-11 22:18:54 +08:00
feat(server): improve context management (#15448)
#### PR Dependency Tree * **PR #15448** 👈 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 artifact upload, browsing, removal, deduplication, and library ownership support. * Copilot now supports scoped document and artifact search, canvas reading, live editor context, and frontend tools. * Added scope and focus selectors with source-resolution receipts in chat. * Added embedding health, progress, synchronization, and retrieval capabilities. * Added BYOK policy visibility, provider restrictions, endpoint dialect selection, and validation. * Added delegated editor interactions and userdata document authorization. * **Bug Fixes** * Improved attachment handling, cancellation, access control, retrieval fallbacks, workspace synchronization, and configuration validation. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -38,8 +38,8 @@ richtext = "1.0.0-alpha02"
|
||||
# @keep
|
||||
targetSdk = "36"
|
||||
timber = "5.0.1"
|
||||
webkit = "1.16.0"
|
||||
version-catalog-update = "1.0.0"
|
||||
webkit = "1.16.0"
|
||||
|
||||
[libraries]
|
||||
android-gradle-plugin = { module = "com.android.tools.build:gradle", version.ref = "android-gradle-plugin" }
|
||||
|
||||
@@ -39,8 +39,11 @@ type WorkspaceByokKey = {
|
||||
description?: string | null;
|
||||
credential: string;
|
||||
definition: {
|
||||
version: number;
|
||||
endpoint: { kind: string; url?: string | null };
|
||||
endpoint: {
|
||||
kind: 'provider_default' | 'openai_compatible';
|
||||
url?: string | null;
|
||||
dialect?: 'responses' | 'chat_completions' | null;
|
||||
};
|
||||
models: Array<{
|
||||
modelId: string;
|
||||
enabled: boolean;
|
||||
@@ -94,8 +97,14 @@ function isAllowedStringArray(
|
||||
|
||||
function isValidEndpoint(value: unknown) {
|
||||
if (!isRecord(value) || typeof value.kind !== 'string') return false;
|
||||
if (value.kind === 'provider_default') return value.url == null;
|
||||
if (value.kind !== 'custom' || typeof value.url !== 'string') return false;
|
||||
if (value.kind === 'provider_default')
|
||||
return value.url == null && value.dialect == null;
|
||||
if (
|
||||
value.kind !== 'openai_compatible' ||
|
||||
typeof value.url !== 'string' ||
|
||||
!['responses', 'chat_completions'].includes(String(value.dialect))
|
||||
)
|
||||
return false;
|
||||
try {
|
||||
const endpoint = new URL(value.url);
|
||||
return (
|
||||
@@ -127,7 +136,6 @@ function isValidDefinition(
|
||||
): value is WorkspaceByokKey['definition'] {
|
||||
return (
|
||||
isRecord(value) &&
|
||||
value.version === 1 &&
|
||||
isValidEndpoint(value.endpoint) &&
|
||||
Array.isArray(value.models) &&
|
||||
value.models.length > 0 &&
|
||||
@@ -155,6 +163,12 @@ function normalizeKey(
|
||||
}
|
||||
const credential = key.credential ?? existing?.credential;
|
||||
const definition = key.definition ?? existing?.definition;
|
||||
if (
|
||||
definition?.endpoint.kind === 'openai_compatible' &&
|
||||
key.provider !== 'openai'
|
||||
) {
|
||||
throw new Error('OpenAI-compatible endpoints require OpenAI provider.');
|
||||
}
|
||||
if (!key.id || !key.name || !credential || !isValidDefinition(definition)) {
|
||||
throw new Error('Invalid BYOK key.');
|
||||
}
|
||||
|
||||
@@ -76,7 +76,6 @@ afterEach(async () => {
|
||||
|
||||
describe('byok storage handlers', () => {
|
||||
const definition = {
|
||||
version: 1,
|
||||
endpoint: { kind: 'provider_default' },
|
||||
models: [
|
||||
{
|
||||
@@ -173,11 +172,21 @@ describe('byok storage handlers', () => {
|
||||
test.each([
|
||||
[
|
||||
'custom endpoint without URL',
|
||||
{ ...definition, endpoint: { kind: 'custom' } },
|
||||
{
|
||||
...definition,
|
||||
endpoint: { kind: 'openai_compatible', dialect: 'responses' },
|
||||
},
|
||||
],
|
||||
[
|
||||
'unsupported endpoint protocol',
|
||||
{ ...definition, endpoint: { kind: 'custom', url: 'file:///tmp/api' } },
|
||||
{
|
||||
...definition,
|
||||
endpoint: {
|
||||
kind: 'openai_compatible',
|
||||
url: 'file:///tmp/api',
|
||||
dialect: 'responses',
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
'malformed capability object',
|
||||
@@ -231,7 +240,11 @@ describe('byok storage handlers', () => {
|
||||
credential: 'sk-openai',
|
||||
definition: {
|
||||
...definition,
|
||||
endpoint: { kind: 'custom', url: 'https://api.openai.example/v1' },
|
||||
endpoint: {
|
||||
kind: 'openai_compatible',
|
||||
url: 'https://api.openai.example/v1',
|
||||
dialect: 'responses',
|
||||
},
|
||||
},
|
||||
sortOrder: 4,
|
||||
enabled: false,
|
||||
@@ -254,7 +267,11 @@ describe('byok storage handlers', () => {
|
||||
description: 'Primary key',
|
||||
definition: {
|
||||
...definition,
|
||||
endpoint: { kind: 'custom', url: 'https://api.openai.example/v1' },
|
||||
endpoint: {
|
||||
kind: 'openai_compatible',
|
||||
url: 'https://api.openai.example/v1',
|
||||
dialect: 'responses',
|
||||
},
|
||||
},
|
||||
sortOrder: 4,
|
||||
enabled: false,
|
||||
@@ -284,7 +301,11 @@ describe('byok storage handlers', () => {
|
||||
credential: 'sk-openai-next',
|
||||
definition: {
|
||||
...definition,
|
||||
endpoint: { kind: 'custom', url: 'https://api.openai.example/v1' },
|
||||
endpoint: {
|
||||
kind: 'openai_compatible',
|
||||
url: 'https://api.openai.example/v1',
|
||||
dialect: 'responses',
|
||||
},
|
||||
},
|
||||
sortOrder: 4,
|
||||
enabled: true,
|
||||
|
||||
Reference in New Issue
Block a user