//! Contract API methods.
use serde::Serialize;
use uuid::Uuid;
use super::client::{ApiClient, ApiError};
use super::supervisor::JsonValue;
// Request types
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ReportRequest {
pub message: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub task_id: Option<Uuid>,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CompletionActionRequest {
pub lines_added: i32,
pub lines_removed: i32,
pub has_code_changes: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub task_id: Option<Uuid>,
#[serde(skip_serializing_if = "Option::is_none")]
pub files_modified: Option<Vec<String>>,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UpdateFileRequest {
pub content: String,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateFileRequest {
pub name: String,
pub content: String,
}
/// Request to update a contract.
#[derive(Serialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct UpdateContractRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
}
impl ApiClient {
/// List all contracts for the authenticated user.
pub async fn list_contracts(&self) -> Result<JsonValue, ApiError> {
self.get("/api/v1/contracts").await
}
/// Delete a contract.
pub async fn delete_contract(&self, contract_id: Uuid) -> Result<(), ApiError> {
self.delete(&format!("/api/v1/contracts/{}", contract_id))
.await
}
/// Update a contract.
pub async fn update_contract(
&self,
contract_id: Uuid,
name: Option<String>,
description: Option<String>,
) -> Result<JsonValue, ApiError> {
let req = UpdateContractRequest { name, description };
self.put(&format!("/api/v1/contracts/{}", contract_id), &req)
.await
}
/// Get contract status.
pub async fn contract_status(&self, contract_id: Uuid) -> Result<JsonValue, ApiError> {
self.get(&format!("/api/v1/contracts/{}/daemon/status", contract_id))
.await
}
/// Get phase checklist.
pub async fn contract_checklist(&self, contract_id: Uuid) -> Result<JsonValue, ApiError> {
self.get(&format!("/api/v1/contracts/{}/daemon/checklist", contract_id))
.await
}
/// Get contract goals.
pub async fn contract_goals(&self, contract_id: Uuid) -> Result<JsonValue, ApiError> {
self.get(&format!("/api/v1/contracts/{}/daemon/goals", contract_id))
.await
}
/// List contract files.
pub async fn contract_files(&self, contract_id: Uuid) -> Result<JsonValue, ApiError> {
self.get(&format!("/api/v1/contracts/{}/daemon/files", contract_id))
.await
}
/// Get a specific file.
pub async fn contract_file(
&self,
contract_id: Uuid,
file_id: Uuid,
) -> Result<JsonValue, ApiError> {
self.get(&format!(
"/api/v1/contracts/{}/daemon/files/{}",
contract_id, file_id
))
.await
}
/// Report progress.
pub async fn contract_report(
&self,
contract_id: Uuid,
message: &str,
task_id: Option<Uuid>,
) -> Result<JsonValue, ApiError> {
let req = ReportRequest {
message: message.to_string(),
task_id,
};
self.post(&format!("/api/v1/contracts/{}/daemon/report", contract_id), &req)
.await
}
/// Get suggested action.
pub async fn contract_suggest_action(&self, contract_id: Uuid) -> Result<JsonValue, ApiError> {
self.post_empty(&format!(
"/api/v1/contracts/{}/daemon/suggest-action",
contract_id
))
.await
}
/// Get completion action recommendation.
pub async fn contract_completion_action(
&self,
contract_id: Uuid,
task_id: Option<Uuid>,
files_modified: Option<Vec<String>>,
lines_added: i32,
lines_removed: i32,
has_code_changes: bool,
) -> Result<JsonValue, ApiError> {
let req = CompletionActionRequest {
task_id,
files_modified,
lines_added,
lines_removed,
has_code_changes,
};
self.post(
&format!("/api/v1/contracts/{}/daemon/completion-action", contract_id),
&req,
)
.await
}
/// Update a file.
pub async fn contract_update_file(
&self,
contract_id: Uuid,
file_id: Uuid,
content: &str,
) -> Result<JsonValue, ApiError> {
let req = UpdateFileRequest {
content: content.to_string(),
};
self.put(
&format!("/api/v1/contracts/{}/daemon/files/{}", contract_id, file_id),
&req,
)
.await
}
/// Create a new file.
pub async fn contract_create_file(
&self,
contract_id: Uuid,
name: &str,
content: &str,
) -> Result<JsonValue, ApiError> {
let req = CreateFileRequest {
name: name.to_string(),
content: content.to_string(),
};
self.post(&format!("/api/v1/contracts/{}/daemon/files", contract_id), &req)
.await
}
}