Single-commit clean baseline after security scrub of niche-tells, project codenames, internal jargon, and contributor-email leaks. Contents: - 100 Rust crates (_primitives/_rust/) - 37 agent manifests (_manifests/) + generated specs (_generated/) - 67 user-invocable skills (skills/) - 33 hooks (hooks/) - Composition blocks (_blocks/) - Documentation (docs/, README.md) - TS adapter packages (_ts_packages/) - Assembler (_assembler/) - Roles (_roles/) - Templates (_templates/) - Forgejo CI (.forgejo/) Author: Denis Parfionovich <info@greendragon.info> License: see LICENSE.
92 lines
3.1 KiB
Rust
92 lines
3.1 KiB
Rust
//! Wire-schema round-trip tests against fixtures matching Ollama's documented
|
|
//! JSON envelopes (`<https://github.com/ollama/ollama/blob/main/docs/api.md>`).
|
|
|
|
use kei_llm_ollama::{ChatResp, GenerateResp, Message, ModelEntry, TagsResp};
|
|
|
|
#[test]
|
|
fn tags_resp_roundtrip() {
|
|
let raw = r#"{
|
|
"models": [
|
|
{
|
|
"name": "qwen3:4b",
|
|
"model": "qwen3:4b",
|
|
"modified_at": "2025-10-06T18:37:52Z",
|
|
"size": 4733124608,
|
|
"digest": "deadbeef",
|
|
"details": {
|
|
"parent_model": "",
|
|
"format": "gguf",
|
|
"family": "qwen3",
|
|
"families": ["qwen3"],
|
|
"parameter_size": "4.0B",
|
|
"quantization_level": "Q4_K_M"
|
|
}
|
|
}
|
|
]
|
|
}"#;
|
|
let parsed: TagsResp = serde_json::from_str(raw).expect("decode tags");
|
|
assert_eq!(parsed.models.len(), 1);
|
|
assert_eq!(parsed.models[0].name, "qwen3:4b");
|
|
let again = serde_json::to_string(&parsed).expect("encode tags");
|
|
let reparsed: TagsResp = serde_json::from_str(&again).expect("re-decode tags");
|
|
assert_eq!(parsed, reparsed);
|
|
}
|
|
|
|
#[test]
|
|
fn generate_resp_roundtrip() {
|
|
let raw = r#"{
|
|
"model": "qwen3:4b",
|
|
"created_at": "2025-04-01T00:00:00Z",
|
|
"response": "Hello, world!",
|
|
"done": true,
|
|
"eval_count": 7,
|
|
"eval_duration": 12345
|
|
}"#;
|
|
let parsed: GenerateResp = serde_json::from_str(raw).expect("decode generate");
|
|
assert!(parsed.done);
|
|
assert_eq!(parsed.response, "Hello, world!");
|
|
assert_eq!(parsed.eval_count, Some(7));
|
|
let again = serde_json::to_string(&parsed).expect("encode generate");
|
|
let reparsed: GenerateResp = serde_json::from_str(&again).expect("re-decode generate");
|
|
assert_eq!(parsed, reparsed);
|
|
}
|
|
|
|
#[test]
|
|
fn chat_resp_roundtrip() {
|
|
let raw = r#"{
|
|
"model": "qwen3:4b",
|
|
"created_at": "2025-04-01T00:00:00Z",
|
|
"message": {"role": "assistant", "content": "Hi!"},
|
|
"done": true,
|
|
"eval_count": 3
|
|
}"#;
|
|
let parsed: ChatResp = serde_json::from_str(raw).expect("decode chat");
|
|
assert_eq!(parsed.message.role, "assistant");
|
|
assert_eq!(parsed.message.content, "Hi!");
|
|
let again = serde_json::to_string(&parsed).expect("encode chat");
|
|
let reparsed: ChatResp = serde_json::from_str(&again).expect("re-decode chat");
|
|
assert_eq!(parsed, reparsed);
|
|
}
|
|
|
|
#[test]
|
|
fn message_round_trip_all_three_roles() {
|
|
for role in ["system", "user", "assistant"] {
|
|
let m = Message {
|
|
role: role.into(),
|
|
content: "x".into(),
|
|
};
|
|
let raw = serde_json::to_string(&m).unwrap();
|
|
let back: Message = serde_json::from_str(&raw).unwrap();
|
|
assert_eq!(m, back);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn model_entry_minimal_decode() {
|
|
// Real-world: the daemon may emit an empty `details` payload.
|
|
let raw = r#"{"name": "tiny:latest"}"#;
|
|
let parsed: ModelEntry = serde_json::from_str(raw).expect("decode minimal model");
|
|
assert_eq!(parsed.name, "tiny:latest");
|
|
assert_eq!(parsed.size, 0);
|
|
assert!(parsed.digest.is_empty());
|
|
}
|