Skip to main content

uarp_sdk/generated/api/
workspaces.rs

1// Code generated by @uarp/codegen from spec/openapi.json. DO NOT EDIT.
2//!
3//! Workspace management, file storage, and sharing
4
5#![allow(unused_imports, clippy::too_many_arguments)]
6
7use reqwest::Method;
8use serde::{Deserialize, Serialize};
9
10use crate::client::{Client, Request, NO_BODY, NO_QUERY};
11use crate::error::Result;
12use crate::generated::models;
13use crate::multipart::{field_text, FilePart};
14use crate::util::encode_path;
15
16/// Query and header parameters for `deleteWorkspaceFile`.
17#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
18pub struct DeleteWorkspaceFileParams {
19    pub path: String,
20    /// Set to `false` to force a permanent delete even for a user-session (JWT) caller. Ignored for
21    /// api-key callers, which always delete permanently.
22    #[serde(default, skip_serializing_if = "Option::is_none")]
23    pub trash: Option<models::DeleteWorkspaceFileTrash>,
24}
25
26/// Query and header parameters for `downloadWorkspaceFile`.
27#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
28pub struct DownloadWorkspaceFileParams {
29    pub path: String,
30}
31
32/// Query and header parameters for `getWorkspaceFileHistoryContent`.
33#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
34pub struct GetWorkspaceFileHistoryContentParams {
35    pub path: String,
36    /// `file_id` of the version.
37    pub version: String,
38}
39
40/// Query and header parameters for `listAgentWorkspaceFiles`.
41#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
42pub struct ListAgentWorkspaceFilesParams {
43    #[serde(default, skip_serializing_if = "Option::is_none")]
44    pub path: Option<String>,
45}
46
47/// Query and header parameters for `listWorkspaceFileHistory`.
48#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
49pub struct ListWorkspaceFileHistoryParams {
50    pub path: String,
51}
52
53/// Query and header parameters for `listWorkspaceFiles`.
54#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
55pub struct ListWorkspaceFilesParams {
56    /// Directory path to list
57    #[serde(default, skip_serializing_if = "Option::is_none")]
58    pub path: Option<String>,
59    /// Walk sub-directories as well. Off by default, so a plain call lists one level — which is how
60    /// generated images, which land in `images/`, stayed invisible to the surfaces meant to show
61    /// them.
62    #[serde(default, skip_serializing_if = "Option::is_none")]
63    pub recursive: Option<bool>,
64}
65
66/// Query and header parameters for `searchWorkspaceFiles`.
67#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
68pub struct SearchWorkspaceFilesParams {
69    /// Search query
70    pub q: String,
71    /// File glob pattern
72    #[serde(default, skip_serializing_if = "Option::is_none")]
73    pub glob: Option<String>,
74    /// Treat query as regex
75    #[serde(default, skip_serializing_if = "Option::is_none")]
76    pub regex: Option<models::SearchWorkspaceFilesRegex>,
77}
78
79/// Query and header parameters for `uploadWorkspaceFile`.
80#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
81pub struct UploadWorkspaceFileParams {
82    /// File path within workspace
83    pub path: String,
84}
85
86/// Workspace management, file storage, and sharing
87#[derive(Debug, Clone)]
88pub struct WorkspacesApi {
89    pub(crate) client: Client,
90}
91
92impl Client {
93    /// Workspace management, file storage, and sharing
94    pub fn workspaces(&self) -> WorkspacesApi {
95        WorkspacesApi { client: self.clone() }
96    }
97}
98
99impl WorkspacesApi {
100    /// Assign agent/team/company to workspace
101    ///
102    /// `POST /api/v1/workspaces/{workspaceId}/assign`
103    ///
104    /// Required scopes: `files:write`.
105    pub async fn assign_workspace(&self, workspace_id: &str, body: &models::AssignWorkspaceRequest) -> Result<models::Workspace> {
106        self.client
107            .request_json(Request {
108                method: Method::POST,
109                path: format!("/api/v1/workspaces/{}/assign", encode_path(workspace_id)),
110                query: NO_QUERY,
111                body: Some(body),
112                headers: Vec::new(),
113                idempotent: true,
114            })
115            .await
116    }
117
118    /// Copy a file within the workspace
119    ///
120    /// `POST /api/v1/workspaces/{workspaceId}/files/copy`
121    ///
122    /// Required scopes: `files:write`.
123    pub async fn copy_workspace_file(&self, workspace_id: &str, body: &models::CopyWorkspaceFileRequest) -> Result<models::WorkspaceFile> {
124        self.client
125            .request_json(Request {
126                method: Method::POST,
127                path: format!("/api/v1/workspaces/{}/files/copy", encode_path(workspace_id)),
128                query: NO_QUERY,
129                body: Some(body),
130                headers: Vec::new(),
131                idempotent: true,
132            })
133            .await
134    }
135
136    /// Create a workspace
137    ///
138    /// `POST /api/v1/workspaces`
139    ///
140    /// Required scopes: `files:write`.
141    pub async fn create(&self, body: &models::CreateWorkspaceRequest) -> Result<models::Workspace> {
142        self.client
143            .request_json(Request {
144                method: Method::POST,
145                path: "/api/v1/workspaces".to_string(),
146                query: NO_QUERY,
147                body: Some(body),
148                headers: Vec::new(),
149                idempotent: true,
150            })
151            .await
152    }
153
154    /// Delete workspace and all files
155    ///
156    /// `DELETE /api/v1/workspaces/{workspaceId}`
157    ///
158    /// Required scopes: `files:write`.
159    pub async fn delete(&self, workspace_id: &str) -> Result<models::DeleteWorkspaceResponse> {
160        self.client
161            .request_json(Request {
162                method: Method::DELETE,
163                path: format!("/api/v1/workspaces/{}", encode_path(workspace_id)),
164                query: NO_QUERY,
165                body: NO_BODY,
166                headers: Vec::new(),
167                idempotent: true,
168            })
169            .await
170    }
171
172    /// Delete a file
173    ///
174    /// `DELETE /api/v1/workspaces/{workspaceId}/files`
175    ///
176    /// Required scopes: `files:write`.
177    pub async fn delete_workspace_file(&self, workspace_id: &str, params: &DeleteWorkspaceFileParams) -> Result<models::DeleteWorkspaceFileResponse> {
178        self.client
179            .request_json(Request {
180                method: Method::DELETE,
181                path: format!("/api/v1/workspaces/{}/files", encode_path(workspace_id)),
182                query: Some(params),
183                body: NO_BODY,
184                headers: Vec::new(),
185                idempotent: true,
186            })
187            .await
188    }
189
190    /// Download file content
191    ///
192    /// `GET /api/v1/workspaces/{workspaceId}/files/content`
193    ///
194    /// Required scopes: `files:read`.
195    pub async fn download_workspace_file(&self, workspace_id: &str, params: &DownloadWorkspaceFileParams) -> Result<bytes::Bytes> {
196        self.client
197            .request_bytes(Request {
198                method: Method::GET,
199                path: format!("/api/v1/workspaces/{}/files/content", encode_path(workspace_id)),
200                query: Some(params),
201                body: NO_BODY,
202                headers: Vec::new(),
203                idempotent: false,
204            })
205            .await
206    }
207
208    /// Permanently empty workspace trash
209    ///
210    /// `DELETE /api/v1/workspaces/{workspaceId}/trash`
211    ///
212    /// Required scopes: `files:write`.
213    pub async fn empty_workspace_trash(&self, workspace_id: &str) -> Result<models::EmptyWorkspaceTrashResponse> {
214        self.client
215            .request_json(Request {
216                method: Method::DELETE,
217                path: format!("/api/v1/workspaces/{}/trash", encode_path(workspace_id)),
218                query: NO_QUERY,
219                body: NO_BODY,
220                headers: Vec::new(),
221                idempotent: true,
222            })
223            .await
224    }
225
226    /// Get workspace metadata
227    ///
228    /// `GET /api/v1/workspaces/{workspaceId}`
229    ///
230    /// Required scopes: `files:read`.
231    pub async fn get(&self, workspace_id: &str) -> Result<models::Workspace> {
232        self.client
233            .request_json(Request {
234                method: Method::GET,
235                path: format!("/api/v1/workspaces/{}", encode_path(workspace_id)),
236                query: NO_QUERY,
237                body: NO_BODY,
238                headers: Vec::new(),
239                idempotent: false,
240            })
241            .await
242    }
243
244    /// Bytes of a prior version
245    ///
246    /// `version` is a `file_id` from `listWorkspaceFileHistory` and must belong to `path`'s history
247    /// — any other id is 404. Served with the version's own `Content-Type`, its `Content-Length`,
248    /// and `Cache-Control: private, max-age=3600`.
249    ///
250    /// `GET /api/v1/workspaces/{workspaceId}/files/history/content`
251    ///
252    /// Required scopes: `files:read`.
253    pub async fn get_workspace_file_history_content(&self, workspace_id: &str, params: &GetWorkspaceFileHistoryContentParams) -> Result<bytes::Bytes> {
254        self.client
255            .request_bytes(Request {
256                method: Method::GET,
257                path: format!("/api/v1/workspaces/{}/files/history/content", encode_path(workspace_id)),
258                query: Some(params),
259                body: NO_BODY,
260                headers: Vec::new(),
261                idempotent: false,
262            })
263            .await
264    }
265
266    /// WebSocket terminal session for workspace
267    ///
268    /// `GET /api/v1/workspaces/{workspaceId}/terminal`
269    ///
270    /// Required scopes: `files:read`.
271    pub async fn get_workspace_terminal(&self, workspace_id: &str) -> Result<serde_json::Value> {
272        self.client
273            .request_json(Request {
274                method: Method::GET,
275                path: format!("/api/v1/workspaces/{}/terminal", encode_path(workspace_id)),
276                query: NO_QUERY,
277                body: NO_BODY,
278                headers: Vec::new(),
279                idempotent: false,
280            })
281            .await
282    }
283
284    /// List all workspaces
285    ///
286    /// `GET /api/v1/workspaces`
287    ///
288    /// Required scopes: `files:read`.
289    pub async fn list(&self) -> Result<models::ListWorkspacesResponse> {
290        self.client
291            .request_json(Request {
292                method: Method::GET,
293                path: "/api/v1/workspaces".to_string(),
294                query: NO_QUERY,
295                body: NO_BODY,
296                headers: Vec::new(),
297                idempotent: false,
298            })
299            .await
300    }
301
302    /// List agent workspace files (shortcut)
303    ///
304    /// `GET /api/v1/agents/{agentId}/workspace/files`
305    ///
306    /// Required scopes: `agents:read`.
307    pub async fn list_agent_workspace_files(&self, agent_id: &str, params: &ListAgentWorkspaceFilesParams) -> Result<models::ListAgentWorkspaceFilesResponse> {
308        self.client
309            .request_json(Request {
310                method: Method::GET,
311                path: format!("/api/v1/agents/{}/workspace/files", encode_path(agent_id)),
312                query: Some(params),
313                body: NO_BODY,
314                headers: Vec::new(),
315                idempotent: false,
316            })
317            .await
318    }
319
320    /// Prior versions of a file
321    ///
322    /// Every earlier version kept for `path`, newest first; the current content is not in the list.
323    /// `versions` is empty for a file that has never been overwritten (measured 2026-09-10). Read a
324    /// version's bytes with `getWorkspaceFileHistoryContent`.
325    ///
326    /// `GET /api/v1/workspaces/{workspaceId}/files/history`
327    ///
328    /// Required scopes: `files:read`.
329    pub async fn list_workspace_file_history(&self, workspace_id: &str, params: &ListWorkspaceFileHistoryParams) -> Result<models::ListWorkspaceFileHistoryResponse> {
330        self.client
331            .request_json(Request {
332                method: Method::GET,
333                path: format!("/api/v1/workspaces/{}/files/history", encode_path(workspace_id)),
334                query: Some(params),
335                body: NO_BODY,
336                headers: Vec::new(),
337                idempotent: false,
338            })
339            .await
340    }
341
342    /// List files in workspace directory
343    ///
344    /// `GET /api/v1/workspaces/{workspaceId}/files`
345    ///
346    /// Required scopes: `files:read`.
347    pub async fn list_workspace_files(&self, workspace_id: &str, params: &ListWorkspaceFilesParams) -> Result<models::ListWorkspaceFilesResponse> {
348        self.client
349            .request_json(Request {
350                method: Method::GET,
351                path: format!("/api/v1/workspaces/{}/files", encode_path(workspace_id)),
352                query: Some(params),
353                body: NO_BODY,
354                headers: Vec::new(),
355                idempotent: false,
356            })
357            .await
358    }
359
360    /// List trashed files in workspace
361    ///
362    /// `GET /api/v1/workspaces/{workspaceId}/trash`
363    ///
364    /// Required scopes: `files:read`.
365    pub async fn list_workspace_trash(&self, workspace_id: &str) -> Result<models::ListWorkspaceTrashResponse> {
366        self.client
367            .request_json(Request {
368                method: Method::GET,
369                path: format!("/api/v1/workspaces/{}/trash", encode_path(workspace_id)),
370                query: NO_QUERY,
371                body: NO_BODY,
372                headers: Vec::new(),
373                idempotent: false,
374            })
375            .await
376    }
377
378    /// Move/rename a file
379    ///
380    /// `POST /api/v1/workspaces/{workspaceId}/files/move`
381    ///
382    /// Required scopes: `files:write`.
383    pub async fn move_workspace_file(&self, workspace_id: &str, body: &models::MoveWorkspaceFileRequest) -> Result<models::WorkspaceFile> {
384        self.client
385            .request_json(Request {
386                method: Method::POST,
387                path: format!("/api/v1/workspaces/{}/files/move", encode_path(workspace_id)),
388                query: NO_QUERY,
389                body: Some(body),
390                headers: Vec::new(),
391                idempotent: true,
392            })
393            .await
394    }
395
396    /// Mint a public share link for an HTML snapshot
397    ///
398    /// Stores a self-contained HTML page (assets already inlined by the client, ≤3 MB) under an
399    /// opaque token for seven days; `GET /public/share/{token}` serves it back as JSON data for the
400    /// sandboxed viewer, never as executable HTML. The workspace id is not consulted beyond scope.
401    ///
402    /// `POST /api/v1/workspaces/{workspaceId}/publish`
403    ///
404    /// Required scopes: `files:write`.
405    pub async fn publish_workspace_snapshot(&self, workspace_id: &str, body: &models::PublishWorkspaceSnapshotRequest) -> Result<models::PublishWorkspaceSnapshotResponse> {
406        self.client
407            .request_json(Request {
408                method: Method::POST,
409                path: format!("/api/v1/workspaces/{}/publish", encode_path(workspace_id)),
410                query: NO_QUERY,
411                body: Some(body),
412                headers: Vec::new(),
413                idempotent: true,
414            })
415            .await
416    }
417
418    /// Restore a trashed file to its original path
419    ///
420    /// `POST /api/v1/workspaces/{workspaceId}/trash/restore`
421    ///
422    /// Required scopes: `files:write`.
423    pub async fn restore_workspace_trash(&self, workspace_id: &str, body: &models::RestoreWorkspaceTrashRequest) -> Result<models::RestoreWorkspaceTrashResponse> {
424        self.client
425            .request_json(Request {
426                method: Method::POST,
427                path: format!("/api/v1/workspaces/{}/trash/restore", encode_path(workspace_id)),
428                query: NO_QUERY,
429                body: Some(body),
430                headers: Vec::new(),
431                idempotent: true,
432            })
433            .await
434    }
435
436    /// Revoke workspace sharing
437    ///
438    /// `DELETE /api/v1/workspaces/{workspaceId}/share/{agentId}`
439    ///
440    /// Required scopes: `files:write`.
441    pub async fn revoke_workspace_share(&self, workspace_id: &str, agent_id: &str) -> Result<models::Workspace> {
442        self.client
443            .request_json(Request {
444                method: Method::DELETE,
445                path: format!("/api/v1/workspaces/{}/share/{}", encode_path(workspace_id), encode_path(agent_id)),
446                query: NO_QUERY,
447                body: NO_BODY,
448                headers: Vec::new(),
449                idempotent: true,
450            })
451            .await
452    }
453
454    /// Execute shell command in workspace
455    ///
456    /// `POST /api/v1/workspaces/{workspaceId}/run-command`
457    ///
458    /// Required scopes: `files:write`.
459    pub async fn run_workspace_command(&self, workspace_id: &str, body: &models::RunWorkspaceCommandRequest) -> Result<models::RunWorkspaceCommandResponse> {
460        self.client
461            .request_json(Request {
462                method: Method::POST,
463                path: format!("/api/v1/workspaces/{}/run-command", encode_path(workspace_id)),
464                query: NO_QUERY,
465                body: Some(body),
466                headers: Vec::new(),
467                idempotent: true,
468            })
469            .await
470    }
471
472    /// Search files in workspace
473    ///
474    /// `GET /api/v1/workspaces/{workspaceId}/search`
475    ///
476    /// Required scopes: `files:read`.
477    pub async fn search_workspace_files(&self, workspace_id: &str, params: &SearchWorkspaceFilesParams) -> Result<models::SearchWorkspaceFilesResponse> {
478        self.client
479            .request_json(Request {
480                method: Method::GET,
481                path: format!("/api/v1/workspaces/{}/search", encode_path(workspace_id)),
482                query: Some(params),
483                body: NO_BODY,
484                headers: Vec::new(),
485                idempotent: false,
486            })
487            .await
488    }
489
490    /// Share workspace with an agent
491    ///
492    /// `POST /api/v1/workspaces/{workspaceId}/share`
493    ///
494    /// Required scopes: `files:write`.
495    pub async fn share(&self, workspace_id: &str, body: &models::ShareWorkspaceRequest) -> Result<models::Workspace> {
496        self.client
497            .request_json(Request {
498                method: Method::POST,
499                path: format!("/api/v1/workspaces/{}/share", encode_path(workspace_id)),
500                query: NO_QUERY,
501                body: Some(body),
502                headers: Vec::new(),
503                idempotent: true,
504            })
505            .await
506    }
507
508    /// Unassign agent/team/company from workspace
509    ///
510    /// The body names WHICH assignment to remove — `agent_id`, `team_id` or `company_id`. It was
511    /// undeclared until 2026-08-31, and the omission did not stay in the document: the SDK
512    /// generator faithfully wrote `body: false`, a proxy honoured that flag and dropped the body,
513    /// and the server still read it. The result was a DELETE that always succeeded and changed
514    /// nothing — 200, no error, unchanged state, under a button labelled Unassign.
515    ///
516    /// Three layers each behaved correctly on what they were given; the mistake in the first passed
517    /// through both and came out the other side as "it works". A spec cannot be checked against a
518    /// spec.
519    ///
520    /// `DELETE /api/v1/workspaces/{workspaceId}/assign`
521    ///
522    /// Required scopes: `files:write`.
523    pub async fn unassign_workspace(&self, workspace_id: &str, body: &models::UnassignWorkspaceRequest) -> Result<models::Workspace> {
524        self.client
525            .request_json(Request {
526                method: Method::DELETE,
527                path: format!("/api/v1/workspaces/{}/assign", encode_path(workspace_id)),
528                query: NO_QUERY,
529                body: Some(body),
530                headers: Vec::new(),
531                idempotent: true,
532            })
533            .await
534    }
535
536    /// Update workspace name
537    ///
538    /// `PATCH /api/v1/workspaces/{workspaceId}`
539    ///
540    /// Required scopes: `files:write`.
541    pub async fn update(&self, workspace_id: &str, body: &models::UpdateWorkspaceRequest) -> Result<models::Workspace> {
542        self.client
543            .request_json(Request {
544                method: Method::PATCH,
545                path: format!("/api/v1/workspaces/{}", encode_path(workspace_id)),
546                query: NO_QUERY,
547                body: Some(body),
548                headers: Vec::new(),
549                idempotent: true,
550            })
551            .await
552    }
553
554    /// Upload or update a file
555    ///
556    /// `PUT /api/v1/workspaces/{workspaceId}/files`
557    ///
558    /// Required scopes: `files:write`.
559    pub async fn upload_workspace_file(&self, workspace_id: &str, body: &models::UploadWorkspaceFileRequest, params: &UploadWorkspaceFileParams) -> Result<serde_json::Value> {
560        self.client
561            .request_multipart(
562                Request {
563                    method: Method::PUT,
564                    path: format!("/api/v1/workspaces/{}/files", encode_path(workspace_id)),
565                    query: Some(params),
566                    body: NO_BODY,
567                    headers: Vec::new(),
568                    idempotent: true,
569                },
570                || {
571                    let mut form = reqwest::multipart::Form::new();
572                    form = form.part("file", body.file.clone().into_part()?);
573                    Ok(form)
574                },
575            )
576            .await
577    }
578}