use serde_json::json; use std::path::PathBuf; use uuid::Uuid; use zeroclaw::tools::{ReadSkillTool, Tool}; #[tokio::test] async fn read_skill_inlines_referenced_markdown_files() { let workspace_dir = temp_workspace_dir(); let skill_dir = workspace_dir.join("skills/zhihu-hotlist"); let refs_dir = skill_dir.join("references"); std::fs::create_dir_all(&refs_dir).unwrap(); std::fs::write( skill_dir.join("SKILL.md"), concat!( "# Zhihu Hotlist\n\n", "Follow [collection-flow.md](references/collection-flow.md).\n", "Apply [data-quality.md](references/data-quality.md).\n", ), ) .unwrap(); std::fs::write( refs_dir.join("collection-flow.md"), "# Collection Flow\n\nCollect rows from the hotlist first.\n", ) .unwrap(); std::fs::write( refs_dir.join("data-quality.md"), "# Data Quality\n\nMark partial metrics explicitly.\n", ) .unwrap(); let tool = ReadSkillTool::new(workspace_dir, false, None); let result = tool.execute(json!({ "name": "zhihu-hotlist" })).await.unwrap(); assert!(result.success); assert!(result.output.contains("# Zhihu Hotlist")); assert!(result.output.contains("## Referenced File: references/collection-flow.md")); assert!(result.output.contains("Collect rows from the hotlist first.")); assert!(result.output.contains("## Referenced File: references/data-quality.md")); assert!(result.output.contains("Mark partial metrics explicitly.")); } #[tokio::test] async fn read_skill_recursively_inlines_relative_asset_references() { let workspace_dir = temp_workspace_dir(); let skill_dir = workspace_dir.join("skills/zhihu-hotlist"); let refs_dir = skill_dir.join("references"); let assets_dir = skill_dir.join("assets"); std::fs::create_dir_all(&refs_dir).unwrap(); std::fs::create_dir_all(&assets_dir).unwrap(); std::fs::write( skill_dir.join("SKILL.md"), "# Zhihu Hotlist\n\nFollow [collection-flow.md](references/collection-flow.md).\n", ) .unwrap(); std::fs::write( refs_dir.join("collection-flow.md"), "Use `assets/zhihu_hotlist_flow.source.json` for exact selectors.\n", ) .unwrap(); std::fs::write( assets_dir.join("zhihu_hotlist_flow.source.json"), "{\n \"selectors\": [\".HotList-list\", \".HotItem\"]\n}\n", ) .unwrap(); let tool = ReadSkillTool::new(workspace_dir, false, None); let result = tool.execute(json!({ "name": "zhihu-hotlist" })).await.unwrap(); assert!(result.success); assert!(result.output.contains("## Referenced File: references/collection-flow.md")); assert!(result.output.contains("## Referenced File: assets/zhihu_hotlist_flow.source.json")); assert!(result.output.contains("\"selectors\": [\".HotList-list\", \".HotItem\"]")); } fn temp_workspace_dir() -> PathBuf { let dir = std::env::temp_dir().join(format!("sgclaw-read-skill-{}", Uuid::new_v4())); std::fs::create_dir_all(&dir).unwrap(); dir }