{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://docs.baijimu.com/contracts/workflow-definition/4.1.0/schema.json",
  "title": "Baijimu Workflow Definition Authoring Contract",
  "description": "baijimu bundle workflow create/update 的 4.1.0 强类型 definition 合同。wait 支持轮询状态或 durable signal 两种互斥模式；signal_wait 是编译器内部节点，作者定义不得直接使用。",
  "type": "object",
  "additionalProperties": false,
  "required": ["code", "name", "startNodeId", "nodes", "edges"],
  "properties": {
    "workspaceId": { "type": "string" },
    "code": { "$ref": "#/$defs/nonEmptyString" },
    "name": { "$ref": "#/$defs/nonEmptyString" },
    "description": { "type": ["string", "null"] },
    "status": { "enum": ["draft", "active", "disabled"] },
    "startNodeId": { "$ref": "#/$defs/nonEmptyString" },
    "inputSchema": {
      "type": "array",
      "items": { "$ref": "#/$defs/paramDefinition" },
      "default": []
    },
    "outputSchema": { "$ref": "#/$defs/lowcodeType" },
    "nodes": {
      "type": "array",
      "minItems": 1,
      "items": { "$ref": "#/$defs/workflowNode" }
    },
    "edges": {
      "type": "array",
      "items": { "$ref": "#/$defs/workflowEdge" }
    },
    "graphLayout": true,
    "tags": {
      "type": "array",
      "items": { "type": "string" },
      "default": []
    }
  },
  "$defs": {
    "nonEmptyString": {
      "type": "string",
      "minLength": 1,
      "pattern": "\\S"
    },
    "moduleResourceLocator": {
      "type": "string",
      "pattern": "^[^/\\s]+/[^/\\s]+/MODULE/[^/\\s]+$"
    },
    "paramDefinition": {
      "type": "object",
      "additionalProperties": false,
      "required": ["name", "type"],
      "properties": {
        "name": { "$ref": "#/$defs/nonEmptyString" },
        "type": { "$ref": "#/$defs/lowcodeType" },
        "description": { "type": ["string", "null"] }
      }
    },
    "lowcodeType": {
      "oneOf": [
        {
          "type": "object",
          "required": ["@type"],
          "properties": {
            "@type": { "const": "DataType" },
            "items": { "$ref": "#/$defs/lowcodeType" },
            "properties": {
              "type": "object",
              "additionalProperties": { "$ref": "#/$defs/lowcodeType" }
            },
            "oneOf": { "type": "array", "items": { "$ref": "#/$defs/lowcodeType" } },
            "anyOf": { "type": "array", "items": { "$ref": "#/$defs/lowcodeType" } },
            "allOf": { "type": "array", "items": { "$ref": "#/$defs/lowcodeType" } }
          },
          "additionalProperties": true
        },
        {
          "type": "object",
          "required": ["@type", "ref"],
          "properties": {
            "@type": { "const": "RefType" },
            "ref": { "$ref": "#/$defs/nonEmptyString" }
          },
          "additionalProperties": true
        },
        {
          "type": "object",
          "required": ["@type"],
          "properties": {
            "@type": { "const": "MethodDefinition" },
            "returnType": { "$ref": "#/$defs/lowcodeType" },
            "paramDefinitions": {
              "type": "array",
              "items": { "$ref": "#/$defs/paramDefinition" }
            }
          },
          "additionalProperties": true
        },
        {
          "type": "object",
          "required": ["@type"],
          "properties": {
            "@type": { "const": "Interface" },
            "methods": { "type": "array", "items": { "$ref": "#/$defs/lowcodeType" } },
            "events": { "type": "array", "items": { "type": "object" } }
          },
          "additionalProperties": true
        },
        {
          "type": "object",
          "required": ["@type"],
          "properties": {
            "@type": { "const": "InterfaceMap" },
            "valueInterface": { "$ref": "#/$defs/lowcodeType" }
          },
          "additionalProperties": true
        },
        {
          "type": "object",
          "required": ["@type"],
          "properties": {
            "@type": { "const": "InterfaceList" },
            "elementInterface": { "$ref": "#/$defs/lowcodeType" }
          },
          "additionalProperties": true
        },
        {
          "type": "object",
          "required": ["@type"],
          "properties": {
            "@type": { "const": "FunctionList" },
            "elementMethodDefinition": { "$ref": "#/$defs/lowcodeType" }
          },
          "additionalProperties": true
        },
        {
          "type": "object",
          "required": ["@type"],
          "properties": {
            "@type": { "const": "FunctionMap" },
            "valueMethodDefinition": { "$ref": "#/$defs/lowcodeType" }
          },
          "additionalProperties": true
        },
        {
          "type": "object",
          "required": ["@type"],
          "properties": { "@type": { "const": "Void" } },
          "additionalProperties": true
        }
      ]
    },
    "workflowEdge": {
      "type": "object",
      "additionalProperties": false,
      "required": ["from", "to"],
      "properties": {
        "from": { "$ref": "#/$defs/nonEmptyString" },
        "to": { "$ref": "#/$defs/nonEmptyString" },
        "label": { "type": ["string", "null"] },
        "description": { "type": ["string", "null"] },
        "guard": {
          "oneOf": [
            { "type": "null" },
            {
              "type": "object",
              "additionalProperties": false,
              "required": ["type", "expression"],
              "properties": {
                "type": { "const": "expression" },
                "expression": { "$ref": "#/$defs/nonEmptyString" }
              }
            }
          ]
        }
      }
    },
    "outgoingPolicy": {
      "type": "object",
      "additionalProperties": false,
      "required": ["mode"],
      "properties": {
        "mode": { "enum": ["first_match", "all_matched", "all"] },
        "onNoMatch": { "enum": ["error", "complete"] }
      }
    },
    "nodeBase": {
      "type": "object",
      "required": ["type", "id"],
      "properties": {
        "type": { "$ref": "#/$defs/nonEmptyString" },
        "id": { "$ref": "#/$defs/nonEmptyString" },
        "name": { "type": ["string", "null"] },
        "description": { "type": ["string", "null"] },
        "outputPath": { "type": ["string", "null"] },
        "outgoingPolicy": { "$ref": "#/$defs/outgoingPolicy" }
      }
    },
    "retryPolicy": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "maxAttempts": { "type": "integer", "minimum": 1, "maximum": 10, "default": 1 },
        "initialDelayMs": { "type": "integer", "minimum": 0, "maximum": 300000, "default": 1000 },
        "maxDelayMs": { "type": "integer", "minimum": 0, "maximum": 600000, "default": 30000 },
        "backoffMultiplier": { "type": "number", "minimum": 1, "maximum": 10, "default": 2.0 }
      }
    },
    "httpRequest": {
      "type": "object",
      "additionalProperties": false,
      "required": ["method", "url"],
      "properties": {
        "method": { "$ref": "#/$defs/nonEmptyString" },
        "url": { "$ref": "#/$defs/nonEmptyString" },
        "destinationPolicy": { "enum": ["external", "platform_internal"], "default": "external" },
        "headers": {
          "type": "object",
          "additionalProperties": { "type": "string" },
          "default": {}
        },
        "body": true,
        "secretRefs": {
          "type": "array",
          "maxItems": 32,
          "items": { "$ref": "#/$defs/secretBinding" },
          "default": []
        },
        "timeoutSecs": { "type": ["integer", "null"], "minimum": 1, "maximum": 86400 },
        "retryPolicy": { "$ref": "#/$defs/retryPolicy" }
      }
    },
    "secretBinding": {
      "type": "object",
      "additionalProperties": false,
      "required": ["secretRef", "target"],
      "properties": {
        "secretRef": {
          "type": "string",
          "pattern": "^workspace-secret://[A-Za-z0-9][A-Za-z0-9._/-]{0,190}$"
        },
        "target": {
          "oneOf": [
            {
              "type": "object",
              "additionalProperties": false,
              "required": ["type", "name"],
              "properties": {
                "type": { "const": "header" },
                "name": { "$ref": "#/$defs/nonEmptyString" }
              }
            },
            {
              "type": "object",
              "additionalProperties": false,
              "required": ["type", "pointer"],
              "properties": {
                "type": { "const": "json_body" },
                "pointer": { "type": "string" }
              }
            }
          ]
        }
      }
    },
    "backendResponse": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "backend_response_format": { "enum": ["cmodel", "plain", "passthrough"] },
        "error_code_field": { "type": "string" },
        "error_message_field": { "type": "string" },
        "data_field": { "type": "string" },
        "success_expression": { "type": "string" },
        "error_code_expression": { "type": "string" },
        "error_message_expression": { "type": "string" },
        "data_expression": { "type": "string" }
      }
    },
    "startNode": {
      "type": "object",
      "allOf": [
        { "$ref": "#/$defs/nodeBase" },
        {
          "type": "object",
          "properties": { "type": { "const": "start" } }
        }
      ],
      "unevaluatedProperties": false
    },
    "endNode": {
      "type": "object",
      "allOf": [
        { "$ref": "#/$defs/nodeBase" },
        {
          "type": "object",
          "properties": {
            "type": { "const": "end" },
            "output": true
          }
        }
      ],
      "unevaluatedProperties": false
    },
    "moduleMethodNode": {
      "type": "object",
      "allOf": [
        { "$ref": "#/$defs/nodeBase" },
        {
          "type": "object",
          "required": ["service", "method"],
          "properties": {
            "type": { "const": "module_method" },
            "service": { "$ref": "#/$defs/moduleResourceLocator" },
            "method": { "$ref": "#/$defs/nonEmptyString" },
            "params": true,
            "timeoutSecs": { "type": ["integer", "null"], "minimum": 1, "maximum": 86400 },
            "retryPolicy": { "$ref": "#/$defs/retryPolicy" }
          }
        }
      ],
      "unevaluatedProperties": false
    },
    "emitEventNode": {
      "type": "object",
      "allOf": [
        { "$ref": "#/$defs/nodeBase" },
        {
          "type": "object",
          "required": ["service", "eventName"],
          "properties": {
            "type": { "const": "emit_event" },
            "service": { "$ref": "#/$defs/moduleResourceLocator" },
            "eventName": { "$ref": "#/$defs/nonEmptyString" },
            "payload": true,
            "idempotencyKey": { "type": ["string", "null"] },
            "timeoutSecs": { "type": ["integer", "null"], "minimum": 1, "maximum": 86400 }
          }
        }
      ],
      "unevaluatedProperties": false
    },
    "agentNode": {
      "type": "object",
      "allOf": [
        { "$ref": "#/$defs/nodeBase" },
        {
          "type": "object",
          "required": ["agentResourceLocator", "promptTemplate"],
          "properties": {
            "type": { "const": "agent" },
            "agentResourceLocator": {
              "type": "string",
              "pattern": "^[^/\\s]+/[^/\\s]+/AGENT/[^/\\s]+$"
            },
            "promptTemplate": { "$ref": "#/$defs/nonEmptyString" },
            "projectIdPath": { "type": ["string", "null"] },
            "workspaceIdPath": { "type": ["string", "null"] },
            "userIdPath": { "type": ["string", "null"] },
            "sessionIdTemplate": { "type": ["string", "null"] },
            "timeoutSecs": { "type": ["integer", "null"], "minimum": 1, "maximum": 86400 },
            "outputFormat": { "enum": ["text", "json"], "default": "text" }
          }
        }
      ],
      "unevaluatedProperties": false
    },
    "httpNode": {
      "type": "object",
      "allOf": [
        { "$ref": "#/$defs/nodeBase" },
        {
          "type": "object",
          "required": ["request", "response"],
          "properties": {
            "type": { "const": "http" },
            "request": { "$ref": "#/$defs/httpRequest" },
            "response": { "$ref": "#/$defs/backendResponse" },
            "retryPolicy": { "$ref": "#/$defs/retryPolicy" }
          }
        }
      ],
      "unevaluatedProperties": false
    },
    "waitCondition": {
      "type": "object",
      "additionalProperties": false,
      "required": ["op"],
      "properties": {
        "op": { "enum": ["eq", "ne", "in", "not_in", "exists", "not_exists", "gt", "gte", "lt", "lte", "contains"] },
        "value": true
      },
      "allOf": [
        {
          "if": { "properties": { "op": { "not": { "enum": ["exists", "not_exists"] } } } },
          "then": { "required": ["value"], "properties": { "value": true } }
        },
        {
          "if": { "properties": { "op": { "enum": ["in", "not_in"] } } },
          "then": { "properties": { "value": { "type": "array" } } }
        }
      ]
    },
    "waitNode": {
      "type": "object",
      "allOf": [
        { "$ref": "#/$defs/nodeBase" },
        {
          "type": "object",
          "properties": {
            "type": { "const": "wait" },
            "state": {
              "type": "object",
              "additionalProperties": false,
              "required": ["type"],
              "properties": {
                "type": { "enum": ["http", "runtime"] },
                "request": { "$ref": "#/$defs/httpRequest" },
                "path": { "type": ["string", "null"] },
                "valuePath": { "type": ["string", "null"] }
              },
              "allOf": [
                {
                  "if": { "properties": { "type": { "const": "http" } } },
                  "then": {
                    "required": ["request"],
                    "properties": { "request": { "$ref": "#/$defs/httpRequest" } }
                  }
                }
              ]
            },
            "until": { "$ref": "#/$defs/waitCondition" },
            "failWhen": { "$ref": "#/$defs/waitCondition" },
            "signal": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "successSignalNames": {
                  "type": "array",
                  "uniqueItems": true,
                  "items": { "$ref": "#/$defs/nonEmptyString" },
                  "default": []
                },
                "failureSignalNames": {
                  "type": "array",
                  "uniqueItems": true,
                  "items": { "$ref": "#/$defs/nonEmptyString" },
                  "default": []
                },
                "cancellationSignalNames": {
                  "type": "array",
                  "uniqueItems": true,
                  "items": { "$ref": "#/$defs/nonEmptyString" },
                  "default": []
                }
              }
            },
            "timeoutSecs": { "type": ["integer", "null"], "minimum": 1, "maximum": 86400 },
            "schedule": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "intervalMillis": { "type": "integer", "minimum": 1, "maximum": 86400000, "default": 1000 },
                "maxIntervalMillis": { "type": ["integer", "null"], "minimum": 1, "maximum": 86400000 },
                "backoffMultiplier": { "type": ["number", "null"], "minimum": 1, "maximum": 100 }
              }
            },
            "output": true
          },
          "oneOf": [
            {
              "required": ["state", "until"],
              "properties": {
                "state": true,
                "until": true,
                "signal": false
              }
            },
            {
              "required": ["signal"],
              "properties": {
                "signal": true,
                "state": false,
                "until": false,
                "failWhen": false,
                "schedule": false
              }
            }
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "humanNode": {
      "type": "object",
      "allOf": [
        { "$ref": "#/$defs/nodeBase" },
        {
          "type": "object",
          "required": ["issueDefinitionKey"],
          "properties": {
            "type": { "const": "human" },
            "issueDefinitionKey": { "$ref": "#/$defs/nonEmptyString" },
            "candidates": {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": false,
                "required": ["identityType", "identityId"],
                "properties": {
                  "identityType": {
                    "description": "候选主体类型。role 表示工作区角色，identityId 必须填写该角色的 roleKey。",
                    "enum": ["user", "department", "group", "role"]
                  },
                  "identityId": {
                    "description": "主体的稳定标识；identityType 为 role 时填写工作区角色 roleKey。",
                    "$ref": "#/$defs/nonEmptyString"
                  }
                }
              },
              "default": []
            }
          }
        }
      ],
      "unevaluatedProperties": false
    },
    "joinNode": {
      "type": "object",
      "allOf": [
        { "$ref": "#/$defs/nodeBase" },
        {
          "type": "object",
          "required": ["joinPolicy"],
          "properties": {
            "type": { "const": "join" },
            "joinPolicy": {
              "type": "object",
              "additionalProperties": false,
              "required": ["mode"],
              "properties": { "mode": { "enum": ["all", "any"] } }
            },
            "output": true
          }
        }
      ],
      "unevaluatedProperties": false
    },
    "forEachNode": {
      "type": "object",
      "allOf": [
        { "$ref": "#/$defs/nodeBase" },
        {
          "type": "object",
          "required": ["itemsPath"],
          "properties": {
            "type": { "const": "for_each" },
            "itemsPath": { "$ref": "#/$defs/nonEmptyString" },
            "itemName": { "type": ["string", "null"] },
            "indexName": { "type": ["string", "null"] },
            "mode": { "const": "sequential", "default": "sequential" },
            "maxIterations": { "type": ["integer", "null"], "minimum": 1, "maximum": 10000 },
            "onItemError": { "enum": ["fail", "continue"], "default": "fail" },
            "body": {
              "type": "array",
              "items": { "$ref": "#/$defs/workflowNode" },
              "default": []
            },
            "itemOutput": true
          }
        }
      ],
      "unevaluatedProperties": false
    },
    "customNode": {
      "allOf": [
        { "$ref": "#/$defs/nodeBase" },
        {
          "type": "object",
          "properties": {
            "type": {
              "allOf": [
                { "$ref": "#/$defs/nonEmptyString" },
                {
                  "not": {
                    "enum": ["start", "end", "http", "wait", "human", "join", "for_each", "module_method", "emit_event", "agent", "signal_wait"]
                  }
                }
              ]
            }
          }
        }
      ]
    },
    "workflowNode": {
      "oneOf": [
        { "$ref": "#/$defs/startNode" },
        { "$ref": "#/$defs/endNode" },
        { "$ref": "#/$defs/httpNode" },
        { "$ref": "#/$defs/waitNode" },
        { "$ref": "#/$defs/humanNode" },
        { "$ref": "#/$defs/joinNode" },
        { "$ref": "#/$defs/forEachNode" },
        { "$ref": "#/$defs/moduleMethodNode" },
        { "$ref": "#/$defs/emitEventNode" },
        { "$ref": "#/$defs/agentNode" },
        { "$ref": "#/$defs/customNode" }
      ]
    }
  }
}
