Internal: build the request and start streaming.
(
input: &StreamInput,
provider: Arc<dyn Provider>,
)
| 808 | |
| 809 | /// Internal: build the request and start streaming. |
| 810 | async fn stream_from_input( |
| 811 | input: &StreamInput, |
| 812 | provider: Arc<dyn Provider>, |
| 813 | ) -> anyhow::Result<StreamOutput> { |
| 814 | let session_id = input.session_id.clone(); |
| 815 | let model_id = input.model.model_id.clone(); |
| 816 | let provider_id = input.model.provider_id.clone(); |
| 817 | let agent_name = input.agent.name.clone(); |
| 818 | |
| 819 | tracing::info!( |
| 820 | session_id = %session_id, |
| 821 | model_id = %model_id, |
| 822 | provider_id = %provider_id, |
| 823 | agent = %agent_name, |
| 824 | "Starting LLM stream" |
| 825 | ); |
| 826 | |
| 827 | let mut system_prompt = build_system_prompt(input); |
| 828 | let system_header_before_hooks = system_prompt.first().cloned().unwrap_or_default(); |
| 829 | |
| 830 | // Plugin hook: chat.system.transform — let plugins modify the system prompt |
| 831 | let system_hook_outputs = opencode_plugin::trigger_collect( |
| 832 | HookContext::new(HookEvent::ChatSystemTransform) |
| 833 | .with_session(&session_id) |
| 834 | .with_data("model_id", serde_json::json!(&model_id)) |
| 835 | .with_data("provider_id", serde_json::json!(&provider_id)) |
| 836 | .with_data("system", serde_json::json!(&system_prompt)), |
| 837 | ) |
| 838 | .await; |
| 839 | apply_chat_system_hook_outputs(&mut system_prompt, system_hook_outputs); |
| 840 | rejoin_system_prompt_if_needed(&mut system_prompt, &system_header_before_hooks); |
| 841 | |
| 842 | let mut tools = resolve_tools(input.tools.clone(), &input.agent); |
| 843 | // Inject LiteLLM dummy tool if needed |
| 844 | inject_litellm_dummy_tool(&mut tools, &input.messages, &input.model.provider_id); |
| 845 | |
| 846 | let mut max_tokens = if input.small { |
| 847 | Some(1024u64) |
| 848 | } else { |
| 849 | Some(input.agent.max_tokens.unwrap_or(OUTPUT_TOKEN_MAX)) |
| 850 | }; |
| 851 | |
| 852 | let mut temperature = if input.small { |
| 853 | Some(0.5f32) |
| 854 | } else { |
| 855 | input.agent.temperature |
| 856 | }; |
| 857 | let mut top_p = input.agent.top_p; |
| 858 | let mut provider_options: HashMap<String, serde_json::Value> = HashMap::new(); |
| 859 | |
| 860 | let (tx, rx) = tokio::sync::mpsc::channel(100); |
| 861 | |
| 862 | // Plugin hook: chat.params — let plugins modify LLM request parameters |
| 863 | let params_hook_outputs = opencode_plugin::trigger_collect( |
| 864 | HookContext::new(HookEvent::ChatParams) |
| 865 | .with_session(&session_id) |
| 866 | .with_data("model_id", serde_json::json!(&model_id)) |
| 867 | .with_data("provider_id", serde_json::json!(&provider_id)) |
nothing calls this directly
no test coverage detected