chore: bump deps
This commit is contained in:
@@ -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"] }
|
||||
|
||||
10
packages/backend/native/index.d.ts
vendored
10
packages/backend/native/index.d.ts
vendored
@@ -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<string>
|
||||
capabilities: Array<CapabilityModelCapability>
|
||||
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<string, ModelRegistryRouteContract>
|
||||
behaviorFlags?: Array<string>
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<String>,
|
||||
@@ -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<String>,
|
||||
#[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<String>,
|
||||
@@ -381,8 +381,8 @@ pub struct ModelRegistryRouteContract {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub protocol: Option<String>,
|
||||
#[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<String>,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 }> = [
|
||||
|
||||
@@ -507,6 +507,7 @@ export type LlmBackendConfig = {
|
||||
request_layer?:
|
||||
| 'anthropic'
|
||||
| 'chat_completions'
|
||||
| 'chat_completions_no_v1'
|
||||
| 'cloudflare_workers_ai'
|
||||
| 'responses'
|
||||
| 'openai_images'
|
||||
|
||||
@@ -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];
|
||||
|
||||
Reference in New Issue
Block a user