From 61a36778835514718327d836413ab558f9a78751 Mon Sep 17 00:00:00 2001 From: despiegk Date: Sun, 23 Nov 2025 04:22:25 +0100 Subject: [PATCH] ... --- examples/ai/flow_test1.vsh | 30 +++++++ lib/ai/flow_calendar/start.v | 2 +- lib/core/flows/coordinator.v | 27 ++++-- lib/core/flows/run.v | 95 +++++++++++++++++++++ lib/core/flows/step.v | 12 +++ lib/hero/heromodels/prd_test.v | 6 -- lib/threefold/models_to_move/core/comment.v | 54 ------------ lib/threefold/models_to_move/flow/flow.v | 2 +- 8 files changed, 159 insertions(+), 69 deletions(-) create mode 100755 examples/ai/flow_test1.vsh create mode 100644 lib/core/flows/run.v delete mode 100644 lib/threefold/models_to_move/core/comment.v diff --git a/examples/ai/flow_test1.vsh b/examples/ai/flow_test1.vsh new file mode 100755 index 00000000..d194fd22 --- /dev/null +++ b/examples/ai/flow_test1.vsh @@ -0,0 +1,30 @@ +#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run + +import incubaid.herolib.ai.client + +mut cl := client.new()! + +// response := cl.llms.llm_local.chat_completion( +// message: 'Explain quantum computing in simple terms' +// temperature: 0.5 +// max_completion_tokens: 1024 +// )! + +response := cl.llms.llm_maverick.chat_completion( + message: 'Explain quantum computing in simple terms' + temperature: 0.5 + max_completion_tokens: 1024 +)! + +println(response) + +// response := cl.llms.llm_embed_local.embed(input: [ +// 'The food was delicious and the waiter..', +// ])! + +// response2 := cl.llms.llm_embed.embed(input: [ +// 'The food was delicious and the waiter..', +// ])! + + +println(response2) diff --git a/lib/ai/flow_calendar/start.v b/lib/ai/flow_calendar/start.v index 78ac630f..ecf07e16 100644 --- a/lib/ai/flow_calendar/start.v +++ b/lib/ai/flow_calendar/start.v @@ -5,7 +5,7 @@ import incubaid.herolib.core.flows type CoordinatorProxy = flows.Coordinator -pub fn (mut c CoordinatorProxy) start(prompt string) ! { +pub fn start(mut c flows.Coordinator, prompt string) ! { // init the heromodels, define well chosen name, needed to call later mut m := heromodels.new(redis: c.redis, name: 'coordinator_${c.name}')! diff --git a/lib/core/flows/coordinator.v b/lib/core/flows/coordinator.v index 30cf1d28..248e5b13 100644 --- a/lib/core/flows/coordinator.v +++ b/lib/core/flows/coordinator.v @@ -10,14 +10,17 @@ import incubaid.herolib.core.logger import incubaid.herolib.ai.client as aiclient import incubaid.herolib.core.redisclient import incubaid.herolib.data.paramsparser +import incubaid.herolib.core.texttools +@[heap] pub struct Coordinator { pub mut: - name string - steps map[string]Step - logger logger.Logger - ai aiclient.AIClient - redis ?&redisclient.Redis + name string + current_step string // links to steps dict + steps map[string]&Step + logger logger.Logger + ai aiclient.AIClient + redis ?&redisclient.Redis } pub fn new() !Coordinator { @@ -41,8 +44,8 @@ pub mut: } // add step to it -pub fn (mut c Coordinator) step_new(args StepNewArgs) !Step { - return Step{ +pub fn (mut c Coordinator) step_new(args StepNewArgs) !&Step { + mut s := Step{ coordinator: &c name: args.name description: args.description @@ -52,4 +55,14 @@ pub fn (mut c Coordinator) step_new(args StepNewArgs) !Step { error: args.error params: args.params } + s.name = texttools.name_fix(s.name) + c.steps[s.name] = &s + c.current_step = s.name + return &s +} + +pub fn (mut c Coordinator) step_current() !&Step { + return c.steps[c.current_step] or { + return error('Current step "${c.current_step}" not found in coordinator "${c.name}"') + } } diff --git a/lib/core/flows/run.v b/lib/core/flows/run.v new file mode 100644 index 00000000..2303e265 --- /dev/null +++ b/lib/core/flows/run.v @@ -0,0 +1,95 @@ +module flows + +import time as ostime + +// Run the entire flow starting from current_step +pub fn (mut c Coordinator) run() ! { + mut s := c.step_current()! + c.run_step(mut s)! +} + +// Run a single step, including error and next steps +pub fn (mut c Coordinator) run_step(mut step Step) ! { + // Initialize step + step.status = .running + step.started_at = ostime.now().unix_milli() + step.store_redis()! + + // Log step start + step.log( + level: .info + message: 'Step "${step.name}" started' + )! + + // Execute main step function + step.main_step(mut step) or { + // Handle error + step.status = .error + step.error_msg = err.msg() + step.finished_at = ostime.now().unix_milli() + step.store_redis()! + + step.log( + level: .error + message: 'Step "${step.name}" failed: ${err.msg()}' + )! + + // Run error steps if any + if step.error_steps.len > 0 { + for mut error_step in step.error_steps { + c.run_step(mut error_step)! + } + } + + return err + } + + // Mark as success + step.status = .success + step.finished_at = ostime.now().unix_milli() + step.store_redis()! + + step.log( + level: .info + message: 'Step "${step.name}" completed successfully' + )! + + // Run next steps if any + if step.next_steps.len > 0 { + for mut next_step in step.next_steps { + c.run_step(mut next_step)! + } + } +} + +// Get step state from redis +pub fn (c Coordinator) get_step_state(step_name string) !map[string]string { + if redis := c.redis { + return redis.hgetall('flow:${c.name}:${step_name}')! + } + return error('Redis not configured') +} + +// Get all steps state from redis (for UI dashboard) +pub fn (c Coordinator) get_all_steps_state() ![]map[string]string { + mut states := []map[string]string{} + if redis := c.redis { + pattern := 'flow:${c.name}:*' + keys := redis.keys(pattern)! + for key in keys { + state := redis.hgetall(key)! + states << state + } + } + return states +} + +pub fn (c Coordinator) clear_redis() ! { + if redis := c.redis { + pattern := 'flow:${c.name}:*' + keys := redis.keys(pattern)! + for key in keys { + redis.del(key)! + } + } +} diff --git a/lib/core/flows/step.v b/lib/core/flows/step.v index 02b08f30..68ddac93 100644 --- a/lib/core/flows/step.v +++ b/lib/core/flows/step.v @@ -3,8 +3,20 @@ module flows import incubaid.herolib.data.paramsparser import incubaid.herolib.core.logger +pub enum StepStatus { + pending + running + success + error + skipped +} + pub struct Step { pub mut: + status StepStatus = .pending + started_at i64 // Unix timestamp + finished_at i64 + error_msg string name string description string main_step fn (mut s Step) ! @[required] diff --git a/lib/hero/heromodels/prd_test.v b/lib/hero/heromodels/prd_test.v index 8efe616d..c85f45e3 100644 --- a/lib/hero/heromodels/prd_test.v +++ b/lib/hero/heromodels/prd_test.v @@ -188,15 +188,9 @@ fn test_prd_list() ! { mut mydb := db.new_test()! // Clear the test database to ensure clean state mydb.redis.flushdb()! - mut db_prd := DBPrd{ db: &mydb } - // Clear any existing PRDs before running the test - existing_prds := db_prd.list()! - for prd_id in existing_prds { - db_prd.delete[ProductRequirementsDoc](u32(prd_id))! - } // Create multiple PRDs for i in 0 .. 3 { diff --git a/lib/threefold/models_to_move/core/comment.v b/lib/threefold/models_to_move/core/comment.v deleted file mode 100644 index a0618777..00000000 --- a/lib/threefold/models_to_move/core/comment.v +++ /dev/null @@ -1,54 +0,0 @@ -module core - -// Comment represents a generic commenting functionality that can be associated with any other model -// It supports threaded conversations through parent_comment_id -@[heap] -pub struct Comment { -pub mut: - id u32 // Unique comment ID - user_id u32 // ID of the user who posted the comment (indexed) - content string // The text content of the comment - parent_comment_id ?u32 // Optional parent comment ID for threaded comments - created_at u64 // Creation timestamp - updated_at u64 // Last update timestamp -} - -// new creates a new Comment with default values -pub fn Comment.new() Comment { - return Comment{ - id: 0 - user_id: 0 - content: '' - parent_comment_id: none - created_at: 0 - updated_at: 0 - } -} - -// user_id sets the user ID for the comment (builder pattern) -pub fn (mut c Comment) user_id(id u32) Comment { - c.user_id = id - return c -} - -// content sets the content for the comment (builder pattern) -pub fn (mut c Comment) content(text string) Comment { - c.content = text - return c -} - -// parent_comment_id sets the parent comment ID for threaded comments (builder pattern) -pub fn (mut c Comment) parent_comment_id(parent_id ?u32) Comment { - c.parent_comment_id = parent_id - return c -} - -// is_top_level returns true if this is a top-level comment (no parent) -pub fn (c Comment) is_top_level() bool { - return c.parent_comment_id == none -} - -// is_reply returns true if this is a reply to another comment -pub fn (c Comment) is_reply() bool { - return c.parent_comment_id != none -} diff --git a/lib/threefold/models_to_move/flow/flow.v b/lib/threefold/models_to_move/flow/flow.v index 8b9ea88a..5de279bb 100644 --- a/lib/threefold/models_to_move/flow/flow.v +++ b/lib/threefold/models_to_move/flow/flow.v @@ -1,4 +1,4 @@ -module flow + module flow // Flow represents a signing flow @[heap]