Skip to main content

max / makenotwork

1.7 KB · 50 lines History Blame Raw
1 //! The `ops-agent` HTTP wire contract, shared by the `AgentRpc` client
2 //! ([`crate::rpc`]) and the agent server ([`crate::agent`]).
3 //!
4 //! `/run` streams a body of newline-delimited JSON [`Frame`]s: zero or more
5 //! `chunk` frames (merged stdout+stderr as it arrives), then exactly one
6 //! terminal frame — `exit` on a clean run or `error` if the agent refused or
7 //! failed before the child produced an exit code.
8
9 use crate::step::Step;
10 use serde::{Deserialize, Serialize};
11
12 /// `POST /run` request body.
13 #[derive(Clone, Debug, Serialize, Deserialize)]
14 pub struct RunRequest {
15 pub step: Step,
16 }
17
18 /// One newline-delimited frame in a `/run` response stream.
19 #[derive(Clone, Debug, Serialize, Deserialize)]
20 #[serde(tag = "t", rename_all = "snake_case")]
21 pub enum Frame {
22 /// A slice of merged stdout/stderr (UTF-8-lossy; not line-aligned).
23 Chunk { text: String },
24 /// Terminal: the child exited with this code.
25 Exit { code: i32 },
26 /// Terminal: the agent refused (capability/identity) or failed to spawn.
27 Error { message: String },
28 }
29
30 impl Frame {
31 /// Serialize as one NDJSON line (trailing `\n` included).
32 pub fn to_line(&self) -> String {
33 let mut s = serde_json::to_string(self).unwrap_or_else(|e| {
34 format!("{{\"t\":\"error\",\"message\":\"frame serialize failed: {e}\"}}")
35 });
36 s.push('\n');
37 s
38 }
39 }
40
41 /// `GET /health` response body.
42 #[derive(Clone, Debug, Serialize, Deserialize)]
43 pub struct HealthResponse {
44 pub ok: bool,
45 /// The agent's own actuate grant tokens (introspection / audit).
46 pub actuate: Vec<String>,
47 /// The agent's own observe grant tokens.
48 pub observe: Vec<String>,
49 }
50