From 60960625ea71f880cc811ccd108ee0d25dec0746 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Mon, 4 Nov 2024 02:19:23 +0000 Subject: [PATCH] feat: GPT generated task spec --- .../features/commands/shared/task-creation.ts | 66 ++++++++++++++++++- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/src/bot/features/commands/shared/task-creation.ts b/src/bot/features/commands/shared/task-creation.ts index 773cffe..9892fa7 100644 --- a/src/bot/features/commands/shared/task-creation.ts +++ b/src/bot/features/commands/shared/task-creation.ts @@ -23,8 +23,6 @@ feature.command("newtask", logHandle("task-creation"), chatAction("typing"), asy const taskToCreate = ctx.message.reply_to_message.text; - console.log("taskToCreate", taskToCreate); - if (!taskToCreate || taskToCreate.length < 10) { return await ctx.reply("A new task needs substantially more content than that"); } @@ -54,12 +52,74 @@ feature.command("newtask", logHandle("task-creation"), chatAction("typing"), asy return await replyFn("Only admins can create tasks"); } + const directives = [ + "Consume the user's message and begin to transform it into a GitHub task specification", + "Include a relevant short title for opening the task with", + "Include the task's description based on the user's message", + "Include any relevant context or constraints", + "Use a structured approach to writing the task", + "Do so without comment or directive, just the requested 'outputStyle'", + ]; + + const constraints = [ + "Never hallucinate details into the specification", + "Ensure the task is clear and actionable", + "Use GitHub flavoured markdown by default", + "Return the markdown within a code block to maintain formatting on GitHub", + "DO NOT use backticks in the markdown", + ]; + + const additionalContext = [ + "The task will be created via the GitHub app under your name; UbiquityOS", + "The correct repository will be selected by the admin who invoked this intent", + "Your output will be JSON parsed for the 'title' and 'body' keys", + "The user credit will be injected into the footer of your spec, so always leave it blank following a '---' separator", + ]; + + const outputStyle = `{ title: "Task Title", body: "Task Body" }`; + + const llmResponse = await ctx.adapters.ai.createCompletion({ + embeddingsSearch: [], + directives, + constraints, + additionalContext, + outputStyle, + model: "gpt-4o", + query: taskToCreate, + }); + + if (!llmResponse) { + return await ctx.reply("Failed to create task"); + } + + const taskFromLlm = llmResponse.answer; + + let taskDetails; + + try { + taskDetails = JSON.parse(taskFromLlm); + } catch { + return await ctx.reply("Failed to parse task"); + } + + const userCredits = await ctx.adapters.storage.retrieveUserByTelegramId(fromId); + + const username = userCredits?.github_username ?? "Anonymous"; + const chatLink = ctx.chat?.type !== "private" && (await ctx.createChatInviteLink()); + + const chatLinkText = chatLink ? ` [here](${chatLink.invite_link})` : ""; + const fullSpec = `${taskDetails.body}\n\n_Originally created by @${username} via Telegram${chatLinkText}_`; const task = await ctx.octokit.rest.issues.create({ owner, repo, - title: taskToCreate, + title: taskDetails.title, + body: fullSpec, }); + if (!task) { + return await ctx.reply("Failed to create task"); + } + return await ctx.reply(`Task created: ${task.data.html_url}`); });