This commit is contained in:
parent
ed4aad72f4
commit
bcb7703ea6
14 changed files with 384 additions and 38 deletions
189
Cargo.lock
generated
189
Cargo.lock
generated
|
@ -268,6 +268,17 @@ version = "2.0.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||
|
||||
[[package]]
|
||||
name = "aes"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cipher",
|
||||
"cpufeatures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.12"
|
||||
|
@ -383,6 +394,15 @@ version = "1.0.98"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
|
||||
|
||||
[[package]]
|
||||
name = "arbitrary"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223"
|
||||
dependencies = [
|
||||
"derive_arbitrary",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.5.2"
|
||||
|
@ -806,6 +826,15 @@ dependencies = [
|
|||
"bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bzip2"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bea8dcd42434048e4f7a304411d9273a411f647446c1234a65ce0554923f4cff"
|
||||
dependencies = [
|
||||
"libbz2-rs-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.27"
|
||||
|
@ -854,6 +883,16 @@ dependencies = [
|
|||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"inout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.4"
|
||||
|
@ -904,6 +943,12 @@ dependencies = [
|
|||
"tiny-keccak",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
|
||||
|
||||
[[package]]
|
||||
name = "convert_case"
|
||||
version = "0.4.0"
|
||||
|
@ -1110,6 +1155,12 @@ version = "2.9.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476"
|
||||
|
||||
[[package]]
|
||||
name = "deflate64"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da692b8d1080ea3045efaab14434d40468c3d8657e42abddfffca87b428f4c1b"
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.7.10"
|
||||
|
@ -1141,6 +1192,17 @@ dependencies = [
|
|||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_arbitrary"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_builder"
|
||||
version = "0.20.2"
|
||||
|
@ -1475,6 +1537,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"libz-rs-sys",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
|
@ -1702,6 +1765,7 @@ dependencies = [
|
|||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"urlencoding",
|
||||
"zip",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2333,6 +2397,15 @@ dependencies = [
|
|||
"hashbrown 0.15.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inout"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.13"
|
||||
|
@ -2532,12 +2605,38 @@ dependencies = [
|
|||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libbz2-rs-sys"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "775bf80d5878ab7c2b1080b5351a48b2f737d9f6f8b383574eebcc22be0dfccb"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.174"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
|
||||
|
||||
[[package]]
|
||||
name = "liblzma"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0791ab7e08ccc8e0ce893f6906eb2703ed8739d8e89b57c0714e71bad09024c8"
|
||||
dependencies = [
|
||||
"liblzma-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "liblzma-sys"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01b9596486f6d60c3bbe644c0e1be1aa6ccc472ad630fe8927b456973d7cb736"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.15"
|
||||
|
@ -2555,6 +2654,15 @@ dependencies = [
|
|||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libz-rs-sys"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "172a788537a2221661b480fee8dc5f96c580eb34fa88764d3205dc356c7e4221"
|
||||
dependencies = [
|
||||
"zlib-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.9.4"
|
||||
|
@ -3030,6 +3138,16 @@ version = "1.0.15"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||
|
||||
[[package]]
|
||||
name = "pbkdf2"
|
||||
version = "0.12.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
|
||||
dependencies = [
|
||||
"digest",
|
||||
"hmac",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pem-rfc7468"
|
||||
version = "0.7.0"
|
||||
|
@ -3230,6 +3348,12 @@ version = "0.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "ppmd-rust"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c834641d8ad1b348c9ee86dec3b9840d805acd5f24daa5f90c788951a52ff59b"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.21"
|
||||
|
@ -4052,6 +4176,12 @@ dependencies = [
|
|||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simd-adler32"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
|
||||
|
||||
[[package]]
|
||||
name = "similar"
|
||||
version = "2.7.0"
|
||||
|
@ -5699,6 +5829,20 @@ name = "zeroize"
|
|||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
|
||||
dependencies = [
|
||||
"zeroize_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize_derive"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerotrie"
|
||||
|
@ -5733,6 +5877,51 @@ dependencies = [
|
|||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zip"
|
||||
version = "4.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9aed4ac33e8eb078c89e6cbb1d5c4c7703ec6d299fc3e7c3695af8f8b423468b"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"arbitrary",
|
||||
"bzip2",
|
||||
"constant_time_eq",
|
||||
"crc32fast",
|
||||
"deflate64",
|
||||
"flate2",
|
||||
"getrandom 0.3.3",
|
||||
"hmac",
|
||||
"indexmap",
|
||||
"liblzma",
|
||||
"memchr",
|
||||
"pbkdf2",
|
||||
"ppmd-rust",
|
||||
"sha1",
|
||||
"time",
|
||||
"zeroize",
|
||||
"zopfli",
|
||||
"zstd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zlib-rs"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "626bd9fa9734751fc50d6060752170984d7053f5a39061f524cda68023d4db8a"
|
||||
|
||||
[[package]]
|
||||
name = "zopfli"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edfc5ee405f504cd4984ecc6f14d02d55cfda60fa4b689434ef4102aae150cd7"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"crc32fast",
|
||||
"log",
|
||||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd"
|
||||
version = "0.13.3"
|
||||
|
|
|
@ -42,4 +42,5 @@ tracing = "0.1"
|
|||
tracing-subscriber = { version = "0.3", features = ["fmt"] }
|
||||
scraper = "0.18"
|
||||
urlencoding = "2.1"
|
||||
regex = "1.10"
|
||||
regex = "1.10"
|
||||
zip = "4.3.0"
|
|
@ -13,7 +13,7 @@ use services::script::*;
|
|||
use services::state::*;
|
||||
use sqlx::PgPool;
|
||||
|
||||
use crate::services::web_automation::BrowserPool;
|
||||
use crate::services::web_automation::{initialize_browser_pool, BrowserPool};
|
||||
//use services:: find::*;
|
||||
mod services;
|
||||
|
||||
|
@ -38,6 +38,10 @@ async fn main() -> std::io::Result<()> {
|
|||
5,
|
||||
"/usr/bin/brave-browser-beta".to_string(),
|
||||
));
|
||||
initialize_browser_pool()
|
||||
.await
|
||||
.expect("Failed to initialize browser pool");
|
||||
|
||||
let app_state = web::Data::new(AppState {
|
||||
db: db.into(),
|
||||
db_custom: db_custom.into(),
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
let items = FIND "gb.rob", "ACTION=EMUL"
|
||||
let items = FIND "gb.rob", "ACTION=EMUL1"
|
||||
FOR EACH item IN items
|
||||
|
||||
PRINT item.company
|
||||
let website = GET WEBSITE item.company "website"
|
||||
PRINT website
|
||||
|
||||
WAIT 10
|
||||
let page = GET website
|
||||
|
||||
let prompt = "Create a website for " + item.company + " with the following details: " + page
|
||||
|
||||
let alias = REWRITE "Return a single word for {item.company} like a token, no spaces, no special characters, no numbers, no uppercase letters."
|
||||
let alias = LLM "Return a single word for {item.company} like a token, no spaces, no special characters, no numbers, no uppercase letters."
|
||||
|
||||
CREATE SITE item.company + "bot", website, "site", prompt
|
||||
|
||||
|
@ -18,4 +20,4 @@ FOR EACH item IN items
|
|||
|
||||
CREATE DRAFT to, subject, body
|
||||
|
||||
NEXT item
|
||||
NEXT item
|
||||
|
|
|
@ -42,7 +42,7 @@ echo "nameserver $PARAM_DNS_INTERNAL_IP" > /etc/resolv.conf
|
|||
|
||||
apt install resolvconf -y
|
||||
apt-get update && apt-get install -y wget libcap2-bin
|
||||
wget -O /tmp/stalwart.tar.gz https://github.com/stalwartlabs/stalwart/releases/download/v0.12.4/stalwart-x86_64-unknown-linux-gnu.tar.gz
|
||||
wget -O /tmp/stalwart.tar.gz https://github.com/stalwartlabs/stalwart/releases/download/v0.13.1/stalwart-x86_64-unknown-linux-gnu.tar.gz
|
||||
|
||||
tar -xzf /tmp/stalwart.tar.gz -C /tmp
|
||||
mkdir -p /opt/gbo/bin
|
||||
|
|
27
src/scripts/utils/add-drive-user.sh
Normal file
27
src/scripts/utils/add-drive-user.sh
Normal file
|
@ -0,0 +1,27 @@
|
|||
export BOT_ID=
|
||||
./mc alias set minio http://localhost:9000 user pass
|
||||
./mc admin user add minio $BOT_ID
|
||||
|
||||
cat > $BOT_ID-policy.json <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"s3:ListBucket",
|
||||
"s3:GetObject",
|
||||
"s3:PutObject",
|
||||
"s3:DeleteObject"
|
||||
],
|
||||
"Resource": [
|
||||
"arn:aws:s3:::pragmatismo-$BOT_ID.gbai",
|
||||
"arn:aws:s3:::pragmatismo-$BOT_ID.gbai/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
|
||||
./mc admin policy create minio $BOT_ID-policy $BOT_ID-policy.json
|
||||
./mc admin policy attach minio $BOT_ID-policy --user $BOT_ID
|
|
@ -4,13 +4,13 @@
|
|||
declare -A container_limits=(
|
||||
# Pattern Memory CPU Allowance
|
||||
["*tables*"]="2048MB:50ms/100ms"
|
||||
["*dns*"]="512MB:50ms/100ms"
|
||||
["*dns*"]="2048MB:100ms/100ms"
|
||||
["*doc-editor*"]="512MB:50ms/100ms"
|
||||
["*proxy*"]="512MB:50ms/100ms"
|
||||
["*directory*"]="512MB:50ms/100ms"
|
||||
["*drive*"]="1024MB:50ms/100ms"
|
||||
["*email*"]="2048MB:90ms/100ms"
|
||||
["*webmail*"]="2048MB:90ms/100ms"
|
||||
["*email*"]="2048MB:50ms/100ms"
|
||||
["*webmail*"]="2048MB:50ms/100ms"
|
||||
["*bot*"]="2048MB:50ms/100ms"
|
||||
["*meeting*"]="1024MB:50ms/100ms"
|
||||
["*alm*"]="512MB:50ms/100ms"
|
||||
|
|
|
@ -35,7 +35,7 @@ async fn execute_create_draft(
|
|||
subject: &str,
|
||||
reply_text: &str,
|
||||
) -> Result<String, String> {
|
||||
let get_result = fetch_latest_email_from_sender(&state.config.clone().unwrap().email, to.clone()).await;
|
||||
let get_result = fetch_latest_email_from_sender(&state.config.clone().unwrap().email, to).await;
|
||||
let email_body = if let Ok(get_result_str) = get_result {
|
||||
if !get_result_str.is_empty() {
|
||||
get_result_str + reply_text
|
||||
|
|
27
src/services/keywords/llm_keyword.rs
Normal file
27
src/services/keywords/llm_keyword.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
use rhai::{Dynamic, Engine};
|
||||
use crate::services::{state::AppState, utils::call_llm};
|
||||
|
||||
pub fn llm_keyword(state: &AppState, engine: &mut Engine) {
|
||||
|
||||
let ai_config = state.config.clone().unwrap().ai.clone();
|
||||
|
||||
engine.register_custom_syntax(
|
||||
&["LLM", "$string$"], // Syntax: LLM "text to process"
|
||||
false, // Expression, not statement
|
||||
move |context, inputs| {
|
||||
let text = context.eval_expression_tree(&inputs[0])?;
|
||||
let text_str = text.to_string();
|
||||
|
||||
println!("LLM processing text: {}", text_str);
|
||||
|
||||
// Use the same pattern as GET
|
||||
|
||||
let fut = call_llm(&text_str, &ai_config);
|
||||
let result = tokio::task::block_in_place(|| {
|
||||
tokio::runtime::Handle::current().block_on(fut)
|
||||
}).map_err(|e| format!("LLM call failed: {}", e))?;
|
||||
|
||||
Ok(Dynamic::from(result))
|
||||
}
|
||||
).unwrap();
|
||||
}
|
|
@ -4,6 +4,7 @@ pub mod find;
|
|||
pub mod for_next;
|
||||
pub mod get;
|
||||
pub mod get_website;
|
||||
pub mod llm_keyword;
|
||||
pub mod print;
|
||||
pub mod set;
|
||||
pub mod wait;
|
|
@ -8,7 +8,7 @@ use langchain_rust::{
|
|||
chain::{Chain, LLMChainBuilder},
|
||||
fmt_message, fmt_template,
|
||||
language_models::llm::LLM,
|
||||
llm::{openai::OpenAI, AzureConfig},
|
||||
llm::{openai::OpenAI},
|
||||
message_formatter,
|
||||
prompt::HumanMessagePromptTemplate,
|
||||
prompt_args,
|
||||
|
@ -16,15 +16,7 @@ use langchain_rust::{
|
|||
template_fstring,
|
||||
};
|
||||
|
||||
use crate::services::{config::AIConfig, state::AppState};
|
||||
|
||||
pub fn from_config(config: &AIConfig) -> AzureConfig {
|
||||
AzureConfig::default()
|
||||
.with_api_key(&config.key)
|
||||
.with_api_base(&config.endpoint)
|
||||
.with_api_version(&config.version)
|
||||
.with_deployment_id(&config.instance)
|
||||
}
|
||||
use crate::services::{ state::AppState, utils::azure_from_config};
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
struct ChatRequest {
|
||||
|
@ -50,7 +42,7 @@ pub async fn chat(
|
|||
web::Json(request): web::Json<String>,
|
||||
state: web::Data<AppState>,
|
||||
) -> Result<impl Responder, actix_web::Error> {
|
||||
let azure_config = from_config(&state.config.clone().unwrap().ai);
|
||||
let azure_config = azure_from_config(&state.config.clone().unwrap().ai);
|
||||
let open_ai = OpenAI::new(azure_config);
|
||||
|
||||
// Parse the context JSON
|
||||
|
@ -107,7 +99,7 @@ pub async fn chat_stream(
|
|||
web::Json(request): web::Json<ChatRequest>,
|
||||
state: web::Data<AppState>,
|
||||
) -> Result<impl Responder, actix_web::Error> {
|
||||
let azure_config = from_config(&state.config.clone().unwrap().ai);
|
||||
let azure_config = azure_from_config(&state.config.clone().unwrap().ai);
|
||||
let open_ai = OpenAI::new(azure_config);
|
||||
|
||||
let prompt = message_formatter![
|
||||
|
|
|
@ -5,6 +5,7 @@ use crate::services::keywords::find::{find_keyword};
|
|||
use crate::services::keywords::for_next::for_keyword;
|
||||
use crate::services::keywords::get::get_keyword;
|
||||
use crate::services::keywords::get_website::get_website_keyword;
|
||||
use crate::services::keywords::llm_keyword::llm_keyword;
|
||||
use crate::services::keywords::print::print_keyword;
|
||||
use crate::services::keywords::set::set_keyword;
|
||||
use crate::services::keywords::wait::wait_keyword;
|
||||
|
@ -26,6 +27,7 @@ impl ScriptService {
|
|||
create_site_keyword(state, &mut engine);
|
||||
find_keyword(state, &mut engine);
|
||||
for_keyword(state, &mut engine);
|
||||
llm_keyword(state, &mut engine);
|
||||
get_keyword(state, &mut engine);
|
||||
get_website_keyword(state, &mut engine);
|
||||
set_keyword(state, &mut engine);
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use crate::services::config::AIConfig;
|
||||
use langchain_rust::llm::OpenAI;
|
||||
use langchain_rust::{language_models::llm::LLM, llm::AzureConfig};
|
||||
use log::{debug, warn};
|
||||
use rhai::{Array, Dynamic};
|
||||
use serde_json::{json, Value};
|
||||
|
@ -5,9 +8,76 @@ use smartstring::SmartString;
|
|||
use sqlx::Column; // Required for .name() method
|
||||
use sqlx::TypeInfo; // Required for .type_info() method
|
||||
use sqlx::{postgres::PgRow, Row};
|
||||
use std::error::Error;
|
||||
use sqlx::{Decode, Type};
|
||||
use std::error::Error;
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
use std::path::Path;
|
||||
use tokio_stream::StreamExt;
|
||||
use zip::ZipArchive;
|
||||
use tokio::fs::File as TokioFile;
|
||||
|
||||
use reqwest::Client;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
|
||||
pub fn azure_from_config(config: &AIConfig) -> AzureConfig {
|
||||
AzureConfig::default()
|
||||
.with_api_key(&config.key)
|
||||
.with_api_base(&config.endpoint)
|
||||
.with_api_version(&config.version)
|
||||
.with_deployment_id(&config.instance)
|
||||
}
|
||||
|
||||
pub async fn call_llm(
|
||||
text: &str,
|
||||
ai_config: &AIConfig,
|
||||
) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
|
||||
let azure_config = azure_from_config(&ai_config.clone());
|
||||
let open_ai = OpenAI::new(azure_config);
|
||||
|
||||
// Directly use the input text as prompt
|
||||
let prompt = text.to_string();
|
||||
|
||||
// Call LLM and return the raw text response
|
||||
match open_ai.invoke(&prompt).await {
|
||||
Ok(response_text) => Ok(response_text),
|
||||
Err(err) => {
|
||||
eprintln!("Error invoking LLM API: {}", err);
|
||||
Err(Box::new(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"Failed to invoke LLM API",
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extract_zip_recursive(
|
||||
zip_path: &Path,
|
||||
destination_path: &Path,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let file = File::open(zip_path)?;
|
||||
let buf_reader = BufReader::new(file);
|
||||
let mut archive = ZipArchive::new(buf_reader)?;
|
||||
|
||||
for i in 0..archive.len() {
|
||||
let mut file = archive.by_index(i)?;
|
||||
let outpath = destination_path.join(file.mangled_name());
|
||||
|
||||
if file.is_dir() {
|
||||
std::fs::create_dir_all(&outpath)?;
|
||||
} else {
|
||||
if let Some(parent) = outpath.parent() {
|
||||
if !parent.exists() {
|
||||
std::fs::create_dir_all(&parent)?;
|
||||
}
|
||||
}
|
||||
let mut outfile = File::create(&outpath)?;
|
||||
std::io::copy(&mut file, &mut outfile)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
pub fn row_to_json(row: PgRow) -> Result<Value, Box<dyn Error>> {
|
||||
let mut result = serde_json::Map::new();
|
||||
let columns = row.columns();
|
||||
|
@ -22,7 +92,9 @@ pub fn row_to_json(row: PgRow) -> Result<Value, Box<dyn Error>> {
|
|||
"INT8" | "int8" => handle_nullable_type::<i64>(&row, i, column_name),
|
||||
"FLOAT4" | "float4" => handle_nullable_type::<f32>(&row, i, column_name),
|
||||
"FLOAT8" | "float8" => handle_nullable_type::<f64>(&row, i, column_name),
|
||||
"TEXT" | "VARCHAR" | "text" | "varchar" => handle_nullable_type::<String>(&row, i, column_name),
|
||||
"TEXT" | "VARCHAR" | "text" | "varchar" => {
|
||||
handle_nullable_type::<String>(&row, i, column_name)
|
||||
}
|
||||
"BOOL" | "bool" => handle_nullable_type::<bool>(&row, i, column_name),
|
||||
"JSON" | "JSONB" | "json" | "jsonb" => handle_json(&row, i, column_name),
|
||||
_ => {
|
||||
|
@ -57,7 +129,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
fn handle_json(row: &PgRow, idx: usize, col_name: &str) -> Value {
|
||||
// First try to get as Option<Value>
|
||||
match row.try_get::<Option<Value>, _>(idx) {
|
||||
|
@ -125,3 +196,23 @@ pub fn to_array(value: Dynamic) -> Array {
|
|||
Array::from([value])
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn download_file(url: &str, output_path: &str) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let client = Client::new();
|
||||
let response = client.get(url).send().await?;
|
||||
|
||||
if response.status().is_success() {
|
||||
let mut file = TokioFile::create(output_path).await?;
|
||||
|
||||
let mut stream = response.bytes_stream();
|
||||
|
||||
while let Some(chunk) = stream.next().await {
|
||||
file.write_all(&chunk?).await?;
|
||||
}
|
||||
debug!("File downloaded successfully to {}", output_path);
|
||||
} else {
|
||||
return Err("Failed to download file".into());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
use crate::services::utils;
|
||||
use log::debug;
|
||||
use std::env;
|
||||
use std::env::temp_dir;
|
||||
use std::error::Error;
|
||||
use std::future::Future;
|
||||
use std::path::Path;
|
||||
use std::pin::Pin;
|
||||
use std::process::Command;
|
||||
use std::sync::Arc;
|
||||
|
@ -47,11 +50,10 @@ impl BrowserPool {
|
|||
caps.add_chrome_arg("--no-sandbox")?;
|
||||
|
||||
let driver = WebDriver::new(&self.webdriver_url, caps).await?;
|
||||
|
||||
|
||||
// Execute user function
|
||||
let result = f(driver).await;
|
||||
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
|
@ -91,11 +93,8 @@ impl BrowserSetup {
|
|||
}
|
||||
|
||||
async fn setup_chromedriver() -> Result<String, Box<dyn std::error::Error>> {
|
||||
let chromedriver_path = String::from(if cfg!(target_os = "windows") {
|
||||
"chromedriver.exe"
|
||||
} else {
|
||||
"chromedriver"
|
||||
});
|
||||
let mut chromedriver_path = env::current_exe()?.parent().unwrap().to_path_buf();
|
||||
chromedriver_path.push("chromedriver");
|
||||
|
||||
// Check if chromedriver exists
|
||||
if fs::metadata(&chromedriver_path).await.is_err() {
|
||||
|
@ -119,14 +118,26 @@ impl BrowserSetup {
|
|||
_ => return Err("Unsupported platform".into()),
|
||||
};
|
||||
|
||||
let _download_url = format!("{}/chromedriver_{}.zip", base_url, platform);
|
||||
|
||||
let zip_path = Path::new("chromedriver.zip");
|
||||
let download_url = format!("{}/chromedriver_{}.zip", base_url, platform);
|
||||
|
||||
let mut zip_path = temp_dir();
|
||||
zip_path.push("chromedriver.zip");
|
||||
|
||||
utils::download_file(&download_url, &zip_path.to_str().unwrap()).await?;
|
||||
|
||||
let extract_result = utils::extract_zip_recursive(&zip_path, &chromedriver_path);
|
||||
if let Err(e) = extract_result {
|
||||
debug!("Error extracting ZIP: {}", e);
|
||||
}
|
||||
// Clean up zip file
|
||||
let _ = fs::remove_file(&zip_path).await;
|
||||
|
||||
if cfg!(target_os = "windows") {
|
||||
chromedriver_path.push("chromedriver.exe");
|
||||
} else {
|
||||
chromedriver_path.push("chromedriver");
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
|
@ -136,7 +147,7 @@ impl BrowserSetup {
|
|||
}
|
||||
}
|
||||
|
||||
Ok(chromedriver_path)
|
||||
Ok(chromedriver_path.to_string_lossy().to_string())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,7 +176,6 @@ async fn is_process_running(name: &str) -> bool {
|
|||
if cfg!(target_os = "windows") {
|
||||
Command::new("tasklist")
|
||||
.output()
|
||||
|
||||
.map(|o| String::from_utf8_lossy(&o.stdout).contains(name))
|
||||
.unwrap_or(false)
|
||||
} else {
|
||||
|
|
Loading…
Add table
Reference in a new issue