mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-21 03:56:23 +08:00
feat(server): adapt gemini3.1 preview (#14583)
#### PR Dependency Tree * **PR #14583** 👈 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 Gemini 3.1 Pro Preview support (text, image, audio) and new GPT‑5 variants as defaults; centralized persistent telemetry state for more reliable client identity. * **UX** * Improved model submenu placement in chat preferences. * More robust mindmap parsing, preview, regeneration and replace behavior. * **Chores** * Bumped AI SDK and related dependencies. * **Tests** * Expanded/updated tests and increased timeouts for flaky flows. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -118,7 +118,6 @@ test.serial.before(async t => {
|
||||
enabled: true,
|
||||
scenarios: {
|
||||
image: 'flux-1/schnell',
|
||||
rerank: 'gpt-5-mini',
|
||||
complex_text_generation: 'gpt-5-mini',
|
||||
coding: 'gpt-5-mini',
|
||||
quick_decision_making: 'gpt-5-mini',
|
||||
@@ -931,8 +930,8 @@ test(
|
||||
t.log('Rerank scores:', scores);
|
||||
t.is(
|
||||
scores.filter(s => s > 0.5).length,
|
||||
4,
|
||||
'should have 4 related chunks'
|
||||
5,
|
||||
'should have 5 related chunks'
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ test('NativeProviderAdapter streamText should append citation footnotes', async
|
||||
const adapter = new NativeProviderAdapter(mockDispatch, {}, 3);
|
||||
const chunks: string[] = [];
|
||||
for await (const chunk of adapter.streamText({
|
||||
model: 'gpt-4.1',
|
||||
model: 'gpt-5-mini',
|
||||
stream: true,
|
||||
messages: [{ role: 'user', content: [{ type: 'text', text: 'hi' }] }],
|
||||
})) {
|
||||
@@ -36,7 +36,7 @@ test('NativeProviderAdapter streamObject should append citation footnotes', asyn
|
||||
const adapter = new NativeProviderAdapter(mockDispatch, {}, 3);
|
||||
const chunks = [];
|
||||
for await (const chunk of adapter.streamObject({
|
||||
model: 'gpt-4.1',
|
||||
model: 'gpt-5-mini',
|
||||
stream: true,
|
||||
messages: [{ role: 'user', content: [{ type: 'text', text: 'hi' }] }],
|
||||
})) {
|
||||
@@ -91,7 +91,7 @@ test('NativeProviderAdapter streamObject should append fallback attachment footn
|
||||
const adapter = new NativeProviderAdapter(dispatch, {}, 3);
|
||||
const chunks = [];
|
||||
for await (const chunk of adapter.streamObject({
|
||||
model: 'gpt-4.1',
|
||||
model: 'gpt-5-mini',
|
||||
stream: true,
|
||||
messages: [{ role: 'user', content: [{ type: 'text', text: 'hi' }] }],
|
||||
})) {
|
||||
@@ -148,7 +148,7 @@ test('NativeProviderAdapter streamObject should map tool and text events', async
|
||||
|
||||
const events = [];
|
||||
for await (const event of adapter.streamObject({
|
||||
model: 'gpt-4.1',
|
||||
model: 'gpt-5-mini',
|
||||
stream: true,
|
||||
messages: [{ role: 'user', content: [{ type: 'text', text: 'read' }] }],
|
||||
})) {
|
||||
@@ -169,7 +169,7 @@ test('NativeProviderAdapter streamObject should map tool and text events', async
|
||||
|
||||
test('buildNativeRequest should include rust middleware from profile', async t => {
|
||||
const { request } = await buildNativeRequest({
|
||||
model: 'gpt-4.1',
|
||||
model: 'gpt-5-mini',
|
||||
messages: [{ role: 'user', content: 'hello' }],
|
||||
tools: {},
|
||||
middleware: {
|
||||
@@ -195,7 +195,7 @@ test('NativeProviderAdapter streamText should skip citation footnotes when disab
|
||||
});
|
||||
const chunks: string[] = [];
|
||||
for await (const chunk of adapter.streamText({
|
||||
model: 'gpt-4.1',
|
||||
model: 'gpt-5-mini',
|
||||
stream: true,
|
||||
messages: [{ role: 'user', content: [{ type: 'text', text: 'hi' }] }],
|
||||
})) {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import test from 'ava';
|
||||
|
||||
import { ProviderMiddlewareConfig } from '../../plugins/copilot/config';
|
||||
import { normalizeOpenAIOptionsForModel } from '../../plugins/copilot/providers/openai';
|
||||
import { CopilotProvider } from '../../plugins/copilot/providers/provider';
|
||||
import { normalizeRerankModel } from '../../plugins/copilot/providers/rerank';
|
||||
import {
|
||||
CopilotProviderType,
|
||||
ModelInputType,
|
||||
@@ -12,7 +14,7 @@ class TestOpenAIProvider extends CopilotProvider<{ apiKey: string }> {
|
||||
readonly type = CopilotProviderType.OpenAI;
|
||||
readonly models = [
|
||||
{
|
||||
id: 'gpt-4.1',
|
||||
id: 'gpt-5-mini',
|
||||
capabilities: [
|
||||
{
|
||||
input: [ModelInputType.Text],
|
||||
@@ -36,7 +38,7 @@ class TestOpenAIProvider extends CopilotProvider<{ apiKey: string }> {
|
||||
}
|
||||
|
||||
exposeMetricLabels() {
|
||||
return this.metricLabels('gpt-4.1');
|
||||
return this.metricLabels('gpt-5-mini');
|
||||
}
|
||||
|
||||
exposeMiddleware() {
|
||||
@@ -97,3 +99,41 @@ test('getActiveProviderMiddleware should merge defaults with profile override',
|
||||
'thinking_format',
|
||||
]);
|
||||
});
|
||||
|
||||
test('normalizeOpenAIOptionsForModel should drop sampling knobs for gpt-5.2', t => {
|
||||
t.deepEqual(
|
||||
normalizeOpenAIOptionsForModel(
|
||||
{
|
||||
temperature: 0.7,
|
||||
topP: 0.8,
|
||||
presencePenalty: 0.2,
|
||||
frequencyPenalty: 0.1,
|
||||
maxTokens: 128,
|
||||
},
|
||||
'gpt-5.4'
|
||||
),
|
||||
{ maxTokens: 128 }
|
||||
);
|
||||
});
|
||||
|
||||
test('normalizeOpenAIOptionsForModel should keep options for gpt-4.1', t => {
|
||||
t.deepEqual(
|
||||
normalizeOpenAIOptionsForModel(
|
||||
{ temperature: 0.7, topP: 0.8, maxTokens: 128 },
|
||||
'gpt-4.1'
|
||||
),
|
||||
{ temperature: 0.7, topP: 0.8, maxTokens: 128 }
|
||||
);
|
||||
});
|
||||
|
||||
test('normalizeOpenAIRerankModel should keep supported rerank models', t => {
|
||||
t.is(normalizeRerankModel('gpt-4.1'), 'gpt-4.1');
|
||||
t.is(normalizeRerankModel('gpt-4.1-mini'), 'gpt-4.1-mini');
|
||||
t.is(normalizeRerankModel('gpt-5.2'), 'gpt-5.2');
|
||||
});
|
||||
|
||||
test('normalizeOpenAIRerankModel should fall back for unsupported models', t => {
|
||||
t.is(normalizeRerankModel('gpt-5-mini'), 'gpt-5.2');
|
||||
t.is(normalizeRerankModel('gemini-2.5-flash'), 'gpt-5.2');
|
||||
t.is(normalizeRerankModel(undefined), 'gpt-5.2');
|
||||
});
|
||||
|
||||
@@ -88,11 +88,11 @@ test('resolveModel should support explicit provider prefix and keep slash models
|
||||
|
||||
const prefixed = resolveModel({
|
||||
registry,
|
||||
modelId: 'openai-main/gpt-4.1',
|
||||
modelId: 'openai-main/gpt-5-mini',
|
||||
});
|
||||
t.deepEqual(prefixed, {
|
||||
rawModelId: 'openai-main/gpt-4.1',
|
||||
modelId: 'gpt-4.1',
|
||||
rawModelId: 'openai-main/gpt-5-mini',
|
||||
modelId: 'gpt-5-mini',
|
||||
explicitProviderId: 'openai-main',
|
||||
candidateProviderIds: ['openai-main'],
|
||||
});
|
||||
@@ -154,12 +154,15 @@ test('stripProviderPrefix should only strip matched provider prefix', t => {
|
||||
});
|
||||
|
||||
t.is(
|
||||
stripProviderPrefix(registry, 'openai-main', 'openai-main/gpt-4.1'),
|
||||
'gpt-4.1'
|
||||
stripProviderPrefix(registry, 'openai-main', 'openai-main/gpt-5-mini'),
|
||||
'gpt-5-mini'
|
||||
);
|
||||
t.is(
|
||||
stripProviderPrefix(registry, 'openai-main', 'another-main/gpt-4.1'),
|
||||
'another-main/gpt-4.1'
|
||||
stripProviderPrefix(registry, 'openai-main', 'another-main/gpt-5-mini'),
|
||||
'another-main/gpt-5-mini'
|
||||
);
|
||||
t.is(
|
||||
stripProviderPrefix(registry, 'openai-main', 'gpt-5-mini'),
|
||||
'gpt-5-mini'
|
||||
);
|
||||
t.is(stripProviderPrefix(registry, 'openai-main', 'gpt-4.1'), 'gpt-4.1');
|
||||
});
|
||||
|
||||
@@ -116,7 +116,7 @@ test('ToolCallLoop should execute tool call and continue to next round', async t
|
||||
|
||||
const events: NativeLlmStreamEvent[] = [];
|
||||
for await (const event of loop.run({
|
||||
model: 'gpt-4.1',
|
||||
model: 'gpt-5-mini',
|
||||
stream: true,
|
||||
messages: [{ role: 'user', content: [{ type: 'text', text: 'read doc' }] }],
|
||||
})) {
|
||||
|
||||
@@ -39,33 +39,6 @@ export class MockCopilotProvider extends OpenAIProvider {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'gpt-4o',
|
||||
capabilities: [
|
||||
{
|
||||
input: [ModelInputType.Text, ModelInputType.Image],
|
||||
output: [ModelOutputType.Text, ModelOutputType.Object],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'gpt-4o-2024-08-06',
|
||||
capabilities: [
|
||||
{
|
||||
input: [ModelInputType.Text, ModelInputType.Image],
|
||||
output: [ModelOutputType.Text, ModelOutputType.Object],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'gpt-4.1-2025-04-14',
|
||||
capabilities: [
|
||||
{
|
||||
input: [ModelInputType.Text, ModelInputType.Image],
|
||||
output: [ModelOutputType.Text, ModelOutputType.Object],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'gpt-5',
|
||||
capabilities: [
|
||||
@@ -97,6 +70,19 @@ export class MockCopilotProvider extends OpenAIProvider {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'gpt-5-nano',
|
||||
capabilities: [
|
||||
{
|
||||
input: [ModelInputType.Text, ModelInputType.Image],
|
||||
output: [
|
||||
ModelOutputType.Text,
|
||||
ModelOutputType.Object,
|
||||
ModelOutputType.Structured,
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'gpt-image-1',
|
||||
capabilities: [
|
||||
@@ -133,6 +119,23 @@ export class MockCopilotProvider extends OpenAIProvider {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'gemini-3.1-pro-preview',
|
||||
capabilities: [
|
||||
{
|
||||
input: [
|
||||
ModelInputType.Text,
|
||||
ModelInputType.Image,
|
||||
ModelInputType.Audio,
|
||||
],
|
||||
output: [
|
||||
ModelOutputType.Text,
|
||||
ModelOutputType.Object,
|
||||
ModelOutputType.Structured,
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
override async text(
|
||||
|
||||
Reference in New Issue
Block a user