Skip to content

Instantly share code, notes, and snippets.

@AlexanderHolmeset
Created October 6, 2023 11:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AlexanderHolmeset/ad17291532d22794e8c7ba4dd44c319f to your computer and use it in GitHub Desktop.
Save AlexanderHolmeset/ad17291532d22794e8c7ba4dd44c319f to your computer and use it in GitHub Desktop.
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"Bot_User": {
"inputs": {
"variables": [
{
"name": "BotUserID",
"type": "string"
}
]
},
"runAfter": {
"NewMessageFromChat": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"Condition": {
"actions": {
"Append_ConversationHistoryReversed": {
"inputs": {
"name": "ConversationHistoryReversed",
"value": "@outputs('Compose_ArrayMessages_Reversed')"
},
"runAfter": {
"Compose_ArrayMessages_Reversed": [
"Succeeded"
]
},
"type": "AppendToStringVariable"
},
"Compose_ArrayMessages": {
"inputs": "@variables('ArrayMessages')",
"runAfter": {
"For_each_2": [
"Succeeded"
]
},
"type": "Compose"
},
"Compose_ArrayMessages_Reversed": {
"inputs": "@reverse(variables('ArrayMessages'))",
"runAfter": {
"Compose_ArrayMessages": [
"Succeeded"
]
},
"type": "Compose"
},
"Compose_ConversationHistoryReversed": {
"inputs": {
"name": "ConversationHistoryReversed",
"value": "@{outputs('Compose_ConversationHistoryReversed_Replace')}"
},
"runAfter": {
"Compose_ConversationHistoryReversed_Replace": [
"Succeeded"
]
},
"type": "SetVariable"
},
"Compose_ConversationHistoryReversed_": {
"inputs": "@replace(variables('ConversationHistoryReversed'), '</p>', '')",
"runAfter": {
"Append_ConversationHistoryReversed": [
"Succeeded"
]
},
"type": "Compose"
},
"Compose_ConversationHistoryReversed_2": {
"inputs": "@substring(variables('ConversationHistoryReversed'), 1, sub(length(variables('ConversationHistoryReversed')),2))",
"runAfter": {
"Set_ConversationHistoryReversed_2": [
"Succeeded"
]
},
"type": "Compose"
},
"Compose_ConversationHistoryReversed_Replace": {
"inputs": "@replace(variables('ConversationHistoryReversed'), '<p>', '')",
"runAfter": {
"Set_ConversationHistoryReversed": [
"Succeeded"
]
},
"type": "Compose"
},
"Compose_ConversationHistoryReversed_SubString": {
"inputs": "@substring(variables('ConversationHistoryReversed'), 1, sub(length(variables('ConversationHistoryReversed')),2))",
"runAfter": {
"Compose_ConversationHistoryReversed": [
"Succeeded"
]
},
"type": "Compose"
},
"Compose_RequestBody": {
"inputs": "[\n{\n@{outputs('Compose_ConversationHistoryReversed_2')}\n}, \n {\n \"role\": \"system\", \"content\": \"You are a helpful assistant. Format all your replies in HTML code, but dont mention HTML in the response.\"\n }\n]",
"runAfter": {
"Compose_ConversationHistoryReversed_2": [
"Succeeded"
]
},
"runtimeConfiguration": {
"secureData": {
"properties": [
"inputs"
]
}
},
"type": "Compose"
},
"For_each_2": {
"actions": {
"Append_MessagesNextLink": {
"inputs": {
"name": "MessagesNextLink",
"value": "@body('Parse_JSON_-_Messages')?['@odata.nextLink']"
},
"runAfter": {
"Parse_JSON_-_Messages": [
"Succeeded"
]
},
"type": "AppendToStringVariable"
},
"For_each_5": {
"actions": {
"Condition_4": {
"actions": {
"Append_ArrayMessages": {
"inputs": {
"name": "ArrayMessages",
"value": {
"content": "@{items('for_each_5')?['body']?['content']}",
"role": "user"
}
},
"runAfter": {},
"type": "AppendToArrayVariable"
}
},
"else": {
"actions": {
"Append_ArrayMessages_2": {
"inputs": {
"name": "ArrayMessages",
"value": {
"content": " @{items('for_each_5')?['body']?['content']}",
"role": "assistant"
}
},
"runAfter": {},
"type": "AppendToArrayVariable"
}
}
},
"expression": {
"and": [
{
"not": {
"equals": [
"@items('For_each_5')?['from']?['id']",
"18c4a91b-4fa9-4fbd-ab1c-b39465d81baf"
]
}
}
]
},
"runAfter": {},
"type": "If"
}
},
"foreach": "@body('Parse_JSON_-_Messages')?['value']",
"runAfter": {
"Append_MessagesNextLink": [
"Succeeded"
]
},
"type": "Foreach"
},
"Parse_JSON_-_Messages": {
"inputs": {
"content": "@body('_HTTP_Get_Messages')",
"schema": {
"properties": {
"@@odata.context": {
"type": [
"string",
"null"
]
},
"@@odata.count": {
"type": "integer"
},
"@@odata.nextLink": {
"type": [
"string",
"null"
]
},
"value": {
"items": {
"properties": {
"attachments": {
"type": "array"
},
"body": {
"properties": {
"content": {
"type": [
"string",
"null"
]
},
"contentType": {
"type": [
"string",
"null"
]
}
},
"type": [
"object",
"null"
]
},
"channelIdentity": {},
"chatId": {
"type": [
"string",
"null"
]
},
"createdDateTime": {
"type": [
"string",
"null"
]
},
"deletedDateTime": {},
"etag": {
"type": [
"string",
"null"
]
},
"eventDetail": {},
"from": {
"properties": {
"application": {},
"device": {},
"user": {
"properties": {
"@@odata.type": {
"type": [
"string",
"null"
]
},
"displayName": {
"type": [
"string",
"null"
]
},
"id": {
"type": [
"string",
"null"
]
},
"tenantId": {
"type": [
"string",
"null"
]
},
"userIdentityType": {
"type": [
"string",
"null"
]
}
},
"type": [
"object",
"null"
]
}
},
"type": [
"object",
"null"
]
},
"id": {
"type": [
"string",
"null"
]
},
"importance": {
"type": [
"string",
"null"
]
},
"lastEditedDateTime": {},
"lastModifiedDateTime": {
"type": [
"string",
"null"
]
},
"locale": {
"type": [
"string",
"null"
]
},
"mentions": {
"type": "array"
},
"messageType": {
"type": [
"string",
"null"
]
},
"policyViolation": {},
"reactions": {
"type": "array"
},
"replyToId": {},
"subject": {},
"summary": {},
"webUrl": {}
},
"required": [
"id",
"replyToId",
"etag",
"messageType",
"createdDateTime",
"lastModifiedDateTime",
"lastEditedDateTime",
"deletedDateTime",
"subject",
"summary",
"chatId",
"importance",
"locale",
"webUrl",
"channelIdentity",
"policyViolation",
"eventDetail",
"from",
"body",
"attachments",
"mentions",
"reactions"
],
"type": [
"object",
"null"
]
},
"type": "array"
}
},
"type": [
"object",
"null"
]
}
},
"runAfter": {
"_HTTP_Get_Messages": [
"Succeeded"
]
},
"type": "ParseJson"
},
"Set_ConversationID": {
"inputs": {
"name": "ConversationID",
"value": "@items('For_each_2')?['conversationId']"
},
"runAfter": {},
"type": "SetVariable"
},
"Until_2": {
"actions": {
"Condition_2": {
"actions": {
"For_each_6": {
"actions": {
"Condition_5": {
"actions": {
"Append_ArrayMessages_3": {
"inputs": {
"name": "ArrayMessages",
"value": {
"content": "@{items('for_each_6')?['body']?['content']}",
"role": "user"
}
},
"runAfter": {},
"type": "AppendToArrayVariable"
}
},
"else": {
"actions": {
"Append_ArrayMessages_4": {
"inputs": {
"name": "ArrayMessages",
"value": {
"content": "@{items('for_each_6')?['body']?['content']}",
"role": "assistant"
}
},
"runAfter": {},
"type": "AppendToArrayVariable"
}
}
},
"expression": {
"and": [
{
"not": {
"equals": [
"@items('For_each_6')?['from']?['id']",
"18c4a91b-4fa9-4fbd-ab1c-b39465d81baf"
]
}
}
]
},
"runAfter": {},
"type": "If"
}
},
"foreach": "@body('Parse_MessagesNextLink')?['value']",
"runAfter": {
"Set_MessagesNextLink": [
"Succeeded"
]
},
"type": "Foreach"
},
"HTTP_MessageNextLink": {
"inputs": {
"authentication": {
"audience": "https://graph.microsoft.com",
"type": "ManagedServiceIdentity"
},
"method": "GET",
"uri": "@variables('MessagesNextLink')"
},
"runAfter": {},
"type": "Http"
},
"Parse_MessagesNextLink": {
"inputs": {
"content": "@body('HTTP_MessageNextLink')",
"schema": {
"properties": {
"@@odata.context": {
"type": [
"string",
"null"
]
},
"@@odata.count": {
"type": "integer"
},
"@@odata.nextLink": {
"type": [
"string",
"null"
]
},
"value": {
"items": {
"properties": {
"attachments": {
"type": "array"
},
"body": {
"properties": {
"content": {
"type": [
"string",
"null"
]
},
"contentType": {
"type": [
"string",
"null"
]
}
},
"type": [
"object",
"null"
]
},
"channelIdentity": {},
"chatId": {
"type": [
"string",
"null"
]
},
"createdDateTime": {
"type": [
"string",
"null"
]
},
"deletedDateTime": {},
"etag": {
"type": [
"string",
"null"
]
},
"eventDetail": {},
"from": {
"properties": {
"application": {},
"device": {},
"user": {
"properties": {
"@@odata.type": {
"type": [
"string",
"null"
]
},
"displayName": {
"type": [
"string",
"null"
]
},
"id": {
"type": [
"string",
"null"
]
},
"tenantId": {
"type": [
"string",
"null"
]
},
"userIdentityType": {
"type": [
"string",
"null"
]
}
},
"type": [
"object",
"null"
]
}
},
"type": [
"object",
"null"
]
},
"id": {
"type": [
"string",
"null"
]
},
"importance": {
"type": [
"string",
"null"
]
},
"lastEditedDateTime": {},
"lastModifiedDateTime": {
"type": [
"string",
"null"
]
},
"locale": {
"type": [
"string",
"null"
]
},
"mentions": {
"type": "array"
},
"messageType": {
"type": [
"string",
"null"
]
},
"policyViolation": {},
"reactions": {
"type": "array"
},
"replyToId": {},
"subject": {},
"summary": {},
"webUrl": {}
},
"required": [
"id",
"replyToId",
"etag",
"messageType",
"createdDateTime",
"lastModifiedDateTime",
"lastEditedDateTime",
"deletedDateTime",
"subject",
"summary",
"chatId",
"importance",
"locale",
"webUrl",
"channelIdentity",
"policyViolation",
"eventDetail",
"from",
"body",
"attachments",
"mentions",
"reactions"
],
"type": [
"object",
"null"
]
},
"type": "array"
}
},
"type": [
"object",
"null"
]
}
},
"runAfter": {
"HTTP_MessageNextLink": [
"Succeeded"
]
},
"type": "ParseJson"
},
"Set_MessagesNextLink": {
"inputs": {
"name": "MessagesNextLink",
"value": "@{body('Parse_MessagesNextLink')?['@odata.nextLink']}"
},
"runAfter": {
"Parse_MessagesNextLink": [
"Succeeded"
]
},
"type": "SetVariable"
}
},
"expression": {
"and": [
{
"not": {
"equals": [
"@variables('MessagesNextLink')",
""
]
}
}
]
},
"runAfter": {},
"type": "If"
}
},
"expression": "@equals(variables('MessagesNextLink'), '')",
"limit": {
"count": 60,
"timeout": "PT1H"
},
"runAfter": {
"For_each_5": [
"Succeeded"
]
},
"type": "Until"
},
"_HTTP_Get_Messages": {
"inputs": {
"authentication": {
"audience": "https://graph.microsoft.com",
"type": "ManagedServiceIdentity"
},
"method": "GET",
"uri": "https://graph.microsoft.com/v1.0/users/brumunddal@alexholmeset.onmicrosoft.com/chats/@{variables('ConversationID')}/messages/"
},
"runAfter": {
"Set_ConversationID": [
"Succeeded"
]
},
"type": "Http"
}
},
"foreach": "@triggerBody()?['value']",
"runAfter": {},
"type": "Foreach"
},
"For_each_4": {
"actions": {
"Post_ChatBot_Response_in_Teams_chat": {
"inputs": {
"body": {
"messageBody": "<p>@{items('For_each_4')?['message']?['content']}</p>",
"recipient": "@variables('ConversationID')"
},
"host": {
"connection": {
"name": "@parameters('$connections')['teams']['connectionId']"
}
},
"method": "post",
"path": "/beta/teams/conversation/message/poster/@{encodeURIComponent('User')}/location/@{encodeURIComponent('Group chat')}"
},
"runAfter": {},
"runtimeConfiguration": {
"secureData": {
"properties": [
"inputs",
"outputs"
]
}
},
"type": "ApiConnection"
}
},
"foreach": "@body('Parse_JSON_Azure_OpenAI_Response')?['choices']",
"runAfter": {
"Parse_JSON_Azure_OpenAI_Response": [
"Succeeded"
]
},
"type": "Foreach"
},
"HTTP_Azure_OpenAI": {
"inputs": {
"authentication": {
"audience": "https://graph.microsoft.com",
"type": "ManagedServiceIdentity"
},
"body": {
"messages": "@body('Parse_JSON_RequestBody')"
},
"headers": {
"api-key": "ff58585670df431cafab8e85fc523d13",
"content-type": "application/json"
},
"method": "POST",
"uri": "https://sharepointdocumentschat.openai.azure.com/openai/deployments/chatgpt4/chat/completions?api-version=2023-06-01-preview"
},
"runAfter": {
"Parse_JSON_RequestBody": [
"Succeeded"
]
},
"type": "Http"
},
"Parse_JSON_Azure_OpenAI_Response": {
"inputs": {
"content": "@body('HTTP_Azure_OpenAI')",
"schema": {
"properties": {
"choices": {
"items": {
"properties": {
"content_filter_results": {
"properties": {
"hate": {
"properties": {
"filtered": {
"type": "boolean"
},
"severity": {
"type": "string"
}
},
"type": "object"
},
"self_harm": {
"properties": {
"filtered": {
"type": "boolean"
},
"severity": {
"type": "string"
}
},
"type": "object"
},
"sexual": {
"properties": {
"filtered": {
"type": "boolean"
},
"severity": {
"type": "string"
}
},
"type": "object"
},
"violence": {
"properties": {
"filtered": {
"type": "boolean"
},
"severity": {
"type": "string"
}
},
"type": "object"
}
},
"type": "object"
},
"finish_reason": {
"type": "string"
},
"index": {
"type": "integer"
},
"message": {
"properties": {
"content": {
"type": "string"
},
"role": {
"type": "string"
}
},
"type": "object"
}
},
"required": [
"index",
"finish_reason",
"message",
"content_filter_results"
],
"type": "object"
},
"type": "array"
},
"created": {
"type": "integer"
},
"id": {
"type": "string"
},
"model": {
"type": "string"
},
"object": {
"type": "string"
},
"prompt_annotations": {
"items": {
"properties": {
"content_filter_results": {
"properties": {
"hate": {
"properties": {
"filtered": {
"type": "boolean"
},
"severity": {
"type": "string"
}
},
"type": "object"
},
"self_harm": {
"properties": {
"filtered": {
"type": "boolean"
},
"severity": {
"type": "string"
}
},
"type": "object"
},
"sexual": {
"properties": {
"filtered": {
"type": "boolean"
},
"severity": {
"type": "string"
}
},
"type": "object"
},
"violence": {
"properties": {
"filtered": {
"type": "boolean"
},
"severity": {
"type": "string"
}
},
"type": "object"
}
},
"type": "object"
},
"prompt_index": {
"type": "integer"
}
},
"required": [
"prompt_index",
"content_filter_results"
],
"type": "object"
},
"type": "array"
},
"usage": {
"properties": {
"completion_tokens": {
"type": "integer"
},
"prompt_tokens": {
"type": "integer"
},
"total_tokens": {
"type": "integer"
}
},
"type": "object"
}
},
"type": "object"
}
},
"runAfter": {
"HTTP_Azure_OpenAI": [
"Succeeded"
]
},
"type": "ParseJson"
},
"Parse_JSON_RequestBody": {
"inputs": {
"content": "@outputs('Compose_RequestBody')",
"schema": {
"items": {
"properties": {
"content": {
"type": "string"
},
"role": {
"type": "string"
}
},
"required": [
"content",
"role"
],
"type": "object"
},
"type": "array"
}
},
"runAfter": {
"Compose_RequestBody": [
"Succeeded"
]
},
"type": "ParseJson"
},
"Set_ConversationHistoryReversed": {
"inputs": {
"name": "ConversationHistoryReversed",
"value": "@{outputs('Compose_ConversationHistoryReversed_')}"
},
"runAfter": {
"Compose_ConversationHistoryReversed_": [
"Succeeded"
]
},
"type": "SetVariable"
},
"Set_ConversationHistoryReversed_2": {
"inputs": {
"name": "ConversationHistoryReversed",
"value": "@{outputs('Compose_ConversationHistoryReversed_SubString')}"
},
"runAfter": {
"Compose_ConversationHistoryReversed_SubString": [
"Succeeded"
]
},
"type": "SetVariable"
}
},
"expression": {
"and": [
{
"not": {
"equals": [
"@variables('BotUserID')",
"18c4a91b-4fa9-4fbd-ab1c-b39465d81baf"
]
}
}
]
},
"runAfter": {
"For_each": [
"Succeeded"
]
},
"type": "If"
},
"ConversationHistory": {
"inputs": {
"variables": [
{
"name": "ConversationHistory",
"type": "string"
}
]
},
"runAfter": {
"ConversationID": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"ConversationHistoryArray": {
"inputs": {
"variables": [
{
"name": "ConversationHistoryArray",
"type": "array"
}
]
},
"runAfter": {
"ConversationHistoryReversed": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"ConversationHistoryReversed": {
"inputs": {
"variables": [
{
"name": "ConversationHistoryReversed",
"type": "string"
}
]
},
"runAfter": {
"ConversationHistoryString": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"ConversationHistoryString": {
"inputs": {
"variables": [
{
"name": "ConversationHistoryString",
"type": "string"
}
]
},
"runAfter": {
"ConversationHistory": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"ConversationID": {
"inputs": {
"variables": [
{
"name": "ConversationID",
"type": "string"
}
]
},
"runAfter": {
"Bot_User": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"For_each": {
"actions": {
"Get_message_details": {
"inputs": {
"body": {
"recipient": "@items('For_each')?['conversationId']"
},
"host": {
"connection": {
"name": "@parameters('$connections')['teams']['connectionId']"
}
},
"method": "post",
"path": "/beta/teams/messages/@{encodeURIComponent(items('For_each')?['messageId'])}/messageType/@{encodeURIComponent('groupchat')}"
},
"runAfter": {},
"type": "ApiConnection"
},
"Parse_JSON_-_Bot_User": {
"inputs": {
"content": "@body('Get_message_details')?['from']?['user']",
"schema": {
"properties": {
"@@odata.type": {
"type": "string"
},
"displayName": {
"type": "string"
},
"id": {
"type": "string"
},
"tenantId": {
"type": "string"
},
"userIdentityType": {
"type": "string"
}
},
"type": "object"
}
},
"runAfter": {
"Parse_JSON_-_New_Message": [
"Succeeded"
]
},
"type": "ParseJson"
},
"Parse_JSON_-_New_Message": {
"inputs": {
"content": "@body('Get_message_details')",
"schema": {
"properties": {
"@@odata.context": {
"type": [
"string",
"null"
]
},
"attachments": {
"type": "array"
},
"body": {
"properties": {
"content": {
"type": [
"string",
"null"
]
},
"contentType": {
"type": [
"string",
"null"
]
},
"plainTextContent": {
"type": [
"string",
"null"
]
}
},
"type": [
"object",
"null"
]
},
"channelIdentity": {},
"chatId": {
"type": [
"string",
"null"
]
},
"conversationId": {
"type": [
"string",
"null"
]
},
"createdDateTime": {
"type": [
"string",
"null"
]
},
"deletedDateTime": {},
"etag": {
"type": [
"string",
"null"
]
},
"eventDetail": {},
"from": {
"properties": {
"application": {},
"device": {},
"user": {
"properties": {
"@@odata.type": {
"type": [
"string",
"null"
]
},
"displayName": {
"type": [
"string",
"null"
]
},
"id": {
"type": [
"string",
"null"
]
},
"tenantId": {
"type": [
"string",
"null"
]
},
"userIdentityType": {
"type": [
"string",
"null"
]
}
},
"type": [
"object",
"null"
]
}
},
"type": [
"object",
"null"
]
},
"id": {
"type": [
"string",
"null"
]
},
"importance": {
"type": [
"string",
"null"
]
},
"lastEditedDateTime": {},
"lastModifiedDateTime": {
"type": [
"string",
"null"
]
},
"locale": {
"type": [
"string",
"null"
]
},
"mentions": {
"type": "array"
},
"messageLink": {
"type": [
"string",
"null"
]
},
"messageType": {
"type": [
"string",
"null"
]
},
"policyViolation": {},
"reactions": {
"type": "array"
},
"replyToId": {
"type": [
"string",
"null"
]
},
"subject": {},
"summary": {},
"threadType": {
"type": [
"string",
"null"
]
},
"webUrl": {}
},
"type": [
"object",
"null"
]
}
},
"runAfter": {
"Get_message_details": [
"Succeeded"
]
},
"type": "ParseJson"
},
"Set_Bot_User": {
"inputs": {
"name": "BotUserID",
"value": "@body('Parse_JSON_-_Bot_User')?['id']"
},
"runAfter": {
"Set_NewMessageFromChat": [
"Succeeded"
]
},
"type": "SetVariable"
},
"Set_NewMessageFromChat": {
"inputs": {
"name": "NewMessgeFromChat",
"value": "@{body('Parse_JSON_-_New_Message')?['body']?['plainTextContent']}"
},
"runAfter": {
"Parse_JSON_-_Bot_User": [
"Succeeded"
]
},
"type": "SetVariable"
}
},
"foreach": "@triggerBody()?['value']",
"runAfter": {
"Initialize_MessagesNextLink": [
"Succeeded"
]
},
"type": "Foreach"
},
"Initialize_ArrayMessages": {
"inputs": {
"variables": [
{
"name": "ArrayMessages",
"type": "array"
}
]
},
"runAfter": {
"Initialize_ConversationHistoryObject": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"Initialize_ConversationHistoryObject": {
"inputs": {
"variables": [
{
"name": "ConversationHistoryObject",
"type": "object"
}
]
},
"runAfter": {
"ConversationHistoryArray": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"Initialize_MessagesNextLink": {
"inputs": {
"variables": [
{
"name": "MessagesNextLink",
"type": "string"
}
]
},
"runAfter": {
"Initialize_ArrayMessages": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"NewMessageFromChat": {
"inputs": {
"variables": [
{
"name": "NewMessgeFromChat",
"type": "string"
}
]
},
"runAfter": {},
"type": "InitializeVariable"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {
"$connections": {
"defaultValue": {},
"type": "Object"
}
},
"triggers": {
"When_a_new_chat_message_is_added": {
"inputs": {
"body": {
"notificationUrl": "@{listCallbackUrl()}"
},
"host": {
"connection": {
"name": "@parameters('$connections')['teams']['connectionId']"
}
},
"path": "/beta/subscriptions/chatmessagetrigger"
},
"type": "ApiConnectionWebhook"
}
}
},
"parameters": {
"$connections": {
"value": {
"teams": {
"connectionId": "",
"connectionName": "",
"id": ""
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment