Files
cell/scripts/config.ce
2025-11-29 23:44:40 -06:00

248 lines
7.0 KiB
Plaintext

// cell config - Manage system and actor configurations
var toml = use('toml')
var shop = use('shop')
var text = use('text')
function print_help() {
log.console("Usage: cell config <command> [options]")
log.console("")
log.console("Commands:")
log.console(" get <key> Get a configuration value")
log.console(" set <key> <value> Set a configuration value")
log.console(" list List all configurations")
log.console(" actor <name> get <key> Get actor-specific config")
log.console(" actor <name> set <key> <val> Set actor-specific config")
log.console(" actor <name> list List actor configurations")
log.console("")
log.console("Examples:")
log.console(" cell config get system.ar_timer")
log.console(" cell config set system.net_service 0.2")
log.console(" cell config actor prosperon/_sdl_video set resolution 1920x1080")
log.console(" cell config actor extramath/spline set precision high")
log.console("")
log.console("System keys:")
log.console(" system.ar_timer - Seconds before idle actor reclamation")
log.console(" system.actor_memory - MB of memory an actor can use (0=unbounded)")
log.console(" system.net_service - Seconds per network service pull")
log.console(" system.reply_timeout - Seconds to hold callback for replies (0=unbounded)")
log.console(" system.actor_max - Max number of simultaneous actors")
log.console(" system.stack_max - MB of memory each actor's stack can grow to")
}
// Parse a dot-notation key into path segments
function parse_key(key) {
return key.split('.')
}
// Get a value from nested object using path
function get_nested(obj, path) {
var current = obj
for (var segment of path) {
if (!current || typeof current != 'object') return null
current = current[segment]
}
return current
}
// Set a value in nested object using path
function set_nested(obj, path, value) {
var current = obj
for (var i = 0; i < path.length - 1; i++) {
var segment = path[i]
if (!current[segment] || typeof current[segment] != 'object') {
current[segment] = {}
}
current = current[segment]
}
current[path[path.length - 1]] = value
}
// Parse value string into appropriate type
function parse_value(str) {
// Boolean
if (str == 'true') return true
if (str == 'false') return false
// Number (including underscores)
var num_str = str.replace(/_/g, '')
if (/^-?\d+$/.test(num_str)) return parseInt(num_str)
if (/^-?\d*\.\d+$/.test(num_str)) return parseFloat(num_str)
// String
return str
}
// Format value for display
function format_value(val) {
if (typeof val == 'string') return '"' + val + '"'
if (typeof val == 'number' && val >= 1000) {
// Add underscores to large numbers
return val.toString().replace(/\B(?=(\d{3})+(?!\d))/g, '_')
}
return String(val)
}
// Print configuration tree recursively
function print_config(obj, prefix = '') {
for (var key in obj) {
var val = obj[key]
var full_key = prefix ? prefix + '.' + key : key
if (val && typeof val == 'object' && !Array.isArray(val)) {
print_config(val, full_key)
} else {
log.console(full_key + ' = ' + format_value(val))
}
}
}
// Main command handling
if (args.length == 0) {
print_help()
$_.stop()
return
}
var config = shop.load_config()
if (!config) {
log.error("Failed to load .cell/cell.toml")
$_.stop()
return
}
var command = args[0]
switch (command) {
case 'help':
case '-h':
case '--help':
print_help()
break
case 'list':
log.console("# Cell Configuration")
log.console("")
print_config(config)
break
case 'get':
if (args.length < 2) {
log.error("Usage: cell config get <key>")
$_.stop()
return
}
var key = args[1]
var path = parse_key(key)
var value = get_nested(config, path)
if (value == null) {
log.error("Key not found: " + key)
} else if (value && typeof value == 'object' && !Array.isArray(value)) {
// Print all nested values
print_config(value, key)
} else {
log.console(key + ' = ' + format_value(value))
}
break
case 'set':
if (args.length < 3) {
log.error("Usage: cell config set <key> <value>")
$_.stop()
return
}
var key = args[1]
var value_str = args[2]
var path = parse_key(key)
var value = parse_value(value_str)
// Validate system keys
if (path[0] == 'system') {
var valid_system_keys = [
'ar_timer', 'actor_memory', 'net_service',
'reply_timeout', 'actor_max', 'stack_max'
]
if (!valid_system_keys.includes(path[1])) {
log.error("Invalid system key. Valid keys: " + valid_system_keys.join(', '))
$_.stop()
return
}
}
set_nested(config, path, value)
shop.save_config(config)
log.console("Set " + key + " = " + format_value(value))
break
case 'actor':
// Handle actor-specific configuration
if (args.length < 3) {
log.error("Usage: cell config actor <name> <command> [options]")
$_.stop()
return
}
var actor_name = args[1]
var actor_cmd = args[2]
// Initialize actors section if needed
config.actors = config.actors || {}
config.actors[actor_name] = config.actors[actor_name] || {}
switch (actor_cmd) {
case 'list':
if (Object.keys(config.actors[actor_name]).length == 0) {
log.console("No configuration for actor: " + actor_name)
} else {
log.console("# Configuration for actor: " + actor_name)
log.console("")
print_config(config.actors[actor_name], 'actors.' + actor_name)
}
break
case 'get':
if (args.length < 4) {
log.error("Usage: cell config actor <name> get <key>")
$_.stop()
return
}
var key = args[3]
var path = parse_key(key)
var value = get_nested(config.actors[actor_name], path)
if (value == null) {
log.error("Key not found for actor " + actor_name + ": " + key)
} else {
log.console('actors.' + actor_name + '.' + key + ' = ' + format_value(value))
}
break
case 'set':
if (args.length < 5) {
log.error("Usage: cell config actor <name> set <key> <value>")
$_.stop()
return
}
var key = args[3]
var value_str = args[4]
var path = parse_key(key)
var value = parse_value(value_str)
set_nested(config.actors[actor_name], path, value)
shop.save_config(config)
log.console("Set actors." + actor_name + "." + key + " = " + format_value(value))
break
default:
log.error("Unknown actor command: " + actor_cmd)
log.console("Valid commands: list, get, set")
}
break
default:
log.error("Unknown command: " + command)
print_help()
}
$_.stop()