diff --git a/step-templates/octopus-ai-prompt.json b/step-templates/octopus-ai-prompt.json index 11ee524ff..9ec043478 100644 --- a/step-templates/octopus-ai-prompt.json +++ b/step-templates/octopus-ai-prompt.json @@ -1,9 +1,9 @@ { "Id": "8ce3eb55-2c35-45c2-be8c-27e71ffbf032", "Name": "Octopus - Prompt AI", - "Description": "Prompt the Octopus AI service with a message and store the result in a variable. See https://octopus.com/docs/administration/copilot for more information.", + "Description": "This step has been deprecated. Do not use this step in new projects.", "ActionType": "Octopus.Script", - "Version": 4, + "Version": 5, "CommunityActionTemplateId": null, "Packages": [], "GitDependencies": [], @@ -11,60 +11,9 @@ "Octopus.Action.RunOnServer": "true", "Octopus.Action.Script.ScriptSource": "Inline", "Octopus.Action.Script.Syntax": "Python", - "Octopus.Action.Script.ScriptBody": "import os\nimport re\nimport http.client\nimport json\nimport time\nfrom urllib.parse import quote\n\n# If this script is not being run as part of an Octopus step, return variables from environment variables.\n# Periods are replaced with underscores, and the variable name is converted to uppercase\nif 'get_octopusvariable' not in globals():\n def get_octopusvariable(variable):\n return os.environ.get(re.sub('\\\\.', '_', variable.upper()))\n\nif 'set_octopusvariable' not in globals():\n def set_octopusvariable(variable, value):\n print(f\"Setting {variable} to {value}\")\n\n# If this script is not being run as part of an Octopus step, print directly to std out.\nif 'printverbose' not in globals():\n def printverbose(msg):\n print(msg)\n\ndef make_post_request(message, auto_approve, github_token, octopus_api_key, octopus_server, retry = 0):\n \"\"\"\n Query the Octopus AI service with a message.\n :param message: The prompt message\n :param github_token: The GitHub token\n :param octopus_api_key: The Octopus API key\n :param octopus_server: The Octopus URL\n :return: The AI response\n \"\"\"\n headers = {\n \"X-GitHub-Token\": github_token,\n \"X-Octopus-ApiKey\": octopus_api_key,\n \"X-Octopus-Server\": octopus_server,\n \"Content-Type\": \"application/json\"\n }\n body = json.dumps({\"messages\": [{\"content\": message}]}).encode(\"utf8\")\n\n conn = http.client.HTTPSConnection(\"aiagent.octopus.com\", timeout=240)\n conn.request(\"POST\", \"/api/form_handler\", body, headers)\n response = conn.getresponse()\n response_data = response.read().decode(\"utf8\")\n conn.close()\n\n if response.status < 200 or response.status > 300:\n if retry < 2:\n printverbose(f\"Request to AI Agent failed with status code {response.status} and message: {response.reason}. Retrying...\")\n time.sleep(400)\n return make_post_request(message, auto_approve, github_token, octopus_api_key, octopus_server, retry + 1)\n return f\"Request to AI Agent failed with status code {response.status} and message: {response.reason}\"\n\n if is_action_response(response_data):\n if auto_approve:\n id = action_response_id(response_data)\n\n if not id:\n return \"Prompt required approval, but no confirmation ID was found in the response.\"\n\n conn = http.client.HTTPSConnection(\"aiagent.octopus.com\", timeout=240)\n conn.request(\"POST\", \"/api/form_handler?confirmation_id=\" + quote(id, safe='') + \"&confirmation_state=accepted\", body, headers)\n response = conn.getresponse()\n response_data = response.read().decode(\"utf8\")\n conn.close()\n return convert_from_sse_response(response_data)\n else:\n return \"Prompt required approval, but auto-approval is disabled. Please enable the auto-approval option in the step.\"\n\n return convert_from_sse_response(response_data)\n\n\ndef convert_from_sse_response(sse_response):\n \"\"\"\n Converts an SSE response into a string.\n :param sse_response: The SSE response to convert.\n :return: The string representation of the SSE response.\n \"\"\"\n\n responses = map(\n lambda line: json.loads(line.replace(\"data: \", \"\")),\n filter(lambda line: line.strip().startswith(\"data:\"), sse_response.split(\"\\n\")),\n )\n content_responses = filter(\n lambda response: \"content\" in response[\"choices\"][0][\"delta\"], responses\n )\n return \"\\n\".join(\n map(\n lambda line: line[\"choices\"][0][\"delta\"][\"content\"].strip(),\n content_responses,\n )\n )\n\ndef is_action_response(sse_response):\n responses = map(\n lambda line: json.loads(line.replace(\"data: \", \"\")),\n filter(lambda line: line.strip().startswith(\"data:\"), sse_response.split(\"\\n\")),\n )\n\n return any(response.get(\"type\") == \"action\" for response in responses)\n\ndef action_response_id(sse_response):\n responses = map(\n lambda line: json.loads(line.replace(\"data: \", \"\")),\n filter(lambda line: line.strip().startswith(\"data:\"), sse_response.split(\"\\n\")),\n )\n\n action = next(filter(lambda response: response.get(\"type\") == \"action\", responses))\n\n return action.get(\"confirmation\", {}).get(\"id\")\n\nstep_name = get_octopusvariable(\"Octopus.Step.Name\")\nmessage = get_octopusvariable(\"OctopusAI.Prompt\")\ngithub_token = get_octopusvariable(\"OctopusAI.GitHub.Token\")\noctopus_api = get_octopusvariable(\"OctopusAI.Octopus.APIKey\")\noctopus_url = get_octopusvariable(\"OctopusAI.Octopus.Url\")\nauto_approve = get_octopusvariable(\"OctopusAI.AutoApprove\").casefold() == \"true\"\n\nif not (octopus_api and octopus_api.startswith(\"API-\")):\n print(\"You must supply a valid Octopus API key\")\n\nif not (octopus_url and octopus_url.startswith(\"http\")):\n print(\"You must supply a valid Octopus URL\")\n\nif not (message and message.strip()):\n print(\"You must supply a prompt\")\n\nresult = make_post_request(message, auto_approve, github_token, octopus_api, octopus_url)\n\nset_octopusvariable(\"AIResult\", result)\n\nprint(result)\nprint(f\"AI result is available in the variable: Octopus.Action[{step_name}].Output.AIResult\")\n" + "Octopus.Action.Script.ScriptBody": "print(\"This step has been deprecated\")\n" }, - "Parameters": [ - { - "Id": "10c6b0c8-92e0-4bce-91a7-0d1d0b275c1a", - "Name": "OctopusAI.Prompt", - "Label": "The prompt to send to the AI service", - "HelpText": null, - "DefaultValue": "Describe deployment \"#{Octopus.Release.Number}\" for project \"#{Octopus.Project.Name}\" to environment \"#{Octopus.Environment.Name}\" in space \"#{Octopus.Space.Name}\"", - "DisplaySettings": { - "Octopus.ControlType": "MultiLineText" - } - }, - { - "Id": "831e4eda-0ad3-460a-9375-42ce580bfd7d", - "Name": "OctopusAI.GitHub.Token", - "Label": "The GitHub Token", - "HelpText": null, - "DefaultValue": "", - "DisplaySettings": { - "Octopus.ControlType": "Sensitive" - } - }, - { - "Id": "7d6a276d-fcb5-4dd9-b5a3-b7a3b48782c1", - "Name": "OctopusAI.Octopus.APIKey", - "Label": "The Octopus API Key", - "HelpText": null, - "DefaultValue": "", - "DisplaySettings": { - "Octopus.ControlType": "Sensitive" - } - }, - { - "Id": "3eb54042-8169-4ae4-8910-a02b14325e71", - "Name": "OctopusAI.Octopus.Url", - "Label": "The Octopus URL", - "HelpText": null, - "DefaultValue": "#{Octopus.Web.ServerUri}", - "DisplaySettings": { - "Octopus.ControlType": "SingleLineText" - } - }, - { - "Id": "380c09c0-2af8-4866-a1a7-db77fa89f7d8", - "Name": "OctopusAI.AutoApprove", - "Label": "Enable this to auto approve any prompts that require approval", - "HelpText": null, - "DefaultValue": "False", - "DisplaySettings": { - "Octopus.ControlType": "Checkbox" - } - } - ], + "Parameters": [], "StepPackageId": "Octopus.Script", "$Meta": { "ExportedAt": "2024-10-03T20:35:41.372Z",