1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use serde::Serialize;

use crate::{
    config::Config,
    error::OpenAIError,
    steps::Steps,
    types::{
        CreateRunRequest, ListRunsResponse, ModifyRunRequest, RunObject,
        SubmitToolOutputsRunRequest,
    },
    Client,
};

/// Represents an execution run on a thread.
///
/// Related guide: [Assistants](https://platform.openai.com/docs/assistants/overview)
pub struct Runs<'c, C: Config> {
    pub thread_id: String,
    client: &'c Client<C>,
}

impl<'c, C: Config> Runs<'c, C> {
    pub fn new(client: &'c Client<C>, thread_id: &str) -> Self {
        Self {
            client,
            thread_id: thread_id.into(),
        }
    }

    ///  [Steps] API group
    pub fn steps(&self, run_id: &str) -> Steps<C> {
        Steps::new(self.client, &self.thread_id, run_id)
    }

    /// Create a run.
    pub async fn create(&self, request: CreateRunRequest) -> Result<RunObject, OpenAIError> {
        self.client
            .post(&format!("/threads/{}/runs", self.thread_id), request)
            .await
    }

    /// Retrieves a run.
    pub async fn retrieve(&self, run_id: &str) -> Result<RunObject, OpenAIError> {
        self.client
            .get(&format!("/threads/{}/runs/{run_id}", self.thread_id))
            .await
    }

    /// Modifies a run.
    pub async fn update(
        &self,
        run_id: &str,
        request: ModifyRunRequest,
    ) -> Result<RunObject, OpenAIError> {
        self.client
            .post(
                &format!("/threads/{}/runs/{run_id}", self.thread_id),
                request,
            )
            .await
    }

    /// Returns a list of runs belonging to a thread.
    pub async fn list<Q>(&self, query: &Q) -> Result<ListRunsResponse, OpenAIError>
    where
        Q: Serialize + ?Sized,
    {
        self.client
            .get_with_query(&format!("/threads/{}/runs", self.thread_id), query)
            .await
    }

    /// When a run has the status: "requires_action" and required_action.type is submit_tool_outputs, this endpoint can be used to submit the outputs from the tool calls once they're all completed. All outputs must be submitted in a single request.
    pub async fn submit_tool_outputs(
        &self,
        run_id: &str,
        request: SubmitToolOutputsRunRequest,
    ) -> Result<RunObject, OpenAIError> {
        self.client
            .post(
                &format!(
                    "/threads/{}/runs/{run_id}/submit_tool_outputs",
                    self.thread_id
                ),
                request,
            )
            .await
    }

    /// Cancels a run that is `in_progress`
    pub async fn cancel(&self, run_id: &str) -> Result<RunObject, OpenAIError> {
        self.client
            .post(
                &format!("/threads/{}/runs/{run_id}/cancel", self.thread_id),
                (),
            )
            .await
    }
}