feat(server): scenario mapping (#13404)

fix AI-404

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

* **New Features**
* Introduced scenario-based configuration for copilot, allowing default
model assignments for various AI use cases.
  * Added a new image generation model to the available options.

* **Improvements**
* Refined copilot provider settings by removing deprecated fallback
options and standardizing base URL configuration.
* Enhanced prompt management to support scenario-driven updates and
improved configuration handling.
* Updated admin and settings interfaces to support new scenario
configurations.

* **Bug Fixes**
* Removed deprecated or unused prompts and related references across
platforms for consistency.

* **Other**
* Improved test coverage and updated test assets to reflect prompt and
scenario changes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
DarkSky
2025-08-04 17:50:38 +08:00
committed by GitHub
parent 7a93db4d12
commit 0fcb4cb0fe
23 changed files with 386 additions and 514 deletions

View File

@@ -1,3 +1,5 @@
import { randomUUID } from 'node:crypto';
import type { ExecutionContext, TestFn } from 'ava';
import ava from 'ava';
import { z } from 'zod';
@@ -5,6 +7,7 @@ import { z } from 'zod';
import { ServerFeature, ServerService } from '../core';
import { AuthService } from '../core/auth';
import { QuotaModule } from '../core/quota';
import { Models } from '../models';
import { CopilotModule } from '../plugins/copilot';
import { prompts, PromptService } from '../plugins/copilot/prompt';
import {
@@ -30,6 +33,8 @@ import { TestAssets } from './utils/copilot';
type Tester = {
auth: AuthService;
module: TestingModule;
models: Models;
service: ServerService;
prompt: PromptService;
factory: CopilotProviderFactory;
workflow: CopilotWorkflowService;
@@ -66,12 +71,15 @@ test.serial.before(async t => {
isCopilotConfigured = service.features.includes(ServerFeature.Copilot);
const auth = module.get(AuthService);
const models = module.get(Models);
const prompt = module.get(PromptService);
const factory = module.get(CopilotProviderFactory);
const workflow = module.get(CopilotWorkflowService);
t.context.module = module;
t.context.auth = auth;
t.context.service = service;
t.context.models = models;
t.context.prompt = prompt;
t.context.factory = factory;
t.context.workflow = workflow;
@@ -84,7 +92,7 @@ test.serial.before(async t => {
});
test.serial.before(async t => {
const { prompt, executors } = t.context;
const { prompt, executors, models, service } = t.context;
executors.image.register();
executors.text.register();
@@ -98,6 +106,28 @@ test.serial.before(async t => {
for (const p of prompts) {
await prompt.set(p.name, p.model, p.messages, p.config);
}
const user = await models.user.create({
email: `${randomUUID()}@affine.pro`,
});
await service.updateConfig(user.id, [
{
module: 'copilot',
key: 'scenarios',
value: {
enabled: true,
scenarios: {
image: 'lcm',
rerank: 'gpt-4.1-mini',
brainstorm: 'gpt-4.1-mini',
coding: 'gpt-4.1-mini',
quick_decision: 'gpt-4.1-mini',
quick_written: 'gpt-4.1-mini',
summary_inspection: 'gemini-2.5-flash',
},
},
},
]);
});
test.after(async t => {
@@ -532,7 +562,6 @@ The term **“CRDT”** was first introduced by Marc Shapiro, Nuno Preguiça, Ca
'Make it shorter',
'Section Edit',
'Chat With AFFiNE AI',
'Search With AFFiNE AI',
],
messages: [{ role: 'user' as const, content: TestAssets.SSOT }],
verifier: (t: ExecutionContext<Tester>, result: string) => {
@@ -655,20 +684,7 @@ The term **“CRDT”** was first introduced by Marc Shapiro, Nuno Preguiça, Ca
type: 'image' as const,
},
{
promptName: ['debug:action:dalle3'],
messages: [
{
role: 'user' as const,
content: 'Panda',
},
],
verifier: (t: ExecutionContext<Tester>, link: string) => {
t.truthy(checkUrl(link), 'should be a valid url');
},
type: 'image' as const,
},
{
promptName: ['debug:action:gpt-image-1'],
promptName: ['Generate image'],
messages: [
{
role: 'user' as const,

View File

@@ -211,7 +211,9 @@ test('should be able to manage prompt', async t => {
'should have two messages'
);
await prompt.update(promptName, [{ role: 'system', content: 'hello' }]);
await prompt.update(promptName, {
messages: [{ role: 'system', content: 'hello' }],
});
t.is(
(await prompt.get(promptName))!.finish({}).length,
1,
@@ -370,7 +372,7 @@ test('should be able to update chat session prompt', async t => {
// Update the session
const updatedSessionId = await session.update({
sessionId,
promptName: 'Search With AFFiNE AI',
promptName: 'Chat With AFFiNE AI',
userId,
});
t.is(updatedSessionId, sessionId, 'should update session with same id');
@@ -380,7 +382,7 @@ test('should be able to update chat session prompt', async t => {
t.truthy(updatedSession, 'should retrieve updated session');
t.is(
updatedSession?.config.promptName,
'Search With AFFiNE AI',
'Chat With AFFiNE AI',
'should have updated prompt name'
);
});