Skip to main content

pax_designtime/
messages.rs

1use std::fmt::Formatter;
2
3use pax_manifest::{
4    ComponentDefinition, ComponentTemplate, PaxManifest, SettingsBlockElement, TimelineDefinition,
5    TypeId,
6};
7use pax_message::ScreenshotData;
8use serde::{Deserialize, Serialize};
9use std::fmt::Debug;
10
11#[derive(Serialize, Deserialize, Debug)]
12pub enum AgentMessage {
13    ProjectFileChangedNotification(FileChangedNotification),
14    ManifestSerializationRequest(ManifestSerializationRequest),
15    // Request to retrieve the manifest from the design server
16    // sent from designtime to design-server
17    LoadManifestRequest(LoadManifestRequest),
18    LoadManifestResponse(LoadManifestResponse),
19    DisconnectNotification(DisconnectNotification),
20    ComponentSerializationRequest(ComponentSerializationRequest),
21    UpdateTemplateRequest(Box<UpdateTemplateRequest>),
22    LoadFileToStaticDirRequest(LoadFileToStaticDirRequest),
23    UserlandSourceUpdateRequest(UserlandSourceUpdateRequest),
24    UserlandSourceUpdateResponse(UserlandSourceUpdateResponse),
25    PrepareAppRevision(PrepareAppRevision),
26    RequestAppRevisionActivation(ActivateAppRevision),
27    CancelAppRevisionActivation(ActivateAppRevision),
28    AppRevisionActivationPrepared(LoadManifestResponse),
29    ActivateAppRevision(ActivateAppRevision),
30    AppRevisionActivationRejected(AppRevisionActivationRejected),
31    DevClientRequest(DevClientRequest),
32    DevClientResponse(DevClientResponse),
33    // LLM Requests to pub.pax.dev
34    LLMRequest(LLMRequest),
35    LLMPartialResponse(LLMPartialResponse),
36    LLMFinalResponse(LLMFinalResponse),
37}
38
39/// Identifies the executable logic generation and the mutable template snapshot
40/// mounted on top of it. Template-only edits advance `template_version` without
41/// requiring a new executable artifact.
42#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
43pub struct RevisionStamp {
44    pub logic_revision_id: String,
45    pub template_version: u64,
46}
47
48/// Describes how a prepared logic revision will execute after host activation.
49/// The protocol deliberately does not encode chassis-specific loading details.
50#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
51#[serde(rename_all = "kebab-case")]
52pub enum DebugLogicExecutionMode {
53    CompiledArtifact,
54    InterpretedModule,
55}
56
57/// Host-resolvable debug artifact metadata. `kind` remains open-ended so a
58/// future language runtime can introduce an artifact without changing the
59/// revision state machine.
60#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
61pub struct DebugArtifact {
62    pub kind: String,
63    pub location: String,
64}
65
66/// Announces a complete candidate revision which the host may prepare and
67/// activate. The active manifest remains authoritative until activation.
68#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
69pub struct PrepareAppRevision {
70    pub logic_revision_id: String,
71    pub execution_mode: DebugLogicExecutionMode,
72    pub artifact: DebugArtifact,
73}
74
75/// Identifies a candidate whose prepared snapshot the host admitted. The final
76/// activation message requests server commit before the host swaps runtimes.
77#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
78pub struct ActivateAppRevision {
79    pub logic_revision_id: String,
80}
81
82/// Rejects an activation acknowledgement which is no longer authoritative.
83/// The mounted runtime remains intact and may receive a newer prepare envelope
84/// or a full snapshot for its existing logic identity.
85#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
86pub struct AppRevisionActivationRejected {
87    pub logic_revision_id: String,
88    pub reason: String,
89}
90
91#[derive(Serialize, Deserialize, Debug, Clone)]
92pub enum DevClientRequest {
93    Look(DevClientLookRequest),
94    InspectTree(DevClientInspectTreeRequest),
95    RayCast(DevClientRayCastRequest),
96    SelectorQuery(DevClientSelectorQueryRequest),
97    ReplaceNode(DevClientReplaceNodeRequest),
98    Logs(DevClientLogsRequest),
99}
100
101#[derive(Serialize, Deserialize, Debug, Clone)]
102pub enum DevClientResponse {
103    Look(DevClientLookResponse),
104    InspectTree(DevClientInspectTreeResponse),
105    RayCast(DevClientRayCastResponse),
106    SelectorQuery(DevClientSelectorQueryResponse),
107    ReplaceNode(DevClientReplaceNodeResponse),
108    Logs(DevClientLogsResponse),
109}
110
111#[derive(Serialize, Deserialize, Debug, Clone)]
112pub struct DevClientLookRequest {
113    pub request_id: String,
114    pub scale: f64,
115    pub period_ms: u64,
116    pub duration_ms: u64,
117}
118
119#[derive(Serialize, Deserialize, Debug, Clone)]
120pub struct DevClientRawCapture {
121    pub rgba_bytes: Vec<u8>,
122    pub compression: Option<String>,
123    pub width: usize,
124    pub height: usize,
125    pub captured_at_ms: u128,
126}
127
128#[derive(Serialize, Deserialize, Debug, Clone)]
129pub struct DevClientLookResponse {
130    pub request_id: String,
131    pub status: String,
132    pub captures: Vec<DevClientRawCapture>,
133    pub error: Option<String>,
134}
135
136#[derive(Serialize, Deserialize, Debug, Clone)]
137pub struct DevClientInspectTreeRequest {
138    pub request_id: String,
139    pub max_depth: Option<usize>,
140}
141
142#[derive(Serialize, Deserialize, Debug, Clone)]
143pub struct DevClientInspectTreeResponse {
144    pub request_id: String,
145    pub status: String,
146    pub node_count: Option<usize>,
147    pub tree_json: Option<String>,
148    pub error: Option<String>,
149}
150
151#[derive(Serialize, Deserialize, Debug, Clone)]
152pub struct DevClientRayCastRequest {
153    pub request_id: String,
154    pub x: f64,
155    pub y: f64,
156    pub hit_invisible: bool,
157}
158
159#[derive(Serialize, Deserialize, Debug, Clone)]
160pub struct DevClientRayCastResponse {
161    pub request_id: String,
162    pub status: String,
163    pub x: f64,
164    pub y: f64,
165    pub hit_invisible: bool,
166    pub node_count: Option<usize>,
167    pub nodes_json: Option<String>,
168    pub error: Option<String>,
169}
170
171#[derive(Serialize, Deserialize, Debug, Clone)]
172pub struct DevClientSelectorQueryRequest {
173    pub request_id: String,
174    pub selector: String,
175}
176
177#[derive(Serialize, Deserialize, Debug, Clone)]
178pub struct DevClientSelectorQueryResponse {
179    pub request_id: String,
180    pub status: String,
181    pub selector: String,
182    pub node_count: Option<usize>,
183    pub nodes_json: Option<String>,
184    pub error: Option<String>,
185}
186
187#[derive(Serialize, Deserialize, Debug, Clone)]
188pub struct DevClientReplaceNodeRequest {
189    pub request_id: String,
190    pub component_type_id: String,
191    pub template_node_id: usize,
192    pub subtemplate: String,
193}
194
195#[derive(Serialize, Deserialize, Debug, Clone)]
196pub struct DevClientReplaceNodeResponse {
197    pub request_id: String,
198    pub status: String,
199    pub component_type_id: String,
200    pub template_node_id: usize,
201    pub reload_scope: String,
202    pub reloaded_template_node_id: Option<usize>,
203    pub source_path: Option<String>,
204    pub error: Option<String>,
205}
206
207#[derive(Serialize, Deserialize, Debug, Clone)]
208pub struct DevClientLogsRequest {
209    pub request_id: String,
210    pub since_seq: Option<u64>,
211    pub limit: Option<usize>,
212}
213
214#[derive(Serialize, Deserialize, Debug, Clone)]
215pub struct DevClientLogEntry {
216    pub seq: u64,
217    pub level: String,
218    pub message: String,
219    pub timestamp_ms: u128,
220}
221
222#[derive(Serialize, Deserialize, Debug, Clone)]
223pub struct DevClientLogsResponse {
224    pub request_id: String,
225    pub status: String,
226    pub entries: Vec<DevClientLogEntry>,
227    pub next_seq: u64,
228    pub oldest_seq: Option<u64>,
229    pub error: Option<String>,
230}
231
232#[derive(Deserialize, Serialize)]
233pub struct LLMRequest {
234    pub manifest: PaxManifest,
235    pub prompt: String,
236    pub request_id: u64,
237    pub screenshot: Option<ScreenshotData>,
238}
239
240impl Debug for LLMRequest {
241    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
242        f.debug_struct("LLMRequest")
243            .field("prompt", &self.prompt)
244            .field("request_id", &self.request_id)
245            .finish()
246    }
247}
248
249impl LLMRequest {
250    pub fn new(
251        manifest: PaxManifest,
252        prompt: String,
253        request_id: u64,
254        screenshot: Option<ScreenshotData>,
255    ) -> Self {
256        Self {
257            manifest,
258            prompt,
259            request_id,
260            screenshot,
261        }
262    }
263}
264
265#[derive(Deserialize, Serialize, Debug)]
266pub struct LLMPartialResponse {
267    pub request_id: u64,
268    pub message: String,
269}
270
271impl LLMPartialResponse {
272    pub fn new(request_id: u64, message: String) -> Self {
273        Self {
274            request_id,
275            message,
276        }
277    }
278}
279
280#[derive(Deserialize, Serialize)]
281pub struct LLMFinalResponse {
282    pub request_id: u64,
283    pub message: String,
284    pub component_definition: ComponentDefinition,
285}
286
287impl Debug for LLMFinalResponse {
288    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
289        f.debug_struct("LLMFinalResponse")
290            .field("request_id", &self.request_id)
291            .field("message", &self.message)
292            .finish()
293    }
294}
295
296impl LLMFinalResponse {
297    pub fn new(
298        request_id: u64,
299        message: String,
300        component_definition: ComponentDefinition,
301    ) -> Self {
302        Self {
303            request_id,
304            message,
305            component_definition,
306        }
307    }
308}
309
310#[derive(Serialize, Deserialize, Debug)]
311pub struct LoadFileToStaticDirRequest {
312    pub name: String,
313    pub data: Vec<u8>,
314}
315
316/// A request from userland to replace a project source file during designtime.
317#[derive(Serialize, Deserialize, Debug, Clone)]
318pub struct UserlandSourceUpdateRequest {
319    pub request_id: String,
320    pub path: String,
321    pub contents: String,
322}
323
324/// A response to a userland source replacement request.
325#[derive(Serialize, Deserialize, Debug, Clone)]
326pub struct UserlandSourceUpdateResponse {
327    pub request_id: String,
328    pub path: String,
329    pub status: String,
330    pub error: Option<String>,
331}
332
333/// A notification indicating that a project file has changed.
334/// This message is sent from `pax-design-server` to `pax-designtime`.
335#[derive(Serialize, Deserialize, Default, Debug)]
336pub struct FileChangedNotification {}
337
338/// A request to serialize the provided manifest into code.
339/// This is sent from `pax-designtime` to `pax-design-server`.
340#[derive(Serialize, Deserialize, Debug)]
341pub struct ManifestSerializationRequest {
342    pub manifest: Vec<u8>,
343}
344
345#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
346pub struct LoadManifestRequest {
347    pub active_revision: Option<RevisionStamp>,
348}
349
350#[derive(Serialize, Deserialize, Debug, Clone)]
351pub struct LoadManifestResponse {
352    pub revision: RevisionStamp,
353    pub manifest: Vec<u8>,
354}
355
356#[derive(Serialize, Deserialize, Debug)]
357pub struct DisconnectNotification {
358    pub allow_reconnect: bool,
359    pub reason: String,
360}
361
362#[derive(Serialize, Deserialize, Debug)]
363pub struct ComponentSerializationRequest {
364    pub component_bytes: Vec<u8>,
365}
366
367/// A request to update the Pax-authored definition of a component.
368// Sent from `pax-priviliged-agent` to `pax-designtime`.
369#[derive(Serialize, Deserialize, Debug, Clone)]
370pub struct UpdateTemplateRequest {
371    /// Revision against which this template was parsed and committed.
372    pub revision: RevisionStamp,
373    /// The type identifier of the component to update.
374    pub type_id: TypeId,
375    /// The new template for the component.
376    pub new_template: ComponentTemplate,
377    /// The settings block for the component.
378    pub settings_block: Vec<SettingsBlockElement>,
379    /// The named timeline blocks for the component.
380    #[serde(default)]
381    pub timelines: Vec<TimelineDefinition>,
382}