mirror of
https://github.com/j3ssie/osmedeus.git
synced 2026-08-30 19:59:48 +02:00
- Add LLM executor supporting OpenAI vision, tool calling, embeddings, and structured outputs - Introduce event emitter/receiver workflows with deduplication and filtering (generate_event functions) - Add workflow extends/override system enabling inheritance chains and step merge modes - Update function naming to snake_case across all testdata (fileExists→file_exists, etc.) - Add comprehensive test fixtures for linter, events, CDN, step dependencies, and extends workflows
114 lines
2.9 KiB
Go
114 lines
2.9 KiB
Go
package template
|
|
|
|
import (
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/flosch/pongo2/v6"
|
|
)
|
|
|
|
// WorkflowTemplates holds pre-compiled templates for a single workflow
|
|
type WorkflowTemplates struct {
|
|
// Templates maps field keys to pre-compiled templates
|
|
// Key format: "stepName:fieldName" (e.g., "scan:command", "scan:exports:output")
|
|
Templates map[string]*pongo2.Template
|
|
}
|
|
|
|
// PrecompiledRegistry stores pre-compiled templates for workflows.
|
|
// Templates are compiled once at workflow load time and reused during execution.
|
|
type PrecompiledRegistry struct {
|
|
mu sync.RWMutex
|
|
workflows map[string]*WorkflowTemplates
|
|
}
|
|
|
|
// NewPrecompiledRegistry creates a new pre-compiled template registry
|
|
func NewPrecompiledRegistry() *PrecompiledRegistry {
|
|
return &PrecompiledRegistry{
|
|
workflows: make(map[string]*WorkflowTemplates),
|
|
}
|
|
}
|
|
|
|
// PrecompileWorkflow pre-compiles all template strings for a workflow.
|
|
// The templates map should use keys like "stepName:fieldName".
|
|
func (r *PrecompiledRegistry) PrecompileWorkflow(workflowName string, templates map[string]string) error {
|
|
compiled := &WorkflowTemplates{
|
|
Templates: make(map[string]*pongo2.Template, len(templates)),
|
|
}
|
|
|
|
for key, tmplStr := range templates {
|
|
// Skip if no template variables
|
|
if !strings.Contains(tmplStr, "{{") {
|
|
continue
|
|
}
|
|
|
|
tpl, err := pongo2.FromString(tmplStr)
|
|
if err != nil {
|
|
// Log warning but continue - invalid templates will be handled at runtime
|
|
continue
|
|
}
|
|
compiled.Templates[key] = tpl
|
|
}
|
|
|
|
r.mu.Lock()
|
|
r.workflows[workflowName] = compiled
|
|
r.mu.Unlock()
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetPrecompiled retrieves a pre-compiled template for a workflow field.
|
|
// Returns nil if not found.
|
|
func (r *PrecompiledRegistry) GetPrecompiled(workflowName, key string) any {
|
|
r.mu.RLock()
|
|
wf, ok := r.workflows[workflowName]
|
|
r.mu.RUnlock()
|
|
|
|
if !ok {
|
|
return nil
|
|
}
|
|
|
|
// Note: the WorkflowTemplates map doesn't need locking for reads
|
|
// as it's never modified after creation
|
|
tpl, exists := wf.Templates[key]
|
|
if !exists {
|
|
return nil
|
|
}
|
|
return tpl
|
|
}
|
|
|
|
// ClearPrecompiled removes pre-compiled templates for a workflow
|
|
func (r *PrecompiledRegistry) ClearPrecompiled(workflowName string) {
|
|
r.mu.Lock()
|
|
delete(r.workflows, workflowName)
|
|
r.mu.Unlock()
|
|
}
|
|
|
|
// ClearAll removes all pre-compiled templates
|
|
func (r *PrecompiledRegistry) ClearAll() {
|
|
r.mu.Lock()
|
|
r.workflows = make(map[string]*WorkflowTemplates)
|
|
r.mu.Unlock()
|
|
}
|
|
|
|
// GetWorkflowCount returns the number of workflows with pre-compiled templates
|
|
func (r *PrecompiledRegistry) GetWorkflowCount() int {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
return len(r.workflows)
|
|
}
|
|
|
|
// GetTemplateCount returns the total number of pre-compiled templates
|
|
func (r *PrecompiledRegistry) GetTemplateCount() int {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
|
|
count := 0
|
|
for _, wf := range r.workflows {
|
|
count += len(wf.Templates)
|
|
}
|
|
return count
|
|
}
|
|
|
|
// Verify interface compliance at compile time
|
|
var _ Precompiler = (*PrecompiledRegistry)(nil)
|