...
This commit is contained in:
42
examples/ai/openaiclient_openrouter.vsh
Executable file
42
examples/ai/openaiclient_openrouter.vsh
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import incubaid.herolib.clients.openai
|
||||
import incubaid.herolib.core.playcmds
|
||||
|
||||
playcmds.run(
|
||||
heroscript: '
|
||||
!!openai.configure name:"default"
|
||||
url:"https://openrouter.ai/api/v1"
|
||||
model_default:"gpt-oss-120b"
|
||||
'
|
||||
reset: false
|
||||
)!
|
||||
|
||||
// Get the client instance
|
||||
mut client := openai.get() or {
|
||||
eprintln('Failed to get client: ${err}')
|
||||
return
|
||||
}
|
||||
|
||||
println(client.list_models()!)
|
||||
|
||||
println('Sending message to OpenRouter...\n')
|
||||
|
||||
// Simple hello message
|
||||
response := client.chat_completion(
|
||||
model: 'qwen/qwen-2.5-coder-32b-instruct'
|
||||
message: 'Say hello in a friendly way!'
|
||||
temperature: 0.7
|
||||
max_completion_tokens: 100
|
||||
) or {
|
||||
eprintln('Failed to get completion: ${err}')
|
||||
return
|
||||
}
|
||||
|
||||
println('Response from AI:')
|
||||
println('─'.repeat(50))
|
||||
println(response.result)
|
||||
println('─'.repeat(50))
|
||||
println('\nTokens used: ${response.usage.total_tokens}')
|
||||
println(' - Prompt: ${response.usage.prompt_tokens}')
|
||||
println(' - Completion: ${response.usage.completion_tokens}')
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Overview
|
||||
|
||||
This folder contains **three example scripts** demonstrating the usage of the OpenRouter V client (`herolib.clients.openrouter`).
|
||||
This folder contains **example scripts** demonstrating the usage of the OpenRouter V client (`herolib.clients.openrouter`).
|
||||
|
||||
* **Goal:** Show how to send messages to OpenRouter models, run a **two-model pipeline** for code enhancement, and illustrate multi-model usage.
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
import incubaid.herolib.clients.openai
|
||||
import incubaid.herolib.core.playcmds
|
||||
|
||||
//to set the API key, either set it here, or set the OPENAI_API_KEY environment variable
|
||||
|
||||
playcmds.run(
|
||||
heroscript: '
|
||||
!!openai.configure name: "default" key: "" url: "https://openrouter.ai/api/v1" model_default: "gpt-oss-120b"
|
||||
@@ -46,6 +46,9 @@ fn obj_init(mycfg_ OpenAI) !OpenAI {
|
||||
}
|
||||
}
|
||||
}
|
||||
if mycfg.api_key == '' {
|
||||
return error('OpenAI client "${mycfg.name}" missing api_key')
|
||||
}
|
||||
return mycfg
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import incubaid.herolib.clients.meilisearch
|
||||
import incubaid.herolib.clients.mycelium
|
||||
import incubaid.herolib.clients.mycelium_rpc
|
||||
import incubaid.herolib.clients.openai
|
||||
import incubaid.herolib.clients.openrouter
|
||||
import incubaid.herolib.clients.postgresql_client
|
||||
import incubaid.herolib.clients.qdrant
|
||||
import incubaid.herolib.clients.rclone
|
||||
@@ -47,6 +48,7 @@ import incubaid.herolib.installers.web.tailwind4
|
||||
import incubaid.herolib.installers.web.traefik
|
||||
import incubaid.herolib.installers.web.zola
|
||||
import incubaid.herolib.virt.hetznermanager
|
||||
import incubaid.herolib.virt.kubernetes
|
||||
|
||||
pub fn run_all(args_ PlayArgs) ! {
|
||||
mut args := args_
|
||||
@@ -64,6 +66,7 @@ pub fn run_all(args_ PlayArgs) ! {
|
||||
mycelium.play(mut plbook)!
|
||||
mycelium_rpc.play(mut plbook)!
|
||||
openai.play(mut plbook)!
|
||||
openrouter.play(mut plbook)!
|
||||
postgresql_client.play(mut plbook)!
|
||||
qdrant.play(mut plbook)!
|
||||
rclone.play(mut plbook)!
|
||||
@@ -101,4 +104,5 @@ pub fn run_all(args_ PlayArgs) ! {
|
||||
traefik.play(mut plbook)!
|
||||
zola.play(mut plbook)!
|
||||
hetznermanager.play(mut plbook)!
|
||||
kubernetes.play(mut plbook)!
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ fn decode_struct[T](_ T, data string) !T {
|
||||
|
||||
$if T is $struct {
|
||||
obj_name := texttools.snake_case(T.name.all_after_last('.'))
|
||||
obj_name2 := texttools.name_fix(T.name.all_after_last('.'))
|
||||
|
||||
// Define possible action name formats to try
|
||||
action_names_to_try := [
|
||||
@@ -28,6 +29,10 @@ fn decode_struct[T](_ T, data string) !T {
|
||||
'configure.${obj_name}',
|
||||
'${obj_name}.define',
|
||||
'${obj_name}.configure',
|
||||
'define.${obj_name2}',
|
||||
'configure.${obj_name2}',
|
||||
'${obj_name2}.define',
|
||||
'${obj_name2}.configure',
|
||||
]
|
||||
|
||||
mut found_action_name := ''
|
||||
@@ -47,7 +52,7 @@ fn decode_struct[T](_ T, data string) !T {
|
||||
}
|
||||
|
||||
if found_action_name == '' {
|
||||
return error('Data does not contain expected action format for ${obj_name}\nData: ${data}')
|
||||
return error('Data does not contain expected action format for obj:${obj_name} or obj:${obj_name2}\nData: ${data}')
|
||||
}
|
||||
|
||||
if actions.len > 1 {
|
||||
|
||||
@@ -54,6 +54,6 @@ fn destroy() ! {
|
||||
// No cleanup needed for kubectl wrapper
|
||||
}
|
||||
|
||||
fn configure() ! {
|
||||
console.print_debug('Kubernetes client configured')
|
||||
}
|
||||
// fn configure() ! {
|
||||
// console.print_debug('Kubernetes client configured')
|
||||
// }
|
||||
|
||||
@@ -9,36 +9,36 @@ import os
|
||||
|
||||
// Execute kubectl command with proper error handling
|
||||
pub fn (mut k KubeClient) kubectl_exec(args KubectlExecArgs) !KubectlResult {
|
||||
mut cmd := '${k.kubectl_path} '
|
||||
mut cmd := 'kubectl'
|
||||
|
||||
if !k.config.namespace.is_empty() {
|
||||
if k.config.namespace.len > 0 {
|
||||
cmd += '--namespace=${k.config.namespace} '
|
||||
}
|
||||
|
||||
if !k.kubeconfig_path.is_empty() {
|
||||
if k.kubeconfig_path.len > 0 {
|
||||
cmd += '--kubeconfig=${k.kubeconfig_path} '
|
||||
}
|
||||
|
||||
if !k.config.context.is_empty() {
|
||||
if k.config.context.len > 0 {
|
||||
cmd += '--context=${k.config.context} '
|
||||
}
|
||||
|
||||
cmd += args.command
|
||||
|
||||
console.print_debug("executing: ${cmd}")
|
||||
console.print_debug('executing: ${cmd}')
|
||||
|
||||
job := osal.exec(
|
||||
cmd: cmd
|
||||
timeout: args.timeout
|
||||
retry: args.retry
|
||||
cmd: cmd
|
||||
timeout: args.timeout
|
||||
retry: args.retry
|
||||
raise_error: false
|
||||
)!
|
||||
|
||||
return KubectlResult{
|
||||
exit_code: job.exit_code
|
||||
stdout: job.output
|
||||
stderr: job.error
|
||||
success: job.exit_code == 0
|
||||
stdout: job.output
|
||||
stderr: job.error
|
||||
success: job.exit_code == 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,80 +76,90 @@ pub fn (mut k KubeClient) cluster_info() !ClusterInfo {
|
||||
return error('Failed to get cluster version: ${result.stderr}')
|
||||
}
|
||||
|
||||
version_data := json.decode(map[string]interface{}, result.stdout)!
|
||||
server_version := version_data['serverVersion'] or { return error('No serverVersion') }
|
||||
println(result.stdout)
|
||||
|
||||
// Get node count
|
||||
nodes_result := k.kubectl_exec(command: 'get nodes -o json')!
|
||||
nodes_count := if nodes_result.success {
|
||||
nodes_data := json.decode(map[string]interface{}, nodes_result.stdout)!
|
||||
items := nodes_data['items'] or { []interface{}{} }
|
||||
items.len
|
||||
} else {
|
||||
0
|
||||
}
|
||||
$dbg;
|
||||
// version_data := json.decode(map[string]interface{}, result.stdout)!
|
||||
// server_version := version_data['serverVersion'] or { return error('No serverVersion') }
|
||||
|
||||
// Get namespace count
|
||||
ns_result := k.kubectl_exec(command: 'get namespaces -o json')!
|
||||
ns_count := if ns_result.success {
|
||||
ns_data := json.decode(map[string]interface{}, ns_result.stdout)!
|
||||
items := ns_data['items'] or { []interface{}{} }
|
||||
items.len
|
||||
} else {
|
||||
0
|
||||
}
|
||||
// // Get node count
|
||||
// nodes_result := k.kubectl_exec(command: 'get nodes -o json')!
|
||||
// nodes_count := if nodes_result.success {
|
||||
// nodes_data := json.decode(map[string]interface{}, nodes_result.stdout)!
|
||||
// items := nodes_data['items'] or { []interface{}{} }
|
||||
// items.len
|
||||
// } else {
|
||||
// 0
|
||||
// }
|
||||
|
||||
// Get running pods count
|
||||
pods_result := k.kubectl_exec(command: 'get pods --all-namespaces -o json')!
|
||||
pods_count := if pods_result.success {
|
||||
pods_data := json.decode(map[string]interface{}, pods_result.stdout)!
|
||||
items := pods_data['items'] or { []interface{}{} }
|
||||
items.len
|
||||
} else {
|
||||
0
|
||||
}
|
||||
// // Get namespace count
|
||||
// ns_result := k.kubectl_exec(command: 'get namespaces -o json')!
|
||||
// ns_count := if ns_result.success {
|
||||
// ns_data := json.decode(map[string]interface{}, ns_result.stdout)!
|
||||
// items := ns_data['items'] or { []interface{}{} }
|
||||
// items.len
|
||||
// } else {
|
||||
// 0
|
||||
// }
|
||||
|
||||
return ClusterInfo{
|
||||
version: 'v1.0.0'
|
||||
nodes: nodes_count
|
||||
namespaces: ns_count
|
||||
running_pods: pods_count
|
||||
api_server: k.config.api_server
|
||||
}
|
||||
// // Get running pods count
|
||||
// pods_result := k.kubectl_exec(command: 'get pods --all-namespaces -o json')!
|
||||
// pods_count := if pods_result.success {
|
||||
// pods_data := json.decode(map[string]interface{}, pods_result.stdout)!
|
||||
// items := pods_data['items'] or { []interface{}{} }
|
||||
// items.len
|
||||
// } else {
|
||||
// 0
|
||||
// }
|
||||
|
||||
// return ClusterInfo{
|
||||
// version: 'v1.0.0'
|
||||
// nodes: nodes_count
|
||||
// namespaces: ns_count
|
||||
// running_pods: pods_count
|
||||
// api_server: k.config.api_server
|
||||
// }
|
||||
return ClusterInfo{}
|
||||
}
|
||||
|
||||
// Get resources (Pods, Deployments, Services, etc.)
|
||||
pub fn (mut k KubeClient) get_pods(namespace string) ![]map[string]interface{} {
|
||||
pub fn (mut k KubeClient) get_pods(namespace string) ! {
|
||||
result := k.kubectl_exec(command: 'get pods -n ${namespace} -o json')!
|
||||
if !result.success {
|
||||
return error('Failed to get pods: ${result.stderr}')
|
||||
}
|
||||
|
||||
data := json.decode(map[string]interface{}, result.stdout)!
|
||||
items := data['items'] or { []interface{}{} }
|
||||
return items as []map[string]interface{}
|
||||
println(result.stdout)
|
||||
$dbg;
|
||||
// data := json.decode(map[string]interface{}, result.stdout)!
|
||||
// items := data['items'] or { []interface{}{} }
|
||||
// return items as []map[string]interface{}
|
||||
|
||||
panic('Not implemented')
|
||||
}
|
||||
|
||||
pub fn (mut k KubeClient) get_deployments(namespace string) ![]map[string]interface{} {
|
||||
pub fn (mut k KubeClient) get_deployments(namespace string) ! {
|
||||
result := k.kubectl_exec(command: 'get deployments -n ${namespace} -o json')!
|
||||
if !result.success {
|
||||
return error('Failed to get deployments: ${result.stderr}')
|
||||
}
|
||||
|
||||
data := json.decode(map[string]interface{}, result.stdout)!
|
||||
items := data['items'] or { []interface{}{} }
|
||||
return items as []map[string]interface{}
|
||||
// data := json.decode(map[string]interface{}, result.stdout)!
|
||||
// items := data['items'] or { []interface{}{} }
|
||||
// return items as []map[string]interface{}
|
||||
panic('Not implemented')
|
||||
}
|
||||
|
||||
pub fn (mut k KubeClient) get_services(namespace string) ![]map[string]interface{} {
|
||||
pub fn (mut k KubeClient) get_services(namespace string) ! {
|
||||
result := k.kubectl_exec(command: 'get services -n ${namespace} -o json')!
|
||||
if !result.success {
|
||||
return error('Failed to get services: ${result.stderr}')
|
||||
}
|
||||
|
||||
data := json.decode(map[string]interface{}, result.stdout)!
|
||||
items := data['items'] or { []interface{}{} }
|
||||
return items as []map[string]interface{}
|
||||
// data := json.decode(map[string]interface{}, result.stdout)!
|
||||
// items := data['items'] or { []interface{}{} }
|
||||
// return items as []map[string]interface{}
|
||||
panic('Not implemented')
|
||||
}
|
||||
|
||||
// Apply YAML file
|
||||
@@ -157,7 +167,7 @@ pub fn (mut k KubeClient) apply_yaml(yaml_path string) !KubectlResult {
|
||||
// Validate before applying
|
||||
validation := yaml_validate(yaml_path)!
|
||||
if !validation.valid {
|
||||
return error('YAML validation failed: ${validation.errors.join(", ")}')
|
||||
return error('YAML validation failed: ${validation.errors.join(', ')}')
|
||||
}
|
||||
|
||||
result := k.kubectl_exec(command: 'apply -f ${yaml_path}')!
|
||||
@@ -204,11 +214,11 @@ pub fn (mut k KubeClient) logs(pod_name string, namespace string, follow bool) !
|
||||
|
||||
// Exec into container
|
||||
pub fn (mut k KubeClient) exec_pod(pod_name string, namespace string, container string, cmd_args []string) !string {
|
||||
cmd := 'exec -it ${pod_name} -n ${namespace}'
|
||||
if !container.is_empty() {
|
||||
mut cmd := 'exec -it ${pod_name} -n ${namespace}'
|
||||
if container.len > 0 {
|
||||
cmd += ' -c ${container}'
|
||||
}
|
||||
cmd += ' -- ${cmd_args.join(" ")}'
|
||||
cmd += ' -- ${cmd_args.join(' ')}'
|
||||
|
||||
result := k.kubectl_exec(command: cmd, timeout: 300)!
|
||||
if !result.success {
|
||||
@@ -228,4 +238,4 @@ pub fn (mut k KubeClient) watch_deployment(name string, namespace string, timeou
|
||||
cmd := 'rollout status deployment/${name} -n ${namespace} --timeout=${timeout_seconds}s'
|
||||
result := k.kubectl_exec(command: cmd, timeout: timeout_seconds + 10)!
|
||||
return result.success
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,16 +11,13 @@ const default = true
|
||||
@[heap]
|
||||
pub struct KubeClient {
|
||||
pub mut:
|
||||
name string = 'default'
|
||||
name string = 'default'
|
||||
kubeconfig_path string
|
||||
config KubeConfig
|
||||
connected bool
|
||||
api_version string = 'v1'
|
||||
kubectl_path string = 'kubectl'
|
||||
cache_enabled bool = true
|
||||
cache_ttl_seconds int = 300
|
||||
|
||||
cache_enabled bool = true
|
||||
cache_ttl_seconds int = 300
|
||||
}
|
||||
|
||||
// your checking & initialization code if needed
|
||||
@@ -41,7 +38,7 @@ fn configure() ! {
|
||||
/////////////NORMALLY NO NEED TO TOUCH
|
||||
|
||||
pub fn heroscript_loads(heroscript string) !KubeClient {
|
||||
//TODO: will have to be implemented manual
|
||||
// TODO: will have to be implemented manual
|
||||
mut obj := encoderhero.decode[KubeClient](heroscript)!
|
||||
return obj
|
||||
}
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
module kubernetes
|
||||
|
||||
import incubaid.herolib.data.paramsparser
|
||||
import incubaid.herolib.data.encoderhero
|
||||
import incubaid.herolib.data.ourjson
|
||||
import os
|
||||
|
||||
pub const version = '1.0.0'
|
||||
const singleton = false
|
||||
const default = true
|
||||
|
||||
// K8s API Version and Kind tracking
|
||||
@[params]
|
||||
pub struct K8sMetadata {
|
||||
@@ -166,7 +160,6 @@ pub mut:
|
||||
insecure_skip_tls_verify bool
|
||||
}
|
||||
|
||||
|
||||
// Validation result for YAML files
|
||||
pub struct K8sValidationResult {
|
||||
pub mut:
|
||||
@@ -186,31 +179,3 @@ pub mut:
|
||||
running_pods int
|
||||
api_server string
|
||||
}
|
||||
|
||||
// Initialization
|
||||
fn obj_init(mut cfg KubeClient) !KubeClient {
|
||||
// Resolve kubeconfig path
|
||||
if cfg.kubeconfig_path.is_empty() {
|
||||
home := os.home_dir()
|
||||
cfg.kubeconfig_path = '${home}/.kube/config'
|
||||
}
|
||||
|
||||
// Ensure kubeconfig exists
|
||||
if !os.path_exists(cfg.kubeconfig_path) {
|
||||
return error('kubeconfig not found at ${cfg.kubeconfig_path}')
|
||||
}
|
||||
|
||||
cfg.config.kubeconfig_path = cfg.kubeconfig_path
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
fn configure() ! {
|
||||
// Configure any defaults or environment-specific settings
|
||||
}
|
||||
|
||||
pub fn heroscript_loads(heroscript string) !KubeClient {
|
||||
// TODO: this will have to be redone, because its much more complicated now, need to define a nice play processors
|
||||
mut obj := encoderhero.decode[KubeClient](heroscript)!
|
||||
return obj_init(obj)!
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user