use awaken_server_contract::{
ConfigRecord, ConfigRecordError, ConfigRecordMerge, RecordMeta, effective_config_record,
};
use serde_json::Value;
pub(crate) fn apply_overrides<T>(spec: T, overrides: Option<&Value>) -> Result<T, ConfigRecordError>
where
T: ConfigRecordMerge,
{
let mut record = ConfigRecord {
spec,
meta: RecordMeta::legacy_user(),
};
record.meta.user_overrides = overrides.cloned();
effective_config_record(record)
}
#[cfg(test)]
pub(crate) fn extract_timestamps(spec: &Value) -> (u64, u64) {
let created = spec.get("created_at").and_then(Value::as_u64).unwrap_or(0);
let updated = spec.get("updated_at").and_then(Value::as_u64).unwrap_or(0);
(created, updated)
}
#[cfg(test)]
pub(crate) fn wrap_user(spec: &Value) -> Result<Value, serde_json::Error> {
let (created_at, updated_at) = extract_timestamps(spec);
let mut meta = RecordMeta::new_user();
if created_at != 0 {
meta.created_at = created_at;
}
if updated_at != 0 {
meta.updated_at = updated_at;
}
let record = ConfigRecord {
spec: spec.clone(),
meta,
};
record.to_value()
}
#[cfg(test)]
pub(crate) fn ensure_envelope(value: Value) -> Result<Value, serde_json::Error> {
if value.is_object()
&& value
.as_object()
.is_some_and(|m| m.contains_key("spec") && m.contains_key("meta"))
{
Ok(value)
} else {
wrap_user(&value)
}
}
pub(crate) fn unwrap_spec(value: Value) -> Value {
if value
.as_object()
.is_some_and(|m| m.contains_key("spec") && m.contains_key("meta"))
{
value.get("spec").cloned().unwrap_or(value)
} else {
value
}
}
#[cfg(test)]
pub(crate) fn spec_field<'a>(value: &'a Value, field: &str) -> Option<&'a Value> {
if value
.as_object()
.is_some_and(|m| m.contains_key("spec") && m.contains_key("meta"))
{
value.get("spec").and_then(|s| s.get(field))
} else {
value.get(field)
}
}
#[cfg(test)]
mod tests {
use awaken_server_contract::{ConfigRecord, RecordSource};
use serde_json::json;
use super::{ensure_envelope, extract_timestamps, spec_field, unwrap_spec, wrap_user};
#[test]
fn wrap_user_creates_envelope_with_user_source() {
let spec = json!({"name": "test-agent"});
let result = wrap_user(&spec).unwrap();
let record: ConfigRecord<serde_json::Value> = serde_json::from_value(result).unwrap();
assert_eq!(record.meta.source, RecordSource::User);
assert_ne!(record.meta.created_at, 0);
}
#[test]
fn wrap_user_lifts_timestamps_from_spec() {
let spec = json!({"name": "test-agent", "created_at": 100u64, "updated_at": 200u64});
let result = wrap_user(&spec).unwrap();
let record: ConfigRecord<serde_json::Value> = serde_json::from_value(result).unwrap();
assert_eq!(record.meta.created_at, 100);
assert_eq!(record.meta.updated_at, 200);
}
#[test]
fn wrap_user_uses_now_when_spec_lacks_timestamps() {
let spec = json!({"name": "test-agent"});
let result = wrap_user(&spec).unwrap();
let record: ConfigRecord<serde_json::Value> = serde_json::from_value(result).unwrap();
assert_ne!(record.meta.created_at, 0);
assert_ne!(record.meta.updated_at, 0);
}
#[test]
fn ensure_envelope_passthrough_for_envelope() {
let spec = json!({"name": "test"});
let envelope = wrap_user(&spec).unwrap();
let result = ensure_envelope(envelope.clone()).unwrap();
assert_eq!(result, envelope);
}
#[test]
fn ensure_envelope_wraps_bare_spec() {
let spec = json!({"name": "test"});
let result = ensure_envelope(spec).unwrap();
assert!(result.get("spec").is_some());
assert!(result.get("meta").is_some());
}
#[test]
fn unwrap_spec_extracts_spec_layer() {
let spec = json!({"name": "test"});
let envelope = wrap_user(&spec).unwrap();
let result = unwrap_spec(envelope);
assert_eq!(result, spec);
}
#[test]
fn unwrap_spec_passthrough_for_bare() {
let spec = json!({"name": "test"});
let result = unwrap_spec(spec.clone());
assert_eq!(result, spec);
}
#[test]
fn spec_field_reads_envelope_spec() {
let spec = json!({"api_key": "x", "name": "test"});
let envelope = wrap_user(&spec).unwrap();
let result = spec_field(&envelope, "api_key");
assert_eq!(result, Some(&json!("x")));
}
#[test]
fn spec_field_reads_bare_spec() {
let spec = json!({"api_key": "x", "name": "test"});
let result = spec_field(&spec, "api_key");
assert_eq!(result, Some(&json!("x")));
}
#[test]
fn extract_timestamps_returns_zeros_for_missing() {
let spec = json!({"name": "test"});
assert_eq!(extract_timestamps(&spec), (0, 0));
}
use super::apply_overrides;
use awaken_server_contract::{AgentSpec, ProviderSpec};
fn minimal_agent_spec(id: &str) -> AgentSpec {
AgentSpec {
id: id.to_owned(),
model_id: "m".to_owned(),
system_prompt: "base-prompt".to_owned(),
max_rounds: 5,
..Default::default()
}
}
#[test]
fn apply_overrides_returns_spec_unchanged_when_overrides_none() {
let spec = minimal_agent_spec("a");
let result = apply_overrides(spec.clone(), None).unwrap();
assert_eq!(result.system_prompt, "base-prompt");
assert_eq!(result.max_rounds, 5);
}
#[test]
fn apply_overrides_merges_agent_spec_when_overrides_some() {
let spec = minimal_agent_spec("a");
let overrides = json!({"system_prompt": "patched"});
let result = apply_overrides(spec, Some(&overrides)).unwrap();
assert_eq!(result.system_prompt, "patched");
assert_eq!(result.max_rounds, 5);
}
#[test]
fn apply_overrides_for_provider_is_noop() {
let spec = ProviderSpec {
id: "p".to_owned(),
adapter: "openai".to_owned(),
..Default::default()
};
let result = apply_overrides(spec.clone(), None).unwrap();
assert_eq!(result.id, "p");
}
#[test]
fn apply_overrides_for_provider_rejects_non_empty_overrides() {
let spec = ProviderSpec {
id: "p".to_owned(),
adapter: "openai".to_owned(),
..Default::default()
};
assert!(apply_overrides(spec, Some(&json!({"adapter": "stub"}))).is_err());
}
#[test]
fn apply_overrides_propagates_decode_error_for_unknown_field() {
let spec = minimal_agent_spec("a");
let bad_overrides = json!({"unknown_field": 1});
let err = apply_overrides(spec, Some(&bad_overrides));
assert!(
err.is_err(),
"unknown field in overrides must produce a decode error"
);
}
#[test]
fn apply_overrides_for_tool_spec_replaces_description_when_some() {
use awaken_server_contract::ToolSpec;
let spec = ToolSpec {
id: "echo".into(),
name: "Echo".into(),
description: "stock".into(),
..Default::default()
};
let overrides = json!({"description": "custom"});
let result = apply_overrides(spec, Some(&overrides)).unwrap();
assert_eq!(result.description, "custom");
}
#[test]
fn apply_overrides_for_tool_spec_keeps_base_when_none() {
use awaken_server_contract::ToolSpec;
let spec = ToolSpec {
id: "echo".into(),
description: "stock".into(),
..Default::default()
};
let result = apply_overrides(spec, None).unwrap();
assert_eq!(result.description, "stock");
}
#[test]
fn apply_overrides_for_tool_spec_rejects_unknown_field() {
use awaken_server_contract::ToolSpec;
let spec = ToolSpec {
id: "echo".into(),
..Default::default()
};
let bad = json!({"name": "renamed"});
assert!(apply_overrides(spec, Some(&bad)).is_err());
}
}