{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Create a Halo link, version 1",
  "type": "object",
  "description": "An existing public catalog Halo or an agent-authored personal Halo. Instructions remain editable. Creation makes an unlisted link; it does not start a session.",
  "oneOf": [
    {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "schema_version",
        "source_id",
        "kind",
        "catalog_halo_id"
      ],
      "properties": {
        "schema_version": {
          "const": 1
        },
        "source_id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100,
          "pattern": "^[A-Za-z0-9][A-Za-z0-9_-]{0,99}(?![\\s\\S])"
        },
        "kind": {
          "const": "catalog"
        },
        "catalog_halo_id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        }
      }
    },
    {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "schema_version",
        "source_id",
        "kind",
        "halo"
      ],
      "properties": {
        "schema_version": {
          "const": 1
        },
        "source_id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100,
          "pattern": "^[A-Za-z0-9][A-Za-z0-9_-]{0,99}(?![\\s\\S])"
        },
        "kind": {
          "const": "personal"
        },
        "halo": {
          "$ref": "#/$defs/halo"
        }
      }
    }
  ],
  "$defs": {
    "halo": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "name",
        "description",
        "conversation_instructions",
        "recap_instructions",
        "run_configuration",
        "saves_recaps",
        "starts_with_front_camera"
      ],
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "description": {
          "type": "string",
          "minLength": 1,
          "maxLength": 1000
        },
        "conversation_instructions": {
          "type": "string",
          "minLength": 1,
          "maxLength": 60000
        },
        "recap_instructions": {
          "type": "string",
          "minLength": 0,
          "maxLength": 20000
        },
        "run_configuration": {
          "$ref": "#/$defs/run_configuration"
        },
        "saves_recaps": {
          "type": "boolean"
        },
        "starts_with_front_camera": {
          "type": "boolean"
        }
      }
    },
    "run_configuration": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "schema_version",
        "type",
        "inputModes",
        "outputMode",
        "outputSchema",
        "cameraPolicy",
        "launchMode",
        "defaultLaunchMode",
        "agentOpensRun"
      ],
      "properties": {
        "schema_version": {
          "const": 1
        },
        "type": {
          "enum": [
            "guided_behavior",
            "roleplay_practice",
            "voice_journal",
            "real_world_recap"
          ]
        },
        "inputModes": {
          "type": "array",
          "minItems": 1,
          "maxItems": 4,
          "uniqueItems": true,
          "items": {
            "enum": [
              "text",
              "voice",
              "image",
              "video_frames"
            ]
          }
        },
        "outputMode": {
          "const": "html"
        },
        "outputSchema": {
          "type": "null"
        },
        "cameraPolicy": {
          "enum": [
            "off",
            "optional",
            "required"
          ]
        },
        "launchMode": {
          "enum": [
            "interactive_audio",
            "interactive_camera",
            "recording_audio",
            "recording_camera"
          ]
        },
        "defaultLaunchMode": {
          "enum": [
            "interactive_audio",
            "interactive_camera",
            "recording_audio",
            "recording_camera"
          ]
        },
        "agentOpensRun": {
          "type": "boolean"
        }
      }
    }
  }
}
