Skip to content

Commit

Permalink
Upgrade Settings Menu & Introduce Build History
Browse files Browse the repository at this point in the history
  • Loading branch information
lucemans committed Dec 17, 2024
1 parent d90c1a9 commit fd61edb
Show file tree
Hide file tree
Showing 21 changed files with 703 additions and 213 deletions.
13 changes: 7 additions & 6 deletions engine/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion engine/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "v3x-property-engine"
version = "0.0.1"
version = "0.0.3"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down Expand Up @@ -80,6 +80,7 @@ rand = "0.8.5"
async-stream = "0.3.6"
futures-core = "0.3.31"
async-trait = "0.1.83"
semver = { version = "1.0.24", features = ["serde"] }

[dependencies.uuid]
version = "1.10.0"
Expand Down
1 change: 1 addition & 0 deletions engine/src/models/settings/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use sqlx::{
use crate::{database::Database, state::AppState};

mod modules;
pub mod version;
pub mod statistics;

build_info::build_info!(fn build_info);
Expand Down
20 changes: 20 additions & 0 deletions engine/src/models/settings/statistics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,23 @@ impl InstanceStatistics {
}
}
}

#[derive(Serialize, Deserialize, Object)]
pub struct StorageStatistics {
pub bucket_file_count: u64,
pub bucket_disk_size: u64,
}

impl StorageStatistics {
pub async fn load(state: &Arc<AppState>) -> Self {
// query s3 to get total bucket size in bytes and store in bucket_disk_size
// also list total files in bucket and store in bucket_file_count
// state.storage.stat
let storage = state.storage.stat_bucket().await.unwrap();

StorageStatistics {
bucket_file_count: storage.0,
bucket_disk_size: storage.1,
}
}
}
136 changes: 136 additions & 0 deletions engine/src/models/settings/version.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
use std::{ops::Deref, sync::Arc};

use ollama_rs::IntoUrlSealed;
use poem_openapi::Object;
use semver::Version;
use serde::{Deserialize, Serialize};

use crate::{routes::error::HttpError, state::AppState};

use super::{build_info, BuildDetails};

#[derive(Serialize, Deserialize, Object)]
pub struct VersionSettings {
pub version: String,
pub latest: String,
pub update_available: bool,
}

impl VersionSettings {
pub async fn load() -> Result<Self, HttpError> {
let build_info: BuildDetails = build_info().into();
let version = Version::parse(&build_info.version).unwrap();
let latest = get_github_latest().await?;

Ok(Self {
version: version.to_string(),
latest: latest.to_string(),
update_available: latest > version,
})
}
}

#[derive(Deserialize)]
struct Token {
token: String,
}

#[derive(Deserialize)]
struct Manifest {
pub tags: Vec<String>,
}

async fn get_github_latest() -> Result<Version, anyhow::Error> {
let client = reqwest::Client::new();

let token_response = client
.get(
"https://ghcr.io/token?scope=repository:v3xlabs/v3x-property/engine:pull&service=ghcr.io",
)
.send()
.await?;
let token = token_response.text().await?;
let token = serde_json::from_str::<Token>(&token)?;
let token = token.token;

let page_size = 50;
let mut next_page = "?n=50".to_string();

let mut all_semvers = Vec::new();

loop {
let manifest_response = client
.get(format!(
"https://ghcr.io/v2/v3xlabs/v3x-property/engine/tags/list{}",
next_page
))
.header("Authorization", format!("Bearer {}", token))
.header("Accept", "application/vnd.oci.image.index.v1+json")
.send()
.await?;
let link_header = manifest_response
.headers()
.get("link")
.map(|x| x.to_str().unwrap().to_string());

// match /tags/list?(.*)>; rel
// using regex
let query_regex = regex::Regex::new(r"/tags/list(.*)>; rel=").unwrap();
let link_header_str = link_header.unwrap_or("".to_string());
let captures = query_regex.captures(&link_header_str);
let query = captures.map(|x| x.get(1).unwrap().as_str());
next_page = query.unwrap_or("").to_owned();

let manifest_str = manifest_response.text().await?;
let manifest = serde_json::from_str::<Manifest>(&manifest_str)?;

let semvers = manifest
.tags
.iter()
.filter_map(|tag| Version::parse(tag.trim_start_matches("v")).ok())
.collect::<Vec<Version>>();

all_semvers.extend(semvers);

if manifest.tags.len() < page_size {
break;
}

if query.is_none() {
break;
}
}

all_semvers.sort();

let last = all_semvers.last().unwrap().clone();

Ok(last)
}

