From a1defa8a3ba0cd1f396e53588decea19338489b9 Mon Sep 17 00:00:00 2001 From: DarkSky <25152247+darkskygit@users.noreply.github.com> Date: Thu, 30 Jul 2026 13:58:07 +0800 Subject: [PATCH] feat(server): update model list (#15375) --- Cargo.lock | 12 +- .../backend/native/src/llm/action/tests.rs | 4 +- .../src/llm/assets/prompts/built-in.json | 117 +++++------ .../native/src/llm/core/model_registry.rs | 28 ++- .../src/llm/core/request_builder/mod.rs | 4 +- .../backend/native/src/llm/prompt_catalog.rs | 25 ++- .../copilot/__snapshots__/copilot.spec.ts.md | 87 +------- .../__snapshots__/copilot.spec.ts.snap | Bin 2501 -> 2161 bytes .../__snapshots__/native-provider.spec.ts.md | 2 +- .../native-provider.spec.ts.snap | Bin 4335 -> 4269 bytes .../__snapshots__/provider-native.spec.ts.md | 4 +- .../provider-native.spec.ts.snap | Bin 3547 -> 3584 bytes .../copilot/copilot-provider.spec.ts | 10 +- .../src/__tests__/copilot/copilot.e2e.ts | 9 +- .../src/__tests__/copilot/copilot.spec.ts | 198 ++++++------------ .../__tests__/copilot/native-provider.spec.ts | 48 ++--- .../__tests__/copilot/provider-native.spec.ts | 6 +- .../copilot/transcript-contract.spec.ts | 24 ++- .../e2e/ai-action/write-an-poem.spec.ts | 6 +- .../e2e/chat-with/attachments.spec.ts | 5 +- .../e2e/chat-with/collections.spec.ts | 5 +- .../e2e/chat-with/image.spec.ts | 1 - .../e2e/settings/embedding.spec.ts | 5 +- .../e2e/utils/test-utils.ts | 17 +- 24 files changed, 253 insertions(+), 364 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f6235fb97e..66dee1c13f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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]] diff --git a/packages/backend/native/src/llm/action/tests.rs b/packages/backend/native/src/llm/action/tests.rs index b1b0008d15..f221cc620a 100644 --- a/packages/backend/native/src/llm/action/tests.rs +++ b/packages/backend/native/src/llm/action/tests.rs @@ -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" } } })), ) diff --git a/packages/backend/native/src/llm/assets/prompts/built-in.json b/packages/backend/native/src/llm/assets/prompts/built-in.json index 9f96bbb515..cb52ec8ec0 100644 --- a/packages/backend/native/src/llm/assets/prompts/built-in.json +++ b/packages/backend/native/src/llm/assets/prompts/built-in.json @@ -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, diff --git a/packages/backend/native/src/llm/core/model_registry.rs b/packages/backend/native/src/llm/core/model_registry.rs index 61f0c94cf0..60032fa74d 100644 --- a/packages/backend/native/src/llm/core/model_registry.rs +++ b/packages/backend/native/src/llm/core/model_registry.rs @@ -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()), }, }) diff --git a/packages/backend/native/src/llm/core/request_builder/mod.rs b/packages/backend/native/src/llm/core/request_builder/mod.rs index e720f68ba7..3020939c12 100644 --- a/packages/backend/native/src/llm/core/request_builder/mod.rs +++ b/packages/backend/native/src/llm/core/request_builder/mod.rs @@ -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::(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", diff --git a/packages/backend/native/src/llm/prompt_catalog.rs b/packages/backend/native/src/llm/prompt_catalog.rs index 309f7f71c8..669ad152e4 100644 --- a/packages/backend/native/src/llm/prompt_catalog.rs +++ b/packages/backend/native/src/llm/prompt_catalog.rs @@ -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::>()), + 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" + ])) + ); } } diff --git a/packages/backend/server/src/__tests__/copilot/__snapshots__/copilot.spec.ts.md b/packages/backend/server/src/__tests__/copilot/__snapshots__/copilot.spec.ts.md index ba92cd97f1..1650e7f294 100644 --- a/packages/backend/server/src/__tests__/copilot/__snapshots__/copilot.spec.ts.md +++ b/packages/backend/server/src/__tests__/copilot/__snapshots__/copilot.spec.ts.md @@ -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' diff --git a/packages/backend/server/src/__tests__/copilot/__snapshots__/copilot.spec.ts.snap b/packages/backend/server/src/__tests__/copilot/__snapshots__/copilot.spec.ts.snap index 317e6e8699e183720788e9b321f50ce01ad5ee04..812d846a51aaf11ce74e72f1a2b0c7402f7b8c1b 100644 GIT binary patch literal 2161 zcmV-%2#)tbRzV7&M;ZUk?AgB9acrvv)KJLKCQ^}dhJ+-IqKJ|bOOPg{ zsUxLn8>HFYv2WwOo$Jh;?c=Y2q@wVE5J&|SBpUHgB@aR32@sVU`Ua{50>lG?m-45e zsz|^KLPEPYyLY#D_S%V)IMwAPd!BE8fmm zK63@*ZYY?Mti~fgFPK;5hH0U7AfrG>ysoR#=+9pEeQx+!a>c<2;(w$}oc97a0N?`v z?jpleWax-eyh%uUH8C*(G73UL#t3<&b>kQzAB+Ddv5(Ss0Q>;JZvniX`WZgyo)?}W zG`pOfoJ^*iBEZ`SaG2ywOWmg9AP&d`?jrQ=_-bg1jCe9KA~Nakv8o6|$(E!FeUNR0 zoFhOwI9%t7*L2QBNy$)TCc3GOs3mjJg1Ls0xmNR5YG|S25a|U1d?6p6(-R)ads~vq z&*n>_5+Qd*xcn|#?0FFh#f@O5D%e~Q@sQPo)_h(Js(a^FcYnURelRyDl!#1PUA7dM zD&vtfRiRib^i&A$?-hbMsTNj{feRKW^uZ3Gl=cBQ1mGxulSN>05{NvJf#q2XmN7zp z6kpQB;O^16-ze|BD6nG_XI&$OS{x^LSf_n`P9nSg2EX{FUcO9&|*8%Qx2CN&fZos-X zH|uQEzr$K8u_#pgnBYmJglEELyWxK(CF;RDk*I$zCh7>%9GK>+Uu@F4)R06tnowo<~NAS2t?+GM-dCfns7##g6krrMQoyk5p^ZDBP2cBH&r;w^8+qi~ooy~P zxhPn+>TH|gb4I8f+TXJ|kNK(?-d`cW*9q|Bn{dqk)6F~P-+IiJ2~9WK+lsY8D>GapZ?0d-5~edT)C=wrM}rVU5TaiY;;# z$cAQ~jQqd^GScnGJr`Rbe*7n$7>>UIh})!j02lJ_@JS&w?v7t2p9xI$Q6+12^Fbbl zqLqS?@to!;)+) zRYlYhI^!zdy)1bjzj{mJrjyqn_qLhXG>GO|Qe7MDK^tr&P2Yg+i+sjICAi;YRjymZ zHtuh2?zo-t+_w%Z#TiK!)4kn~Boo|WK^`g&vPT`dBmGb3XFPiW#7)<=;wXz0a^cB1 zyXOwEndN%OgNQxd;E`$6m?vxXMuJLL1!692jy{iIMh0gA-39rhdz|*X* zg2)T%q0rO0rHs~-M1O?WGAc~YHflAlnk)sg&EK@mUqff&$69yCpSIXc+QbGjO11Re z-CF9&dJsy(JS8J`Ub?#95XFS#?>sw=ZWh>li>pg9ya@q?8j~exvTHQ45eyUrC zeVP^MW!frGKZm>W4pSp8}g@06f zGc{NEeh|&KJnwNb&nK9+yAfYnIdnztL*rK8-W+I_E02TSUc_AR@%_Mr+a+p&cs|=cfQ(0`QAmcr+(N^mhRMkTcrS|BKnbWTL-~w0N48Wj{&F z@>IX47)}pYmI?5wyjidEf0Y2=SgZ11T}9o0zseY;eZb+olL9*_@K{cpOSud>=P2M= zAzwxDR~LAiN7*}8(&I#klcZmwSrxA5_G>i#?3unsfj0^t!_w^z!15|tE)=*eb`5P! zDcis7S*QKp7VQ@EJ(1;`?Tn6lyw2Sq3`~>NWf*u(R+ZYY^n?}nr*$P+LK&vS(+#1G zW^R+|hO0dl)DxfDaMS2GY<}KK*V{8X4`GUo&(}?5|MY>15lV3@3+Yr<8A+ASApG{M z*46edS6fq8VI#_Wn&V;Ua&IC2;Mo^*yb+ppdOB9*snxC9#m0Kw&XM0x@gIx|c&y}W zo^#&{d5C0GxpD7DtoM50E%XZ|k{wgt*i;W)_f*_7!D4!D-O)AClo#@bFDhC_kua5g nl>@mG!HV$d>%2IMQ|pF6Tqv2)A^s|-ck2HG2AirssWSiokJTrn literal 2501 zcmV;$2|D&cRzV6%s_1NCrddJ-v-<|mskf0WRR0yO33KET=ppqX!;ujz)HLZjYPzeMTKPr$= z`6#F=qVNNRM0a;~ZLfW|xy$9Na(+0rXZC&Po%ea3d1pNLbh+qCdsaPuUT8>jpN+{(>&ru$)tE$xMv*$}CuK7uF!NL%Ne{t(!4X0}7W_{F8@X=-_#S}Y0(d>PGkBzU zTG*P<=uHu^k)~5fingu^zJsGnQ?!g88-~vj;6(zwmJP!Z3aq2RUFm5Z z=<50?1&S0no9;T;)%6()T%f>9>8?Xp4(@-^w;{MM!=S}EU!9>@#bR+8tlMA#8?8R; z`mF1-?(NMwQ}o|qdir8c_^oY%Eq!0u+HJN9{?Erm-E}h(^-tME9iqS}1tznJdYl3e zQ{dy-L_J4=^Axyr6^Q!Rt4CC_V|AE7rdE-lWalakYI+&uoUnj*ttL6Q7|K=oTtG}; zh?sVY6-8P4!mu&k_aRliY0t zxPt%(2~f;t*jWO6kpLI68TJbT{F(r7X6%FV#9B`QMuB}93|k3pihbJjJdb*U0#B~y zmTPOWxYXpFV9BVHWrmlv@Kb2tc4Kby{cL!DnE+oSzz?s&HvbP-Z<~MZF`FkeUTm)` z*7~JPzm&O=HMw8P^h=q3Dbp`y`lZYbi`na6%9w+kP2IoV`VEgcwcr7wxF1efFx;BdHl*c99Q;lK>?XiG0iL|_ zdm$M)3ZZmyd1BRCfnFxSE7|H90rsD5UUHgOREXFOZ`IoyDR4LKob|y>#0EB|yD%Ai zJ7bXd{zPNElJLXx;kqwtbsgOhi6Uh@@DeM`fuz{;O0GySdn~#cay;nMIyYvG(C!@f z9obOKmR`xxj`UPZg3d+&f9OZ;_zrFv1=13T%9%7MNoI;~4KAykaCG&7FqjW=*A)@G zhDK9e2gQP;v7)P1G%#(Y(H zZJ{&n2lcTj4<5RBP2#2#E025ZK+x6kDlE*d33itW)|0wtz~-tD?-#hTd}(D zc(zk_g_=waWjK<;kMLSTg^6R0T8;Zn7K7Q$-=vwphDyXQ7Sgix%}kn!b)*+->H9jh z)RuL}m73YU^w?=xRK0$H`ofqWb!>}q;k@B1@{{D1GTztn)Osg$B8sa(2F!mP%nd<(*|QI zA9j>-yhf9FbAdmZ8RYhsPv=7vZqEvFcN@RJ5l~_Jv zEax-!nRLzqK9N3=N*|$gw&uHx{KNuYNE=zRq>;7VFwFs@xs;L7%o29sv@Es?*i9ww zxXpO(3TDO%BFJk&C5g?nv$@kwoXtWlN@qcvd}bQj+Iv7c%3+}-?Se?MXe4cY_)H)} zOxaaYYPf-j+T3-Ok^JYbbk9g_08aLPF(UV;(SzLdTL7M2az7IJO;yJGxsJ7agP9H% z<|nRORC}l=t%JRmw+An4c^f0dYa4q0v@8Z|w+dUHYHJw|_d%vDPplsUcpkvdQ{mB+ z4AGYXyprm)ruUuvKPRF;Mk1ajX_<*PSoG0e=cHB_R~88HsdTq)<^Ku+zJ9sNe{l(Q z|J@R8l=c9Jbvp$%QQ$$k)Mh_VtWy-QjgT*)_)80X*Z%80i|KJF#Nni$qe&K4^7thh z|6v7vjRJ3E{?J3$TL4R|WIj{i)|fH0G$n7o*|E(2QxWav(lwFco2iTr*}Tq+j_c?q zt4r6ho2)98X7LUys88#@WFcjkFCJ?Mr4=hSnQ9c3?K}0*rqWzD+BTby8|m7R(0Kss z$XG?x9M36CP0keRzBIZJ`>IM$`mqa9YPmJGZtt))(Ppdc2Kw4*t;}7w$nDwSWUeI2 zyy5BGp6wNqC)?a! zxx0H-?2g;onTt2GTRNPrw_V;SiGq@zCv;)DFmvzJ_NkfeyQg-i_6v(*tEZRC3+d>x zu@PiXhJ*=j2KI1oNO?FpEmG2*6Q*nHu&2nCD6xQc-5g}xE5%zPTY6=u(r0C#m3>yO PoR$9vHIY%O!#e-~-}~Ag diff --git a/packages/backend/server/src/__tests__/copilot/__snapshots__/native-provider.spec.ts.md b/packages/backend/server/src/__tests__/copilot/__snapshots__/native-provider.spec.ts.md index 68319f7235..62f6c47dd2 100644 --- a/packages/backend/server/src/__tests__/copilot/__snapshots__/native-provider.spec.ts.md +++ b/packages/backend/server/src/__tests__/copilot/__snapshots__/native-provider.spec.ts.md @@ -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, diff --git a/packages/backend/server/src/__tests__/copilot/__snapshots__/native-provider.spec.ts.snap b/packages/backend/server/src/__tests__/copilot/__snapshots__/native-provider.spec.ts.snap index 58115b871c183a93c83f821fcf5cb55b425791f4..582236a8c7bc0507b0e87284b767dd7afa3a7fce 100644 GIT binary patch literal 4269 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 literal 4335 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 diff --git a/packages/backend/server/src/__tests__/copilot/__snapshots__/provider-native.spec.ts.md b/packages/backend/server/src/__tests__/copilot/__snapshots__/provider-native.spec.ts.md index 93e674d8d9..9dc47b3221 100644 --- a/packages/backend/server/src/__tests__/copilot/__snapshots__/provider-native.spec.ts.md +++ b/packages/backend/server/src/__tests__/copilot/__snapshots__/provider-native.spec.ts.md @@ -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 diff --git a/packages/backend/server/src/__tests__/copilot/__snapshots__/provider-native.spec.ts.snap b/packages/backend/server/src/__tests__/copilot/__snapshots__/provider-native.spec.ts.snap index 742c073e14bd16b77249bda76b5b23e183e4e38b..ed0603fc0e907073bc2dfc3afeb034ea78f61f5d 100644 GIT binary patch literal 3584 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 literal 3547 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, 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, 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', }, ]; diff --git a/packages/backend/server/src/__tests__/copilot/copilot.e2e.ts b/packages/backend/server/src/__tests__/copilot/copilot.e2e.ts index 4cc7673448..ec68f29e5d 100644 --- a/packages/backend/server/src/__tests__/copilot/copilot.e2e.ts +++ b/packages/backend/server/src/__tests__/copilot/copilot.e2e.ts @@ -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'; diff --git a/packages/backend/server/src/__tests__/copilot/copilot.spec.ts b/packages/backend/server/src/__tests__/copilot/copilot.spec.ts index 3d2af6816d..0af1b515ce 100644 --- a/packages/backend/server/src/__tests__/copilot/copilot.spec.ts +++ b/packages/backend/server/src/__tests__/copilot/copilot.spec.ts @@ -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({ diff --git a/packages/backend/server/src/__tests__/copilot/native-provider.spec.ts b/packages/backend/server/src/__tests__/copilot/native-provider.spec.ts index 413c873af1..b287c0fb16 100644 --- a/packages/backend/server/src/__tests__/copilot/native-provider.spec.ts +++ b/packages/backend/server/src/__tests__/copilot/native-provider.spec.ts @@ -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', diff --git a/packages/backend/server/src/__tests__/copilot/provider-native.spec.ts b/packages/backend/server/src/__tests__/copilot/provider-native.spec.ts index 303765c48c..9f1e7b11ea 100644 --- a/packages/backend/server/src/__tests__/copilot/provider-native.spec.ts +++ b/packages/backend/server/src/__tests__/copilot/provider-native.spec.ts @@ -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'); diff --git a/packages/backend/server/src/__tests__/copilot/transcript-contract.spec.ts b/packages/backend/server/src/__tests__/copilot/transcript-contract.spec.ts index 3aa3981ee7..681e4f5592 100644 --- a/packages/backend/server/src/__tests__/copilot/transcript-contract.spec.ts +++ b/packages/backend/server/src/__tests__/copilot/transcript-contract.spec.ts @@ -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, { @@ -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/ } ); diff --git a/tests/affine-cloud-copilot/e2e/ai-action/write-an-poem.spec.ts b/tests/affine-cloud-copilot/e2e/ai-action/write-an-poem.spec.ts index aff4092fb9..3063832a1b 100644 --- a/tests/affine-cloud-copilot/e2e/ai-action/write-an-poem.spec.ts +++ b/tests/affine-cloud-copilot/e2e/ai-action/write-an-poem.spec.ts @@ -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'])); }); diff --git a/tests/affine-cloud-copilot/e2e/chat-with/attachments.spec.ts b/tests/affine-cloud-copilot/e2e/chat-with/attachments.spec.ts index 0f99b79def..2c24a6c6e6 100644 --- a/tests/affine-cloud-copilot/e2e/chat-with/attachments.spec.ts +++ b/tests/affine-cloud-copilot/e2e/chat-with/attachments.spec.ts @@ -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); }); diff --git a/tests/affine-cloud-copilot/e2e/chat-with/collections.spec.ts b/tests/affine-cloud-copilot/e2e/chat-with/collections.spec.ts index 1c7d5ea0e6..43e4922b08 100644 --- a/tests/affine-cloud-copilot/e2e/chat-with/collections.spec.ts +++ b/tests/affine-cloud-copilot/e2e/chat-with/collections.spec.ts @@ -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); diff --git a/tests/affine-cloud-copilot/e2e/chat-with/image.spec.ts b/tests/affine-cloud-copilot/e2e/chat-with/image.spec.ts index 9a05516bc2..bd0290d81c 100644 --- a/tests/affine-cloud-copilot/e2e/chat-with/image.spec.ts +++ b/tests/affine-cloud-copilot/e2e/chat-with/image.spec.ts @@ -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 }); }); diff --git a/tests/affine-cloud-copilot/e2e/settings/embedding.spec.ts b/tests/affine-cloud-copilot/e2e/settings/embedding.spec.ts index 08625c0eb8..c3475bedb2 100644 --- a/tests/affine-cloud-copilot/e2e/settings/embedding.spec.ts +++ b/tests/affine-cloud-copilot/e2e/settings/embedding.spec.ts @@ -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); }); diff --git a/tests/affine-cloud-copilot/e2e/utils/test-utils.ts b/tests/affine-cloud-copilot/e2e/utils/test-utils.ts index b8573daece..d371713607 100644 --- a/tests/affine-cloud-copilot/e2e/utils/test-utils.ts +++ b/tests/affine-cloud-copilot/e2e/utils/test-utils.ts @@ -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); }