Skip to main content

uarp_sdk/generated/api/
missions.rs

1// Code generated by @uarp/codegen from spec/openapi.json. DO NOT EDIT.
2//!
3//! Mission Execution Framework: goal → objectives → authorization gate → execution →
4//! after-action review
5
6#![allow(unused_imports, clippy::too_many_arguments)]
7
8use reqwest::Method;
9use serde::{Deserialize, Serialize};
10
11use crate::client::{Client, Request, NO_BODY, NO_QUERY};
12use crate::error::Result;
13use crate::generated::models;
14use crate::multipart::{field_text, FilePart};
15use crate::sse::EventStream;
16use crate::util::encode_path;
17
18/// Query and header parameters for `listMissions`.
19#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
20pub struct ListMissionsParams {
21    /// Scope to one chat session — a cheaper scan than the tenant-wide list.
22    #[serde(default, skip_serializing_if = "Option::is_none")]
23    pub session_id: Option<String>,
24    /// Capped at 200; a non-numeric or non-positive value falls back to 50.
25    #[serde(default, skip_serializing_if = "Option::is_none")]
26    pub limit: Option<i64>,
27}
28
29/// Mission Execution Framework: goal → objectives → authorization gate → execution →
30/// after-action review
31#[derive(Debug, Clone)]
32pub struct MissionsApi {
33    pub(crate) client: Client,
34}
35
36impl Client {
37    /// Mission Execution Framework: goal → objectives → authorization gate → execution →
38    /// after-action review
39    pub fn missions(&self) -> MissionsApi {
40        MissionsApi { client: self.clone() }
41    }
42}
43
44impl MissionsApi {
45    /// Abort a mission
46    ///
47    /// Terminal and not resumable. The in-flight walk is signalled to stop between objectives, so
48    /// an abort ends spending rather than only marking the record. The body is optional.
49    ///
50    /// MEF is gated twice: globally by the server flag and per tenant by `mef_config.enabled`. When
51    /// either is off the route answers **404** with a plain body — deliberately the same answer as
52    /// a mission that does not exist, so an opted-out tenant cannot discover the surface.
53    ///
54    /// `POST /api/v1/missions/{missionId}/abort`
55    ///
56    /// Required scopes: `agents:write`.
57    pub async fn abort_mission(&self, mission_id: &str, body: &models::AbortMissionRequest) -> Result<models::Mission> {
58        self.client
59            .request_json(Request {
60                method: Method::POST,
61                path: format!("/api/v1/missions/{}/abort", encode_path(mission_id)),
62                query: NO_QUERY,
63                body: Some(body),
64                headers: Vec::new(),
65                idempotent: true,
66            })
67            .await
68    }
69
70    /// Pass the authorization gate
71    ///
72    /// Moves a mission held at `awaiting_authorization` on to `executing`. It does not start the
73    /// walk — call `/run` after this.
74    ///
75    /// MEF is gated twice: globally by the server flag and per tenant by `mef_config.enabled`. When
76    /// either is off the route answers **404** with a plain body — deliberately the same answer as
77    /// a mission that does not exist, so an opted-out tenant cannot discover the surface.
78    ///
79    /// `POST /api/v1/missions/{missionId}/authorize`
80    ///
81    /// Required scopes: `agents:write`.
82    pub async fn authorize_mission(&self, mission_id: &str) -> Result<models::Mission> {
83        self.client
84            .request_json(Request {
85                method: Method::POST,
86                path: format!("/api/v1/missions/{}/authorize", encode_path(mission_id)),
87                query: NO_QUERY,
88                body: NO_BODY,
89                headers: Vec::new(),
90                idempotent: true,
91            })
92            .await
93    }
94
95    /// Read a mission
96    ///
97    /// The record as stored. Poll this alongside the event stream — the stream is the fast path,
98    /// this is the authoritative one.
99    ///
100    /// MEF is gated twice: globally by the server flag and per tenant by `mef_config.enabled`. When
101    /// either is off the route answers **404** with a plain body — deliberately the same answer as
102    /// a mission that does not exist, so an opted-out tenant cannot discover the surface.
103    ///
104    /// `GET /api/v1/missions/{missionId}`
105    ///
106    /// Required scopes: `agents:read`.
107    pub async fn get(&self, mission_id: &str) -> Result<models::Mission> {
108        self.client
109            .request_json(Request {
110                method: Method::GET,
111                path: format!("/api/v1/missions/{}", encode_path(mission_id)),
112                query: NO_QUERY,
113                body: NO_BODY,
114                headers: Vec::new(),
115                idempotent: false,
116            })
117            .await
118    }
119
120    /// Read the after-action review
121    ///
122    /// Available once the mission is terminal. Before that the answer is 404 — the review is built,
123    /// not partially accumulated, so there is nothing truthful to return early.
124    ///
125    /// MEF is gated twice: globally by the server flag and per tenant by `mef_config.enabled`. When
126    /// either is off the route answers **404** with a plain body — deliberately the same answer as
127    /// a mission that does not exist, so an opted-out tenant cannot discover the surface.
128    ///
129    /// `GET /api/v1/missions/{missionId}/aar`
130    ///
131    /// Required scopes: `agents:read`.
132    pub async fn get_mission_aar(&self, mission_id: &str) -> Result<models::Aar> {
133        self.client
134            .request_json(Request {
135                method: Method::GET,
136                path: format!("/api/v1/missions/{}/aar", encode_path(mission_id)),
137                query: NO_QUERY,
138                body: NO_BODY,
139                headers: Vec::new(),
140                idempotent: false,
141            })
142            .await
143    }
144
145    /// List missions
146    ///
147    /// Most recent first. Without `session_id` this is the tenant-wide list.
148    ///
149    /// MEF is gated twice: globally by the server flag and per tenant by `mef_config.enabled`. When
150    /// either is off the route answers **404** with a plain body — deliberately the same answer as
151    /// a mission that does not exist, so an opted-out tenant cannot discover the surface.
152    ///
153    /// `GET /api/v1/missions`
154    ///
155    /// Required scopes: `agents:read`.
156    pub async fn list(&self, params: &ListMissionsParams) -> Result<models::ListMissionsResponse> {
157        self.client
158            .request_json(Request {
159                method: Method::GET,
160                path: "/api/v1/missions".to_string(),
161                query: Some(params),
162                body: NO_BODY,
163                headers: Vec::new(),
164                idempotent: false,
165            })
166            .await
167    }
168
169    /// List a mission's objectives
170    ///
171    /// Full objective records, including budgets spent so far — `Mission.objective_ids` carries
172    /// only the ids.
173    ///
174    /// MEF is gated twice: globally by the server flag and per tenant by `mef_config.enabled`. When
175    /// either is off the route answers **404** with a plain body — deliberately the same answer as
176    /// a mission that does not exist, so an opted-out tenant cannot discover the surface.
177    ///
178    /// `GET /api/v1/missions/{missionId}/objectives`
179    ///
180    /// Required scopes: `agents:read`.
181    pub async fn list_mission_objectives(&self, mission_id: &str) -> Result<models::ListMissionObjectivesResponse> {
182        self.client
183            .request_json(Request {
184                method: Method::GET,
185                path: format!("/api/v1/missions/{}/objectives", encode_path(mission_id)),
186                query: NO_QUERY,
187                body: NO_BODY,
188                headers: Vec::new(),
189                idempotent: false,
190            })
191            .await
192    }
193
194    /// Pause a running mission
195    ///
196    /// Cooperative: the walk is asked to hold at the next safe point, so the record reaches
197    /// `paused` after the current objective settles, not at the moment of the call — poll for the
198    /// status change. Only a mission running **in this process** can be paused; anything else is
199    /// 409.
200    ///
201    /// MEF is gated twice: globally by the server flag and per tenant by `mef_config.enabled`. When
202    /// either is off the route answers **404** with a plain body — deliberately the same answer as
203    /// a mission that does not exist, so an opted-out tenant cannot discover the surface.
204    ///
205    /// `POST /api/v1/missions/{missionId}/pause`
206    ///
207    /// Required scopes: `agents:write`.
208    pub async fn pause_mission(&self, mission_id: &str) -> Result<models::PauseMissionResponse> {
209        self.client
210            .request_json(Request {
211                method: Method::POST,
212                path: format!("/api/v1/missions/{}/pause", encode_path(mission_id)),
213                query: NO_QUERY,
214                body: NO_BODY,
215                headers: Vec::new(),
216                idempotent: true,
217            })
218            .await
219    }
220
221    /// Resume a paused mission
222    ///
223    /// Returns the mission to `executing` and relaunches the walk. Verified objectives are reloaded
224    /// from their checkpoints and the blocked objective continues against its persisted budget, so
225    /// a resume does not re-spend what a completed objective already cost. A mission already
226    /// running answers 409.
227    ///
228    /// MEF is gated twice: globally by the server flag and per tenant by `mef_config.enabled`. When
229    /// either is off the route answers **404** with a plain body — deliberately the same answer as
230    /// a mission that does not exist, so an opted-out tenant cannot discover the surface.
231    ///
232    /// `POST /api/v1/missions/{missionId}/resume`
233    ///
234    /// Required scopes: `agents:write`.
235    pub async fn resume(&self, mission_id: &str) -> Result<models::ResumeMissionResponse> {
236        self.client
237            .request_json(Request {
238                method: Method::POST,
239                path: format!("/api/v1/missions/{}/resume", encode_path(mission_id)),
240                query: NO_QUERY,
241                body: NO_BODY,
242                headers: Vec::new(),
243                idempotent: true,
244            })
245            .await
246    }
247
248    /// Start executing a mission
249    ///
250    /// Answers immediately; the executor walk is detached. Watch progress on the event stream or by
251    /// polling the mission — this endpoint used to run the walk synchronously and was killed by the
252    /// edge proxy's two-minute timeout before a multi-objective mission could finish.
253    ///
254    /// A second call while a walk is in flight is a no-op that answers **200** with `accepted:
255    /// false` and `already_running: true`, not 202 and not an error: the executor is not safe under
256    /// concurrent walks over one mission. Requires status `executing` — anything else is 409,
257    /// including a mission still waiting on its authorization gate.
258    ///
259    /// MEF is gated twice: globally by the server flag and per tenant by `mef_config.enabled`. When
260    /// either is off the route answers **404** with a plain body — deliberately the same answer as
261    /// a mission that does not exist, so an opted-out tenant cannot discover the surface.
262    ///
263    /// `POST /api/v1/missions/{missionId}/run`
264    ///
265    /// Required scopes: `agents:write`.
266    pub async fn run(&self, mission_id: &str) -> Result<models::RunMissionResponse> {
267        self.client
268            .request_json(Request {
269                method: Method::POST,
270                path: format!("/api/v1/missions/{}/run", encode_path(mission_id)),
271                query: NO_QUERY,
272                body: NO_BODY,
273                headers: Vec::new(),
274                idempotent: true,
275            })
276            .await
277    }
278
279    /// Start a mission
280    ///
281    /// Two ways in. Supply `plan` and it is used as written. Omit it and the server's LLM planner
282    /// decomposes `goal`, which requires `available_agents` and a planner wired on the server —
283    /// without one the request is rejected with 400 rather than silently producing an empty
284    /// mission.
285    ///
286    /// MEF is gated twice: globally by the server flag and per tenant by `mef_config.enabled`. When
287    /// either is off the route answers **404** with a plain body — deliberately the same answer as
288    /// a mission that does not exist, so an opted-out tenant cannot discover the surface.
289    ///
290    /// `POST /api/v1/missions`
291    ///
292    /// Required scopes: `agents:write`.
293    pub async fn start_mission(&self, body: &models::StartMissionRequest) -> Result<models::MissionStartResponse> {
294        self.client
295            .request_json(Request {
296                method: Method::POST,
297                path: "/api/v1/missions".to_string(),
298                query: NO_QUERY,
299                body: Some(body),
300                headers: Vec::new(),
301                idempotent: true,
302            })
303            .await
304    }
305
306    /// Stream mission progress (SSE)
307    ///
308    /// Server-sent events, poll-backed. Event names: `connected` (handshake), `mission` (snapshot
309    /// on connect), `status_change`, `checkpoint_added` (one per new checkpoint id),
310    /// `aar_finalized`, and `terminal` as the last event before the server closes. The stream
311    /// closes itself on a terminal status so a client stops reconnecting, and is capped at 15
312    /// minutes per connection regardless — a long mission is expected to reconnect.
313    ///
314    /// MEF is gated twice: globally by the server flag and per tenant by `mef_config.enabled`. When
315    /// either is off the route answers **404** with a plain body — deliberately the same answer as
316    /// a mission that does not exist, so an opted-out tenant cannot discover the surface.
317    ///
318    /// `GET /api/v1/missions/{missionId}/events`
319    ///
320    /// Required scopes: `agents:read`.
321    ///
322    /// Returns a server-sent event stream.
323    pub fn stream_mission_events(&self, mission_id: &str) -> EventStream {
324        self.client.request_stream(
325            &format!("/api/v1/missions/{}/events", encode_path(mission_id)),
326            NO_QUERY,
327            Vec::new(),
328        )
329    }
330
331    /// Edit one objective's configuration
332    ///
333    /// Configuration only: assignment, budget ceilings, deadline, rules of engagement, commander's
334    /// intent, decision points, priority and text. Lifecycle stays with the executor — there is no
335    /// way to set `status` from here. An empty patch is rejected with 400 rather than answering 200
336    /// for a write that did nothing. Sending `assigned_agent_id` or `assigned_team_id` as an empty
337    /// string clears the assignment.
338    ///
339    /// MEF is gated twice: globally by the server flag and per tenant by `mef_config.enabled`. When
340    /// either is off the route answers **404** with a plain body — deliberately the same answer as
341    /// a mission that does not exist, so an opted-out tenant cannot discover the surface.
342    ///
343    /// `PATCH /api/v1/missions/{missionId}/objectives/{objectiveId}`
344    ///
345    /// Required scopes: `agents:write`.
346    pub async fn update_mission_objective(&self, mission_id: &str, objective_id: &str, body: &models::UpdateMissionObjectiveRequest) -> Result<models::Objective> {
347        self.client
348            .request_json(Request {
349                method: Method::PATCH,
350                path: format!("/api/v1/missions/{}/objectives/{}", encode_path(mission_id), encode_path(objective_id)),
351                query: NO_QUERY,
352                body: Some(body),
353                headers: Vec::new(),
354                idempotent: true,
355            })
356            .await
357    }
358}