From 0b5a424b69209aeb21ce4588b6af3bc5f64821bc Mon Sep 17 00:00:00 2001 From: Akash K <57758277+amk-dev@users.noreply.github.com> Date: Mon, 30 Sep 2024 22:21:14 +0530 Subject: [PATCH] feat: modify body with ai & feedback on ai requests `hoppscotch-common` bindings (#4386) Co-authored-by: jamesgeorge007 <25279263+jamesgeorge007@users.noreply.github.com> --- packages/hoppscotch-common/locales/en.json | 10 +- packages/hoppscotch-common/package.json | 1 + .../components/aiexperiments/MergeView.vue | 82 ++++++++++ .../aiexperiments/ModifyBodyModal.vue | 140 ++++++++++++++++++ .../src/components/collections/AddRequest.vue | 92 ++++++++++-- .../components/collections/EditRequest.vue | 91 ++++++++++-- .../components/collections/SaveRequest.vue | 90 +++++++++-- .../collections/graphql/AddRequest.vue | 88 +++++++++-- .../collections/graphql/EditRequest.vue | 88 +++++++++-- .../src/components/http/RawBody.vue | 24 +++ .../src/composables/ai-experiments.ts | 122 ++++++++++++++- .../src/platform/experiments.ts | 28 +++- pnpm-lock.yaml | 14 ++ 13 files changed, 791 insertions(+), 79 deletions(-) create mode 100644 packages/hoppscotch-common/src/components/aiexperiments/MergeView.vue create mode 100644 packages/hoppscotch-common/src/components/aiexperiments/ModifyBodyModal.vue diff --git a/packages/hoppscotch-common/locales/en.json b/packages/hoppscotch-common/locales/en.json index b1e96397a..875ff64d5 100644 --- a/packages/hoppscotch-common/locales/en.json +++ b/packages/hoppscotch-common/locales/en.json @@ -1138,6 +1138,14 @@ }, "ai_experiments": { "generate_request_name": "Generate Request Name Using AI", - "generate_or_modify_request_body": "Generate or Modify Request Body" + "generate_or_modify_request_body": "Generate or Modify Request Body", + "modify_with_ai": "Modify with AI", + "generate_or_modify_request_body_input_placeholder": "Enter your prompt to modify request body", + "accept_change": "Accept Change", + "feedback_success": "Feedback submitted successfully", + "feedback_failure": "Failed to submit feedback", + "feedback_thank_you": "Thank you for your feedback!", + "feedback_cta_text_long": "Rate the generation, helps us to improve", + "feedback_cta_request_name": "Did you like name generated?" } } diff --git a/packages/hoppscotch-common/package.json b/packages/hoppscotch-common/package.json index 66302da93..62ebd7590 100644 --- a/packages/hoppscotch-common/package.json +++ b/packages/hoppscotch-common/package.json @@ -30,6 +30,7 @@ "@codemirror/language": "6.10.1", "@codemirror/legacy-modes": "6.3.3", "@codemirror/lint": "6.5.0", + "@codemirror/merge": "6.7.0", "@codemirror/search": "6.5.6", "@codemirror/state": "6.4.1", "@codemirror/view": "6.25.1", diff --git a/packages/hoppscotch-common/src/components/aiexperiments/MergeView.vue b/packages/hoppscotch-common/src/components/aiexperiments/MergeView.vue new file mode 100644 index 000000000..05efd5d26 --- /dev/null +++ b/packages/hoppscotch-common/src/components/aiexperiments/MergeView.vue @@ -0,0 +1,82 @@ + + + diff --git a/packages/hoppscotch-common/src/components/aiexperiments/ModifyBodyModal.vue b/packages/hoppscotch-common/src/components/aiexperiments/ModifyBodyModal.vue new file mode 100644 index 000000000..66957de27 --- /dev/null +++ b/packages/hoppscotch-common/src/components/aiexperiments/ModifyBodyModal.vue @@ -0,0 +1,140 @@ + + + diff --git a/packages/hoppscotch-common/src/components/collections/AddRequest.vue b/packages/hoppscotch-common/src/components/collections/AddRequest.vue index 8633cf823..011c67dfb 100644 --- a/packages/hoppscotch-common/src/components/collections/AddRequest.vue +++ b/packages/hoppscotch-common/src/components/collections/AddRequest.vue @@ -3,7 +3,7 @@ v-if="show" dialog :title="t('request.new')" - @close="$emit('hide-modal')" + @close="hideModal" > @@ -54,9 +95,14 @@ import { useI18n } from "@composables/i18n" import { useToast } from "@composables/toast" import { useService } from "dioc/vue" import { RESTTabService } from "~/services/tab/rest" -import { useRequestNameGeneration } from "~/composables/ai-experiments" +import { + useRequestNameGeneration, + useSubmitFeedback, +} from "~/composables/ai-experiments" import { HoppRESTRequest } from "@hoppscotch/data" import IconSparkle from "~icons/lucide/sparkles" +import IconThumbsUp from "~icons/lucide/thumbs-up" +import IconThumbsDown from "~icons/lucide/thumbs-down" const toast = useToast() const t = useI18n() @@ -85,8 +131,22 @@ const { generateRequestName, isGenerateRequestNamePending, canDoRequestNameGeneration, + lastTraceID, } = useRequestNameGeneration(editingName) +watch( + () => props.show, + (newVal) => { + if (!newVal) { + submittedFeedback.value = false + lastTraceID.value = null + } + } +) + +const submittedFeedback = ref(false) +const { submitFeedback, isSubmitFeedbackPending } = useSubmitFeedback() + const tabs = useService(RESTTabService) watch( () => props.show, diff --git a/packages/hoppscotch-common/src/components/collections/EditRequest.vue b/packages/hoppscotch-common/src/components/collections/EditRequest.vue index cfcd72c70..be3901e6d 100644 --- a/packages/hoppscotch-common/src/components/collections/EditRequest.vue +++ b/packages/hoppscotch-common/src/components/collections/EditRequest.vue @@ -30,20 +30,61 @@ @@ -53,8 +94,14 @@ import { useI18n } from "@composables/i18n" import { useToast } from "@composables/toast" import { HoppRESTRequest } from "@hoppscotch/data" import { useVModel } from "@vueuse/core" -import { useRequestNameGeneration } from "~/composables/ai-experiments" +import { ref, watch } from "vue" +import { + useRequestNameGeneration, + useSubmitFeedback, +} from "~/composables/ai-experiments" import IconSparkle from "~icons/lucide/sparkles" +import IconThumbsUp from "~icons/lucide/thumbs-up" +import IconThumbsDown from "~icons/lucide/thumbs-down" const toast = useToast() const t = useI18n() @@ -85,8 +132,22 @@ const { generateRequestName, canDoRequestNameGeneration, isGenerateRequestNamePending, + lastTraceID, } = useRequestNameGeneration(editingName) +watch( + () => props.show, + (newVal) => { + if (!newVal) { + submittedFeedback.value = false + lastTraceID.value = null + } + } +) + +const submittedFeedback = ref(false) +const { submitFeedback, isSubmitFeedbackPending } = useSubmitFeedback() + const editRequest = () => { if (editingName.value.trim() === "") { toast.error(t("request.invalid_name")) diff --git a/packages/hoppscotch-common/src/components/collections/SaveRequest.vue b/packages/hoppscotch-common/src/components/collections/SaveRequest.vue index 569af1a73..7531b10ee 100644 --- a/packages/hoppscotch-common/src/components/collections/SaveRequest.vue +++ b/packages/hoppscotch-common/src/components/collections/SaveRequest.vue @@ -52,20 +52,61 @@ @@ -84,7 +125,10 @@ import * as TE from "fp-ts/TaskEither" import { pipe } from "fp-ts/function" import { cloneDeep } from "lodash-es" import { computed, nextTick, reactive, ref, watch } from "vue" -import { useRequestNameGeneration } from "~/composables/ai-experiments" +import { + useRequestNameGeneration, + useSubmitFeedback, +} from "~/composables/ai-experiments" import { GQLError } from "~/helpers/backend/GQLClient" import { createRequestInCollection, @@ -103,6 +147,8 @@ import { GQLTabService } from "~/services/tab/graphql" import { RESTTabService } from "~/services/tab/rest" import { TeamWorkspace } from "~/services/workspace.service" import IconSparkle from "~icons/lucide/sparkles" +import IconThumbsDown from "~icons/lucide/thumbs-down" +import IconThumbsUp from "~icons/lucide/thumbs-up" const t = useI18n() const toast = useToast() @@ -185,8 +231,22 @@ const { canDoRequestNameGeneration, generateRequestName, isGenerateRequestNamePending, + lastTraceID, } = useRequestNameGeneration(requestName) +watch( + () => props.show, + (newVal) => { + if (!newVal) { + submittedFeedback.value = false + lastTraceID.value = null + } + } +) + +const submittedFeedback = ref(false) +const { submitFeedback, isSubmitFeedbackPending } = useSubmitFeedback() + watch( () => [RESTTabs.currentActiveTab.value, GQLTabs.currentActiveTab.value], () => { diff --git a/packages/hoppscotch-common/src/components/collections/graphql/AddRequest.vue b/packages/hoppscotch-common/src/components/collections/graphql/AddRequest.vue index e123cc8f9..757c76022 100644 --- a/packages/hoppscotch-common/src/components/collections/graphql/AddRequest.vue +++ b/packages/hoppscotch-common/src/components/collections/graphql/AddRequest.vue @@ -30,19 +30,60 @@ @@ -54,9 +95,14 @@ import { HoppRESTRequest } from "@hoppscotch/data" import { useService } from "dioc/vue" import { ref, watch } from "vue" -import { useRequestNameGeneration } from "~/composables/ai-experiments" +import { + useRequestNameGeneration, + useSubmitFeedback, +} from "~/composables/ai-experiments" import { GQLTabService } from "~/services/tab/graphql" import IconSparkle from "~icons/lucide/sparkles" +import IconThumbsUp from "~icons/lucide/thumbs-up" +import IconThumbsDown from "~icons/lucide/thumbs-down" const toast = useToast() const t = useI18n() @@ -86,8 +132,22 @@ const { generateRequestName, isGenerateRequestNamePending, canDoRequestNameGeneration, + lastTraceID, } = useRequestNameGeneration(editingName) +watch( + () => props.show, + (newVal) => { + if (!newVal) { + submittedFeedback.value = false + lastTraceID.value = null + } + } +) + +const submittedFeedback = ref(false) +const { submitFeedback, isSubmitFeedbackPending } = useSubmitFeedback() + watch( () => props.show, (show) => { diff --git a/packages/hoppscotch-common/src/components/collections/graphql/EditRequest.vue b/packages/hoppscotch-common/src/components/collections/graphql/EditRequest.vue index 2f9c0886e..142beca47 100644 --- a/packages/hoppscotch-common/src/components/collections/graphql/EditRequest.vue +++ b/packages/hoppscotch-common/src/components/collections/graphql/EditRequest.vue @@ -30,19 +30,60 @@ @@ -52,9 +93,14 @@ import { useI18n } from "@composables/i18n" import { useToast } from "@composables/toast" import { HoppGQLRequest } from "@hoppscotch/data" import { ref, watch } from "vue" -import { useRequestNameGeneration } from "~/composables/ai-experiments" +import { + useRequestNameGeneration, + useSubmitFeedback, +} from "~/composables/ai-experiments" import { editGraphqlRequest } from "~/newstore/collections" import IconSparkle from "~icons/lucide/sparkles" +import IconThumbsUp from "~icons/lucide/thumbs-up" +import IconThumbsDown from "~icons/lucide/thumbs-down" const t = useI18n() const toast = useToast() @@ -85,8 +131,22 @@ const { canDoRequestNameGeneration, generateRequestName, isGenerateRequestNamePending, + lastTraceID, } = useRequestNameGeneration(editingName) +watch( + () => props.show, + (newVal) => { + if (!newVal) { + submittedFeedback.value = false + lastTraceID.value = null + } + } +) + +const submittedFeedback = ref(false) +const { submitFeedback, isSubmitFeedbackPending } = useSubmitFeedback() + const saveRequest = () => { if (!editingName.value) { toast.error(`${t("collection.invalid_name")}`) diff --git a/packages/hoppscotch-common/src/components/http/RawBody.vue b/packages/hoppscotch-common/src/components/http/RawBody.vue index 42fc11c9f..35532f615 100644 --- a/packages/hoppscotch-common/src/components/http/RawBody.vue +++ b/packages/hoppscotch-common/src/components/http/RawBody.vue @@ -42,6 +42,13 @@ :icon="prettifyIcon" @click="prettifyRequestBody" /> +