clippy --fix: 合并嵌套if、简化map_or、移除冗余引用等机械性优化
This commit is contained in:
parent
ceb8234a30
commit
81e9f1e7db
@ -162,7 +162,7 @@ impl LoopDetector {
|
||||
.count();
|
||||
|
||||
// Warn every warn_every times
|
||||
if consecutive > 0 && consecutive % self.config.warn_every == 0 {
|
||||
if consecutive > 0 && consecutive.is_multiple_of(self.config.warn_every) {
|
||||
LoopDetectionResult::Warning(format!(
|
||||
"注意: 工具 '{}' 已连续执行 {} 次,参数相同。如果任务没有进展,请尝试其他方法。",
|
||||
last.name, consecutive
|
||||
@ -339,7 +339,7 @@ impl AgentLoop {
|
||||
tracing::debug!(history_len = messages.len(), max_iterations = self.max_iterations, "Starting agent process");
|
||||
|
||||
// Build and inject system prompt if not present
|
||||
let has_system = messages.first().map_or(false, |m| m.role == "system");
|
||||
let has_system = messages.first().is_some_and(|m| m.role == "system");
|
||||
if !has_system {
|
||||
let system_prompt = build_system_prompt(&self.workspace_dir, &self.model_name, &self.tools, None, None);
|
||||
#[cfg(debug_assertions)]
|
||||
|
||||
@ -186,14 +186,13 @@ impl PromptSection for UserProfileSection {
|
||||
let mut output = String::from("## 用户配置\n\n");
|
||||
|
||||
// Load USER.md from ~/.picobot/USER.md
|
||||
if let Some(user_config_dir) = get_user_config_dir() {
|
||||
if let Some(content) =
|
||||
if let Some(user_config_dir) = get_user_config_dir()
|
||||
&& let Some(content) =
|
||||
load_file_from_dir(&user_config_dir, "USER.md", BOOTSTRAP_MAX_CHARS)
|
||||
{
|
||||
output.push_str(&content);
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
// No USER.md found, return empty
|
||||
String::new()
|
||||
|
||||
@ -32,6 +32,12 @@ pub struct CliChatChannel {
|
||||
clients: Mutex<Vec<Arc<Client>>>,
|
||||
}
|
||||
|
||||
impl Default for CliChatChannel {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl CliChatChannel {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
|
||||
@ -229,12 +229,11 @@ impl FeishuChannel {
|
||||
// 1. Check cache
|
||||
{
|
||||
let cached = self.tenant_token.read().await;
|
||||
if let Some(ref token) = *cached {
|
||||
if Instant::now() < token.refresh_after {
|
||||
if let Some(ref token) = *cached
|
||||
&& Instant::now() < token.refresh_after {
|
||||
return Ok(token.value.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Fetch new token
|
||||
let (token, ttl) = self.fetch_new_token().await?;
|
||||
@ -901,11 +900,10 @@ impl FeishuChannel {
|
||||
let (mut content, media) = self.parse_and_download_message(msg_type, &raw_content, &message_id).await?;
|
||||
|
||||
// Fetch and prepend quoted message content if this is a reply
|
||||
if let Some(ref pid) = parent_id {
|
||||
if let Some(reply_ctx) = self.get_message_content(pid).await {
|
||||
if let Some(ref pid) = parent_id
|
||||
&& let Some(reply_ctx) = self.get_message_content(pid).await {
|
||||
content = format!("{}\n{}", reply_ctx, content);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
if let Some(ref m) = media {
|
||||
@ -1296,8 +1294,8 @@ fn parse_post_content(content: &str) -> String {
|
||||
// Fall back: try any dict child
|
||||
if let Some(root_obj) = root.as_object() {
|
||||
for (_key, val) in root_obj {
|
||||
if let Some(obj) = val.as_object() {
|
||||
if obj.get("content").and_then(|c| c.as_array()).is_some() {
|
||||
if let Some(obj) = val.as_object()
|
||||
&& obj.get("content").and_then(|c| c.as_array()).is_some() {
|
||||
parse_block(val, &mut texts);
|
||||
let result = texts.join("");
|
||||
if !result.trim().is_empty() {
|
||||
@ -1307,7 +1305,6 @@ fn parse_post_content(content: &str) -> String {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
content.to_string()
|
||||
}
|
||||
@ -1329,22 +1326,19 @@ fn extract_interactive_content(content: &str) -> Result<(String, Option<MediaIte
|
||||
}
|
||||
|
||||
// Extract from card object
|
||||
if let Some(card) = parsed.get("card").and_then(|c| c.as_object()) {
|
||||
if let Some(elements) = card.get("elements").and_then(|e| e.as_array()) {
|
||||
if let Some(card) = parsed.get("card").and_then(|c| c.as_object())
|
||||
&& let Some(elements) = card.get("elements").and_then(|e| e.as_array()) {
|
||||
for el in elements {
|
||||
extract_element_content(el, &mut texts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extract from header
|
||||
if let Some(header) = parsed.get("header").and_then(|h| h.as_object()) {
|
||||
if let Some(title) = header.get("title").and_then(|t| t.as_object()) {
|
||||
if let Some(text) = title.get("content").and_then(|c| c.as_str()) {
|
||||
if let Some(header) = parsed.get("header").and_then(|h| h.as_object())
|
||||
&& let Some(title) = header.get("title").and_then(|t| t.as_object())
|
||||
&& let Some(text) = title.get("content").and_then(|c| c.as_str()) {
|
||||
texts.push(format!("title: {}\n", text));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let result = texts.join("").trim().to_string();
|
||||
if result.is_empty() {
|
||||
@ -1495,13 +1489,12 @@ fn collect_list_items(items: &[serde_json::Value], lines: &mut Vec<String>, dept
|
||||
None
|
||||
}
|
||||
})
|
||||
}) {
|
||||
if let Some(children) = children_arr.as_object().and_then(|o| o.get("children")).and_then(|c| c.as_array()) {
|
||||
})
|
||||
&& let Some(children) = children_arr.as_object().and_then(|o| o.get("children")).and_then(|c| c.as_array()) {
|
||||
collect_list_items(children, lines, depth + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract text from inline elements (text, link, at-mention)
|
||||
fn extract_inline_text(el: &serde_json::Value, out: &mut String) {
|
||||
@ -2088,7 +2081,7 @@ impl Channel for FeishuChannel {
|
||||
content: Self::strip_thinking_tags(&msg.content),
|
||||
..msg
|
||||
};
|
||||
let receive_id = if msg.chat_id.starts_with("oc_") { &msg.chat_id } else { &msg.reply_to.as_ref().unwrap_or(&msg.chat_id) };
|
||||
let receive_id = if msg.chat_id.starts_with("oc_") { &msg.chat_id } else { msg.reply_to.as_ref().unwrap_or(&msg.chat_id) };
|
||||
let receive_id_type = if msg.chat_id.starts_with("oc_") { "chat_id" } else { "open_id" };
|
||||
|
||||
// If no media, use smart format detection
|
||||
|
||||
@ -32,7 +32,7 @@ pub fn render(f: &mut Frame, area: Rect, app: &App) {
|
||||
let alias = cmd.aliases.first().map(|a| a.as_str()).unwrap_or(&cmd.name);
|
||||
|
||||
ListItem::new(Line::from(vec![
|
||||
Span::styled(alias, style.clone()),
|
||||
Span::styled(alias, style),
|
||||
Span::styled(" - ", Style::default().fg(Color::Gray)),
|
||||
Span::styled(&cmd.description, style),
|
||||
]))
|
||||
|
||||
@ -13,8 +13,7 @@ pub fn render(f: &mut Frame, area: Rect, app: &App) {
|
||||
.map(|session| {
|
||||
let is_current = app
|
||||
.current_session_id
|
||||
.as_ref()
|
||||
.map_or(false, |id| id == &session.session_id);
|
||||
.as_ref() == Some(&session.session_id);
|
||||
let archived = session.archived_at.is_some();
|
||||
|
||||
let mut content = if is_current {
|
||||
|
||||
@ -36,12 +36,11 @@ async fn handle_socket(ws: WebSocket, state: Arc<GatewayState>) {
|
||||
// Task: forward from receiver to WebSocket
|
||||
tokio::spawn(async move {
|
||||
while let Some(msg) = receiver.recv().await {
|
||||
if let Ok(text) = serialize_outbound(&msg) {
|
||||
if ws_sender.send(WsMessage::Text(text.into())).await.is_err() {
|
||||
if let Ok(text) = serialize_outbound(&msg)
|
||||
&& ws_sender.send(WsMessage::Text(text.into())).await.is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Main loop: receive WebSocket messages and forward to CliChatChannel
|
||||
|
||||
@ -26,11 +26,10 @@ pub fn init_logging() {
|
||||
let log_dir = get_default_log_dir();
|
||||
|
||||
// Create log directory if it doesn't exist
|
||||
if !log_dir.exists() {
|
||||
if let Err(e) = std::fs::create_dir_all(&log_dir) {
|
||||
if !log_dir.exists()
|
||||
&& let Err(e) = std::fs::create_dir_all(&log_dir) {
|
||||
eprintln!("Warning: Failed to create log directory {}: {}", log_dir.display(), e);
|
||||
}
|
||||
}
|
||||
|
||||
// Create file appender with daily rotation
|
||||
let file_appender = RollingFileAppender::new(
|
||||
|
||||
@ -11,11 +11,10 @@ use std::sync::Arc;
|
||||
use crate::storage::Storage;
|
||||
|
||||
fn convert_content_blocks(blocks: &[ContentBlock]) -> Value {
|
||||
if blocks.len() == 1 {
|
||||
if let ContentBlock::Text { text } = &blocks[0] {
|
||||
if blocks.len() == 1
|
||||
&& let ContentBlock::Text { text } = &blocks[0] {
|
||||
return Value::String(text.clone());
|
||||
}
|
||||
}
|
||||
Value::Array(blocks.iter().map(|b| match b {
|
||||
ContentBlock::Text { text } => json!({ "type": "text", "text": text }),
|
||||
ContentBlock::ImageUrl { image_url } => {
|
||||
@ -77,7 +76,7 @@ impl OpenAIProvider {
|
||||
"tool_call_id": m.tool_call_id,
|
||||
"name": m.name,
|
||||
})
|
||||
} else if m.role == "assistant" && m.tool_calls.as_ref().map_or(false, |c| !c.is_empty()) {
|
||||
} else if m.role == "assistant" && m.tool_calls.as_ref().is_some_and(|c| !c.is_empty()) {
|
||||
json!({
|
||||
"role": m.role,
|
||||
"content": convert_content_blocks(&m.content),
|
||||
@ -187,8 +186,8 @@ impl LLMProvider for OpenAIProvider {
|
||||
for (i, msg) in msgs.iter().enumerate() {
|
||||
if let Some(content) = msg.get("content").and_then(|c| c.as_array()) {
|
||||
for (j, item) in content.iter().enumerate() {
|
||||
if item.get("type").and_then(|t| t.as_str()) == Some("image_url") {
|
||||
if let Some(url_str) = item.get("image_url").and_then(|u| u.get("url")).and_then(|v| v.as_str()) {
|
||||
if item.get("type").and_then(|t| t.as_str()) == Some("image_url")
|
||||
&& let Some(url_str) = item.get("image_url").and_then(|u| u.get("url")).and_then(|v| v.as_str()) {
|
||||
let prefix: String = url_str.chars().take(20).collect();
|
||||
tracing::debug!(msg_idx = i, item_idx = j, image_prefix = %prefix, image_url_len = %url_str.len(), "Image in LLM request (first 20 bytes shown)");
|
||||
}
|
||||
@ -197,7 +196,6 @@ impl LLMProvider for OpenAIProvider {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut req_builder = self
|
||||
.client
|
||||
|
||||
@ -22,7 +22,7 @@ use crate::agent::{AgentLoop, AgentError, ContextCompressor};
|
||||
use crate::agent::system_prompt::build_system_prompt;
|
||||
use crate::agent::context_compressor::ContextCompressionConfig;
|
||||
use crate::providers::{create_provider, LLMProvider};
|
||||
use crate::session::session_id::{UnifiedSessionId, DEFAULT_DIALOG_ID};
|
||||
use crate::session::session_id::UnifiedSessionId;
|
||||
use crate::session::events::DialogInfo;
|
||||
use crate::skills::SkillsLoader;
|
||||
use crate::tools::{ToolRegistry, create_default_tools};
|
||||
@ -193,8 +193,8 @@ impl Session {
|
||||
self.seq_counter += 1;
|
||||
|
||||
// Persist to Storage
|
||||
if persist {
|
||||
if let Some(ref storage) = self.storage {
|
||||
if persist
|
||||
&& let Some(ref storage) = self.storage {
|
||||
let msg_meta = crate::storage::message::MessageMeta {
|
||||
id: message.id.clone(),
|
||||
session_id: self.id.to_string(),
|
||||
@ -214,7 +214,6 @@ impl Session {
|
||||
};
|
||||
storage.append_message_with_retry(&self.id.to_string(), &msg_meta).await?;
|
||||
}
|
||||
}
|
||||
|
||||
// Update in-memory state
|
||||
self.messages.push(message);
|
||||
@ -411,7 +410,7 @@ impl Session {
|
||||
|
||||
/// 将当前 session 导出为 markdown 文档并保存到文件
|
||||
pub fn dump_to_file(&self, system_prompt: &str) -> std::io::Result<String> {
|
||||
use chrono::{DateTime, Local};
|
||||
use chrono::Local;
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
|
||||
@ -440,7 +439,7 @@ impl Session {
|
||||
let now = Local::now().format("%Y-%m-%d %H:%M:%S");
|
||||
|
||||
let mut md = String::new();
|
||||
md.push_str(&format!("# Session Dump\n\n"));
|
||||
md.push_str(&"# Session Dump\n\n".to_string());
|
||||
md.push_str(&format!("- **Session ID**: `{}`\n", self.id));
|
||||
md.push_str(&format!("- **Channel**: `{}`\n", self.id.channel));
|
||||
md.push_str(&format!("- **Chat ID**: `{}`\n", self.id.chat_id));
|
||||
@ -473,7 +472,7 @@ impl Session {
|
||||
md.push_str("```\n");
|
||||
|
||||
if let Some(ref tool_calls) = msg.tool_calls {
|
||||
md.push_str(&format!("[Tool Calls]\n"));
|
||||
md.push_str(&"[Tool Calls]\n".to_string());
|
||||
for tc in tool_calls {
|
||||
md.push_str(&format!("- {}: {:?}\n", tc.name, tc.arguments));
|
||||
}
|
||||
@ -599,11 +598,10 @@ fn repair_tool_call_chains(messages: &mut Vec<ChatMessage>) {
|
||||
let mut j = i + 1;
|
||||
while j < messages.len() && found < expected_count {
|
||||
if messages[j].role == "tool" {
|
||||
if let Some(ref tc_id) = messages[j].tool_call_id {
|
||||
if expected_ids.contains(tc_id.as_str()) {
|
||||
if let Some(ref tc_id) = messages[j].tool_call_id
|
||||
&& expected_ids.contains(tc_id.as_str()) {
|
||||
found += 1;
|
||||
}
|
||||
}
|
||||
} else if messages[j].role == "user" || messages[j].role == "assistant" {
|
||||
// Next user/assistant message — stop scanning, chain is broken
|
||||
break;
|
||||
@ -1031,7 +1029,7 @@ impl SessionManager {
|
||||
self.tools.clone(),
|
||||
Some(self.storage.clone()),
|
||||
String::new(),
|
||||
format!("新对话"),
|
||||
"新对话".to_string(),
|
||||
self.memory_manager.clone(),
|
||||
).await?;
|
||||
|
||||
@ -1165,15 +1163,12 @@ impl SessionManager {
|
||||
};
|
||||
|
||||
if let Some(ref current_id) = current_id {
|
||||
match self.storage.get_session(current_id).await {
|
||||
Ok(_) => {
|
||||
if let Ok(_) = self.storage.get_session(current_id).await {
|
||||
let parts: Vec<&str> = current_id.split(':').collect();
|
||||
if parts.len() == 3 {
|
||||
return Ok(UnifiedSessionId::new(channel, chat_id, parts[2]));
|
||||
}
|
||||
}
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
let ttl_millis = self.inner.lock().await.session_ttl.as_millis() as i64;
|
||||
@ -1310,7 +1305,7 @@ impl SessionManager {
|
||||
let skills_prompt = self.skills_loader.build_skills_prompt();
|
||||
|
||||
// Fetch memory context
|
||||
let memory_context = match self.memory_manager.recall(&content, 5, Some(crate::memory::MemoryCategory::Knowledge)).await {
|
||||
let memory_context = match self.memory_manager.recall(content, 5, Some(crate::memory::MemoryCategory::Knowledge)).await {
|
||||
Ok(entries) if !entries.is_empty() => {
|
||||
Some(entries.iter()
|
||||
.map(|e| format!("- {}: {}", e.key, e.content))
|
||||
@ -1342,11 +1337,10 @@ impl SessionManager {
|
||||
}
|
||||
|
||||
// Check if we need to generate a title (after 10 user messages)
|
||||
if session_guard.should_generate_title() {
|
||||
if let Err(e) = session_guard.generate_title().await {
|
||||
if session_guard.should_generate_title()
|
||||
&& let Err(e) = session_guard.generate_title().await {
|
||||
tracing::warn!("failed to generate title: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
result.final_response.content
|
||||
};
|
||||
@ -1456,11 +1450,10 @@ impl SessionManager {
|
||||
.map_err(|e| AgentError::Other(format!("persist error: {}", e)))?;
|
||||
}
|
||||
|
||||
if session_guard.should_generate_title() {
|
||||
if let Err(e) = session_guard.generate_title().await {
|
||||
if session_guard.should_generate_title()
|
||||
&& let Err(e) = session_guard.generate_title().await {
|
||||
tracing::warn!("failed to generate title: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
let raw_response = result.final_response.content;
|
||||
let prefix = format!(
|
||||
|
||||
@ -12,6 +12,7 @@ pub struct Skill {
|
||||
pub path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct SkillMarkdownMeta {
|
||||
name: Option<String>,
|
||||
description: Option<String>,
|
||||
@ -147,24 +148,21 @@ impl SkillsLoader {
|
||||
fn get_dir_mtime(dir: &Path) -> Option<SystemTime> {
|
||||
let mut max_mtime = None;
|
||||
|
||||
if let Ok(metadata) = std::fs::metadata(dir) {
|
||||
if let Ok(mtime) = metadata.modified() {
|
||||
if let Ok(metadata) = std::fs::metadata(dir)
|
||||
&& let Ok(mtime) = metadata.modified() {
|
||||
max_mtime = Some(mtime);
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(entries) = std::fs::read_dir(dir) {
|
||||
for entry in entries.flatten() {
|
||||
let path = entry.path();
|
||||
if let Ok(metadata) = std::fs::metadata(&path) {
|
||||
if let Ok(mtime) = metadata.modified() {
|
||||
if max_mtime.map_or(true, |current| mtime > current) {
|
||||
if let Ok(metadata) = std::fs::metadata(&path)
|
||||
&& let Ok(mtime) = metadata.modified()
|
||||
&& max_mtime.is_none_or(|current| mtime > current) {
|
||||
max_mtime = Some(mtime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
max_mtime
|
||||
}
|
||||
@ -424,15 +422,6 @@ impl Default for SkillsLoader {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SkillMarkdownMeta {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
name: None,
|
||||
description: None,
|
||||
always: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract first non-empty, non-heading line as description
|
||||
fn extract_description(content: &str) -> String {
|
||||
|
||||
@ -96,7 +96,7 @@ impl super::Storage {
|
||||
.cut(query, true)
|
||||
.into_iter()
|
||||
.filter(|w| w.len() > 1 || w.bytes().any(|b| b > 127))
|
||||
.map(|w| w.replace('%', "").replace('_', ""))
|
||||
.map(|w| w.replace(['%', '_'], ""))
|
||||
.collect();
|
||||
|
||||
if !terms.is_empty() {
|
||||
@ -159,7 +159,7 @@ impl super::Storage {
|
||||
.cut(q, true)
|
||||
.into_iter()
|
||||
.filter(|w| w.len() > 1 || w.bytes().any(|b| b > 127))
|
||||
.map(|w| w.replace('%', "").replace('_', ""))
|
||||
.map(|w| w.replace(['%', '_'], ""))
|
||||
.collect();
|
||||
|
||||
if terms.is_empty() {
|
||||
|
||||
@ -144,7 +144,7 @@ impl Tool for BashTool {
|
||||
let cwd = self
|
||||
.working_dir
|
||||
.as_ref()
|
||||
.map(|d| Path::new(d))
|
||||
.map(Path::new)
|
||||
.unwrap_or_else(|| Path::new("."));
|
||||
|
||||
let result = timeout(
|
||||
@ -217,7 +217,7 @@ impl BashTool {
|
||||
let stderr_str = String::from_utf8_lossy(&stderr);
|
||||
if !stderr_str.trim().is_empty() {
|
||||
if !output.is_empty() {
|
||||
output.push_str("\n");
|
||||
output.push('\n');
|
||||
}
|
||||
output.push_str("STDERR:\n");
|
||||
output.push_str(&stderr_str);
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
use std::io::Read;
|
||||
use std::path::Path;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use serde_json::json;
|
||||
|
||||
use crate::bus::message::ContentBlock;
|
||||
use crate::tools::traits::{Tool, ToolResult};
|
||||
|
||||
const MAX_CHARS: usize = 128_000;
|
||||
|
||||
@ -113,17 +113,15 @@ impl Tool for FileWriteTool {
|
||||
};
|
||||
|
||||
// Create parent directories if needed
|
||||
if let Some(parent) = resolved.parent() {
|
||||
if !parent.exists() {
|
||||
if let Err(e) = std::fs::create_dir_all(parent) {
|
||||
if let Some(parent) = resolved.parent()
|
||||
&& !parent.exists()
|
||||
&& let Err(e) = std::fs::create_dir_all(parent) {
|
||||
return Ok(ToolResult {
|
||||
success: false,
|
||||
output: String::new(),
|
||||
error: Some(format!("Failed to create parent directory: {}", e)),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match std::fs::write(&resolved, content) {
|
||||
Ok(_) => Ok(ToolResult {
|
||||
|
||||
@ -78,17 +78,15 @@ impl HttpRequestTool {
|
||||
|
||||
if let Some(obj) = headers.as_object() {
|
||||
for (key, value) in obj {
|
||||
if let Some(str_val) = value.as_str() {
|
||||
if let Ok(name) = reqwest::header::HeaderName::from_bytes(key.as_bytes()) {
|
||||
if let Ok(val) =
|
||||
if let Some(str_val) = value.as_str()
|
||||
&& let Ok(name) = reqwest::header::HeaderName::from_bytes(key.as_bytes())
|
||||
&& let Ok(val) =
|
||||
reqwest::header::HeaderValue::from_str(str_val)
|
||||
{
|
||||
header_map.insert(name, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
header_map
|
||||
}
|
||||
|
||||
@ -114,11 +114,10 @@ impl SchemaCleanr {
|
||||
anyhow::bail!("Schema missing required 'type' field");
|
||||
}
|
||||
|
||||
if let Some(Value::String(t)) = obj.get("type") {
|
||||
if t == "object" && !obj.contains_key("properties") {
|
||||
if let Some(Value::String(t)) = obj.get("type")
|
||||
&& t == "object" && !obj.contains_key("properties") {
|
||||
tracing::warn!("Object schema without 'properties' field may cause issues");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -173,11 +172,10 @@ impl SchemaCleanr {
|
||||
}
|
||||
|
||||
// Handle anyOf/oneOf simplification
|
||||
if obj.contains_key("anyOf") || obj.contains_key("oneOf") {
|
||||
if let Some(simplified) = Self::try_simplify_union(&obj, defs, strategy, ref_stack) {
|
||||
if (obj.contains_key("anyOf") || obj.contains_key("oneOf"))
|
||||
&& let Some(simplified) = Self::try_simplify_union(&obj, defs, strategy, ref_stack) {
|
||||
return simplified;
|
||||
}
|
||||
}
|
||||
|
||||
// Build cleaned object
|
||||
let mut cleaned = Map::new();
|
||||
@ -244,14 +242,13 @@ impl SchemaCleanr {
|
||||
return Self::preserve_meta(obj, Value::Object(Map::new()));
|
||||
}
|
||||
|
||||
if let Some(def_name) = Self::parse_local_ref(ref_value) {
|
||||
if let Some(definition) = defs.get(def_name.as_str()) {
|
||||
if let Some(def_name) = Self::parse_local_ref(ref_value)
|
||||
&& let Some(definition) = defs.get(def_name.as_str()) {
|
||||
ref_stack.insert(ref_value.to_string());
|
||||
let cleaned = Self::clean_with_defs(definition.clone(), defs, strategy, ref_stack);
|
||||
ref_stack.remove(ref_value);
|
||||
return Self::preserve_meta(obj, cleaned);
|
||||
}
|
||||
}
|
||||
|
||||
tracing::warn!("Cannot resolve $ref: {}", ref_value);
|
||||
Self::preserve_meta(obj, Value::Object(Map::new()))
|
||||
@ -342,17 +339,15 @@ impl SchemaCleanr {
|
||||
if let Some(Value::Null) = obj.get("const") {
|
||||
return true;
|
||||
}
|
||||
if let Some(Value::Array(arr)) = obj.get("enum") {
|
||||
if arr.len() == 1 && matches!(arr[0], Value::Null) {
|
||||
if let Some(Value::Array(arr)) = obj.get("enum")
|
||||
&& arr.len() == 1 && matches!(arr[0], Value::Null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if let Some(Value::String(t)) = obj.get("type") {
|
||||
if t == "null" {
|
||||
if let Some(Value::String(t)) = obj.get("type")
|
||||
&& t == "null" {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user