From aea128f0b9c5bb4b76ab5124815e4b0f8848223a Mon Sep 17 00:00:00 2001 From: DarkSky Date: Sat, 11 Jul 2026 06:43:04 +0800 Subject: [PATCH] chore: bump deps --- Cargo.lock | 76 ++++++++++++++----- Cargo.toml | 4 +- packages/backend/native/Cargo.toml | 2 +- packages/backend/native/index.d.ts | 10 +-- .../backend/native/src/llm/contract_schema.rs | 23 +++--- .../native/src/llm/core/contracts/mod.rs | 14 ++-- .../native/src/llm/core/model_registry.rs | 74 ++++++++++++++++++ .../src/__tests__/auth/jwt-session.spec.ts | 41 +++++----- packages/backend/server/src/native.ts | 1 + .../server/src/plugins/copilot/config.ts | 1 + 10 files changed, 183 insertions(+), 63 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 07f768b81e..544a0e9b85 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -70,7 +70,7 @@ dependencies = [ "napi", "rand 0.9.4", "rayon", - "sha3", + "sha3 0.12.0", "tempfile", ] @@ -264,7 +264,7 @@ dependencies = [ "serde", "serde_json", "sha2 0.11.0", - "sha3", + "sha3 0.12.0", "sqlx", "tempfile", "thiserror 2.0.18", @@ -531,7 +531,7 @@ dependencies = [ "futures-util", "hex", "serde", - "sha3", + "sha3 0.11.0", "sqlx", "tempfile", "thiserror 2.0.18", @@ -2320,6 +2320,17 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "fancy-regex" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1e1dacd0d2082dfcf1351c4bdd566bbe89a2b263235a2b50058f1e130a47277" +dependencies = [ + "bit-set 0.8.0", + "regex-automata", + "regex-syntax", +] + [[package]] name = "fast-float2" version = "0.2.3" @@ -3988,25 +3999,25 @@ dependencies = [ [[package]] name = "jsonschema" -version = "0.46.2" +version = "0.47.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50180452e7808015fe083eae3efcf1ec98b89b45dd8cc204f7b4a6b7b81ea675" +checksum = "281c43ff06dcb331e9356d30e38853d559ce3d0a3f693e0b0e102667dec14fb1" dependencies = [ "ahash", "bytecount", "data-encoding", "email_address", - "fancy-regex 0.17.0", + "fancy-regex 0.18.0", "fraction", "getrandom 0.3.4", "idna", "itoa", + "jsonschema-regex", "num-cmp", "num-traits", "percent-encoding", "referencing", "regex", - "regex-syntax", "reqwest", "rustls", "serde", @@ -4015,6 +4026,15 @@ dependencies = [ "uuid-simd", ] +[[package]] +name = "jsonschema-regex" +version = "0.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee0b351864e7ffbc5db9273daf7fa1b4d5177b0946713d667ca571b83c0b4045" +dependencies = [ + "regex-syntax", +] + [[package]] name = "kamadak-exif" version = "0.6.1" @@ -4273,16 +4293,16 @@ dependencies = [ [[package]] name = "llm_adapter" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332397a6ccde5ac47fc32b29a2eed447135eb4ff6fd05ffb88dfe937ea9c8211" +checksum = "b5edfe10ad51d5301468a395532cb0068caac1057fbda942edebe423fe585509" dependencies = [ "base64", "jsonschema", "schemars", "serde", "serde_json", - "sha2 0.10.9", + "sha2 0.11.0", "thiserror 2.0.18", "ureq", "url", @@ -4290,9 +4310,9 @@ dependencies = [ [[package]] name = "llm_runtime" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804da5b8087fe2ec5d48f4b0716d5cf3639d6feb1c4242a6364ccdb7ef5bfa61" +checksum = "2705eff96fcd8e21cb9f23245da8f6da260133dfaa9e6280840f426a6290cb9e" dependencies = [ "jsonschema", "llm_adapter", @@ -6095,14 +6115,14 @@ dependencies = [ [[package]] name = "referencing" -version = "0.46.2" +version = "0.47.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acb0c66c7b78c1da928bee668b5cc638c678642ff587faff6e6222f797be9d4c" +checksum = "348e860aeb0b7bd035778fd11dd9cd5290d32e4aed3b8f2274a00287a9fd362b" dependencies = [ "ahash", "fluent-uri", "getrandom 0.3.4", - "hashbrown 0.16.1", + "hashbrown 0.17.1", "itoa", "micromap", "parking_lot", @@ -6497,11 +6517,12 @@ dependencies = [ [[package]] name = "schemars" -version = "0.8.22" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" dependencies = [ "dyn-clone", + "ref-cast", "schemars_derive", "serde", "serde_json", @@ -6509,9 +6530,9 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.22" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" +checksum = "7d115b50f4aaeea07e79c1912f645c7513d81715d0420f8bc77a18c6260b307f" dependencies = [ "proc-macro2", "quote", @@ -6757,6 +6778,17 @@ dependencies = [ "keccak", ] +[[package]] +name = "sha3" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc9bad02c26382724b2d2692c6f179285e4b54eeecd7968f52a50059c3c11759" +dependencies = [ + "digest 0.11.3", + "keccak", + "sponge-cursor", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -6924,6 +6956,12 @@ dependencies = [ "der", ] +[[package]] +name = "sponge-cursor" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a0219bd7d979d58245a4f41f695e1ac9f8befdffadd7f61f1bae9e39abc6620" + [[package]] name = "sqlx" version = "0.8.6" diff --git a/Cargo.toml b/Cargo.toml index 000420ccaf..6534a1baec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,12 +78,12 @@ resolver = "3" rayon = "1.10" rubato = "0.16" safefetch = "0.1.0" - schemars = "0.8" + schemars = "1.2" screencapturekit = "0.3" serde = "1" serde_json = "1" sha2 = "0.11" - sha3 = "0.11" + sha3 = "0.12" sqlx = { version = "0.8", default-features = false, features = [ "chrono", "macros", diff --git a/packages/backend/native/Cargo.toml b/packages/backend/native/Cargo.toml index e88be067d7..cee5a1556e 100644 --- a/packages/backend/native/Cargo.toml +++ b/packages/backend/native/Cargo.toml @@ -25,7 +25,7 @@ homedir = { workspace = true } image = { workspace = true } infer = { workspace = true } instant-xml = "0.7.5" -jsonschema = "0.46" +jsonschema = "0.47" libwebp-sys = "0.9.6" little_exif = { workspace = true } llm_adapter = { workspace = true, features = ["schema", "ureq-client"] } diff --git a/packages/backend/native/index.d.ts b/packages/backend/native/index.d.ts index a89d127825..ea33ccd869 100644 --- a/packages/backend/native/index.d.ts +++ b/packages/backend/native/index.d.ts @@ -574,7 +574,7 @@ export interface ModelConditionsContract { } export interface ModelRegistryMatchRequest { - backendKind: 'openai_chat' | 'openai_responses' | 'anthropic' | 'cloudflare_workers_ai' | 'gemini_api' | 'gemini_vertex' | 'fal' | 'anthropic_vertex' + backendKind: 'openai_chat' | 'openai_responses' | 'anthropic' | 'cloudflare_workers_ai' | 'gemini_api' | 'gemini_vertex' | 'fal' | 'anthropic_vertex' | 'deepseek' | 'kimi' | 'opencode_go' | 'opencode_zen' cond: ModelConditionsContract } @@ -583,7 +583,7 @@ export interface ModelRegistryMatchResponse { } export interface ModelRegistryResolveRequest { - backendKind?: 'openai_chat' | 'openai_responses' | 'anthropic' | 'cloudflare_workers_ai' | 'gemini_api' | 'gemini_vertex' | 'fal' | 'anthropic_vertex' + backendKind?: 'openai_chat' | 'openai_responses' | 'anthropic' | 'cloudflare_workers_ai' | 'gemini_api' | 'gemini_vertex' | 'fal' | 'anthropic_vertex' | 'deepseek' | 'kimi' | 'opencode_go' | 'opencode_zen' modelId: string } @@ -594,11 +594,11 @@ export interface ModelRegistryResolveResponse { export interface ModelRegistryRouteContract { protocol?: 'openai_chat' | 'openai_responses' | 'openai_images' | 'anthropic' | 'gemini' | 'fal_image' - requestLayer?: 'anthropic' | 'chat_completions' | 'cloudflare_workers_ai' | 'responses' | 'openai_images' | 'fal' | 'vertex' | 'vertex_anthropic' | 'gemini_api' | 'gemini_vertex' + requestLayer?: 'anthropic' | 'chat_completions' | 'chat_completions_no_v1' | 'cloudflare_workers_ai' | 'responses' | 'openai_images' | 'fal' | 'vertex' | 'vertex_anthropic' | 'gemini_api' | 'gemini_vertex' } export interface ModelRegistryVariantContract { - backendKind: 'openai_chat' | 'openai_responses' | 'anthropic' | 'cloudflare_workers_ai' | 'gemini_api' | 'gemini_vertex' | 'fal' | 'anthropic_vertex' + backendKind: 'openai_chat' | 'openai_responses' | 'anthropic' | 'cloudflare_workers_ai' | 'gemini_api' | 'gemini_vertex' | 'fal' | 'anthropic_vertex' | 'deepseek' | 'kimi' | 'opencode_go' | 'opencode_zen' canonicalKey: string rawModelId: string displayName?: string @@ -606,7 +606,7 @@ export interface ModelRegistryVariantContract { legacyAliases?: Array capabilities: Array protocol?: 'openai_chat' | 'openai_responses' | 'openai_images' | 'anthropic' | 'gemini' | 'fal_image' - requestLayer?: 'anthropic' | 'chat_completions' | 'cloudflare_workers_ai' | 'responses' | 'openai_images' | 'fal' | 'vertex' | 'vertex_anthropic' | 'gemini_api' | 'gemini_vertex' + requestLayer?: 'anthropic' | 'chat_completions' | 'chat_completions_no_v1' | 'cloudflare_workers_ai' | 'responses' | 'openai_images' | 'fal' | 'vertex' | 'vertex_anthropic' | 'gemini_api' | 'gemini_vertex' routeOverrides?: Record behaviorFlags?: Array } diff --git a/packages/backend/native/src/llm/contract_schema.rs b/packages/backend/native/src/llm/contract_schema.rs index 263fd50ef5..e9369deaa6 100644 --- a/packages/backend/native/src/llm/contract_schema.rs +++ b/packages/backend/native/src/llm/contract_schema.rs @@ -1,6 +1,6 @@ use jsonschema::Draft; use napi::{Error, Result, Status}; -use schemars::{JsonSchema, r#gen::SchemaSettings}; +use schemars::{JsonSchema, generate::SchemaSettings}; use serde_json::Value; use super::{ @@ -61,15 +61,18 @@ fn mark_property_nullable(schema: &mut Value, property: &str) { } fn mark_definition_property_nullable(schema: &mut Value, definition: &str, property: &str) { - if let Some(property_schema) = schema - .get_mut("definitions") - .and_then(Value::as_object_mut) - .and_then(|definitions| definitions.get_mut(definition)) - .and_then(|schema| schema.get_mut("properties")) - .and_then(Value::as_object_mut) - .and_then(|properties| properties.get_mut(property)) - { - mark_schema_nullable(property_schema); + for definitions_key in ["definitions", "$defs"] { + if let Some(property_schema) = schema + .get_mut(definitions_key) + .and_then(Value::as_object_mut) + .and_then(|definitions| definitions.get_mut(definition)) + .and_then(|schema| schema.get_mut("properties")) + .and_then(Value::as_object_mut) + .and_then(|properties| properties.get_mut(property)) + { + mark_schema_nullable(property_schema); + return; + } } } diff --git a/packages/backend/native/src/llm/core/contracts/mod.rs b/packages/backend/native/src/llm/core/contracts/mod.rs index 15d096fb3c..f17b91fab2 100644 --- a/packages/backend/native/src/llm/core/contracts/mod.rs +++ b/packages/backend/native/src/llm/core/contracts/mod.rs @@ -319,7 +319,7 @@ pub struct RequestedModelMatchResponse { pub struct ModelRegistryResolveRequest { #[napi( ts_type = "'openai_chat' | 'openai_responses' | 'anthropic' | 'cloudflare_workers_ai' | 'gemini_api' | \ - 'gemini_vertex' | 'fal' | 'anthropic_vertex'" + 'gemini_vertex' | 'fal' | 'anthropic_vertex' | 'deepseek' | 'kimi' | 'opencode_go' | 'opencode_zen'" )] #[serde(skip_serializing_if = "Option::is_none")] pub backend_kind: Option, @@ -333,7 +333,7 @@ pub struct ModelRegistryResolveRequest { pub struct ModelRegistryMatchRequest { #[napi( ts_type = "'openai_chat' | 'openai_responses' | 'anthropic' | 'cloudflare_workers_ai' | 'gemini_api' | \ - 'gemini_vertex' | 'fal' | 'anthropic_vertex'" + 'gemini_vertex' | 'fal' | 'anthropic_vertex' | 'deepseek' | 'kimi' | 'opencode_go' | 'opencode_zen'" )] pub backend_kind: String, pub cond: ModelConditionsContract, @@ -346,7 +346,7 @@ pub struct ModelRegistryMatchRequest { pub struct ModelRegistryVariantContract { #[napi( ts_type = "'openai_chat' | 'openai_responses' | 'anthropic' | 'cloudflare_workers_ai' | 'gemini_api' | \ - 'gemini_vertex' | 'fal' | 'anthropic_vertex'" + 'gemini_vertex' | 'fal' | 'anthropic_vertex' | 'deepseek' | 'kimi' | 'opencode_go' | 'opencode_zen'" )] pub backend_kind: String, pub canonical_key: String, @@ -361,8 +361,8 @@ pub struct ModelRegistryVariantContract { #[serde(skip_serializing_if = "Option::is_none")] pub protocol: Option, #[napi( - ts_type = "'anthropic' | 'chat_completions' | 'cloudflare_workers_ai' | 'responses' | 'openai_images' | 'fal' | \ - 'vertex' | 'vertex_anthropic' | 'gemini_api' | 'gemini_vertex'" + ts_type = "'anthropic' | 'chat_completions' | 'chat_completions_no_v1' | 'cloudflare_workers_ai' | 'responses' | \ + 'openai_images' | 'fal' | 'vertex' | 'vertex_anthropic' | 'gemini_api' | 'gemini_vertex'" )] #[serde(skip_serializing_if = "Option::is_none")] pub request_layer: Option, @@ -381,8 +381,8 @@ pub struct ModelRegistryRouteContract { #[serde(skip_serializing_if = "Option::is_none")] pub protocol: Option, #[napi( - ts_type = "'anthropic' | 'chat_completions' | 'cloudflare_workers_ai' | 'responses' | 'openai_images' | 'fal' | \ - 'vertex' | 'vertex_anthropic' | 'gemini_api' | 'gemini_vertex'" + ts_type = "'anthropic' | 'chat_completions' | 'chat_completions_no_v1' | 'cloudflare_workers_ai' | 'responses' | \ + 'openai_images' | 'fal' | 'vertex' | 'vertex_anthropic' | 'gemini_api' | 'gemini_vertex'" )] #[serde(skip_serializing_if = "Option::is_none")] pub request_layer: Option, diff --git a/packages/backend/native/src/llm/core/model_registry.rs b/packages/backend/native/src/llm/core/model_registry.rs index 71e5915bb6..61f0c94cf0 100644 --- a/packages/backend/native/src/llm/core/model_registry.rs +++ b/packages/backend/native/src/llm/core/model_registry.rs @@ -111,6 +111,80 @@ mod tests { assert_eq!(response.variant.unwrap().raw_model_id, "gemini-embedding-001"); } + #[test] + fn should_resolve_deepseek_provider_variants() { + let response = llm_resolve_model_registry_variant(ModelRegistryResolveRequest { + backend_kind: Some("deepseek".to_string()), + model_id: "deepseek-v4-pro".to_string(), + }) + .unwrap(); + let variant = response.variant.unwrap(); + + assert_eq!(variant.raw_model_id, "deepseek-v4-pro"); + assert_eq!(variant.request_layer.as_deref(), Some("chat_completions_no_v1")); + + let legacy = llm_resolve_model_registry_variant(ModelRegistryResolveRequest { + backend_kind: Some("deepseek".to_string()), + model_id: "deepseek-chat".to_string(), + }) + .unwrap(); + + assert_eq!(legacy.matched_by.as_deref(), Some("legacy_alias")); + assert_eq!(legacy.variant.unwrap().raw_model_id, "deepseek-v4-flash"); + } + + #[test] + fn should_resolve_kimi_provider_default_model() { + let response = llm_resolve_model_registry_variant(ModelRegistryResolveRequest { + backend_kind: Some("kimi".to_string()), + model_id: "kimi-k2.7-code-highspeed".to_string(), + }) + .unwrap(); + let variant = response.variant.unwrap(); + + assert_eq!(variant.raw_model_id, "kimi-k2.7-code-highspeed"); + assert_eq!(variant.protocol.as_deref(), Some("openai_chat")); + assert_eq!(variant.request_layer.as_deref(), Some("chat_completions")); + assert_eq!( + variant.behavior_flags.as_deref(), + Some(&["omit_tool_choice".to_string(), "reasoning_supported".to_string()][..]) + ); + } + + #[test] + fn should_resolve_opencode_go_prefixed_alias() { + let response = llm_resolve_model_registry_variant(ModelRegistryResolveRequest { + backend_kind: Some("opencode_go".to_string()), + model_id: "opencode-go/kimi-k2.7-code".to_string(), + }) + .unwrap(); + let variant = response.variant.unwrap(); + + assert_eq!(response.matched_by.as_deref(), Some("alias")); + assert_eq!(variant.backend_kind, "opencode_go"); + assert_eq!(variant.raw_model_id, "kimi-k2.7-code"); + } + + #[test] + fn should_match_opencode_zen_default_variant() { + let response = llm_match_model_registry(ModelRegistryMatchRequest { + backend_kind: "opencode_zen".to_string(), + cond: ModelConditionsContract { + input_types: Some(vec!["text".to_string()]), + attachment_kinds: None, + attachment_source_kinds: None, + has_remote_attachments: None, + model_id: None, + output_type: Some("text".to_string()), + }, + }) + .unwrap(); + let variant = response.variant.unwrap(); + + assert_eq!(variant.raw_model_id, "kimi-k2.7-code"); + assert_eq!(variant.backend_kind, "opencode_zen"); + } + #[test] fn should_resolve_gemini_embedding_2() { let response = llm_resolve_model_registry_variant(ModelRegistryResolveRequest { diff --git a/packages/backend/server/src/__tests__/auth/jwt-session.spec.ts b/packages/backend/server/src/__tests__/auth/jwt-session.spec.ts index 310cb6728f..19deddb9d7 100644 --- a/packages/backend/server/src/__tests__/auth/jwt-session.spec.ts +++ b/packages/backend/server/src/__tests__/auth/jwt-session.spec.ts @@ -107,28 +107,31 @@ test.serial('should sign and verify a user session jwt', async t => { t.true(signed.expiresAt.getTime() > Date.now()); }); -test.serial('should use application session ttl for jwt expiration', async t => { - const defaultSigned = t.context.jwtSession.sign( - t.context.user.id, - t.context.sessionId - ); - assertSignedTtl(t, defaultSigned, DEFAULT_SESSION_TTL); +test.serial( + 'should use application session ttl for jwt expiration', + async t => { + const defaultSigned = t.context.jwtSession.sign( + t.context.user.id, + t.context.sessionId + ); + assertSignedTtl(t, defaultSigned, DEFAULT_SESSION_TTL); - const ttl = 120; - t.context.config.override({ - auth: { - session: { - ttl, + const ttl = 120; + t.context.config.override({ + auth: { + session: { + ttl, + }, }, - }, - }); + }); - const configuredSigned = t.context.jwtSession.sign( - t.context.user.id, - t.context.sessionId - ); - assertSignedTtl(t, configuredSigned, ttl); -}); + const configuredSigned = t.context.jwtSession.sign( + t.context.user.id, + t.context.sessionId + ); + assertSignedTtl(t, configuredSigned, ttl); + } +); test.serial('should reject invalid jwt cases', async t => { const cases: Array<{ name: string; token: string }> = [ diff --git a/packages/backend/server/src/native.ts b/packages/backend/server/src/native.ts index d821a67c1b..a33e2a22b1 100644 --- a/packages/backend/server/src/native.ts +++ b/packages/backend/server/src/native.ts @@ -507,6 +507,7 @@ export type LlmBackendConfig = { request_layer?: | 'anthropic' | 'chat_completions' + | 'chat_completions_no_v1' | 'cloudflare_workers_ai' | 'responses' | 'openai_images' diff --git a/packages/backend/server/src/plugins/copilot/config.ts b/packages/backend/server/src/plugins/copilot/config.ts index 266632d54e..c55772428b 100644 --- a/packages/backend/server/src/plugins/copilot/config.ts +++ b/packages/backend/server/src/plugins/copilot/config.ts @@ -37,6 +37,7 @@ export const RustRequestMiddlewareValues = [ 'clamp_max_tokens', 'tool_schema_rewrite', 'openai_request_compat', + 'omit_tool_choice', ] as const; export type RustRequestMiddleware = (typeof RustRequestMiddlewareValues)[number];