sim_lib_agent_runner_process/
effects.rs1use crate::{ModelRequest, ModelResponse, ProcessRunner};
2use sim_kernel::{
3 CapabilityName, Cx, Datum, DatumStore, Effect, Expr, Ref, Result, Symbol, core_any_ref, effect,
4 value_from_ref,
5};
6
7pub fn host_process_capability() -> CapabilityName {
13 CapabilityName::new("exec")
14}
15
16pub(super) fn resolve_process_effect<F>(
17 runner: &ProcessRunner,
18 cx: &mut Cx,
19 request: ModelRequest,
20 perform: F,
21) -> Result<ModelResponse>
22where
23 F: FnOnce(&ProcessRunner, ModelRequest) -> Result<ModelResponse>,
24{
25 let required_capability = process_effect_capability(cx);
26 let effect = process_effect(runner, cx, &request, required_capability)?;
27 let result = effect::resolve_effect(cx, effect, |cx, _effect| {
28 let response = perform(runner, request)?;
29 response_ref(cx, response)
30 })?;
31 response_from_ref(cx, &result)
32}
33
34fn process_effect(
35 runner: &ProcessRunner,
36 cx: &mut Cx,
37 request: &ModelRequest,
38 required_capability: CapabilityName,
39) -> Result<Effect> {
40 let input = Datum::Node {
41 tag: Symbol::qualified("agent", "ProcessRunnerInput"),
42 fields: vec![
43 (Symbol::new("runner"), Datum::Symbol(runner.runner.clone())),
44 (Symbol::new("model"), Datum::String(runner.model.clone())),
45 (
46 Symbol::new("request"),
47 Datum::try_from(Expr::from(request.clone()))?,
48 ),
49 ],
50 };
51 let input = Ref::Content(cx.datum_store_mut().intern(input)?);
52 Effect::new(
53 host_process_effect_kind(),
54 Ref::Symbol(runner.runner.clone()),
55 input,
56 core_any_ref(),
57 effect::effect_resume_op_key(),
58 effect::effect_abort_op_key(),
59 )
60 .with_replay_key(Some(Ref::Symbol(Symbol::qualified(
61 "agent",
62 "process-runner-v1",
63 ))))
64 .map(|effect| effect.requiring(required_capability))
65}
66
67fn host_process_effect_kind() -> Symbol {
68 Symbol::qualified("effect", "host-process")
69}
70
71fn process_effect_capability(cx: &Cx) -> CapabilityName {
72 granted_capability_or_alias(cx, host_process_capability(), exec_aliases())
73 .unwrap_or_else(host_process_capability)
74}
75
76fn exec_aliases() -> &'static [&'static str] {
77 &["host.process"]
78}
79
80fn granted_capability_or_alias(
81 cx: &Cx,
82 canonical: CapabilityName,
83 aliases: &'static [&'static str],
84) -> Option<CapabilityName> {
85 if cx.capabilities().contains(&canonical) {
86 return Some(canonical);
87 }
88 aliases
89 .iter()
90 .copied()
91 .map(CapabilityName::new)
92 .find(|alias| cx.capabilities().contains(alias))
93}
94
95fn response_ref(cx: &mut Cx, response: ModelResponse) -> Result<Ref> {
96 Ok(Ref::Content(
97 cx.datum_store_mut()
98 .intern(Datum::try_from(Expr::from(response))?)?,
99 ))
100}
101
102fn response_from_ref(cx: &mut Cx, reference: &Ref) -> Result<ModelResponse> {
103 ModelResponse::try_from(value_from_ref(cx, reference)?.object().as_expr(cx)?)
104}