1use sim_codec_bridge::{BridgePacket, BridgePart};
2use sim_kernel::{Error, Expr, Result, Symbol};
3use sim_lib_agent_runner_core::{ModelResponse, OutputContract};
4use sim_lib_stream_fabric::ContentKey;
5use sim_value::access::field;
6
7use crate::rx::{shape_from_contract_expr, terminal_bridge_text as rx_terminal_bridge_text};
8use crate::tx::eval_request_for_checked_packet;
9
10pub fn terminal_bridge_text(response: &ModelResponse) -> Result<&str> {
12 rx_terminal_bridge_text(response)
13}
14
15pub fn terminal_response_packet(
17 response: &ModelResponse,
18 book: &sim_codec_bridge::BridgeBook,
19) -> Result<BridgePacket> {
20 sim_codec_bridge::decode_bridge_text(terminal_bridge_text(response)?, book)
21}
22
23pub fn bridge_request_content_key(
25 cx: &mut sim_kernel::Cx,
26 book: &sim_codec_bridge::BridgeBook,
27 packet: &BridgePacket,
28) -> Result<ContentKey> {
29 let request = eval_request_for_checked_packet(cx, book, packet)?;
30 Ok(ContentKey::from_request(&request))
31}
32
33pub fn output_contract_for_packet(packet: &BridgePacket) -> Result<OutputContract> {
35 let output = output_part(packet).ok_or_else(|| {
36 Error::Eval(format!(
37 "BRIDGE packet output part {} is missing",
38 packet.header.output
39 ))
40 })?;
41 let codec = match field(&output.payload, "codec") {
42 Some(Expr::Symbol(symbol)) => symbol.clone(),
43 None => Symbol::qualified("codec", "bridge"),
44 Some(other) => {
45 return Err(Error::Eval(format!(
46 "BRIDGE Return codec must be a symbol, found {other:?}"
47 )));
48 }
49 };
50 let shape_expr = field(&output.payload, "shape")
51 .cloned()
52 .unwrap_or_else(|| Expr::Symbol(Symbol::qualified("core", "Any")));
53 let required = !matches!(field(&output.payload, "strict"), Some(Expr::Bool(false)));
54 let Some(shape) = shape_from_contract_expr(&shape_expr) else {
55 return Ok(OutputContract::new(codec, shape_expr, None, required));
56 };
57 Ok(OutputContract::for_shape(
58 codec,
59 shape_expr,
60 shape.as_ref(),
61 required,
62 ))
63}
64
65fn output_part(packet: &BridgePacket) -> Option<&BridgePart> {
66 packet
67 .body
68 .iter()
69 .find(|part| part.id == packet.header.output)
70}