storkit: merge 90_story_fetch_real_context_window_size_from_anthropic_models_api

This commit is contained in:
Dave
2026-03-21 11:58:33 +00:00
parent 30a56d03e5
commit a6c8cf0daf
3 changed files with 664 additions and 608 deletions

View File

@@ -3,7 +3,7 @@ use crate::llm::chat;
use crate::store::StoreOps;
use poem_openapi::{Object, OpenApi, Tags, payload::Json};
use reqwest::header::{HeaderMap, HeaderValue};
use serde::Deserialize;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
const ANTHROPIC_MODELS_URL: &str = "https://api.anthropic.com/v1/models";
@@ -18,6 +18,13 @@ struct AnthropicModelsResponse {
#[derive(Deserialize)]
struct AnthropicModelInfo {
id: String,
context_window: u64,
}
#[derive(Serialize, Object)]
struct AnthropicModelSummary {
id: String,
context_window: u64,
}
fn get_anthropic_api_key(ctx: &AppContext) -> Result<String, String> {
@@ -84,7 +91,7 @@ impl AnthropicApi {
/// List available Anthropic models.
#[oai(path = "/anthropic/models", method = "get")]
async fn list_anthropic_models(&self) -> OpenApiResult<Json<Vec<String>>> {
async fn list_anthropic_models(&self) -> OpenApiResult<Json<Vec<AnthropicModelSummary>>> {
self.list_anthropic_models_from(ANTHROPIC_MODELS_URL).await
}
}
@@ -93,7 +100,7 @@ impl AnthropicApi {
async fn list_anthropic_models_from(
&self,
url: &str,
) -> OpenApiResult<Json<Vec<String>>> {
) -> OpenApiResult<Json<Vec<AnthropicModelSummary>>> {
let api_key = get_anthropic_api_key(self.ctx.as_ref()).map_err(bad_request)?;
let client = reqwest::Client::new();
let mut headers = HeaderMap::new();
@@ -128,7 +135,14 @@ impl AnthropicApi {
.json::<AnthropicModelsResponse>()
.await
.map_err(|e| bad_request(e.to_string()))?;
let models = body.data.into_iter().map(|m| m.id).collect();
let models = body
.data
.into_iter()
.map(|m| AnthropicModelSummary {
id: m.id,
context_window: m.context_window,
})
.collect();
Ok(Json(models))
}
@@ -276,4 +290,29 @@ mod tests {
let dir = TempDir::new().unwrap();
let _api = make_api(&dir);
}
#[test]
fn anthropic_model_info_deserializes_context_window() {
let json = json!({
"id": "claude-opus-4-5",
"context_window": 200000
});
let info: AnthropicModelInfo = serde_json::from_value(json).unwrap();
assert_eq!(info.id, "claude-opus-4-5");
assert_eq!(info.context_window, 200000);
}
#[test]
fn anthropic_models_response_deserializes_multiple_models() {
let json = json!({
"data": [
{ "id": "claude-opus-4-5", "context_window": 200000 },
{ "id": "claude-haiku-4-5-20251001", "context_window": 100000 }
]
});
let response: AnthropicModelsResponse = serde_json::from_value(json).unwrap();
assert_eq!(response.data.len(), 2);
assert_eq!(response.data[0].context_window, 200000);
assert_eq!(response.data[1].context_window, 100000);
}
}