fix(security): resolve rebase conflicts and provider regressions
This commit is contained in:
parent
5d131a8903
commit
0087bcc496
4 changed files with 23 additions and 44 deletions
|
|
@ -281,16 +281,12 @@ fn parse_sse_line(line: &str) -> StreamResult<Option<String>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert SSE byte stream to text chunks.
|
/// Convert SSE byte stream to text chunks.
|
||||||
async fn sse_bytes_to_chunks(
|
fn sse_bytes_to_chunks(
|
||||||
mut response: reqwest::Response,
|
response: reqwest::Response,
|
||||||
count_tokens: bool,
|
count_tokens: bool,
|
||||||
) -> stream::BoxStream<'static, StreamResult<StreamChunk>> {
|
) -> stream::BoxStream<'static, StreamResult<StreamChunk>> {
|
||||||
use tokio::io::AsyncBufReadExt;
|
|
||||||
|
|
||||||
let name = "stream".to_string();
|
|
||||||
|
|
||||||
// Create a channel to send chunks
|
// Create a channel to send chunks
|
||||||
let (mut tx, rx) = tokio::sync::mpsc::channel::<StreamResult<StreamChunk>>(100);
|
let (tx, rx) = tokio::sync::mpsc::channel::<StreamResult<StreamChunk>>(100);
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
// Buffer for incomplete lines
|
// Buffer for incomplete lines
|
||||||
|
|
@ -341,10 +337,7 @@ async fn sse_bytes_to_chunks(
|
||||||
return; // Receiver dropped
|
return; // Receiver dropped
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(None) => {
|
Ok(None) => {}
|
||||||
// Empty line or [DONE] sentinel - continue
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let _ = tx.send(Err(e)).await;
|
let _ = tx.send(Err(e)).await;
|
||||||
return;
|
return;
|
||||||
|
|
@ -365,10 +358,7 @@ async fn sse_bytes_to_chunks(
|
||||||
|
|
||||||
// Convert channel receiver to stream
|
// Convert channel receiver to stream
|
||||||
stream::unfold(rx, |mut rx| async {
|
stream::unfold(rx, |mut rx| async {
|
||||||
match rx.recv().await {
|
rx.recv().await.map(|chunk| (chunk, rx))
|
||||||
Some(chunk) => Some((chunk, rx)),
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
@ -692,7 +682,7 @@ impl Provider for OpenAiCompatibleProvider {
|
||||||
temperature: f64,
|
temperature: f64,
|
||||||
options: StreamOptions,
|
options: StreamOptions,
|
||||||
) -> stream::BoxStream<'static, StreamResult<StreamChunk>> {
|
) -> stream::BoxStream<'static, StreamResult<StreamChunk>> {
|
||||||
let api_key = match self.api_key.as_ref() {
|
let credential = match self.credential.as_ref() {
|
||||||
Some(key) => key.clone(),
|
Some(key) => key.clone(),
|
||||||
None => {
|
None => {
|
||||||
let provider_name = self.name.clone();
|
let provider_name = self.name.clone();
|
||||||
|
|
@ -739,10 +729,10 @@ impl Provider for OpenAiCompatibleProvider {
|
||||||
// Apply auth header
|
// Apply auth header
|
||||||
req_builder = match &auth_header {
|
req_builder = match &auth_header {
|
||||||
AuthStyle::Bearer => {
|
AuthStyle::Bearer => {
|
||||||
req_builder.header("Authorization", format!("Bearer {}", api_key))
|
req_builder.header("Authorization", format!("Bearer {}", credential))
|
||||||
}
|
}
|
||||||
AuthStyle::XApiKey => req_builder.header("x-api-key", &api_key),
|
AuthStyle::XApiKey => req_builder.header("x-api-key", &credential),
|
||||||
AuthStyle::Custom(header) => req_builder.header(header, &api_key),
|
AuthStyle::Custom(header) => req_builder.header(header, &credential),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set accept header for streaming
|
// Set accept header for streaming
|
||||||
|
|
@ -771,7 +761,7 @@ impl Provider for OpenAiCompatibleProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert to chunk stream and forward to channel
|
// Convert to chunk stream and forward to channel
|
||||||
let mut chunk_stream = sse_bytes_to_chunks(response, options.count_tokens).await;
|
let mut chunk_stream = sse_bytes_to_chunks(response, options.count_tokens);
|
||||||
while let Some(chunk) = chunk_stream.next().await {
|
while let Some(chunk) = chunk_stream.next().await {
|
||||||
if tx.send(chunk).await.is_err() {
|
if tx.send(chunk).await.is_err() {
|
||||||
break; // Receiver dropped
|
break; // Receiver dropped
|
||||||
|
|
@ -781,10 +771,7 @@ impl Provider for OpenAiCompatibleProvider {
|
||||||
|
|
||||||
// Convert channel receiver to stream
|
// Convert channel receiver to stream
|
||||||
stream::unfold(rx, |mut rx| async move {
|
stream::unfold(rx, |mut rx| async move {
|
||||||
match rx.recv().await {
|
rx.recv().await.map(|chunk| (chunk, rx))
|
||||||
Some(chunk) => Some((chunk, rx)),
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -409,7 +409,7 @@ impl Provider for OpenRouterProvider {
|
||||||
model: &str,
|
model: &str,
|
||||||
temperature: f64,
|
temperature: f64,
|
||||||
) -> anyhow::Result<ProviderChatResponse> {
|
) -> anyhow::Result<ProviderChatResponse> {
|
||||||
let api_key = self.api_key.as_ref().ok_or_else(|| {
|
let credential = self.credential.as_ref().ok_or_else(|| {
|
||||||
anyhow::anyhow!(
|
anyhow::anyhow!(
|
||||||
"OpenRouter API key not set. Run `zeroclaw onboard` or set OPENROUTER_API_KEY env var."
|
"OpenRouter API key not set. Run `zeroclaw onboard` or set OPENROUTER_API_KEY env var."
|
||||||
)
|
)
|
||||||
|
|
@ -462,7 +462,7 @@ impl Provider for OpenRouterProvider {
|
||||||
let response = self
|
let response = self
|
||||||
.client
|
.client
|
||||||
.post("https://openrouter.ai/api/v1/chat/completions")
|
.post("https://openrouter.ai/api/v1/chat/completions")
|
||||||
.header("Authorization", format!("Bearer {api_key}"))
|
.header("Authorization", format!("Bearer {credential}"))
|
||||||
.header(
|
.header(
|
||||||
"HTTP-Referer",
|
"HTTP-Referer",
|
||||||
"https://github.com/theonlyhennygod/zeroclaw",
|
"https://github.com/theonlyhennygod/zeroclaw",
|
||||||
|
|
|
||||||
|
|
@ -329,21 +329,11 @@ pub trait Provider: Send + Sync {
|
||||||
/// Default implementation falls back to stream_chat_with_system with last user message.
|
/// Default implementation falls back to stream_chat_with_system with last user message.
|
||||||
fn stream_chat_with_history(
|
fn stream_chat_with_history(
|
||||||
&self,
|
&self,
|
||||||
messages: &[ChatMessage],
|
_messages: &[ChatMessage],
|
||||||
model: &str,
|
_model: &str,
|
||||||
temperature: f64,
|
_temperature: f64,
|
||||||
options: StreamOptions,
|
_options: StreamOptions,
|
||||||
) -> stream::BoxStream<'static, StreamResult<StreamChunk>> {
|
) -> stream::BoxStream<'static, StreamResult<StreamChunk>> {
|
||||||
let system = messages
|
|
||||||
.iter()
|
|
||||||
.find(|m| m.role == "system")
|
|
||||||
.map(|m| m.content.clone());
|
|
||||||
let last_user = messages
|
|
||||||
.iter()
|
|
||||||
.rfind(|m| m.role == "user")
|
|
||||||
.map(|m| m.content.clone())
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
// For default implementation, we need to convert to owned strings
|
// For default implementation, we need to convert to owned strings
|
||||||
// This is a limitation of the default implementation
|
// This is a limitation of the default implementation
|
||||||
let provider_name = "unknown".to_string();
|
let provider_name = "unknown".to_string();
|
||||||
|
|
|
||||||
|
|
@ -94,14 +94,16 @@ impl Tool for HardwareMemoryReadTool {
|
||||||
.get("address")
|
.get("address")
|
||||||
.and_then(|v| v.as_str())
|
.and_then(|v| v.as_str())
|
||||||
.unwrap_or("0x20000000");
|
.unwrap_or("0x20000000");
|
||||||
let address = parse_hex_address(address_str).unwrap_or(NUCLEO_RAM_BASE);
|
let _address = parse_hex_address(address_str).unwrap_or(NUCLEO_RAM_BASE);
|
||||||
|
|
||||||
let length = args.get("length").and_then(|v| v.as_u64()).unwrap_or(128) as usize;
|
let requested_length = args.get("length").and_then(|v| v.as_u64()).unwrap_or(128);
|
||||||
let length = length.min(256).max(1);
|
let _length = usize::try_from(requested_length)
|
||||||
|
.unwrap_or(256)
|
||||||
|
.clamp(1, 256);
|
||||||
|
|
||||||
#[cfg(feature = "probe")]
|
#[cfg(feature = "probe")]
|
||||||
{
|
{
|
||||||
match probe_read_memory(chip.unwrap(), address, length) {
|
match probe_read_memory(chip.unwrap(), _address, _length) {
|
||||||
Ok(output) => {
|
Ok(output) => {
|
||||||
return Ok(ToolResult {
|
return Ok(ToolResult {
|
||||||
success: true,
|
success: true,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue