1use crate::error::RuntimeError;
14use crate::loaded::ExtensionId;
15use crate::runtime::ExtensionRuntime;
16
17const COMPOSER_VERSIONS: &[&str] = &["0.2.0", "0.1.0"];
19const COMPOSER_IFACE_BASE: &str = "greentic:dw-composer/composer";
21
22impl ExtensionRuntime {
23 pub fn invoke_composer_metadata(&self, ext_id: &str) -> Result<String, RuntimeError> {
35 let loaded = self
36 .loaded()
37 .get(&ExtensionId(ext_id.to_string()))
38 .cloned()
39 .ok_or_else(|| RuntimeError::NotFound(ext_id.to_string()))?;
40
41 let (mut store, instance) = loaded
42 .build_store_and_instance(
43 self.engine(),
44 self.host_overrides().clone(),
45 &crate::host_ports::HostCallContext::default(),
46 )
47 .map_err(RuntimeError::Wasmtime)?;
48
49 let (iface_idx, iface_name, _version) = resolve_dw_composer_iface(&mut store, &instance)?;
50
51 let func_idx = instance
52 .get_export_index(&mut store, Some(&iface_idx), "metadata")
53 .ok_or_else(|| {
54 RuntimeError::Wasmtime(anyhow::anyhow!(
55 "interface '{iface_name}' does not export 'metadata'"
56 ))
57 })?;
58
59 let func = instance
60 .get_typed_func::<(), (String,)>(&mut store, &func_idx)
61 .map_err(|e| RuntimeError::Wasmtime(e.into()))?;
62
63 let (result,) = func
64 .call(&mut store, ())
65 .map_err(|e| RuntimeError::Wasmtime(e.into()))?;
66
67 Ok(result)
68 }
69
70 pub fn invoke_composer_compose(
88 &self,
89 ext_id: &str,
90 intent_json: &str,
91 ) -> Result<Result<String, crate::types::HostExtensionError>, RuntimeError> {
92 let loaded = self
93 .loaded()
94 .get(&ExtensionId(ext_id.to_string()))
95 .cloned()
96 .ok_or_else(|| RuntimeError::NotFound(ext_id.to_string()))?;
97
98 let (mut store, instance) = loaded
99 .build_store_and_instance(
100 self.engine(),
101 self.host_overrides().clone(),
102 &crate::host_ports::HostCallContext::default(),
103 )
104 .map_err(RuntimeError::Wasmtime)?;
105
106 let (iface_idx, iface_name, version) = resolve_dw_composer_iface(&mut store, &instance)?;
107
108 let func_idx = instance
109 .get_export_index(&mut store, Some(&iface_idx), "compose")
110 .ok_or_else(|| {
111 RuntimeError::Wasmtime(anyhow::anyhow!(
112 "interface '{iface_name}' does not export 'compose'"
113 ))
114 })?;
115
116 let result: Result<String, crate::types::HostExtensionError> = if version == "0.2.0" {
117 use crate::host_bindings::dw_composer_v02::greentic::extension_base0_2_0::types::ExtensionError as E2;
118 let func = instance
119 .get_typed_func::<(String,), (Result<String, E2>,)>(&mut store, &func_idx)
120 .map_err(|e| RuntimeError::Wasmtime(e.into()))?;
121 let (r,) = func
122 .call(&mut store, (intent_json.to_string(),))
123 .map_err(|e| RuntimeError::Wasmtime(e.into()))?;
124 r.map_err(crate::ext_error::from_composer_v02)
125 } else {
126 let func = instance
127 .get_typed_func::<(String,), (Result<String, String>,)>(&mut store, &func_idx)
128 .map_err(|e| RuntimeError::Wasmtime(e.into()))?;
129 let (r,) = func
130 .call(&mut store, (intent_json.to_string(),))
131 .map_err(|e| RuntimeError::Wasmtime(e.into()))?;
132 r.map_err(crate::ext_error::from_composer_v01)
133 };
134
135 Ok(result)
136 }
137
138 pub fn invoke_composer_validate(
150 &self,
151 ext_id: &str,
152 manifest_json: &str,
153 ) -> Result<String, RuntimeError> {
154 let loaded = self
155 .loaded()
156 .get(&ExtensionId(ext_id.to_string()))
157 .cloned()
158 .ok_or_else(|| RuntimeError::NotFound(ext_id.to_string()))?;
159
160 let (mut store, instance) = loaded
161 .build_store_and_instance(
162 self.engine(),
163 self.host_overrides().clone(),
164 &crate::host_ports::HostCallContext::default(),
165 )
166 .map_err(RuntimeError::Wasmtime)?;
167
168 let (iface_idx, iface_name, _version) = resolve_dw_composer_iface(&mut store, &instance)?;
169
170 let func_idx = instance
171 .get_export_index(&mut store, Some(&iface_idx), "validate")
172 .ok_or_else(|| {
173 RuntimeError::Wasmtime(anyhow::anyhow!(
174 "interface '{iface_name}' does not export 'validate'"
175 ))
176 })?;
177
178 let func = instance
179 .get_typed_func::<(String,), (String,)>(&mut store, &func_idx)
180 .map_err(|e| RuntimeError::Wasmtime(e.into()))?;
181
182 let (result,) = func
183 .call(&mut store, (manifest_json.to_string(),))
184 .map_err(|e| RuntimeError::Wasmtime(e.into()))?;
185
186 Ok(result)
187 }
188
189 pub fn invoke_composer_templates(&self, ext_id: &str) -> Result<String, RuntimeError> {
197 let loaded = self
198 .loaded()
199 .get(&ExtensionId(ext_id.to_string()))
200 .cloned()
201 .ok_or_else(|| RuntimeError::NotFound(ext_id.to_string()))?;
202
203 let (mut store, instance) = loaded
204 .build_store_and_instance(
205 self.engine(),
206 self.host_overrides().clone(),
207 &crate::host_ports::HostCallContext::default(),
208 )
209 .map_err(RuntimeError::Wasmtime)?;
210
211 let (iface_idx, iface_name, _version) = resolve_dw_composer_iface(&mut store, &instance)?;
212
213 let func_idx = instance
214 .get_export_index(&mut store, Some(&iface_idx), "templates")
215 .ok_or_else(|| {
216 RuntimeError::Wasmtime(anyhow::anyhow!(
217 "interface '{iface_name}' does not export 'templates'"
218 ))
219 })?;
220
221 let func = instance
222 .get_typed_func::<(), (String,)>(&mut store, &func_idx)
223 .map_err(|e| RuntimeError::Wasmtime(e.into()))?;
224
225 let (result,) = func
226 .call(&mut store, ())
227 .map_err(|e| RuntimeError::Wasmtime(e.into()))?;
228
229 Ok(result)
230 }
231}
232
233fn resolve_dw_composer_iface(
245 store: &mut wasmtime::Store<crate::host_state::HostState>,
246 instance: &wasmtime::component::Instance,
247) -> Result<
248 (
249 wasmtime::component::ComponentExportIndex,
250 String,
251 &'static str,
252 ),
253 RuntimeError,
254> {
255 crate::runtime::resolve_iface_versions(store, instance, COMPOSER_IFACE_BASE, COMPOSER_VERSIONS)
256}