soma_integrations/
codemode.rs1use std::sync::{Arc, Mutex};
29
30use async_trait::async_trait;
31use serde_json::{json, Value};
32
33use soma_application::{CodeModeExecuteRequest, CodeModePort, ExecutionContext, PortError};
34use soma_codemode::{execute::execute_inline, CodeModeConfig, ToolError, UiLink};
35
36#[derive(Clone, Default)]
37pub struct CodeModeApplicationPort {
38 config: CodeModeConfig,
39}
40
41impl CodeModeApplicationPort {
42 pub fn new(config: CodeModeConfig) -> Self {
43 Self { config }
44 }
45}
46
47#[async_trait]
48impl CodeModePort for CodeModeApplicationPort {
49 async fn execute(
50 &self,
51 request: CodeModeExecuteRequest,
52 _context: &ExecutionContext,
53 ) -> Result<Value, PortError> {
54 if !self.config.enabled {
55 let mut port_error = PortError::new(
56 "codemode_disabled",
57 "Code Mode is disabled for this instance",
58 );
59 port_error.remediation =
60 "Enable Code Mode in the runtime configuration and retry.".to_owned();
61 return Err(port_error);
62 }
63 let ui_capture: Arc<Mutex<Option<UiLink>>> = Arc::new(Mutex::new(None));
64 let outcome = execute_inline(&request.source, self.config.clone(), ui_capture)
65 .await
66 .map_err(codemode_port_error)?;
67 Ok(json!({
68 "result": outcome.display_response.result,
69 "logs": outcome.display_response.logs,
70 }))
71 }
72}
73
74fn codemode_port_error(error: ToolError) -> PortError {
79 let (retryable, remediation): (bool, String) = match &error {
80 ToolError::MissingParam { .. } | ToolError::InvalidParam { .. } => (
81 false,
82 "Fix the Code Mode snippet or its parameters and retry.".to_owned(),
83 ),
84 ToolError::UnknownAction { .. } | ToolError::UnknownInstance { .. } => (
85 false,
86 "Check the referenced action or instance name and retry.".to_owned(),
87 ),
88 ToolError::AmbiguousTool { .. } => (
89 false,
90 "Disambiguate the referenced tool and retry.".to_owned(),
91 ),
92 ToolError::Forbidden {
93 required_scopes, ..
94 } => (
95 false,
96 format!(
97 "Request the required scope(s) and retry: {}",
98 required_scopes.join(", ")
99 ),
100 ),
101 ToolError::Conflict { .. } => (
102 false,
103 "Resolve the conflicting resource and retry.".to_owned(),
104 ),
105 ToolError::ConfirmationRequired { .. } => {
106 (false, "Re-run with explicit confirmation.".to_owned())
107 }
108 ToolError::Sdk { .. } => (
109 true,
110 "Retry; if this persists, check the Code Mode runner's health.".to_owned(),
111 ),
112 };
113 let code = format!("codemode_{}", error.kind());
114 let mut port_error = PortError::new(code, error.to_string());
115 port_error.retryable = retryable;
116 port_error.remediation = remediation;
117 port_error
118}
119
120#[cfg(test)]
121#[path = "codemode_tests.rs"]
122mod tests;