feat(server): adapt gpt5 (#13478)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- New Features
- Added GPT-5 family and made GPT-5/-mini the new defaults for Copilot
scenarios and prompts.

- Bug Fixes
- Improved streaming chunk formats and reasoning/text semantics,
consistent attachment mediaType handling, and more reliable reranking
via log-prob handling.

- Refactor
- Unified maxOutputTokens usage; removed per-call step caps and migrated
several tools to a unified inputSchema shape.

- Chores
- Upgraded AI SDK dependencies and bumped an internal dependency
version.

- Tests
- Updated mocks and tests to reference GPT-5 variants and new stream
formats.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
DarkSky
2025-08-13 10:32:15 +08:00
committed by GitHub
parent fda7e9008d
commit 072557eba1
29 changed files with 410 additions and 374 deletions
@@ -118,11 +118,11 @@ test.serial.before(async t => {
enabled: true,
scenarios: {
image: 'flux-1/schnell',
rerank: 'gpt-4.1-mini',
complex_text_generation: 'gpt-4.1-mini',
coding: 'gpt-4.1-mini',
quick_decision_making: 'gpt-4.1-mini',
quick_text_generation: 'gpt-4.1-mini',
rerank: 'gpt-5-mini',
complex_text_generation: 'gpt-5-mini',
coding: 'gpt-5-mini',
quick_decision_making: 'gpt-5-mini',
quick_text_generation: 'gpt-5-mini',
polish_and_summarize: 'gemini-2.5-flash',
},
},
@@ -5,6 +5,7 @@ import { ProjectRoot } from '@affine-tools/utils/path';
import { PrismaClient } from '@prisma/client';
import type { TestFn } from 'ava';
import ava from 'ava';
import { nanoid } from 'nanoid';
import Sinon from 'sinon';
import { EventBus, JobQueue } from '../base';
@@ -1340,16 +1341,16 @@ test('TextStreamParser should format different types of chunks correctly', t =>
textDelta: {
chunk: {
type: 'text-delta' as const,
textDelta: 'Hello world',
} as any,
text: 'Hello world',
},
expected: 'Hello world',
description: 'should format text-delta correctly',
},
reasoning: {
chunk: {
type: 'reasoning' as const,
textDelta: 'I need to think about this',
} as any,
type: 'reasoning-delta' as const,
text: 'I need to think about this',
},
expected: '\n> [!]\n> I need to think about this',
description: 'should format reasoning as callout',
},
@@ -1358,8 +1359,8 @@ test('TextStreamParser should format different types of chunks correctly', t =>
type: 'tool-call' as const,
toolName: 'web_search_exa' as const,
toolCallId: 'test-id-1',
args: { query: 'test query', mode: 'AUTO' as const },
} as any,
input: { query: 'test query', mode: 'AUTO' as const },
},
expected: '\n> [!]\n> \n> Searching the web "test query"\n> ',
description: 'should format web search tool call correctly',
},
@@ -1368,8 +1369,8 @@ test('TextStreamParser should format different types of chunks correctly', t =>
type: 'tool-call' as const,
toolName: 'web_crawl_exa' as const,
toolCallId: 'test-id-2',
args: { url: 'https://example.com' },
} as any,
input: { url: 'https://example.com' },
},
expected: '\n> [!]\n> \n> Crawling the web "https://example.com"\n> ',
description: 'should format web crawl tool call correctly',
},
@@ -1378,8 +1379,8 @@ test('TextStreamParser should format different types of chunks correctly', t =>
type: 'tool-result' as const,
toolName: 'web_search_exa' as const,
toolCallId: 'test-id-1',
args: { query: 'test query', mode: 'AUTO' as const },
result: [
input: { query: 'test query', mode: 'AUTO' as const },
output: [
{
title: 'Test Title',
url: 'https://test.com',
@@ -1406,7 +1407,7 @@ test('TextStreamParser should format different types of chunks correctly', t =>
chunk: {
type: 'error' as const,
error: { type: 'testError', message: 'Test error message' },
} as any,
},
errorMessage: 'Test error message',
description: 'should throw error for error chunks',
},
@@ -1436,78 +1437,85 @@ test('TextStreamParser should process a sequence of message chunks', t => {
chunks: [
// Reasoning chunks
{
type: 'reasoning' as const,
textDelta: 'The user is asking about',
} as any,
id: nanoid(),
type: 'reasoning-delta' as const,
text: 'The user is asking about',
},
{
type: 'reasoning' as const,
textDelta: ' recent advances in quantum computing',
} as any,
id: nanoid(),
type: 'reasoning-delta' as const,
text: ' recent advances in quantum computing',
},
{
type: 'reasoning' as const,
textDelta: ' and how it might impact',
} as any,
id: nanoid(),
type: 'reasoning-delta' as const,
text: ' and how it might impact',
},
{
type: 'reasoning' as const,
textDelta: ' cryptography and data security.',
} as any,
id: nanoid(),
type: 'reasoning-delta' as const,
text: ' cryptography and data security.',
},
{
type: 'reasoning' as const,
textDelta:
' I should provide information on quantum supremacy achievements',
} as any,
id: nanoid(),
type: 'reasoning-delta' as const,
text: ' I should provide information on quantum supremacy achievements',
},
// Text delta
{
id: nanoid(),
type: 'text-delta' as const,
textDelta:
'Let me search for the latest breakthroughs in quantum computing and their ',
} as any,
text: 'Let me search for the latest breakthroughs in quantum computing and their ',
},
// Tool call
{
type: 'tool-call' as const,
toolCallId: 'toolu_01ABCxyz123456789',
toolName: 'web_search_exa' as const,
args: {
input: {
query: 'latest quantum computing breakthroughs cryptography impact',
},
} as any,
},
// Tool result
{
type: 'tool-result' as const,
toolCallId: 'toolu_01ABCxyz123456789',
toolName: 'web_search_exa' as const,
args: {
input: {
query: 'latest quantum computing breakthroughs cryptography impact',
},
result: [
output: [
{
title: 'IBM Unveils 1000-Qubit Quantum Processor',
url: 'https://example.com/tech/quantum-computing-milestone',
},
],
} as any,
},
// More text deltas
{
id: nanoid(),
type: 'text-delta' as const,
textDelta: 'implications for security.',
} as any,
text: 'implications for security.',
},
{
id: nanoid(),
type: 'text-delta' as const,
textDelta: '\n\nQuantum computing has made ',
} as any,
text: '\n\nQuantum computing has made ',
},
{
id: nanoid(),
type: 'text-delta' as const,
textDelta: 'remarkable progress in the past year. ',
} as any,
text: 'remarkable progress in the past year. ',
},
{
id: nanoid(),
type: 'text-delta' as const,
textDelta:
'The development of more stable qubits has accelerated research significantly.',
} as any,
text: 'The development of more stable qubits has accelerated research significantly.',
},
],
expected:
'\n> [!]\n> The user is asking about recent advances in quantum computing and how it might impact cryptography and data security. I should provide information on quantum supremacy achievements\n\nLet me search for the latest breakthroughs in quantum computing and their \n> [!]\n> \n> Searching the web "latest quantum computing breakthroughs cryptography impact"\n> \n> \n> \n> [IBM Unveils 1000-Qubit Quantum Processor](https://example.com/tech/quantum-computing-milestone)\n> \n> \n> \n\nimplications for security.\n\nQuantum computing has made remarkable progress in the past year. The development of more stable qubits has accelerated research significantly.',
@@ -57,15 +57,6 @@ export class MockCopilotProvider extends OpenAIProvider {
},
],
},
{
id: 'gpt-4.1',
capabilities: [
{
input: [ModelInputType.Text, ModelInputType.Image],
output: [ModelOutputType.Text, ModelOutputType.Object],
},
],
},
{
id: 'gpt-4.1-2025-04-14',
capabilities: [
@@ -76,7 +67,25 @@ export class MockCopilotProvider extends OpenAIProvider {
],
},
{
id: 'gpt-4.1-mini',
id: 'gpt-5',
capabilities: [
{
input: [ModelInputType.Text, ModelInputType.Image],
output: [ModelOutputType.Text, ModelOutputType.Object],
},
],
},
{
id: 'gpt-5-2025-08-07',
capabilities: [
{
input: [ModelInputType.Text, ModelInputType.Image],
output: [ModelOutputType.Text, ModelOutputType.Object],
},
],
},
{
id: 'gpt-5-mini',
capabilities: [
{
input: [ModelInputType.Text, ModelInputType.Image],
@@ -48,7 +48,7 @@ let docId = 'doc1';
test.beforeEach(async t => {
await t.context.module.initTestingDB();
await t.context.copilotSession.createPrompt('prompt-name', 'gpt-4.1');
await t.context.copilotSession.createPrompt('prompt-name', 'gpt-5-mini');
user = await t.context.user.create({
email: 'test@affine.pro',
});
@@ -58,9 +58,9 @@ const createTestPrompts = async (
copilotSession: CopilotSessionModel,
db: PrismaClient
) => {
await copilotSession.createPrompt(TEST_PROMPTS.NORMAL, 'gpt-4.1');
await copilotSession.createPrompt(TEST_PROMPTS.NORMAL, 'gpt-5-mini');
await db.aiPrompt.create({
data: { name: TEST_PROMPTS.ACTION, model: 'gpt-4.1', action: 'edit' },
data: { name: TEST_PROMPTS.ACTION, model: 'gpt-5-mini', action: 'edit' },
});
};
@@ -116,7 +116,7 @@ const addMessagesToSession = async (
await copilotSession.updateMessages({
sessionId,
userId: user.id,
prompt: { model: 'gpt-4.1' },
prompt: { model: 'gpt-5-mini' },
messages: [
{
role: 'user',
@@ -807,7 +807,7 @@ test('should handle fork and session attachment operations', async t => {
pinned: forkConfig.pinned,
title: null,
parentSessionId,
prompt: { name: TEST_PROMPTS.NORMAL, action: null, model: 'gpt-4.1' },
prompt: { name: TEST_PROMPTS.NORMAL, action: null, model: 'gpt-5-mini' },
messages: [
{
role: 'user',