mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-10-20 06:27:53 +02:00
fix: validate workflows and preserve execution outcomes
This commit is contained in:
1 parent
bdefa535b0
commit
8550325dfe
16 files changed
+494
-35
No files matched your search
@@ -0,0 +1,35 @@
|
||||
package workflow
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestToolArgumentTemplatesResolveAfterJSONParsing(t *testing.T) {
|
||||
state := newWorkflowLocalState(map[string]interface{}{"target": "https://example.test/a?x=\"quoted\"\nnext"}, "run")
|
||||
cfg := map[string]any{"arguments": `{"target":"{{inputs.target}}","headers":{"label":"probe {{inputs.target}}"},"items":["{{inputs.target}}",{"count":2}],"empty":"","enabled":true}`}
|
||||
args, err := resolveToolArguments(cfg, state)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if args["target"] != state.Inputs["target"] {
|
||||
t.Fatalf("unexpanded target: %#v", args)
|
||||
}
|
||||
if args["headers"].(map[string]interface{})["label"] != "probe "+state.Inputs["target"].(string) {
|
||||
t.Fatal("nested template did not resolve")
|
||||
}
|
||||
if args["items"].([]interface{})[0] != state.Inputs["target"] {
|
||||
t.Fatal("array template did not resolve")
|
||||
}
|
||||
if args["empty"] != "" || args["enabled"] != true {
|
||||
t.Fatal("non-template values changed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestExplicitToolArgumentBindingsRemainAuthoritative(t *testing.T) {
|
||||
state := newWorkflowLocalState(map[string]interface{}{"port": 8080}, "run")
|
||||
cfg := map[string]any{"arguments": `{"port":"wrong"}`, "argument_bindings": map[string]any{"port": map[string]any{"from": "inputs", "field": "port"}}}
|
||||
args, err := resolveToolArguments(cfg, state)
|
||||
if err != nil || args["port"] != 8080 {
|
||||
t.Fatalf("binding changed: %#v %v", args, err)
|
||||
}
|
||||
}
|
||||
@@ -149,5 +149,28 @@ func resolveToolArguments(cfg map[string]any, state *WorkflowLocalState) (map[st
|
||||
if args == nil {
|
||||
args = map[string]interface{}{}
|
||||
}
|
||||
resolveArgumentTemplates(args, state)
|
||||
return args, nil
|
||||
}
|
||||
|
||||
// Expand after parsing JSON so quotes and newlines in state values remain data.
|
||||
func resolveArgumentTemplates(value any, state *WorkflowLocalState) {
|
||||
switch v := value.(type) {
|
||||
case map[string]interface{}:
|
||||
for key, item := range v {
|
||||
if text, ok := item.(string); ok && templateVarRe.MatchString(text) {
|
||||
v[key] = resolveTemplate(text, state)
|
||||
} else {
|
||||
resolveArgumentTemplates(item, state)
|
||||
}
|
||||
}
|
||||
case []interface{}:
|
||||
for i, item := range v {
|
||||
if text, ok := item.(string); ok && templateVarRe.MatchString(text) {
|
||||
v[i] = resolveTemplate(text, state)
|
||||
} else {
|
||||
resolveArgumentTemplates(item, state)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user