Merge branch 'development_heroprompt' of https://github.com/freeflowuniverse/herolib into development_heroprompt

This commit is contained in:
Mahmoud-Emad
2025-08-21 13:07:09 +03:00
38 changed files with 282 additions and 282 deletions

View File

@@ -19,7 +19,7 @@ println(actor_spec)
// )!
actor_module := generator.generate_actor_module(actor_spec,
interfaces: [ .http]
interfaces: [.http]
)!
actor_module.write(example_dir,

View File

@@ -12,7 +12,9 @@ println('Total countries loaded: ${all_countries.len}')
// --- Example: Print the first few countries ---
println('\n--- First 5 Countries ---')
for i, country in all_countries {
if i >= 5 { break }
if i >= 5 {
break
}
println(country.str())
}

View File

@@ -19,7 +19,9 @@ println('selected (initial): ${workspace.selected_children()}')
// Add a directory and a file
workspace.add_dir(path: '${os.home_dir()}/code/github/freeflowuniverse/herolib/docker')!
workspace.add_file(path: '${os.home_dir()}/code/github/freeflowuniverse/herolib/docker/docker_ubuntu_install.sh')!
workspace.add_file(
path: '${os.home_dir()}/code/github/freeflowuniverse/herolib/docker/docker_ubuntu_install.sh'
)!
println('selected (after add): ${workspace.selected_children()}')
// Build a prompt from current selection (should be empty now)
@@ -39,7 +41,9 @@ println('selected (after remove): ${workspace.selected_children()}')
// List workspaces (names only)
mut all := heroprompt.list_workspaces() or { []&heroprompt.Workspace{} }
mut names := []string{}
for w in all { names << w.name }
for w in all {
names << w.name
}
println('workspaces: ${names}')
// Optionally delete the example workspace

View File

@@ -8,7 +8,7 @@ println(installer)
installer.start()!
$dbg;
// $dbg;
mut r := mycelium.inspect()!
println(r)

View File

@@ -1,4 +1,5 @@
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
import freeflowuniverse.herolib.lib.lang.codewalker
import freeflowuniverse.herolib.core.pathlib
import freeflowuniverse.herolib.osal.core as osal

View File

@@ -1,10 +1,10 @@
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
import os
import freeflowuniverse.herolib.core.code { Alias, Struct }
import freeflowuniverse.herolib.core.code { Alias }
import freeflowuniverse.herolib.core.pathlib
import freeflowuniverse.herolib.schemas.openrpc
import freeflowuniverse.herolib.schemas.openrpc.codegen {generate_model}
import freeflowuniverse.herolib.schemas.openrpc.codegen { generate_model }
const doc_path = '${os.dir(@FILE)}/testdata/openrpc.json'
@@ -18,8 +18,7 @@ assert model[0] is Alias
pet_id := model[0] as Alias
assert pet_id.name == 'PetId'
println(pet_id)
$dbg;
// $dbg;
// assert pet_id.typ.symbol == 'int'

View File

@@ -5,10 +5,8 @@ import json
import net.http { Method }
// https://cassiomolin.com/2016/09/09/which-http-status-codes-are-cacheable/
const (
default_cacheable_codes = [200, 203, 204, 206, 300, 404, 405, 410, 414, 501]
unsafe_http_methods = [Method.put, .patch, .post, .delete]
)
const default_cacheable_codes = [200, 203, 204, 206, 300, 404, 405, 410, 414, 501]
const unsafe_http_methods = [Method.put, .patch, .post, .delete]
pub struct CacheConfig {
pub mut:

View File

@@ -1,10 +1,8 @@
module countries
// --- Embed the data file content at compile time ---
// The path is relative to the location of this `factory.v` file.
// get_all_countries parses the country data embedded in the executable.
// It returns a list of Country structs.
pub fn get_all_countries() ![]Country {
@@ -26,7 +24,8 @@ pub fn get_all_countries() ![]Country {
// --- Identify and skip the header ---
// Check if this line looks like the header (contains key identifiers)
if !found_header && trimmed_line.contains('ISO') && trimmed_line.contains('Country') && trimmed_line.contains('CurrencyCode') {
if !found_header && trimmed_line.contains('ISO') && trimmed_line.contains('Country')
&& trimmed_line.contains('CurrencyCode') {
found_header = true
continue // Skip the header line itself
}
@@ -37,7 +36,6 @@ pub fn get_all_countries() ![]Country {
// Use strings.split to split the line by tab character
fields := line.split_by_space()
// --- Create Country struct instance ---
// Map fields by index based on the header structure.
// Handle potential out-of-bounds or missing data gracefully using `or {}`.

View File

@@ -10,7 +10,7 @@ pub:
pub struct FMError {
pub:
message string
linenr int //is optional
linenr int // is optional
category string
filename string
}

View File

@@ -37,5 +37,5 @@ pub mut:
pub struct GitRepoConfig {
pub mut:
remote_check_period int = 3600*24*7 // seconds = 7d
remote_check_period int = 3600 * 24 * 7 // seconds = 7d
}

View File

@@ -19,9 +19,9 @@ fn startupcmd() ![]startupmanager.ZProcessNewArgs {
mut peers_str := installer.peers.join(' ')
mut tun_name := 'tun${installer.tun_nr}'
mut cmd:='mycelium --key-file ${osal.hero_path()!}/cfg/priv_key.bin --peers ${peers_str} --tun-name ${tun_name}'
mut cmd := 'mycelium --key-file ${osal.hero_path()!}/cfg/priv_key.bin --peers ${peers_str} --tun-name ${tun_name}'
if core.is_osx()! {
cmd = "sudo ${cmd}"
cmd = 'sudo ${cmd}'
}
res << startupmanager.ZProcessNewArgs{

View File

@@ -218,10 +218,7 @@ pub fn (mut self MyceliumInstaller) start() ! {
start_pre()!
for zprocess in startupcmd()! {
mut sm := startupmanager_get(zprocess.startuptype)!
console.print_debug('starting mycelium_installer with ${zprocess.startuptype}...')
@@ -229,7 +226,6 @@ pub fn (mut self MyceliumInstaller) start() ! {
sm.new(zprocess)!
sm.start(zprocess.name)!
}
start_post()!

View File

@@ -154,16 +154,16 @@ fn destroy() ! {
return error('failed to uninstall garage_s3: ${res.output}')
}
mut zinit_factory := zinit_lib.Zinit{}
// mut zinit_factory := zinit_lib.Zinit{}
if zinit_factory.exists('garage_s3') {
zinit_factory.stop('garage_s3')! or {
return error('Could not stop garage_s3 service due to: ${err}')
}
zinit_factory.delete('garage_s3')! or {
return error('Could not delete garage_s3 service due to: ${err}')
}
}
// if zinit_factory.exists('garage_s3'){
// zinit_factory.stop('garage_s3') or {
// return error('Could not stop garage_s3 service due to: ${err}')
// }
// zinit_factory.delete('garage_s3') or {
// return error('Could not delete garage_s3 service due to: ${err}')
// }
// }
console.print_header('garage_s3 is uninstalled')
}

View File

@@ -47,8 +47,8 @@ pub fn new(args_ PythonEnvArgs) !PythonEnv {
// Check if the Python environment exists and is properly configured
pub fn (py PythonEnv) exists() bool {
return os.exists('${py.path.path}/.venv/bin/activate') &&
os.exists('${py.path.path}/pyproject.toml')
return os.exists('${py.path.path}/.venv/bin/activate')
&& os.exists('${py.path.path}/pyproject.toml')
}
// Initialize the Python environment using uv
@@ -110,7 +110,7 @@ pub fn (py PythonEnv) add_dependencies(packages []string, dev bool) ! {
return
}
console.print_debug('Adding Python packages: ${packages.join(", ")}')
console.print_debug('Adding Python packages: ${packages.join(', ')}')
packages_str := packages.join(' ')
mut cmd := '
@@ -122,7 +122,7 @@ pub fn (py PythonEnv) add_dependencies(packages []string, dev bool) ! {
}
osal.exec(cmd: cmd)!
console.print_debug('Successfully added packages: ${packages.join(", ")}')
console.print_debug('Successfully added packages: ${packages.join(', ')}')
}
// Remove dependencies from the project
@@ -131,7 +131,7 @@ pub fn (py PythonEnv) remove_dependencies(packages []string, dev bool) ! {
return
}
console.print_debug('Removing Python packages: ${packages.join(", ")}')
console.print_debug('Removing Python packages: ${packages.join(', ')}')
packages_str := packages.join(' ')
mut cmd := '
@@ -143,7 +143,7 @@ pub fn (py PythonEnv) remove_dependencies(packages []string, dev bool) ! {
}
osal.exec(cmd: cmd)!
console.print_debug('Successfully removed packages: ${packages.join(", ")}')
console.print_debug('Successfully removed packages: ${packages.join(', ')}')
}
// Legacy pip method for backward compatibility - now uses uv add

View File

@@ -123,10 +123,18 @@ source env.sh
## Dependencies
### Production
${if args.dependencies.len > 0 { '- ' + args.dependencies.join('\n- ') } else { 'None' }}
${if args.dependencies.len > 0 {
'- ' + args.dependencies.join('\n- ')
} else {
'None'
}}
### Development
${if args.dev_dependencies.len > 0 { '- ' + args.dev_dependencies.join('\n- ') } else { 'None' }}
${if args.dev_dependencies.len > 0 {
'- ' + args.dev_dependencies.join('\n- ')
} else {
'None'
}}
'
mut readme_file := py.path.file_get_new('README.md')!

View File

@@ -80,7 +80,7 @@ pub fn (mut sm StartupManager) new(args ZProcessNewArgs) ! {
test: args.cmd_test // Direct mapping
oneshot: args.oneshot // Use the oneshot flag directly
after: args.after // Direct mapping
log: "ring"
log: 'ring'
env: args.env // Direct mapping
dir: args.workdir // Direct mapping
shutdown_timeout: 0 // Default, or add to ZProcessNewArgs if needed

View File

@@ -2,7 +2,6 @@ module datamodel
import time
// NodeTotalSim represents the aggregated data for a node simulation, including hardware specs, pricing, and location.
pub struct NodeTotalSim {
pub mut:

View File

@@ -11,10 +11,9 @@ pub mut:
devices DeviceInfo
country string // 2 letter code as specified in lib/data/countries/data/countryInfo.txt, use that library for validation
capacity NodeCapacity // Hardware capacity details
provisiontime u32 //lets keep it simple and compatible
provisiontime u32 // lets keep it simple and compatible
}
pub struct DeviceInfo {
pub mut:
vendor string
@@ -24,23 +23,24 @@ pub mut:
gpu []GPUDevice
network []NetworkDevice
}
pub struct StorageDevice {
pub mut:
id string //can be used in node
id string // can be used in node
size_gb f64 // Size of the storage device in gigabytes
description string // Description of the storage device
}
pub struct MemoryDevice {
pub mut:
id string //can be used in node
id string // can be used in node
size_gb f64 // Size of the memory device in gigabytes
description string // Description of the memory device
}
pub struct CPUDevice {
pub mut:
id string //can be used in node
id string // can be used in node
cores int // Number of CPU cores
passmark int
description string // Description of the CPU
@@ -50,18 +50,17 @@ pub mut:
pub struct GPUDevice {
pub mut:
id string //can be used in node
id string // can be used in node
cores int // Number of GPU cores
memory_gb f64 // Size of the GPU memory in gigabytes
description string // Description of the GPU
gpu_brand string
gpu_version string
}
pub struct NetworkDevice {
pub mut:
id string //can be used in node
id string // can be used in node
speed_mbps int // Network speed in Mbps
description string // Description of the network device
}
@@ -84,5 +83,5 @@ pub mut:
}
fn (mut n Node) check() ! {
//todo
// todo
}

View File

@@ -1,31 +1,30 @@
module datamodel
// is a root object, is the only obj farmer needs to configure in the UI, this defines how slices will be created
@[heap]
//is a root object, is the only obj farmer needs to configure in the UI, this defines how slices will be created
pub struct NodeGroup {
pub mut:
id u32
farmerid u32 //link back to farmer who owns the nodegroup, is a user?
secret string //only visible by farmer, in future encrypted, used to boot a node
farmerid u32 // link back to farmer who owns the nodegroup, is a user?
secret string // only visible by farmer, in future encrypted, used to boot a node
description string
slapolicy SLAPolicy
pricingpolicy PricingPolicy
compute_slice_normalized_pricing_cc f64 //pricing in CC - cloud credit, per 2GB node slice
storage_slice_normalized_pricing_cc f64 //pricing in CC - cloud credit, per 1GB storage slice
reputation int = 50 //between 0 and 100, earned over time
uptime int //between 0 and 100, set by system, farmer has no ability to set this
compute_slice_normalized_pricing_cc f64 // pricing in CC - cloud credit, per 2GB node slice
storage_slice_normalized_pricing_cc f64 // pricing in CC - cloud credit, per 1GB storage slice
reputation int = 50 // between 0 and 100, earned over time
uptime int // between 0 and 100, set by system, farmer has no ability to set this
}
pub struct SLAPolicy {
pub mut:
sla_uptime int //should +90
sla_bandwidth_mbit int //minimal mbits we can expect avg over 1h per node, 0 means we don't guarantee
sla_penalty int //0-100, percent of money given back in relation to month if sla breached, e.g. 200 means we return 2 months worth of rev if sla missed
sla_uptime int // should +90
sla_bandwidth_mbit int // minimal mbits we can expect avg over 1h per node, 0 means we don't guarantee
sla_penalty int // 0-100, percent of money given back in relation to month if sla breached, e.g. 200 means we return 2 months worth of rev if sla missed
}
pub struct PricingPolicy {
pub mut:
marketplace_year_discounts []int = [30,40,50] //e.g. 30,40,50 means if user has more CC in wallet than 1 year utilization on all his purchaes then this provider gives 30%, 2Y 40%, ...
volume_discounts []int = [10,20,30] //e.g. 10,20,30
marketplace_year_discounts []int = [30, 40, 50] // e.g. 30,40,50 means if user has more CC in wallet than 1 year utilization on all his purchaes then this provider gives 30%, 2Y 40%, ...
volume_discounts []int = [10, 20, 30] // e.g. 10,20,30
}

View File

@@ -3,5 +3,5 @@ module datamodel
pub struct NodeSim {
Node
pub mut:
cost f64 //free
cost f64 // free
}

View File

@@ -1,10 +1,10 @@
module datamodel
//typically 1GB of memory, but can be adjusted based based on size of machine
// typically 1GB of memory, but can be adjusted based based on size of machine
pub struct ComputeSlice {
pub mut:
nodeid u32 //the node in the grid, there is an object describing the node
id int //the id of the slice in the node
nodeid u32 // the node in the grid, there is an object describing the node
id int // the id of the slice in the node
mem_gb f64
storage_gb f64
passmark int
@@ -12,21 +12,18 @@ pub mut:
cpu_oversubscription int
storage_oversubscription int
price_range []f64 = [0.0, 0.0]
gpus u8 //nr of GPU's see node to know what GPU's are
price_cc f64 //price per slice (even if the grouped one)
gpus u8 // nr of GPU's see node to know what GPU's are
price_cc f64 // price per slice (even if the grouped one)
pricing_policy PricingPolicy
sla_policy SLAPolicy
}
//1GB of storage
// 1GB of storage
pub struct StorageSlice {
pub mut:
nodeid u32 //the node in the grid
id int //the id of the slice in the node, are tracked in the node itself
price_cc f64 //price per slice (even if the grouped one)
nodeid u32 // the node in the grid
id int // the id of the slice in the node, are tracked in the node itself
price_cc f64 // price per slice (even if the grouped one)
pricing_policy PricingPolicy
sla_policy SLAPolicy
}

View File

@@ -2,7 +2,6 @@ module datamodelsimulator
import time
// NodeTotalSim represents the aggregated data for a node simulation, including hardware specs, pricing, and location.
pub struct NodeTotalSim {
pub mut:

View File

@@ -8,7 +8,7 @@ pub fn play(mut plbook PlayBook) !map[string]&Node {
mut nodesdict := map[string]&Node{}
for action in actions2 {
echo("TODO: Implement action handling for ${action.name}")
echo('TODO: Implement action handling for ${action.name}')
}
return nodesdict
}

View File

@@ -62,10 +62,10 @@ fn render_index(app &App) string {
}
fn render_index_fallback(app &App) string {
return '<!doctype html>\n<html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>'
+ html_escape(app.title)
+ '</title><link rel="stylesheet" href="/static/css/main.css"></head><body><div class="container"><h1>'
+ html_escape(app.title)
+ '</h1><p>Heroprompt server is running.</p></div><script src="/static/js/main.js"></script></body></html>'
return
'<!doctype html>\n<html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>' +
html_escape(app.title) +
'</title><link rel="stylesheet" href="/static/css/main.css"></head><body><div class="container"><h1>' +
html_escape(app.title) +
'</h1><p>Heroprompt server is running.</p></div><script src="/static/js/main.js"></script></body></html>'
}

View File

@@ -3,7 +3,6 @@ module ui
import veb
import os
// Public Context type for veb
pub struct Context {
veb.Context
@@ -33,17 +32,16 @@ pub mut:
pub struct App {
veb.StaticHandler
pub mut:
title string = "default"
title string = 'default'
menu []MenuItem
port int = 7711
}
// Start the webserver (blocking)
pub fn start(args WebArgs) !{
pub fn start(args WebArgs) ! {
mut app := App{
title: args.title,
menu: args.menu,
title: args.title
menu: args.menu
port: args.port
}
veb.run[App, Context](mut app, app.port)

View File

@@ -8,7 +8,11 @@ fn menu_html(items []MenuItem, depth int, prefix string) string {
if it.children.len > 0 {
// expandable group
out << '<div class="item">'
out << '<a class="list-group-item list-group-item-action d-flex justify-content-between align-items-center" data-bs-toggle="collapse" href="#${id}" role="button" aria-expanded="${if depth == 0 { 'true' } else { 'false' }}" aria-controls="${id}">'
out << '<a class="list-group-item list-group-item-action d-flex justify-content-between align-items-center" data-bs-toggle="collapse" href="#${id}" role="button" aria-expanded="${if depth == 0 {
'true'
} else {
'false'
}}" aria-controls="${id}">'
out << '<span>${it.title}</span><span class="chev">&rsaquo;</span>'
out << '</a>'
out << '<div class="collapse ${if depth == 0 { 'show' } else { '' }}" id="${id}">'
@@ -24,4 +28,3 @@ fn menu_html(items []MenuItem, depth int, prefix string) string {
}
return out.join('\n')
}

View File

@@ -137,21 +137,21 @@ fn destroy() ! {
'
osal.execute_silent(cmd) or {}
mut zinit_factory := zinit_lib.Zinit{}
// mut zinit_factory := zinit_lib.Zinit{}
if zinit_factory.exists('dagu') {
zinit_factory.stop('dagu')! or { return error('Could not stop dagu service due to: ${err}') }
zinit_factory.delete('dagu')! or {
return error('Could not delete dagu service due to: ${err}')
}
}
// if zinit_factory.exists('dagu') {
// zinit_factory.stop('dagu')! or { return error('Could not stop dagu service due to: ${err}') }
// zinit_factory.delete('dagu')! or {
// return error('Could not delete dagu service due to: ${err}')
// }
// }
if zinit_factory.exists('dagu_scheduler') {
zinit_factory.stop('dagu_scheduler')! or {
return error('Could not stop dagu_scheduler service due to: ${err}')
}
zinit_factory.delete('dagu_scheduler')! or {
return error('Could not delete dagu_scheduler service due to: ${err}')
}
}
// if zinit_factory.exists('dagu_scheduler') {
// zinit_factory.stop('dagu_scheduler')! or {
// return error('Could not stop dagu_scheduler service due to: ${err}')
// }
// zinit_factory.delete('dagu_scheduler')! or {
// return error('Could not delete dagu_scheduler service due to: ${err}')
// }
// }
}