Skip to main content

vv_agent/sdk/client/runtime/
runners.rs

1use crate::config::{apply_resolved_model_limits, ResolvedModelConfig};
2use crate::llm::{LlmClient, ScriptedLlmClient};
3use crate::runtime::AgentRuntime;
4use crate::sdk::session::AgentSessionRunRequest;
5use crate::sdk::types::{AgentDefinition, AgentRun, AgentSDKOptions};
6
7use super::controls::run_controls_from_request;
8use super::llm::build_llm_from_options;
9use super::options::configure_runtime_from_options;
10use crate::sdk::client::task::{merge_request_metadata, task_from_definition_with_task_name};
11
12pub trait RunAgent {
13    fn run(&self, definition: &AgentDefinition, prompt: String) -> Result<AgentRun, String> {
14        self.run_with_session(definition, AgentSessionRunRequest::new(prompt))
15    }
16
17    fn run_with_session(
18        &self,
19        definition: &AgentDefinition,
20        request: AgentSessionRunRequest,
21    ) -> Result<AgentRun, String>;
22}
23
24impl<C: LlmClient + Clone + 'static> RunAgent for AgentRuntime<C> {
25    fn run_with_session(
26        &self,
27        definition: &AgentDefinition,
28        request: AgentSessionRunRequest,
29    ) -> Result<AgentRun, String> {
30        let controls = run_controls_from_request(&request);
31        let workspace = request.workspace.clone();
32        let mut task = task_from_definition_with_task_name(
33            definition,
34            request.prompt,
35            workspace.as_deref(),
36            request.task_name.as_deref(),
37        );
38        merge_request_metadata(&mut task, request.metadata);
39        task.initial_messages = request.initial_messages;
40        task.initial_shared_state = request.shared_state;
41        let result = self
42            .run_with_controls(task, controls)
43            .map_err(|err| err.to_string())?;
44        Ok(AgentRun {
45            agent_name: definition.model.clone(),
46            result,
47            resolved: unresolved_definition_model(definition),
48        })
49    }
50}
51
52impl RunAgent for ScriptedLlmClient {
53    fn run_with_session(
54        &self,
55        definition: &AgentDefinition,
56        request: AgentSessionRunRequest,
57    ) -> Result<AgentRun, String> {
58        let runtime = AgentRuntime::new(self.clone());
59        let controls = run_controls_from_request(&request);
60        let workspace = request.workspace.clone();
61        let mut task = task_from_definition_with_task_name(
62            definition,
63            request.prompt,
64            workspace.as_deref(),
65            request.task_name.as_deref(),
66        );
67        merge_request_metadata(&mut task, request.metadata);
68        task.initial_messages = request.initial_messages;
69        task.initial_shared_state = request.shared_state;
70        runtime
71            .run_with_controls(task, controls)
72            .map_err(|err| err.to_string())
73            .map(|result| AgentRun {
74                agent_name: definition.model.clone(),
75                resolved: unresolved_definition_model(definition),
76                result,
77            })
78    }
79}
80
81#[derive(Clone)]
82pub(in crate::sdk::client) struct SettingsRunAgent {
83    pub(in crate::sdk::client) options: AgentSDKOptions,
84}
85
86impl RunAgent for SettingsRunAgent {
87    fn run_with_session(
88        &self,
89        definition: &AgentDefinition,
90        request: AgentSessionRunRequest,
91    ) -> Result<AgentRun, String> {
92        let backend = definition
93            .backend
94            .clone()
95            .unwrap_or_else(|| self.options.default_backend.clone());
96        let (llm, resolved) = build_llm_from_options(&self.options, &backend, &definition.model)?;
97        let mut runtime = AgentRuntime::new(llm);
98        configure_runtime_from_options(&mut runtime, &self.options);
99
100        let controls = run_controls_from_request(&request);
101        let effective_workspace = request
102            .workspace
103            .clone()
104            .unwrap_or_else(|| self.options.workspace.clone());
105        let mut task = task_from_definition_with_task_name(
106            definition,
107            request.prompt,
108            Some(effective_workspace.as_path()),
109            request.task_name.as_deref(),
110        );
111        task.model = resolved.model_id.clone();
112        apply_resolved_model_limits(&mut task, &resolved);
113        merge_request_metadata(&mut task, request.metadata);
114        task.initial_messages = request.initial_messages;
115        task.initial_shared_state = request.shared_state;
116        let result = runtime
117            .run_with_controls(task, controls)
118            .map_err(|err| err.to_string())?;
119        Ok(AgentRun {
120            agent_name: definition.model.clone(),
121            result,
122            resolved,
123        })
124    }
125}
126
127fn unresolved_definition_model(definition: &AgentDefinition) -> ResolvedModelConfig {
128    ResolvedModelConfig::new(
129        definition
130            .backend
131            .clone()
132            .unwrap_or_else(|| "moonshot".to_string()),
133        definition.model.clone(),
134        definition.model.clone(),
135        definition.model.clone(),
136        Vec::new(),
137    )
138}