monoloop_testkit/
pipeline.rs1use monoloop_contracts::{
4 ConnectionId, DialectBinding, DialectDescriptor, ExternalSessionId, InterpretationId,
5 InterpretationLimits, InterpreterOutputEvent,
6};
7use monoloop_interpreter::{DefaultInterpreterFactory, InterpreterFactory, StartInterpretation};
8use std::sync::Arc;
9
10use crate::console::{ConsoleRenderer, ConsoleRendererConfig, ConsoleSink, SyncMemorySink};
11
12pub fn cursor_acp_binding() -> DialectBinding {
14 DialectBinding::negotiated(DialectDescriptor::cursor_acp("1"))
15}
16
17pub fn agy_acp_binding() -> DialectBinding {
19 DialectBinding::negotiated(DialectDescriptor::agy_acp("1"))
20}
21
22pub fn codex_acp_binding() -> DialectBinding {
24 DialectBinding::negotiated(DialectDescriptor::codex_acp("1"))
25}
26
27pub fn zai_cli_binding() -> DialectBinding {
29 DialectBinding::negotiated(DialectDescriptor::zai_cli("1"))
30}
31
32pub fn claude_code_binding() -> DialectBinding {
34 DialectBinding::negotiated(DialectDescriptor::claude_code("1"))
35}
36
37pub async fn interpret_bytes(
39 dialect: DialectBinding,
40 bytes: &[u8],
41 external_session_id: Option<ExternalSessionId>,
42) -> Vec<InterpreterOutputEvent> {
43 feed_chunks(
44 dialect,
45 &[bytes::Bytes::copy_from_slice(bytes)],
46 external_session_id,
47 )
48 .await
49}
50
51pub async fn feed_chunks(
53 dialect: DialectBinding,
54 chunks: &[bytes::Bytes],
55 external_session_id: Option<ExternalSessionId>,
56) -> Vec<InterpreterOutputEvent> {
57 let factory = DefaultInterpreterFactory::new();
58 let interp = factory
59 .start(StartInterpretation {
60 interpretation_id: InterpretationId::generate(),
61 connection_id: ConnectionId::new("test-conn"),
62 external_session_id,
63 dialect,
64 limits: InterpretationLimits::default(),
65 })
66 .expect("start");
67
68 for chunk in chunks {
69 interp.input.push_bytes(chunk.clone()).await.expect("push");
70 }
71 interp.input.finish_clean().await.expect("finish");
72 collect_interpretation(&interp).await
73}
74
75pub async fn collect_interpretation(
77 interp: &monoloop_interpreter::Interpretation,
78) -> Vec<InterpreterOutputEvent> {
79 let mut out = Vec::new();
80 loop {
81 match interp.events.recv().await {
82 Some(ev) => {
83 let done = matches!(ev, InterpreterOutputEvent::Ended(_));
84 out.push(ev);
85 if done {
86 break;
87 }
88 }
89 None => break,
90 }
91 }
92 out
93}
94
95pub async fn interpret_and_render(
97 dialect: DialectBinding,
98 chunks: &[bytes::Bytes],
99) -> (Vec<InterpreterOutputEvent>, String) {
100 let events = feed_chunks(dialect, chunks, None).await;
101 let sink = Arc::new(SyncMemorySink::new());
102 let renderer = ConsoleRenderer::new(ConsoleRendererConfig::default(), sink.clone());
103 for ev in &events {
104 renderer.render(ev);
105 }
106 (events, sink.join())
107}
108
109pub fn acp_binding() -> DialectBinding {
111 DialectBinding::negotiated(DialectDescriptor::acp_json_rpc("1"))
112}
113
114pub fn test_text_binding() -> DialectBinding {
116 DialectBinding::fixed(DialectDescriptor::test_raw())
117}
118
119pub fn render_all(events: &[InterpreterOutputEvent], sink: Arc<dyn ConsoleSink>) {
121 let renderer = ConsoleRenderer::new(ConsoleRendererConfig::default(), sink);
122 for ev in events {
123 renderer.render(ev);
124 }
125}