Files
CyberStrikeAI/internal/workflow/structured_outputs.go
T
2026-07-06 11:34:50 +08:00

151 lines
4.6 KiB
Go

package workflow
type NodeOutputEnvelope struct {
Kind string `json:"kind"`
NodeID string `json:"node_id"`
NodeType string `json:"node_type"`
Status string `json:"status"`
Output any `json:"output"`
}
type StartOutput struct {
NodeOutputEnvelope
Message any `json:"message"`
ConversationID any `json:"conversationId"`
ProjectID any `json:"projectId"`
}
type ConditionOutput struct {
NodeOutputEnvelope
Condition string `json:"condition"`
Matched bool `json:"matched"`
}
type ToolOutput struct {
NodeOutputEnvelope
ToolName string `json:"tool_name"`
Arguments map[string]any `json:"arguments"`
ExecutionID string `json:"execution_id"`
IsError bool `json:"is_error"`
}
type AgentOutput struct {
NodeOutputEnvelope
Mode string `json:"mode"`
MCPExecutionIDs []string `json:"mcp_execution_ids"`
}
type HITLOutput struct {
NodeOutputEnvelope
Prompt string `json:"prompt"`
Reviewer string `json:"reviewer"`
Approved bool `json:"approved"`
Mode string `json:"mode"`
}
type OutputNodeOutput struct {
NodeOutputEnvelope
OutputKey string `json:"output_key"`
Outputs map[string]any `json:"outputs"`
}
func envelope(kind, nodeID, nodeType, status string, output any) NodeOutputEnvelope {
return NodeOutputEnvelope{Kind: kind, NodeID: nodeID, NodeType: nodeType, Status: status, Output: output}
}
func outputMap(env NodeOutputEnvelope, extra map[string]any) map[string]any {
out := map[string]any{
"kind": env.Kind,
"node_id": env.NodeID,
"node_type": env.NodeType,
"status": env.Status,
"output": env.Output,
"typed": env,
}
for k, v := range extra {
out[k] = v
}
return out
}
func startOutputMap(node graphNode, message, conversationID, projectID any) map[string]any {
typed := StartOutput{
NodeOutputEnvelope: envelope("start", node.ID, node.Type, "completed", message),
Message: message,
ConversationID: conversationID,
ProjectID: projectID,
}
return outputMap(typed.NodeOutputEnvelope, map[string]any{
"message": typed.Message,
"conversationId": typed.ConversationID,
"projectId": typed.ProjectID,
"typed": typed,
})
}
func conditionOutputMap(node graphNode, expr string, matched bool) map[string]any {
typed := ConditionOutput{
NodeOutputEnvelope: envelope("condition", node.ID, node.Type, "completed", matched),
Condition: expr,
Matched: matched,
}
return outputMap(typed.NodeOutputEnvelope, map[string]any{"condition": expr, "matched": matched, "typed": typed})
}
func outputNodeOutputMap(node graphNode, key string, value any) map[string]any {
typed := OutputNodeOutput{
NodeOutputEnvelope: envelope("output", node.ID, node.Type, "completed", value),
OutputKey: key,
Outputs: map[string]any{key: value},
}
return outputMap(typed.NodeOutputEnvelope, map[string]any{"output_key": key, "outputs": typed.Outputs, "typed": typed})
}
func endOutputMap(node graphNode, value any) map[string]any {
typed := envelope("end", node.ID, node.Type, "completed", value)
return outputMap(typed, nil)
}
func toolOutputMap(node graphNode, output string, toolName string, args map[string]any, executionID string, isError bool) map[string]any {
typed := ToolOutput{
NodeOutputEnvelope: envelope("tool", node.ID, node.Type, "completed", output),
ToolName: toolName,
Arguments: args,
ExecutionID: executionID,
IsError: isError,
}
return outputMap(typed.NodeOutputEnvelope, map[string]any{
"tool_name": toolName,
"arguments": args,
"execution_id": executionID,
"is_error": isError,
"typed": typed,
})
}
func agentOutputMap(node graphNode, response, mode string, mcpIDs []string) map[string]any {
typed := AgentOutput{
NodeOutputEnvelope: envelope("agent", node.ID, node.Type, "completed", response),
Mode: mode,
MCPExecutionIDs: mcpIDs,
}
return outputMap(typed.NodeOutputEnvelope, map[string]any{"mode": mode, "mcp_execution_ids": mcpIDs, "typed": typed})
}
func hitlOutputMap(node graphNode, status string, output string, prompt string, reviewer string, approved bool) map[string]any {
typed := HITLOutput{
NodeOutputEnvelope: envelope("hitl", node.ID, node.Type, status, output),
Prompt: prompt,
Reviewer: reviewer,
Approved: approved,
Mode: "interactive",
}
return outputMap(typed.NodeOutputEnvelope, map[string]any{
"prompt": prompt,
"reviewer": reviewer,
"approved": approved,
"mode": "interactive",
"typed": typed,
})
}