1use serde::{Deserialize, Serialize};
2
3pub mod contracts;
4pub mod settings;
5
6pub const V1: &str = "v1";
7pub const STATUS_CONTRACT: &str = "mhome.node.status.v1";
8pub const PROTOCOL_V1_MANIFEST: &str = include_str!("../../contract/node-runtime-protocol-v1.json");
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
11#[serde(rename_all = "camelCase", deny_unknown_fields)]
12pub struct RuntimeRequest<T> {
13 pub version: String,
14 pub payload: T,
15}
16
17#[derive(Debug, Clone, Serialize, Deserialize)]
18#[serde(rename_all = "camelCase")]
19pub struct RuntimeResponse<T> {
20 pub version: String,
21 pub data: T,
22}
23
24pub fn require_version(actual: &str, expected: &str) -> Result<(), UnsupportedVersion> {
25 if actual == expected {
26 Ok(())
27 } else {
28 Err(UnsupportedVersion {
29 actual: actual.to_string(),
30 expected: expected.to_string(),
31 })
32 }
33}
34
35#[derive(Debug, Clone, PartialEq, Eq)]
36pub struct UnsupportedVersion {
37 actual: String,
38 expected: String,
39}
40
41impl std::fmt::Display for UnsupportedVersion {
42 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43 write!(
44 formatter,
45 "UNSUPPORTED_NODE_PROTOCOL_VERSION: requested version {}, supported version {}",
46 self.actual, self.expected
47 )
48 }
49}
50
51impl std::error::Error for UnsupportedVersion {}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 #[test]
58 fn manifest_matches_internal_targets() {
59 let manifest: serde_json::Value = serde_json::from_str(PROTOCOL_V1_MANIFEST).unwrap();
60 assert_eq!(manifest["version"], V1);
61 assert_eq!(
62 manifest["settings"]["changedTarget"],
63 settings::CHANGED_TARGET
64 );
65 assert_eq!(
66 manifest["llm"]["completeTarget"],
67 crate::llm::COMPLETE_TARGET
68 );
69 }
70}