#[cfg(test)]
mod tests {
use super::*;

#[async_std::test]
async fn test_get_github_latest() {
let latest = get_github_latest().await.unwrap();
println!("latest: {:?}", latest);
}

#[async_std::test]
async fn test_semver() {
let tags = vec!["v0.0.1", "v0.0.2", "v0.0.3", "v0.0.4", "v0.0.5"];

let mut versions = Vec::new();
for tag in tags {
let version = Version::parse(tag.strip_prefix("v").unwrap()).unwrap();
versions.push(version);
}

versions.sort();

let latest = versions.last().unwrap();
println!("latest: {}", latest);
}
}
26 changes: 13 additions & 13 deletions engine/src/modules/intelligence/gemini/structured.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,19 +254,19 @@ pub struct GeminiStructuredContentResponseCandidateContentPartFunctionCallArgs {

#[async_std::test]
async fn test_gemini_structured_content() {
let conversation = Conversation {
index: 0,
strategy: crate::modules::intelligence::structured::strategy::Strategy::Basic,
system_instruction: None,
messages: vec![ConversationMessage {
role: "user".to_string(),
parts: vec![ConversationMessagePart::Text("Hello there".to_string())],
}],
};
// let conversation = Conversation {
// index: 0,
// strategy: crate::modules::intelligence::structured::strategy::Strategy::Basic,
// system_instruction: None,
// messages: vec![ConversationMessage {
// role: "user".to_string(),
// parts: vec![ConversationMessagePart::Text("Hello there".to_string())],
// }],
// };

let body = GeminiStructuredContentRequest::from_conversation(&conversation, &[]);
// let body = GeminiStructuredContentRequest::from_conversation(&conversation, &StrategyConfig::default());

// output the serde_json to string of conversation
let x = serde_json::to_string(&body).unwrap();
println!("{}", x);
// // output the serde_json to string of conversation
// let x = serde_json::to_string(&body).unwrap();
// println!("{}", x);
}
22 changes: 22 additions & 0 deletions engine/src/modules/storage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use s3::creds::Credentials;
use s3::Bucket;
use s3::Region;
use std::env;
use tracing::info;
use uuid::Uuid;

pub struct Storage {
Expand Down Expand Up @@ -76,4 +77,25 @@ impl Storage {

Ok(())
}

// Gets the total bucket size in bytes and the total number of files in the bucket
pub async fn stat_bucket(&self) -> Result<(u64, u64), anyhow::Error> {
let bucket_size = self.bucket.list("".to_string(), None).await?;

let mut total_files = 0;
let mut total_size = 0;

for object in bucket_size {
// let size = object.size;
// let file_count += 1;
for content in object.contents {
let size = content.size;

total_size += size;
}
total_files += 1;
}

Ok((total_files, total_size))
}
}
45 changes: 36 additions & 9 deletions engine/src/routes/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ use poem_openapi::{payload::Json, OpenApi};

use super::{error::HttpError, ApiTags};
use crate::{
auth::{
middleware::AuthUser,
permissions::Action,
auth::{middleware::AuthUser, permissions::Action},
models::settings::{
statistics::{InstanceStatistics, StorageStatistics},
version::VersionSettings,
InstanceSettings, InstanceSettingsConfigurable,
},
models::settings::{statistics::InstanceStatistics, InstanceSettings, InstanceSettingsConfigurable},
state::AppState,
};
pub struct InstanceApi;
Expand Down Expand Up @@ -44,17 +45,43 @@ impl InstanceApi {
user.check_policy("instance", "settings", Action::Write)
.await?;

InstanceSettings::update_instance_settings(&state.database, &settings)
.await;
InstanceSettings::update_instance_settings(&state.database, &settings).await;

Ok(())
}

/// /instance/statistics
///
///
/// Get the instance statistics
#[oai(path = "/instance/statistics", method = "get", tag = "ApiTags::Instance")]
pub async fn statistics(&self, state: Data<&Arc<AppState>>) -> Result<Json<InstanceStatistics>> {
#[oai(
path = "/instance/statistics",
method = "get",
tag = "ApiTags::Instance"
)]
pub async fn statistics(
&self,
state: Data<&Arc<AppState>>,
) -> Result<Json<InstanceStatistics>> {
Ok(Json(InstanceStatistics::load(&state).await))
}

/// /instance/storage
///
/// Get the instance storage statistics
#[oai(
path = "/instance/statistics/storage",
method = "get",
tag = "ApiTags::Instance"
)]
pub async fn storage(&self, state: Data<&Arc<AppState>>) -> Result<Json<StorageStatistics>> {
Ok(Json(StorageStatistics::load(&state).await))
}

/// /instance/version
///
/// Get the instance version & potentially available updates
#[oai(path = "/instance/version", method = "get", tag = "ApiTags::Instance")]
pub async fn version(&self) -> Result<Json<VersionSettings>> {
Ok(Json(VersionSettings::load().await?))
}
}
1 change: 1 addition & 0 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"javascript-time-ago": "^2.5.11",
"leaflet": "^1.9.4",
"postcss": "^8.4.38",
"pretty-bytes": "^6.1.1",
"react": "^18.3.1",
"react-barcode": "^1.5.3",
"react-dom": "^18.3.1",
Expand Down
Loading

0 comments on commit fd61edb

Please sign in to comment.