mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-31 17:19:56 +08:00
feat(server): update model list (#15375)
This commit is contained in:
Generated
+6
-6
@@ -2930,7 +2930,7 @@ dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"rustversion",
|
||||
"windows-link 0.2.1",
|
||||
"windows-link 0.1.3",
|
||||
"windows-result 0.4.1",
|
||||
]
|
||||
|
||||
@@ -4712,9 +4712,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "llm_adapter"
|
||||
version = "0.2.8"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5edfe10ad51d5301468a395532cb0068caac1057fbda942edebe423fe585509"
|
||||
checksum = "c44c287854e9dbe2a92e14b1a41590859a47570e328ec3fbc382645f5cc06e94"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"jsonschema",
|
||||
@@ -4729,9 +4729,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "llm_runtime"
|
||||
version = "0.2.6"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2705eff96fcd8e21cb9f23245da8f6da260133dfaa9e6280840f426a6290cb9e"
|
||||
checksum = "85273703c62321335888c3417462b4ace530d38479bcb4c920760808a953707f"
|
||||
dependencies = [
|
||||
"jsonschema",
|
||||
"llm_adapter",
|
||||
@@ -10158,7 +10158,7 @@ version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -67,7 +67,7 @@ fn built_in_transcript_action_final_result_is_schema_checked() {
|
||||
"openQuestions": [],
|
||||
"blockers": []
|
||||
},
|
||||
"providerMeta": { "provider": "gemini", "model": "gemini-2.5-flash" }
|
||||
"providerMeta": { "provider": "gemini", "model": "gemini-3.5-flash-lite" }
|
||||
}
|
||||
})),
|
||||
)
|
||||
@@ -97,7 +97,7 @@ fn built_in_transcript_action_rejects_malformed_summary() {
|
||||
"transcribe": {
|
||||
"normalizedTranscript": "00:00:01 A: Hello",
|
||||
"summaryJson": { "title": "Sync" },
|
||||
"providerMeta": { "provider": "gemini", "model": "gemini-2.5-flash" }
|
||||
"providerMeta": { "provider": "gemini", "model": "gemini-3.5-flash-lite" }
|
||||
}
|
||||
})),
|
||||
)
|
||||
|
||||
@@ -2,33 +2,20 @@
|
||||
{
|
||||
"name": "Transcript audio",
|
||||
"action": "Transcript audio",
|
||||
"model": "gemini-2.5-flash",
|
||||
"optionalModels": [
|
||||
"gemini-2.5-flash",
|
||||
"gemini-2.5-pro",
|
||||
"gemini-3.1-pro-preview"
|
||||
],
|
||||
"model": "gemini-3.5-flash-lite",
|
||||
"optionalModels": ["gemini-3.5-flash-lite", "gemini-3.6-flash"],
|
||||
"config": {
|
||||
"requireContent": false,
|
||||
"requireAttachment": true,
|
||||
"maxRetries": 1
|
||||
},
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"template": "\nConvert a multi-speaker audio recording into a structured JSON format by transcribing the speech and identifying individual speakers.\n\n1. Analyze the audio to detect the presence of multiple speakers using distinct microphone inputs.\n2. Transcribe the audio content for each speaker and note the time intervals of speech.\n\n# Examples\n\n**Example Input:**\n- A multi-speaker audio file\n\n**Example Output:**\n\n[{\"a\":\"A\",\"s\":30,\"e\":45,\"t\":\"Hello, everyone.\"},{\"a\":\"B\",\"s\":46,\"e\":70,\"t\":\"Hi, thank you for joining the meeting today.\"}]\n\n# Notes\n\n- Ensure the accurate differentiation of speakers even if multiple speakers overlap slightly or switch rapidly.\n- Maintain a consistent speaker labeling system throughout the transcription.\n- If the provided audio or data does not contain valid talk, you should return an empty JSON array.\n"
|
||||
}
|
||||
]
|
||||
"messages": []
|
||||
},
|
||||
{
|
||||
"name": "Transcript audio structured",
|
||||
"action": "Transcript audio structured",
|
||||
"model": "gemini-2.5-flash",
|
||||
"optionalModels": [
|
||||
"gemini-2.5-flash",
|
||||
"gemini-2.5-pro",
|
||||
"gemini-3.1-pro-preview"
|
||||
],
|
||||
"model": "gemini-3.5-flash-lite",
|
||||
"optionalModels": ["gemini-3.5-flash-lite", "gemini-3.6-flash"],
|
||||
"config": {
|
||||
"requireContent": false,
|
||||
"requireAttachment": true,
|
||||
@@ -48,7 +35,7 @@
|
||||
{
|
||||
"name": "Generate a caption",
|
||||
"action": "Generate a caption",
|
||||
"model": "gemini-2.5-flash",
|
||||
"model": "gemini-3.5-flash-lite",
|
||||
"config": {
|
||||
"requireContent": false,
|
||||
"requireAttachment": true
|
||||
@@ -63,7 +50,7 @@
|
||||
{
|
||||
"name": "Conversation Summary",
|
||||
"action": "Conversation Summary",
|
||||
"model": "gpt-5-mini",
|
||||
"model": "gpt-5.6-luna",
|
||||
"config": {
|
||||
"requireContent": false
|
||||
},
|
||||
@@ -81,7 +68,7 @@
|
||||
{
|
||||
"name": "Summary",
|
||||
"action": "Summary",
|
||||
"model": "gpt-5-mini",
|
||||
"model": "gpt-5.6-luna",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -96,7 +83,7 @@
|
||||
{
|
||||
"name": "Summary as title",
|
||||
"action": "Summary as title",
|
||||
"model": "gpt-5-mini",
|
||||
"model": "gpt-5.6-luna",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -111,7 +98,7 @@
|
||||
{
|
||||
"name": "Summary the webpage",
|
||||
"action": "Summary the webpage",
|
||||
"model": "gpt-5-mini",
|
||||
"model": "gpt-5.6-luna",
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
@@ -122,7 +109,7 @@
|
||||
{
|
||||
"name": "Explain this",
|
||||
"action": "Explain this",
|
||||
"model": "gpt-5-mini",
|
||||
"model": "gpt-5.6-luna",
|
||||
"builtins": ["language"],
|
||||
"messages": [
|
||||
{
|
||||
@@ -138,7 +125,7 @@
|
||||
{
|
||||
"name": "Explain this image",
|
||||
"action": "Explain this image",
|
||||
"model": "gemini-2.5-flash",
|
||||
"model": "gemini-3.5-flash-lite",
|
||||
"config": {
|
||||
"requireContent": false,
|
||||
"requireAttachment": true
|
||||
@@ -157,7 +144,7 @@
|
||||
{
|
||||
"name": "Explain this code",
|
||||
"action": "Explain this code",
|
||||
"model": "gemini-2.5-flash",
|
||||
"model": "gemini-3.5-flash-lite",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -172,7 +159,7 @@
|
||||
{
|
||||
"name": "Translate to",
|
||||
"action": "Translate",
|
||||
"model": "gemini-2.5-flash",
|
||||
"model": "gemini-3.5-flash-lite",
|
||||
"params": {
|
||||
"language": {
|
||||
"default": "English",
|
||||
@@ -205,7 +192,7 @@
|
||||
{
|
||||
"name": "Summarize the meeting structured",
|
||||
"action": "Summarize the meeting structured",
|
||||
"model": "gpt-5-mini",
|
||||
"model": "gpt-5.6-luna",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -220,7 +207,7 @@
|
||||
{
|
||||
"name": "Summarize the meeting",
|
||||
"action": "Summarize the meeting",
|
||||
"model": "gpt-5-mini",
|
||||
"model": "gpt-5.6-luna",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -235,7 +222,7 @@
|
||||
{
|
||||
"name": "Find action for summary",
|
||||
"action": "Find action for summary",
|
||||
"model": "gpt-5-mini",
|
||||
"model": "gpt-5.6-luna",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -250,7 +237,7 @@
|
||||
{
|
||||
"name": "Write an article about this",
|
||||
"action": "Write an article about this",
|
||||
"model": "gemini-2.5-pro",
|
||||
"model": "gpt-5.6-luna",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -265,7 +252,7 @@
|
||||
{
|
||||
"name": "Write a twitter about this",
|
||||
"action": "Write a twitter about this",
|
||||
"model": "gemini-2.5-flash",
|
||||
"model": "gemini-3.5-flash-lite",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -280,7 +267,7 @@
|
||||
{
|
||||
"name": "Write a poem about this",
|
||||
"action": "Write a poem about this",
|
||||
"model": "gemini-2.5-flash",
|
||||
"model": "gemini-3.5-flash-lite",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -295,7 +282,7 @@
|
||||
{
|
||||
"name": "Write a blog post about this",
|
||||
"action": "Write a blog post about this",
|
||||
"model": "gemini-2.5-pro",
|
||||
"model": "gpt-5.6-luna",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -310,7 +297,7 @@
|
||||
{
|
||||
"name": "Write outline",
|
||||
"action": "Write outline",
|
||||
"model": "gemini-2.5-flash",
|
||||
"model": "gemini-3.5-flash-lite",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -325,7 +312,7 @@
|
||||
{
|
||||
"name": "Change tone to",
|
||||
"action": "Change tone",
|
||||
"model": "gemini-2.5-flash",
|
||||
"model": "gemini-3.5-flash-lite",
|
||||
"params": {
|
||||
"tone": {
|
||||
"default": "professional",
|
||||
@@ -346,7 +333,7 @@
|
||||
{
|
||||
"name": "Brainstorm ideas about this",
|
||||
"action": "Brainstorm ideas about this",
|
||||
"model": "gemini-2.5-flash",
|
||||
"model": "gemini-3.5-flash-lite",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -361,7 +348,7 @@
|
||||
{
|
||||
"name": "Brainstorm mindmap",
|
||||
"action": "Brainstorm mindmap",
|
||||
"model": "gpt-5-mini",
|
||||
"model": "gpt-5.6-luna",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -376,7 +363,7 @@
|
||||
{
|
||||
"name": "Expand mind map",
|
||||
"action": "Expand mind map",
|
||||
"model": "gpt-5-mini",
|
||||
"model": "gpt-5.6-luna",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -395,7 +382,7 @@
|
||||
{
|
||||
"name": "Improve writing for it",
|
||||
"action": "Improve writing for it",
|
||||
"model": "gemini-2.5-flash",
|
||||
"model": "gemini-3.5-flash-lite",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -410,7 +397,7 @@
|
||||
{
|
||||
"name": "Improve grammar for it",
|
||||
"action": "Improve grammar for it",
|
||||
"model": "gpt-5-mini",
|
||||
"model": "gpt-5.6-luna",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -425,7 +412,7 @@
|
||||
{
|
||||
"name": "Fix spelling for it",
|
||||
"action": "Fix spelling for it",
|
||||
"model": "gemini-2.5-flash",
|
||||
"model": "gemini-3.5-flash-lite",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -440,7 +427,7 @@
|
||||
{
|
||||
"name": "Find action items from it",
|
||||
"action": "Find action items from it",
|
||||
"model": "gpt-5-mini",
|
||||
"model": "gpt-5.6-luna",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -455,7 +442,7 @@
|
||||
{
|
||||
"name": "Check code error",
|
||||
"action": "Check code error",
|
||||
"model": "gpt-5-mini",
|
||||
"model": "gpt-5.6-luna",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -470,7 +457,7 @@
|
||||
{
|
||||
"name": "Create a presentation",
|
||||
"action": "Create a presentation",
|
||||
"model": "gpt-5-mini",
|
||||
"model": "gpt-5.6-luna",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -485,7 +472,7 @@
|
||||
{
|
||||
"name": "Create headings",
|
||||
"action": "Create headings",
|
||||
"model": "gemini-2.5-flash",
|
||||
"model": "gemini-3.5-flash-lite",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -500,7 +487,7 @@
|
||||
{
|
||||
"name": "Make it real",
|
||||
"action": "Make it real",
|
||||
"model": "claude-sonnet-4-5@20250929",
|
||||
"model": "claude-sonnet-4-6",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -515,7 +502,7 @@
|
||||
{
|
||||
"name": "Make it real with text",
|
||||
"action": "Make it real with text",
|
||||
"model": "claude-sonnet-4-5@20250929",
|
||||
"model": "claude-sonnet-4-6",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -530,7 +517,7 @@
|
||||
{
|
||||
"name": "Make it longer",
|
||||
"action": "Make it longer",
|
||||
"model": "gemini-2.5-flash",
|
||||
"model": "gemini-3.5-flash-lite",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -545,7 +532,7 @@
|
||||
{
|
||||
"name": "Make it shorter",
|
||||
"action": "Make it shorter",
|
||||
"model": "gemini-2.5-flash",
|
||||
"model": "gemini-3.5-flash-lite",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -560,7 +547,7 @@
|
||||
{
|
||||
"name": "Continue writing",
|
||||
"action": "Continue writing",
|
||||
"model": "gemini-2.5-flash",
|
||||
"model": "gemini-3.5-flash-lite",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -575,7 +562,7 @@
|
||||
{
|
||||
"name": "Section Edit",
|
||||
"action": "Section Edit",
|
||||
"model": "claude-sonnet-4@20250514",
|
||||
"model": "claude-sonnet-4-6",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -688,7 +675,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Code Artifact",
|
||||
"model": "claude-sonnet-4-5@20250929",
|
||||
"model": "claude-sonnet-4-6",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -702,11 +689,11 @@
|
||||
},
|
||||
{
|
||||
"name": "Chat With AFFiNE AI",
|
||||
"model": "gemini-2.5-flash",
|
||||
"model": "gpt-5.6-luna",
|
||||
"optionalModels": [
|
||||
"gemini-2.5-flash",
|
||||
"gemini-2.5-pro",
|
||||
"gemini-3.5-flash",
|
||||
"gpt-5.6-luna",
|
||||
"gpt-5.6-terra",
|
||||
"gemini-3.6-flash",
|
||||
"claude-sonnet-4-6"
|
||||
],
|
||||
"config": {
|
||||
@@ -722,7 +709,7 @@
|
||||
"codeArtifact",
|
||||
"blobRead"
|
||||
],
|
||||
"proModels": ["gemini-2.5-pro", "gemini-3.5-flash", "claude-sonnet-4-6"]
|
||||
"proModels": ["gpt-5.6-terra", "gemini-3.6-flash", "claude-sonnet-4-6"]
|
||||
},
|
||||
"builtins": [
|
||||
"date",
|
||||
@@ -747,7 +734,7 @@
|
||||
{
|
||||
"name": "mindmap.generate",
|
||||
"action": "mindmap.generate",
|
||||
"model": "gpt-5-mini",
|
||||
"model": "gpt-5.6-luna",
|
||||
"config": {
|
||||
"frequencyPenalty": 0.5,
|
||||
"presencePenalty": 0.5,
|
||||
@@ -772,7 +759,7 @@
|
||||
{
|
||||
"name": "slides.outline",
|
||||
"action": "slides.outline",
|
||||
"model": "gpt-5-mini",
|
||||
"model": "gpt-5.6-luna",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -877,7 +864,7 @@
|
||||
{
|
||||
"name": "workflow:presentation:step1",
|
||||
"action": "workflow:presentation:step1",
|
||||
"model": "gpt-5-mini",
|
||||
"model": "gpt-5.6-luna",
|
||||
"config": {
|
||||
"temperature": 0.7
|
||||
},
|
||||
@@ -895,7 +882,7 @@
|
||||
{
|
||||
"name": "workflow:presentation:step2",
|
||||
"action": "workflow:presentation:step2",
|
||||
"model": "gpt-5-mini",
|
||||
"model": "gpt-5.6-luna",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -914,7 +901,7 @@
|
||||
{
|
||||
"name": "workflow:presentation:step4",
|
||||
"action": "workflow:presentation:step4",
|
||||
"model": "gpt-5-mini",
|
||||
"model": "gpt-5.6-luna",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -939,7 +926,7 @@
|
||||
{
|
||||
"name": "workflow:brainstorm:step1",
|
||||
"action": "workflow:brainstorm:step1",
|
||||
"model": "gpt-5-mini",
|
||||
"model": "gpt-5.6-luna",
|
||||
"config": {
|
||||
"temperature": 0.7
|
||||
},
|
||||
@@ -957,7 +944,7 @@
|
||||
{
|
||||
"name": "workflow:brainstorm:step2",
|
||||
"action": "workflow:brainstorm:step2",
|
||||
"model": "gpt-5-mini",
|
||||
"model": "gpt-5.6-luna",
|
||||
"config": {
|
||||
"frequencyPenalty": 0.5,
|
||||
"presencePenalty": 0.5,
|
||||
|
||||
@@ -58,7 +58,7 @@ mod tests {
|
||||
use crate::llm::core::contracts::{ModelConditionsContract, ModelRegistryMatchRequest, ModelRegistryResolveRequest};
|
||||
|
||||
#[test]
|
||||
fn should_resolve_backend_scoped_alias() {
|
||||
fn should_resolve_current_chat_models() {
|
||||
let response = llm_resolve_model_registry_variant(ModelRegistryResolveRequest {
|
||||
backend_kind: Some("anthropic_vertex".to_string()),
|
||||
model_id: "claude-sonnet-4.6".to_string(),
|
||||
@@ -67,6 +67,26 @@ mod tests {
|
||||
|
||||
assert_eq!(response.matched_by.as_deref(), Some("canonical"));
|
||||
assert_eq!(response.variant.unwrap().raw_model_id, "claude-sonnet-4-6");
|
||||
|
||||
for model_id in ["gpt-5.6-luna", "gpt-5.6-terra"] {
|
||||
let response = llm_resolve_model_registry_variant(ModelRegistryResolveRequest {
|
||||
backend_kind: Some("openai_responses".to_string()),
|
||||
model_id: model_id.to_string(),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.matched_by.as_deref(), Some("raw_model_id"));
|
||||
assert_eq!(response.variant.unwrap().raw_model_id, model_id);
|
||||
}
|
||||
|
||||
let response = llm_resolve_model_registry_variant(ModelRegistryResolveRequest {
|
||||
backend_kind: Some("gemini_api".to_string()),
|
||||
model_id: "gemini-3.6-flash".to_string(),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.matched_by.as_deref(), Some("raw_model_id"));
|
||||
assert_eq!(response.variant.unwrap().raw_model_id, "gemini-3.6-flash");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -181,7 +201,7 @@ mod tests {
|
||||
.unwrap();
|
||||
let variant = response.variant.unwrap();
|
||||
|
||||
assert_eq!(variant.raw_model_id, "kimi-k2.7-code");
|
||||
assert_eq!(variant.raw_model_id, "kimi-k3");
|
||||
assert_eq!(variant.backend_kind, "opencode_zen");
|
||||
}
|
||||
|
||||
@@ -201,7 +221,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_keep_same_raw_id_as_two_backend_variants() {
|
||||
fn should_keep_legacy_model_raw_id_across_backend_variants() {
|
||||
let api_variant = llm_resolve_model_registry_variant(ModelRegistryResolveRequest {
|
||||
backend_kind: Some("gemini_api".to_string()),
|
||||
model_id: "gemini-2.5-flash".to_string(),
|
||||
@@ -281,7 +301,7 @@ mod tests {
|
||||
attachment_kinds: None,
|
||||
attachment_source_kinds: None,
|
||||
has_remote_attachments: None,
|
||||
model_id: Some("gemini-2.5-flash".to_string()),
|
||||
model_id: Some("gemini-3.6-flash".to_string()),
|
||||
output_type: Some("image".to_string()),
|
||||
},
|
||||
})
|
||||
|
||||
@@ -237,7 +237,7 @@ mod tests {
|
||||
fn should_materialize_structured_request_with_response_contract() {
|
||||
let response = llm_build_canonical_structured_request(
|
||||
serde_json::from_value::<CanonicalStructuredRequestContract>(json!({
|
||||
"model": "gemini-2.5-flash",
|
||||
"model": "gemini-3.6-flash",
|
||||
"messages": [
|
||||
{ "role": "user", "content": "hello" }
|
||||
],
|
||||
@@ -253,7 +253,7 @@ mod tests {
|
||||
assert_eq!(
|
||||
response,
|
||||
json!({
|
||||
"model": "gemini-2.5-flash",
|
||||
"model": "gemini-3.6-flash",
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
|
||||
@@ -335,7 +335,7 @@ mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn should_expand_partials_and_collect_prompt_params() {
|
||||
fn should_load_prompt_catalog() {
|
||||
let prompt = built_in_prompt("Translate to").expect("translate prompt");
|
||||
let user_message = prompt
|
||||
.messages
|
||||
@@ -353,5 +353,28 @@ mod tests {
|
||||
.map(|values| values.len()),
|
||||
Some(11)
|
||||
);
|
||||
|
||||
let chat = built_in_prompt("Chat With AFFiNE AI").expect("chat prompt");
|
||||
assert_eq!(chat.model, "gpt-5.6-luna");
|
||||
assert_eq!(
|
||||
chat
|
||||
.optional_models
|
||||
.as_ref()
|
||||
.map(|models| models.iter().map(String::as_str).collect::<Vec<_>>()),
|
||||
Some(vec![
|
||||
"gpt-5.6-luna",
|
||||
"gpt-5.6-terra",
|
||||
"gemini-3.6-flash",
|
||||
"claude-sonnet-4-6"
|
||||
])
|
||||
);
|
||||
assert_eq!(
|
||||
chat.config.as_ref().and_then(|config| config.get("proModels")),
|
||||
Some(&serde_json::json!([
|
||||
"gpt-5.6-terra",
|
||||
"gemini-3.6-flash",
|
||||
"claude-sonnet-4-6"
|
||||
]))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,43 +282,6 @@ Generated by [AVA](https://avajs.dev).
|
||||
},
|
||||
]
|
||||
|
||||
## should be able to run image executor
|
||||
|
||||
> should generate image stream
|
||||
|
||||
[
|
||||
{
|
||||
params: {
|
||||
key: [
|
||||
'https://example.com/test-image.jpg',
|
||||
'tag1, tag2, tag3, tag4, tag5, ',
|
||||
],
|
||||
},
|
||||
type: 2,
|
||||
},
|
||||
]
|
||||
|
||||
> should render the prompt with params array
|
||||
|
||||
[
|
||||
{
|
||||
modelId: 'test-image',
|
||||
},
|
||||
[
|
||||
{
|
||||
content: 'tag1, tag2, tag3, tag4, tag5, ',
|
||||
params: {
|
||||
tags: [
|
||||
'tag4',
|
||||
'tag5',
|
||||
],
|
||||
},
|
||||
role: 'user',
|
||||
},
|
||||
],
|
||||
{},
|
||||
]
|
||||
|
||||
## should handle generateSessionTitle correctly under various conditions
|
||||
|
||||
> should generate title when conditions are met
|
||||
@@ -437,66 +400,32 @@ Generated by [AVA](https://avajs.dev).
|
||||
|
||||
> should honor requested pro model
|
||||
|
||||
'gemini-2.5-pro'
|
||||
'gpt-5.6-terra'
|
||||
|
||||
> should fallback to default model
|
||||
|
||||
'gemini-2.5-flash'
|
||||
'gpt-5.6-luna'
|
||||
|
||||
> should fallback to default model when requesting pro model during trialing
|
||||
|
||||
'gemini-2.5-flash'
|
||||
'gpt-5.6-luna'
|
||||
|
||||
> should honor requested non-pro model during trialing
|
||||
|
||||
'gemini-2.5-flash'
|
||||
'gpt-5.6-luna'
|
||||
|
||||
> should pick default model when no requested model during trialing
|
||||
|
||||
'gemini-2.5-flash'
|
||||
'gpt-5.6-luna'
|
||||
|
||||
> should pick default model when no requested model during active
|
||||
|
||||
'gemini-2.5-flash'
|
||||
'gpt-5.6-luna'
|
||||
|
||||
> should honor requested pro model during active
|
||||
|
||||
'claude-sonnet-4-5@20250929'
|
||||
'claude-sonnet-4-6'
|
||||
|
||||
> should fallback to default model when requesting non-optional model during active
|
||||
|
||||
'gemini-2.5-flash'
|
||||
|
||||
## should resolve model correctly based on subscription status and prompt config
|
||||
|
||||
> should honor requested pro model
|
||||
|
||||
'gemini-2.5-pro'
|
||||
|
||||
> should fallback to default model
|
||||
|
||||
'gemini-2.5-flash'
|
||||
|
||||
> should fallback to default model when requesting pro model during trialing
|
||||
|
||||
'gemini-2.5-flash'
|
||||
|
||||
> should honor requested non-pro model during trialing
|
||||
|
||||
'gemini-2.5-flash'
|
||||
|
||||
> should pick default model when no requested model during trialing
|
||||
|
||||
'gemini-2.5-flash'
|
||||
|
||||
> should pick default model when no requested model during active
|
||||
|
||||
'gemini-2.5-flash'
|
||||
|
||||
> should honor requested pro model during active
|
||||
|
||||
'claude-sonnet-4-5@20250929'
|
||||
|
||||
> should fallback to default model when requesting non-optional model during active
|
||||
|
||||
'gemini-2.5-flash'
|
||||
'gpt-5.6-luna'
|
||||
|
||||
Binary file not shown.
+1
-1
@@ -364,7 +364,7 @@ Generated by [AVA](https://avajs.dev).
|
||||
'tool_schema_rewrite',
|
||||
],
|
||||
},
|
||||
model: 'gemini-2.5-flash',
|
||||
model: 'gemini-3.6-flash',
|
||||
responseMimeType: 'application/json',
|
||||
schema: {
|
||||
additionalProperties: false,
|
||||
|
||||
BIN
Binary file not shown.
+2
-2
@@ -71,14 +71,14 @@ Generated by [AVA](https://avajs.dev).
|
||||
|
||||
{
|
||||
matchedOptionalModel: true,
|
||||
selectedModel: 'openai-default/gemini-2.5-pro',
|
||||
selectedModel: 'openai-default/gpt-5.6-terra',
|
||||
}
|
||||
|
||||
> prefixed optional miss
|
||||
|
||||
{
|
||||
matchedOptionalModel: false,
|
||||
selectedModel: 'gemini-2.5-flash',
|
||||
selectedModel: 'gpt-5.6-luna',
|
||||
}
|
||||
|
||||
## ExecutionPlan should serialize routed request state and reject host-only signal
|
||||
|
||||
BIN
Binary file not shown.
@@ -441,7 +441,7 @@ The term **“CRDT”** was first introduced by Marc Shapiro, Nuno Preguiça, Ca
|
||||
messages: singleUserPromptMessages(
|
||||
'In one short sentence, explain what AFFiNE AI is and mention AFFiNE by name.'
|
||||
),
|
||||
config: { model: 'gemini-2.5-flash' },
|
||||
config: { model: 'gemini-3.6-flash' },
|
||||
verifier: (t: ExecutionContext<Tester>, result: string) => {
|
||||
assertNotWrappedInCodeBlock(t, result);
|
||||
t.assert(
|
||||
@@ -458,7 +458,7 @@ The term **“CRDT”** was first introduced by Marc Shapiro, Nuno Preguiça, Ca
|
||||
messages: singleUserPromptMessages(
|
||||
'Respond with one short sentence about AFFiNE AI and mention AFFiNE by name.'
|
||||
),
|
||||
config: { model: 'gemini-2.5-flash' },
|
||||
config: { model: 'gemini-3.6-flash' },
|
||||
verifier: (t: ExecutionContext<Tester>, result: string) => {
|
||||
t.truthy(checkStreamObjects(result), 'should be valid stream objects');
|
||||
const assembledText = getStreamObjectText(result);
|
||||
@@ -985,19 +985,19 @@ const TRANSCRIPT_AUDIO_CASES = [
|
||||
name: 'short audio',
|
||||
url: 'https://cdn.affine.pro/copilot-test/MP9qDGuYgnY+ILoEAmHpp3h9Npuw2403EAYMEA.mp3',
|
||||
mimeType: 'audio/mpeg',
|
||||
modelId: 'gemini-2.5-flash',
|
||||
modelId: 'gemini-3.5-flash-lite',
|
||||
},
|
||||
{
|
||||
name: 'middle audio',
|
||||
url: 'https://cdn.affine.pro/copilot-test/2ed05eo1KvZ2tWB_BAjFo67EAPZZY-w4LylUAw.m4a',
|
||||
mimeType: 'audio/m4a',
|
||||
modelId: 'gemini-2.5-flash',
|
||||
modelId: 'gemini-3.5-flash-lite',
|
||||
},
|
||||
{
|
||||
name: 'long audio',
|
||||
url: 'https://cdn.affine.pro/copilot-test/nC9-e7P85PPI2rU29QWwf8slBNRMy92teLIIMw.opus',
|
||||
mimeType: 'audio/opus',
|
||||
modelId: 'gemini-2.5-pro',
|
||||
modelId: 'gemini-3.6-flash',
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -588,7 +588,7 @@ test('should be able to chat with api', async t => {
|
||||
t.is(
|
||||
array2sse(sse2array(ret3).filter(e => e.event !== 'event')),
|
||||
textToEventStream(
|
||||
['https://example.com/gpt-image-1.jpg'],
|
||||
['https://example.com/gpt-image-2.jpg'],
|
||||
messageId,
|
||||
'attachment'
|
||||
),
|
||||
@@ -717,14 +717,13 @@ test('should map action stream preparation errors to SSE error events', async t
|
||||
});
|
||||
|
||||
test('should be able to chat with special image model', async t => {
|
||||
const { app, prompt, storage } = t.context;
|
||||
const { app, storage } = t.context;
|
||||
|
||||
Sinon.stub(storage, 'handleRemoteLink').resolvesArg(2);
|
||||
|
||||
const { id } = await createWorkspace(app);
|
||||
|
||||
const testWithModel = async (promptName: string, finalPrompt: string) => {
|
||||
const model = (await prompt.get(promptName))?.model;
|
||||
const sessionId = await createCopilotSession(
|
||||
app,
|
||||
id,
|
||||
@@ -739,7 +738,7 @@ test('should be able to chat with special image model', async t => {
|
||||
ret3,
|
||||
textToEventStream(
|
||||
[
|
||||
`https://example.com/${model}.jpg`,
|
||||
'https://example.com/gpt-image-2.jpg',
|
||||
`https://example.com/generated/${encodeURIComponent(finalPrompt)}.jpg`,
|
||||
],
|
||||
messageId,
|
||||
@@ -1915,7 +1914,7 @@ test('should be able to transcript', async t => {
|
||||
const route = input.input?.preparedRoutes?.transcribe?.[0] ?? {};
|
||||
const result = buildTranscriptActionResult(
|
||||
route,
|
||||
'gemini-2.5-flash',
|
||||
'gemini-3.5-flash-lite',
|
||||
input.input ?? {}
|
||||
);
|
||||
const actionVersion = input.recipeVersion ?? 'v1';
|
||||
|
||||
@@ -2414,63 +2414,47 @@ test('model selection policy should resolve requested optional models consistent
|
||||
|
||||
t.deepEqual(
|
||||
modelSelection.resolveRequestedModel({
|
||||
defaultModel: 'gemini-2.5-flash',
|
||||
optionalModels: [
|
||||
'gemini-2.5-flash',
|
||||
'gemini-2.5-pro',
|
||||
'claude-sonnet-4-5@20250929',
|
||||
],
|
||||
requestedModelId: 'gemini-2.5-pro',
|
||||
defaultModel: 'gpt-5.6-luna',
|
||||
optionalModels: ['gpt-5.6-luna', 'gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
requestedModelId: 'gpt-5.6-terra',
|
||||
}),
|
||||
{
|
||||
selectedModel: 'gemini-2.5-pro',
|
||||
selectedModel: 'gpt-5.6-terra',
|
||||
matchedOptionalModel: true,
|
||||
}
|
||||
);
|
||||
|
||||
t.deepEqual(
|
||||
modelSelection.resolveRequestedModel({
|
||||
defaultModel: 'gemini-2.5-flash',
|
||||
optionalModels: [
|
||||
'gemini-2.5-flash',
|
||||
'gemini-2.5-pro',
|
||||
'claude-sonnet-4-5@20250929',
|
||||
],
|
||||
requestedModelId: 'openai-default/gemini-2.5-pro',
|
||||
defaultModel: 'gpt-5.6-luna',
|
||||
optionalModels: ['gpt-5.6-luna', 'gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
requestedModelId: 'openai-default/gpt-5.6-terra',
|
||||
}),
|
||||
{
|
||||
selectedModel: 'openai-default/gemini-2.5-pro',
|
||||
selectedModel: 'openai-default/gpt-5.6-terra',
|
||||
matchedOptionalModel: true,
|
||||
}
|
||||
);
|
||||
|
||||
t.deepEqual(
|
||||
modelSelection.resolveRequestedModel({
|
||||
defaultModel: 'gemini-2.5-flash',
|
||||
optionalModels: [
|
||||
'gemini-2.5-flash',
|
||||
'gemini-2.5-pro',
|
||||
'claude-sonnet-4-5@20250929',
|
||||
],
|
||||
defaultModel: 'gpt-5.6-luna',
|
||||
optionalModels: ['gpt-5.6-luna', 'gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
requestedModelId: 'not-in-optional',
|
||||
}),
|
||||
{
|
||||
selectedModel: 'gemini-2.5-flash',
|
||||
selectedModel: 'gpt-5.6-luna',
|
||||
matchedOptionalModel: false,
|
||||
}
|
||||
);
|
||||
|
||||
t.is(
|
||||
modelSelection.resolveRequestedModel({
|
||||
defaultModel: 'gemini-2.5-flash',
|
||||
optionalModels: [
|
||||
'gemini-2.5-flash',
|
||||
'gemini-2.5-pro',
|
||||
'claude-sonnet-4-5@20250929',
|
||||
],
|
||||
defaultModel: 'gpt-5.6-luna',
|
||||
optionalModels: ['gpt-5.6-luna', 'gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
requestedModelId: 'not-in-optional',
|
||||
}).selectedModel,
|
||||
'gemini-2.5-flash'
|
||||
'gpt-5.6-luna'
|
||||
);
|
||||
});
|
||||
|
||||
@@ -2494,45 +2478,33 @@ test('capability policy host should gate pro model requests by subscription stat
|
||||
{
|
||||
const model1 = await capabilityPolicy.resolveChatModel({
|
||||
userId,
|
||||
defaultModel: 'gemini-2.5-flash',
|
||||
optionalModels: [
|
||||
'gemini-2.5-flash',
|
||||
'gemini-2.5-pro',
|
||||
'claude-sonnet-4-5@20250929',
|
||||
],
|
||||
proModels: ['gemini-2.5-pro', 'claude-sonnet-4-5@20250929'],
|
||||
requestedModelId: 'gemini-2.5-pro',
|
||||
defaultModel: 'gpt-5.6-luna',
|
||||
optionalModels: ['gpt-5.6-luna', 'gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
proModels: ['gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
requestedModelId: 'gpt-5.6-terra',
|
||||
paymentEnabled: false,
|
||||
});
|
||||
t.snapshot(model1, 'should honor requested pro model');
|
||||
|
||||
const model1WithPrefix = await capabilityPolicy.resolveChatModel({
|
||||
userId,
|
||||
defaultModel: 'gemini-2.5-flash',
|
||||
optionalModels: [
|
||||
'gemini-2.5-flash',
|
||||
'gemini-2.5-pro',
|
||||
'claude-sonnet-4-5@20250929',
|
||||
],
|
||||
proModels: ['gemini-2.5-pro', 'claude-sonnet-4-5@20250929'],
|
||||
requestedModelId: 'openai-default/gemini-2.5-pro',
|
||||
defaultModel: 'gpt-5.6-luna',
|
||||
optionalModels: ['gpt-5.6-luna', 'gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
proModels: ['gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
requestedModelId: 'openai-default/gpt-5.6-terra',
|
||||
paymentEnabled: false,
|
||||
});
|
||||
t.is(
|
||||
model1WithPrefix,
|
||||
'openai-default/gemini-2.5-pro',
|
||||
'openai-default/gpt-5.6-terra',
|
||||
'should honor requested prefixed pro model'
|
||||
);
|
||||
|
||||
const model2 = await capabilityPolicy.resolveChatModel({
|
||||
userId,
|
||||
defaultModel: 'gemini-2.5-flash',
|
||||
optionalModels: [
|
||||
'gemini-2.5-flash',
|
||||
'gemini-2.5-pro',
|
||||
'claude-sonnet-4-5@20250929',
|
||||
],
|
||||
proModels: ['gemini-2.5-pro', 'claude-sonnet-4-5@20250929'],
|
||||
defaultModel: 'gpt-5.6-luna',
|
||||
optionalModels: ['gpt-5.6-luna', 'gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
proModels: ['gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
requestedModelId: 'not-in-optional',
|
||||
paymentEnabled: false,
|
||||
});
|
||||
@@ -2544,14 +2516,10 @@ test('capability policy host should gate pro model requests by subscription stat
|
||||
mockStatus(SubscriptionStatus.Trialing);
|
||||
const model3 = await capabilityPolicy.resolveChatModel({
|
||||
userId,
|
||||
defaultModel: 'gemini-2.5-flash',
|
||||
optionalModels: [
|
||||
'gemini-2.5-flash',
|
||||
'gemini-2.5-pro',
|
||||
'claude-sonnet-4-5@20250929',
|
||||
],
|
||||
proModels: ['gemini-2.5-pro', 'claude-sonnet-4-5@20250929'],
|
||||
requestedModelId: 'gemini-2.5-pro',
|
||||
defaultModel: 'gpt-5.6-luna',
|
||||
optionalModels: ['gpt-5.6-luna', 'gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
proModels: ['gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
requestedModelId: 'gpt-5.6-terra',
|
||||
paymentEnabled: true,
|
||||
});
|
||||
t.snapshot(
|
||||
@@ -2561,45 +2529,33 @@ test('capability policy host should gate pro model requests by subscription stat
|
||||
|
||||
const model3WithPrefix = await capabilityPolicy.resolveChatModel({
|
||||
userId,
|
||||
defaultModel: 'gemini-2.5-flash',
|
||||
optionalModels: [
|
||||
'gemini-2.5-flash',
|
||||
'gemini-2.5-pro',
|
||||
'claude-sonnet-4-5@20250929',
|
||||
],
|
||||
proModels: ['gemini-2.5-pro', 'claude-sonnet-4-5@20250929'],
|
||||
requestedModelId: 'openai-default/gemini-2.5-pro',
|
||||
defaultModel: 'gpt-5.6-luna',
|
||||
optionalModels: ['gpt-5.6-luna', 'gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
proModels: ['gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
requestedModelId: 'openai-default/gpt-5.6-terra',
|
||||
paymentEnabled: true,
|
||||
});
|
||||
t.is(
|
||||
model3WithPrefix,
|
||||
'gemini-2.5-flash',
|
||||
'gpt-5.6-luna',
|
||||
'should fallback to default model when requesting prefixed pro model during trialing'
|
||||
);
|
||||
|
||||
const model4 = await capabilityPolicy.resolveChatModel({
|
||||
userId,
|
||||
defaultModel: 'gemini-2.5-flash',
|
||||
optionalModels: [
|
||||
'gemini-2.5-flash',
|
||||
'gemini-2.5-pro',
|
||||
'claude-sonnet-4-5@20250929',
|
||||
],
|
||||
proModels: ['gemini-2.5-pro', 'claude-sonnet-4-5@20250929'],
|
||||
requestedModelId: 'gemini-2.5-flash',
|
||||
defaultModel: 'gpt-5.6-luna',
|
||||
optionalModels: ['gpt-5.6-luna', 'gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
proModels: ['gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
requestedModelId: 'gpt-5.6-luna',
|
||||
paymentEnabled: true,
|
||||
});
|
||||
t.snapshot(model4, 'should honor requested non-pro model during trialing');
|
||||
|
||||
const model5 = await capabilityPolicy.resolveChatModel({
|
||||
userId,
|
||||
defaultModel: 'gemini-2.5-flash',
|
||||
optionalModels: [
|
||||
'gemini-2.5-flash',
|
||||
'gemini-2.5-pro',
|
||||
'claude-sonnet-4-5@20250929',
|
||||
],
|
||||
proModels: ['gemini-2.5-pro', 'claude-sonnet-4-5@20250929'],
|
||||
defaultModel: 'gpt-5.6-luna',
|
||||
optionalModels: ['gpt-5.6-luna', 'gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
proModels: ['gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
paymentEnabled: true,
|
||||
});
|
||||
t.snapshot(
|
||||
@@ -2613,13 +2569,9 @@ test('capability policy host should gate pro model requests by subscription stat
|
||||
mockStatus(SubscriptionStatus.Active);
|
||||
const model6 = await capabilityPolicy.resolveChatModel({
|
||||
userId,
|
||||
defaultModel: 'gemini-2.5-flash',
|
||||
optionalModels: [
|
||||
'gemini-2.5-flash',
|
||||
'gemini-2.5-pro',
|
||||
'claude-sonnet-4-5@20250929',
|
||||
],
|
||||
proModels: ['gemini-2.5-pro', 'claude-sonnet-4-5@20250929'],
|
||||
defaultModel: 'gpt-5.6-luna',
|
||||
optionalModels: ['gpt-5.6-luna', 'gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
proModels: ['gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
paymentEnabled: true,
|
||||
});
|
||||
t.snapshot(
|
||||
@@ -2629,45 +2581,33 @@ test('capability policy host should gate pro model requests by subscription stat
|
||||
|
||||
const model7 = await capabilityPolicy.resolveChatModel({
|
||||
userId,
|
||||
defaultModel: 'gemini-2.5-flash',
|
||||
optionalModels: [
|
||||
'gemini-2.5-flash',
|
||||
'gemini-2.5-pro',
|
||||
'claude-sonnet-4-5@20250929',
|
||||
],
|
||||
proModels: ['gemini-2.5-pro', 'claude-sonnet-4-5@20250929'],
|
||||
requestedModelId: 'claude-sonnet-4-5@20250929',
|
||||
defaultModel: 'gpt-5.6-luna',
|
||||
optionalModels: ['gpt-5.6-luna', 'gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
proModels: ['gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
requestedModelId: 'claude-sonnet-4-6',
|
||||
paymentEnabled: true,
|
||||
});
|
||||
t.snapshot(model7, 'should honor requested pro model during active');
|
||||
|
||||
const model7WithPrefix = await capabilityPolicy.resolveChatModel({
|
||||
userId,
|
||||
defaultModel: 'gemini-2.5-flash',
|
||||
optionalModels: [
|
||||
'gemini-2.5-flash',
|
||||
'gemini-2.5-pro',
|
||||
'claude-sonnet-4-5@20250929',
|
||||
],
|
||||
proModels: ['gemini-2.5-pro', 'claude-sonnet-4-5@20250929'],
|
||||
requestedModelId: 'openai-default/claude-sonnet-4-5@20250929',
|
||||
defaultModel: 'gpt-5.6-luna',
|
||||
optionalModels: ['gpt-5.6-luna', 'gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
proModels: ['gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
requestedModelId: 'openai-default/claude-sonnet-4-6',
|
||||
paymentEnabled: true,
|
||||
});
|
||||
t.is(
|
||||
model7WithPrefix,
|
||||
'openai-default/claude-sonnet-4-5@20250929',
|
||||
'openai-default/claude-sonnet-4-6',
|
||||
'should honor requested prefixed pro model during active'
|
||||
);
|
||||
|
||||
const model8 = await capabilityPolicy.resolveChatModel({
|
||||
userId,
|
||||
defaultModel: 'gemini-2.5-flash',
|
||||
optionalModels: [
|
||||
'gemini-2.5-flash',
|
||||
'gemini-2.5-pro',
|
||||
'claude-sonnet-4-5@20250929',
|
||||
],
|
||||
proModels: ['gemini-2.5-pro', 'claude-sonnet-4-5@20250929'],
|
||||
defaultModel: 'gpt-5.6-luna',
|
||||
optionalModels: ['gpt-5.6-luna', 'gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
proModels: ['gpt-5.6-terra', 'claude-sonnet-4-6'],
|
||||
requestedModelId: 'not-in-optional',
|
||||
paymentEnabled: true,
|
||||
});
|
||||
@@ -2684,10 +2624,10 @@ test('prompt runtime should resolve prefixed optional models consistently', asyn
|
||||
const promptName = randomUUID().replaceAll('-', '');
|
||||
await prompt.set(
|
||||
promptName,
|
||||
'gemini-2.5-flash',
|
||||
'gpt-5.6-luna',
|
||||
[{ role: 'user', content: '{{content}}' }],
|
||||
{ proModels: ['gemini-2.5-pro'] },
|
||||
{ optionalModels: ['gemini-2.5-pro'] }
|
||||
{ proModels: ['gpt-5.6-terra'] },
|
||||
{ optionalModels: ['gpt-5.6-terra'] }
|
||||
);
|
||||
|
||||
const textStub = Sinon.stub(chatRuntime, 'text').resolves('ok');
|
||||
@@ -2695,11 +2635,11 @@ test('prompt runtime should resolve prefixed optional models consistently', asyn
|
||||
await promptRuntime.runText(
|
||||
promptName,
|
||||
{ content: 'hello' },
|
||||
{ modelId: 'openai-default/gemini-2.5-pro' }
|
||||
{ modelId: 'openai-default/gpt-5.6-terra' }
|
||||
);
|
||||
t.is(
|
||||
textStub.firstCall.args[0].modelId,
|
||||
'openai-default/gemini-2.5-pro',
|
||||
'openai-default/gpt-5.6-terra',
|
||||
'should preserve accepted provider-prefixed optional model'
|
||||
);
|
||||
|
||||
@@ -2710,7 +2650,7 @@ test('prompt runtime should resolve prefixed optional models consistently', asyn
|
||||
);
|
||||
t.is(
|
||||
textStub.secondCall.args[0].modelId,
|
||||
'gemini-2.5-flash',
|
||||
'gpt-5.6-luna',
|
||||
'should fallback to default model for non-optional prefixed model'
|
||||
);
|
||||
});
|
||||
@@ -2722,10 +2662,10 @@ test('resolver models should use resolved provider metadata for display names',
|
||||
const promptName = randomUUID().replaceAll('-', '');
|
||||
await prompt.set(
|
||||
promptName,
|
||||
'gemini-2.5-flash',
|
||||
'gpt-5.6-luna',
|
||||
[{ role: 'system', content: 'test' }],
|
||||
{ proModels: ['gemini-2.5-pro'] },
|
||||
{ optionalModels: ['gemini-2.5-flash', 'gemini-2.5-pro'] }
|
||||
{ proModels: ['gpt-5.6-terra'] },
|
||||
{ optionalModels: ['gpt-5.6-luna', 'gpt-5.6-terra'] }
|
||||
);
|
||||
|
||||
const resolveProvider = Sinon.stub(factory, 'resolveProvider').callsFake(
|
||||
@@ -2754,11 +2694,11 @@ test('resolver models should use resolved provider metadata for display names',
|
||||
const models = await resolver.models(promptName);
|
||||
|
||||
t.deepEqual(models.optionalModels, [
|
||||
{ id: 'gemini-2.5-flash', name: 'Resolved gemini-2.5-flash' },
|
||||
{ id: 'gemini-2.5-pro', name: 'Resolved gemini-2.5-pro' },
|
||||
{ id: 'gpt-5.6-luna', name: 'Resolved gpt-5.6-luna' },
|
||||
{ id: 'gpt-5.6-terra', name: 'Resolved gpt-5.6-terra' },
|
||||
]);
|
||||
t.deepEqual(models.proModels, [
|
||||
{ id: 'gemini-2.5-pro', name: 'Resolved gemini-2.5-pro' },
|
||||
{ id: 'gpt-5.6-terra', name: 'Resolved gpt-5.6-terra' },
|
||||
]);
|
||||
t.true(
|
||||
resolveProvider.alwaysCalledWithMatch({
|
||||
|
||||
@@ -362,7 +362,7 @@ class TestGeminiProvider extends GeminiProvider<{ apiKey: string }> {
|
||||
structuredFactory: (request: LlmStructuredRequest) => LlmStructuredResponse =
|
||||
() => ({
|
||||
id: 'structured_1',
|
||||
model: 'gemini-2.5-flash',
|
||||
model: 'gemini-3.6-flash',
|
||||
output_text: '{"summary":"AFFiNE native"}',
|
||||
output_json: { summary: 'AFFiNE native' },
|
||||
usage: {
|
||||
@@ -1070,7 +1070,7 @@ test('buildCanonicalNativeStructuredRequest should honor explicit structured opt
|
||||
test('buildCanonicalNativeStructuredRequest should honor explicit responseSchema for array outputs', async t => {
|
||||
const schema = z.array(z.object({ speaker: z.string(), text: z.string() }));
|
||||
const { request } = await buildCanonicalNativeStructuredRequest({
|
||||
model: 'gemini-2.5-flash',
|
||||
model: 'gemini-3.6-flash',
|
||||
messages: jsonOnlyPromptMessages('Transcribe this audio.'),
|
||||
options: {},
|
||||
responseContract: buildStructuredResponseContract(schema),
|
||||
@@ -1083,7 +1083,7 @@ test('buildCanonicalNativeStructuredRequest should consume explicit structured r
|
||||
const schema = z.object({ summary: z.string() });
|
||||
const responseContract = buildStructuredResponseContract(schema);
|
||||
const { request } = await buildCanonicalNativeStructuredRequest({
|
||||
model: 'gemini-2.5-flash',
|
||||
model: 'gemini-3.6-flash',
|
||||
messages: jsonOnlyPromptMessages('Summarize AFFiNE.'),
|
||||
options: { strict: false },
|
||||
responseContract,
|
||||
@@ -1120,7 +1120,7 @@ test('buildNativeRequest should canonicalize Gemini attachments', async t => {
|
||||
{
|
||||
title: 'remote file url',
|
||||
input: {
|
||||
model: 'gemini-2.5-flash',
|
||||
model: 'gemini-3.6-flash',
|
||||
messages: [
|
||||
{
|
||||
role: 'user' as const,
|
||||
@@ -1134,7 +1134,7 @@ test('buildNativeRequest should canonicalize Gemini attachments', async t => {
|
||||
{
|
||||
title: 'remote image url',
|
||||
input: {
|
||||
model: 'gemini-2.5-flash',
|
||||
model: 'gemini-3.6-flash',
|
||||
messages: [
|
||||
{
|
||||
role: 'user' as const,
|
||||
@@ -1147,7 +1147,7 @@ test('buildNativeRequest should canonicalize Gemini attachments', async t => {
|
||||
{
|
||||
title: 'data url',
|
||||
input: {
|
||||
model: 'gemini-2.5-flash',
|
||||
model: 'gemini-3.6-flash',
|
||||
messages: [
|
||||
{
|
||||
role: 'user' as const,
|
||||
@@ -1161,7 +1161,7 @@ test('buildNativeRequest should canonicalize Gemini attachments', async t => {
|
||||
{
|
||||
title: 'remote audio url',
|
||||
input: {
|
||||
model: 'gemini-2.5-flash',
|
||||
model: 'gemini-3.6-flash',
|
||||
messages: [
|
||||
{
|
||||
role: 'user' as const,
|
||||
@@ -1175,7 +1175,7 @@ test('buildNativeRequest should canonicalize Gemini attachments', async t => {
|
||||
{
|
||||
title: 'bytes and file handle',
|
||||
input: {
|
||||
model: 'gemini-2.5-flash',
|
||||
model: 'gemini-3.6-flash',
|
||||
messages: [
|
||||
{
|
||||
role: 'user' as const,
|
||||
@@ -1316,7 +1316,7 @@ test('buildNativeRequest should preserve tool schemas and defer Gemini rewrite t
|
||||
const [{ request: geminiRequest }, { request: openaiRequest }] =
|
||||
await Promise.all([
|
||||
buildNativeRequest({
|
||||
model: 'gemini-2.5-flash',
|
||||
model: 'gemini-3.6-flash',
|
||||
messages: promptMessages(userPrompt('read doc')),
|
||||
toolContracts: buildToolContracts({
|
||||
doc_read: defineTool({
|
||||
@@ -1371,7 +1371,7 @@ test('buildNativeStructuredRequest should preserve schemas and defer Gemini rewr
|
||||
const [{ request: geminiRequest }, { request: openaiRequest }] =
|
||||
await Promise.all([
|
||||
buildNativeStructuredRequest({
|
||||
model: 'gemini-2.5-flash',
|
||||
model: 'gemini-3.6-flash',
|
||||
messages: promptMessages(userPrompt('Summarize AFFiNE.')),
|
||||
responseContract: buildStructuredResponseContract(schema),
|
||||
}),
|
||||
@@ -1418,7 +1418,7 @@ test('GeminiProvider should use native path for text-only requests', async t =>
|
||||
const provider = new TestGeminiProvider();
|
||||
|
||||
const result = await getProviderRuntimeHost(provider).run.text(
|
||||
{ modelId: 'gemini-2.5-flash' },
|
||||
{ modelId: 'gemini-3.6-flash' },
|
||||
promptMessages(userPrompt('hello')),
|
||||
{ reasoning: true }
|
||||
);
|
||||
@@ -1439,7 +1439,7 @@ test('GeminiProvider should use native path for structured requests', async t =>
|
||||
|
||||
const schema = z.object({ summary: z.string() });
|
||||
const result = await getProviderRuntimeHost(provider).run.structured(
|
||||
{ modelId: 'gemini-2.5-flash' },
|
||||
{ modelId: 'gemini-3.6-flash' },
|
||||
jsonOnlyPromptMessages('Summarize AFFiNE in one short sentence.'),
|
||||
structuredOptions(schema),
|
||||
structuredContract(schema)
|
||||
@@ -1468,7 +1468,7 @@ test('GeminiProvider should retry when native structured dispatch returns invali
|
||||
}
|
||||
return {
|
||||
id: `structured_retry_${attempts}`,
|
||||
model: 'gemini-2.5-flash',
|
||||
model: 'gemini-3.6-flash',
|
||||
output_text: '{"summary":"ok"}',
|
||||
output_json: { summary: 'ok' },
|
||||
usage: {
|
||||
@@ -1481,7 +1481,7 @@ test('GeminiProvider should retry when native structured dispatch returns invali
|
||||
};
|
||||
|
||||
const result = await getProviderRuntimeHost(provider).run.structured(
|
||||
{ modelId: 'gemini-2.5-flash' },
|
||||
{ modelId: 'gemini-3.6-flash' },
|
||||
jsonOnlyPromptMessages('Summarize AFFiNE in one short sentence.'),
|
||||
structuredOptions(z.object({ summary: z.string() }), { maxRetries: 2 }),
|
||||
structuredContract(z.object({ summary: z.string() }))
|
||||
@@ -1502,7 +1502,7 @@ test('GeminiProvider should treat maxRetries as retry count for backend failures
|
||||
|
||||
const error = await t.throwsAsync(
|
||||
getProviderRuntimeHost(provider).run.structured(
|
||||
{ modelId: 'gemini-2.5-flash' },
|
||||
{ modelId: 'gemini-3.6-flash' },
|
||||
jsonOnlyPromptMessages('Summarize AFFiNE in one short sentence.'),
|
||||
structuredOptions(z.object({ summary: z.string() }), { maxRetries: 2 }),
|
||||
structuredContract(z.object({ summary: z.string() }))
|
||||
@@ -1524,7 +1524,7 @@ test('GeminiProvider should use native structured path for audio attachments', a
|
||||
});
|
||||
provider.structuredFactory = () => ({
|
||||
id: 'structured_audio_1',
|
||||
model: 'gemini-2.5-flash',
|
||||
model: 'gemini-3.6-flash',
|
||||
output_text: '[{"a":"Speaker 1","s":0,"e":1,"t":"Hello"}]',
|
||||
output_json: [{ a: 'Speaker 1', s: 0, e: 1, t: 'Hello' }],
|
||||
usage: { prompt_tokens: 4, completion_tokens: 3, total_tokens: 7 },
|
||||
@@ -1532,7 +1532,7 @@ test('GeminiProvider should use native structured path for audio attachments', a
|
||||
});
|
||||
|
||||
const result = await getProviderRuntimeHost(provider).run.structured(
|
||||
{ modelId: 'gemini-2.5-flash' },
|
||||
{ modelId: 'gemini-3.6-flash' },
|
||||
promptMessages(
|
||||
systemPrompt('Return JSON only.'),
|
||||
userPrompt('transcribe the audio', {
|
||||
@@ -1653,7 +1653,7 @@ test('GeminiProvider should canonicalize native text attachments', async t => {
|
||||
testCase.setup(provider);
|
||||
|
||||
const result = await getProviderRuntimeHost(provider).run.text(
|
||||
{ modelId: 'gemini-2.5-flash' },
|
||||
{ modelId: 'gemini-3.6-flash' },
|
||||
testCase.messages
|
||||
);
|
||||
|
||||
@@ -1677,7 +1677,7 @@ test('GeminiProvider should pass abort signal to remote attachment prefetch', as
|
||||
const controller = new AbortController();
|
||||
|
||||
await getProviderRuntimeHost(provider).run.text(
|
||||
{ modelId: 'gemini-2.5-flash' },
|
||||
{ modelId: 'gemini-3.6-flash' },
|
||||
[
|
||||
{
|
||||
role: 'user',
|
||||
@@ -1701,7 +1701,7 @@ test('GeminiProvider should not pass materialized inline attachment URL to nativ
|
||||
});
|
||||
|
||||
await getProviderRuntimeHost(provider).run.text(
|
||||
{ modelId: 'gemini-2.5-flash' },
|
||||
{ modelId: 'gemini-3.6-flash' },
|
||||
[
|
||||
{
|
||||
role: 'user',
|
||||
@@ -1733,7 +1733,7 @@ test('GeminiProvider should reject unsupported attachment schemes at input valid
|
||||
|
||||
const error = await t.throwsAsync(
|
||||
getProviderRuntimeHost(provider).run.text(
|
||||
{ modelId: 'gemini-2.5-flash' },
|
||||
{ modelId: 'gemini-3.6-flash' },
|
||||
[
|
||||
{
|
||||
role: 'user',
|
||||
@@ -1756,7 +1756,7 @@ test('GeminiProvider should validate malformed attachments before canonicalizati
|
||||
|
||||
const error = await t.throwsAsync(
|
||||
getProviderRuntimeHost(provider).run.text(
|
||||
{ modelId: 'gemini-2.5-flash' },
|
||||
{ modelId: 'gemini-3.6-flash' },
|
||||
[
|
||||
{
|
||||
role: 'user',
|
||||
@@ -1804,7 +1804,7 @@ test('GeminiProvider should drive tool loop on native path', async t => {
|
||||
};
|
||||
|
||||
const result = await getProviderRuntimeHost(provider).run.text(
|
||||
{ modelId: 'gemini-2.5-flash' },
|
||||
{ modelId: 'gemini-3.6-flash' },
|
||||
[{ role: 'user', content: 'read doc a1' }],
|
||||
{}
|
||||
);
|
||||
@@ -1859,7 +1859,7 @@ test('GeminiVertexProvider should materialize remote attachments before native t
|
||||
});
|
||||
|
||||
const result = await getProviderRuntimeHost(provider).run.text(
|
||||
{ modelId: 'gemini-2.5-flash' },
|
||||
{ modelId: 'gemini-3.6-flash' },
|
||||
[
|
||||
{
|
||||
role: 'user',
|
||||
|
||||
@@ -1443,9 +1443,9 @@ test('checkParams should infer remote image capability from url extension withou
|
||||
test('llmResolveRequestedModelMatch should preserve provider-prefixed optional matches', t => {
|
||||
const request = parseRequestedModelMatchRequest({
|
||||
providerIds: ['openai-default', 'gemini-default'],
|
||||
defaultModel: 'gemini-2.5-flash',
|
||||
optionalModels: ['gemini-2.5-flash', 'gemini-2.5-pro'],
|
||||
requestedModelId: 'openai-default/gemini-2.5-pro',
|
||||
defaultModel: 'gpt-5.6-luna',
|
||||
optionalModels: ['gpt-5.6-luna', 'gpt-5.6-terra'],
|
||||
requestedModelId: 'openai-default/gpt-5.6-terra',
|
||||
});
|
||||
|
||||
t.snapshot(llmResolveRequestedModelMatch(request), 'prefixed optional hit');
|
||||
|
||||
@@ -103,7 +103,7 @@ async function buildNativeTranscriptResult(input: any, runId: string) {
|
||||
openQuestions: [],
|
||||
blockers: [],
|
||||
},
|
||||
providerMeta: { provider: 'gemini', model: 'gemini-2.5-flash' },
|
||||
providerMeta: { provider: 'gemini', model: 'gemini-3.5-flash-lite' },
|
||||
version: 'transcript-result-v1',
|
||||
strategy: 'gemini',
|
||||
},
|
||||
@@ -319,7 +319,7 @@ test('retryTask reuses failed task and queues a new action attempt', async t =>
|
||||
const payload = TranscriptPayloadSchema.parse({
|
||||
normalizedTranscript: '00:00:05 A: Kickoff',
|
||||
summaryJson: null,
|
||||
providerMeta: { provider: 'gemini', model: 'gemini-2.5-flash' },
|
||||
providerMeta: { provider: 'gemini', model: 'gemini-3.5-flash-lite' },
|
||||
});
|
||||
const service = createCopilotTranscriptionService(
|
||||
{
|
||||
@@ -341,7 +341,7 @@ test('retryTask reuses failed task and queues a new action attempt', async t =>
|
||||
} as never,
|
||||
{} as never,
|
||||
{
|
||||
resolveTranscriptionModel: Sinon.stub().resolves('gemini-2.5-flash'),
|
||||
resolveTranscriptionModel: Sinon.stub().resolves('gemini-3.5-flash-lite'),
|
||||
} as never,
|
||||
{} as never,
|
||||
{} as never
|
||||
@@ -382,7 +382,7 @@ test('retryTask prechecks quota or BYOK before queueing provider work', async t
|
||||
{ add } as never,
|
||||
{} as never,
|
||||
{
|
||||
resolveTranscriptionModel: Sinon.stub().resolves('gemini-2.5-flash'),
|
||||
resolveTranscriptionModel: Sinon.stub().resolves('gemini-3.5-flash-lite'),
|
||||
} as never,
|
||||
{} as never,
|
||||
{} as never,
|
||||
@@ -427,7 +427,9 @@ for (const status of ['ready', 'settled']) {
|
||||
} as never,
|
||||
{} as never,
|
||||
{
|
||||
resolveTranscriptionModel: Sinon.stub().resolves('gemini-2.5-flash'),
|
||||
resolveTranscriptionModel: Sinon.stub().resolves(
|
||||
'gemini-3.5-flash-lite'
|
||||
),
|
||||
} as never,
|
||||
{} as never,
|
||||
{} as never
|
||||
@@ -453,7 +455,9 @@ for (const status of ['ready', 'settled']) {
|
||||
|
||||
test('submitTask prechecks quota or BYOK before persisting uploads', async t => {
|
||||
const assertQuotaOrByok = Sinon.stub().rejects(new Error('quota exceeded'));
|
||||
const resolveTranscriptionModel = Sinon.stub().resolves('gemini-2.5-flash');
|
||||
const resolveTranscriptionModel = Sinon.stub().resolves(
|
||||
'gemini-3.5-flash-lite'
|
||||
);
|
||||
const service = createCopilotTranscriptionService(
|
||||
{
|
||||
copilotTranscriptTask: {
|
||||
@@ -492,7 +496,7 @@ test('submitTask rejects unavailable transcript strategy', async t => {
|
||||
{} as never,
|
||||
{} as never,
|
||||
{
|
||||
resolveTranscriptionModel: Sinon.stub().resolves('gemini-2.5-flash'),
|
||||
resolveTranscriptionModel: Sinon.stub().resolves('gemini-3.5-flash-lite'),
|
||||
} as never,
|
||||
{} as never,
|
||||
{} as never
|
||||
@@ -555,7 +559,7 @@ test('transcriptTask runs native transcript recipe through action bridge when av
|
||||
await service.transcriptTask({
|
||||
taskId: 'task-1',
|
||||
payload,
|
||||
modelId: 'gemini-2.5-flash',
|
||||
modelId: 'gemini-3.5-flash-lite',
|
||||
});
|
||||
|
||||
t.like(bridgeInputs[0] as Record<string, unknown>, {
|
||||
@@ -567,7 +571,7 @@ test('transcriptTask runs native transcript recipe through action bridge when av
|
||||
.prepareStructuredRoutes,
|
||||
{
|
||||
stepId: 'transcribe',
|
||||
modelId: 'gemini-2.5-flash',
|
||||
modelId: 'gemini-3.5-flash-lite',
|
||||
}
|
||||
);
|
||||
const messages = (
|
||||
@@ -641,7 +645,7 @@ test('transcriptTask fails task when native action bridge reports an error event
|
||||
service.transcriptTask({
|
||||
taskId: 'task-1',
|
||||
payload,
|
||||
modelId: 'gemini-2.5-flash',
|
||||
modelId: 'gemini-3.5-flash-lite',
|
||||
}),
|
||||
{ message: /native_failed/ }
|
||||
);
|
||||
|
||||
@@ -17,7 +17,7 @@ test.describe('AIAction/WriteAnPoemAboutThis', () => {
|
||||
'AFFiNE is a workspace with fully merged docs'
|
||||
);
|
||||
const { answer, responses } = await writePoem();
|
||||
await expect(answer).toHaveText(/AFFiNE/);
|
||||
await expect(answer.locator('text-renderer')).toContainText(/\S/);
|
||||
expect(responses).toEqual(new Set(['insert-below', 'replace-selection']));
|
||||
});
|
||||
|
||||
@@ -35,7 +35,7 @@ test.describe('AIAction/WriteAnPoemAboutThis', () => {
|
||||
}
|
||||
);
|
||||
const { answer, responses } = await writePoem();
|
||||
await expect(answer).toHaveText(/AFFiNE/);
|
||||
await expect(answer.locator('text-renderer')).toContainText(/\S/);
|
||||
expect(responses).toEqual(new Set(['insert-below']));
|
||||
});
|
||||
|
||||
@@ -53,7 +53,7 @@ test.describe('AIAction/WriteAnPoemAboutThis', () => {
|
||||
}
|
||||
);
|
||||
const { answer, responses } = await writePoem();
|
||||
await expect(answer).toHaveText(/AFFiNE/);
|
||||
await expect(answer.locator('text-renderer')).toContainText(/\S/);
|
||||
expect(responses).toEqual(new Set(['insert-below']));
|
||||
});
|
||||
|
||||
|
||||
@@ -6,10 +6,7 @@ test.describe.configure({ mode: 'serial' });
|
||||
|
||||
test.describe('AIChatWith/Attachments', () => {
|
||||
test.beforeEach(async ({ loggedInPage: page, utils }) => {
|
||||
await utils.testUtils.setupTestEnvironment(
|
||||
page,
|
||||
'claude-sonnet-4-5@20250929'
|
||||
);
|
||||
await utils.testUtils.setupTestEnvironment(page, 'claude-sonnet-4-6');
|
||||
await utils.chatPanel.openChatPanel(page);
|
||||
});
|
||||
|
||||
|
||||
@@ -6,10 +6,7 @@ test.describe.configure({ mode: 'serial' });
|
||||
|
||||
test.describe('AIChatWith/Collections', () => {
|
||||
test.beforeEach(async ({ loggedInPage: page, utils }) => {
|
||||
await utils.testUtils.setupTestEnvironment(
|
||||
page,
|
||||
'claude-sonnet-4-5@20250929'
|
||||
);
|
||||
await utils.testUtils.setupTestEnvironment(page, 'claude-sonnet-4-6');
|
||||
await utils.chatPanel.openChatPanel(page);
|
||||
await utils.editor.clearAllCollections(page);
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@ test.describe('AIChatWith/Image', () => {
|
||||
|
||||
await expect(async () => {
|
||||
const { content } = await utils.chatPanel.getLatestAssistantMessage(page);
|
||||
expect(content.length).toBeGreaterThan(20);
|
||||
expect(content).toMatch(/cat|kitten|feline|tabby|fluffy/i);
|
||||
}).toPass({ timeout: 20000 });
|
||||
});
|
||||
|
||||
@@ -7,10 +7,7 @@ test.describe.configure({ mode: 'serial' });
|
||||
|
||||
test.describe('AISettings/Embedding', () => {
|
||||
test.beforeEach(async ({ loggedInPage: page, utils }) => {
|
||||
await utils.testUtils.setupTestEnvironment(
|
||||
page,
|
||||
'claude-sonnet-4-5@20250929'
|
||||
);
|
||||
await utils.testUtils.setupTestEnvironment(page, 'claude-sonnet-4-6');
|
||||
await utils.chatPanel.openChatPanel(page);
|
||||
});
|
||||
|
||||
|
||||
@@ -62,19 +62,16 @@ export class TestUtils {
|
||||
}
|
||||
|
||||
public async setupTestEnvironment(page: Page, defaultModel?: string) {
|
||||
const hasExplicitModel = defaultModel !== undefined;
|
||||
const selectedModel = defaultModel ?? 'gemini-2.5-flash';
|
||||
const selectedModel = defaultModel ?? 'gpt-5.6-luna';
|
||||
await switchDefaultChatModel(selectedModel);
|
||||
|
||||
await skipOnboarding(page.context());
|
||||
if (hasExplicitModel) {
|
||||
await page.context().addInitScript(model => {
|
||||
window.localStorage.setItem(
|
||||
'global-state:AIModelId',
|
||||
JSON.stringify(model)
|
||||
);
|
||||
}, selectedModel);
|
||||
}
|
||||
await page.context().addInitScript(model => {
|
||||
window.localStorage.setItem(
|
||||
'global-state:AIModelId',
|
||||
JSON.stringify(model)
|
||||
);
|
||||
}, selectedModel);
|
||||
await openHomePage(page);
|
||||
await this.createNewPage(page);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user