#![allow(dead_code)]
use std::path::{Path, PathBuf};
use std::process::{Command, Output};
use std::sync::atomic::{AtomicUsize, Ordering};
static DIR_SEQ: AtomicUsize = AtomicUsize::new(0);
pub fn unique_dir(name: &str) -> PathBuf {
let seq = DIR_SEQ.fetch_add(1, Ordering::Relaxed);
std::env::temp_dir().join(format!("code_repo_wiki_{}_{}_{}", name, std::process::id(), seq))
}
pub fn copy_dir(src: &Path, dst: &Path) {
std::fs::create_dir_all(dst).unwrap();
for entry in std::fs::read_dir(src).unwrap() {
let entry = entry.unwrap();
let target = dst.join(entry.file_name());
if entry.file_type().unwrap().is_dir() {
copy_dir(&entry.path(), &target);
} else {
std::fs::copy(entry.path(), target).unwrap();
}
}
}
pub fn run_bin(dir: &Path, args: &[&str]) -> Output {
run_bin_with_envs(dir, args, &[])
}
pub fn run_bin_with_envs(dir: &Path, args: &[&str], envs: &[(&str, &str)]) -> Output {
let mut cmd = Command::new(env!("CARGO_BIN_EXE_code-repo-wiki"));
cmd.args(args)
.current_dir(dir)
.env("RUST_LOG", "off") .env_remove("OPENAI_API_KEY"); for (k, v) in envs {
cmd.env(k, v);
}
cmd.output().expect("执行 code-repo-wiki 二进制失败")
}
pub fn mock_config() -> String {
r#"
[llm]
provider = "mock"
model = "mock-model"
api_key = "mock"
api_key_env = ""
max_concurrent = 1
[embed]
provider = "mock"
model = "mock-embed"
api_key_env = ""
"#
.to_string()
}
pub fn openai_compatible_config(port: u16) -> String {
format!(
r#"
[llm]
provider = "openai-compatible"
model = "gpt-4o"
base_url = "http://127.0.0.1:{port}/v1"
api_key = "mock"
api_key_env = "OPENAI_API_KEY"
max_concurrent = 1
[embed]
provider = "mock"
model = "mock-embed"
api_key_env = ""
"#
)
}
pub fn mock_llm_server() -> u16 {
let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
let port = listener.local_addr().unwrap().port();
std::thread::spawn(move || {
use std::io::{Read, Write};
let content = r#"{"summary": "Mock 生成的摘要", "key_entities": []}"#;
let payload = serde_json::json!({ "choices": [{ "delta": { "content": content } }] });
let body = format!("data: {}\n\ndata: [DONE]\n\n", payload);
for stream in listener.incoming() {
let mut s = match stream {
Ok(s) => s,
Err(_) => continue,
};
let mut buf = [0u8; 4096];
let _ = s.read(&mut buf);
let head = format!(
"HTTP/1.1 200 OK\r\nContent-Type: text/event-stream\r\nContent-Length: {}\r\nConnection: close\r\n\r\n",
body.len()
);
let _ = s.write_all(head.as_bytes());
let _ = s.write_all(body.as_bytes());
}
});
port
}