diff --git a/packages/hoppscotch-common/locales/en.json b/packages/hoppscotch-common/locales/en.json
index 541ec7d6..04fd14df 100644
--- a/packages/hoppscotch-common/locales/en.json
+++ b/packages/hoppscotch-common/locales/en.json
@@ -1250,6 +1250,9 @@
"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 the generated name?",
- "modify_request_body_error": "Failed to modify request body"
+ "modify_request_body_error": "Failed to modify request body",
+ "generate_or_modify_prerequest_input_placeholder": "Enter a prompt to generate or modify the pre-request script",
+ "generate_or_modify_test_script_input_placeholder": "Enter a prompt to generate or modify the test script",
+ "modify_test_script_error": "Failed to modify test script"
}
}
diff --git a/packages/hoppscotch-common/src/components.d.ts b/packages/hoppscotch-common/src/components.d.ts
index aafb1837..109b1ced 100644
--- a/packages/hoppscotch-common/src/components.d.ts
+++ b/packages/hoppscotch-common/src/components.d.ts
@@ -16,6 +16,8 @@ declare module 'vue' {
AccessTokensOverview: typeof import('./components/accessTokens/Overview.vue')['default']
AiexperimentsMergeView: typeof import('./components/aiexperiments/MergeView.vue')['default']
AiexperimentsModifyBodyModal: typeof import('./components/aiexperiments/ModifyBodyModal.vue')['default']
+ AiexperimentsModifyPreRequestModal: typeof import('./components/aiexperiments/ModifyPreRequestModal.vue')['default']
+ AiexperimentsModifyTestScriptModal: typeof import('./components/aiexperiments/ModifyTestScriptModal.vue')['default']
AppActionHandler: typeof import('./components/app/ActionHandler.vue')['default']
AppAnnouncement: (typeof import("./components/app/Announcement.vue"))["default"]
AppBanner: typeof import('./components/app/Banner.vue')['default']
diff --git a/packages/hoppscotch-common/src/components/aiexperiments/ModifyPreRequestModal.vue b/packages/hoppscotch-common/src/components/aiexperiments/ModifyPreRequestModal.vue
new file mode 100644
index 00000000..80256336
--- /dev/null
+++ b/packages/hoppscotch-common/src/components/aiexperiments/ModifyPreRequestModal.vue
@@ -0,0 +1,159 @@
+
+
+
+
+
+ {
+ if (e.key === 'Enter') {
+ await modifyPreRequestScript()
+ submittedFeedback = false
+ }
+ }
+ "
+ />
+
+ {
+ await modifyPreRequestScript()
+ submittedFeedback = false
+ }
+ "
+ />
+
+
+
+
+
+
+
+
+
+
{{ t("ai_experiments.feedback_cta_text_long") }}
+
+ {
+ if (lastTraceID) {
+ await submitFeedback('positive', lastTraceID)
+ submittedFeedback = true
+ }
+ }
+ "
+ />
+ {
+ if (lastTraceID) {
+ await submitFeedback('negative', lastTraceID)
+ submittedFeedback = true
+ }
+ }
+ "
+ />
+
+
+
+
+
+
{{ t("ai_experiments.feedback_thank_you") }}
+
+
+
+
+ {
+ emit('updateScript', generatedScriptContent)
+ emit('closeModal')
+ }
+ "
+ />
+
+
+
+
+
+
+
diff --git a/packages/hoppscotch-common/src/components/aiexperiments/ModifyTestScriptModal.vue b/packages/hoppscotch-common/src/components/aiexperiments/ModifyTestScriptModal.vue
new file mode 100644
index 00000000..50b0d524
--- /dev/null
+++ b/packages/hoppscotch-common/src/components/aiexperiments/ModifyTestScriptModal.vue
@@ -0,0 +1,159 @@
+
+
+
+
+
+ {
+ if (e.key === 'Enter') {
+ await modifyTestScript()
+ submittedFeedback = false
+ }
+ }
+ "
+ />
+
+ {
+ await modifyTestScript()
+ submittedFeedback = false
+ }
+ "
+ />
+
+
+
+
+
+
+
+
+
+
{{ t("ai_experiments.feedback_cta_text_long") }}
+
+ {
+ if (lastTraceID) {
+ await submitFeedback('positive', lastTraceID)
+ submittedFeedback = true
+ }
+ }
+ "
+ />
+ {
+ if (lastTraceID) {
+ await submitFeedback('negative', lastTraceID)
+ submittedFeedback = true
+ }
+ }
+ "
+ />
+
+
+
+
+
+
{{ t("ai_experiments.feedback_thank_you") }}
+
+
+
+
+ {
+ emit('updateScript', generatedScriptContent)
+ emit('closeModal')
+ }
+ "
+ />
+
+
+
+
+
+
+
diff --git a/packages/hoppscotch-common/src/components/http/PreRequestScript.vue b/packages/hoppscotch-common/src/components/http/PreRequestScript.vue
index 1646cfec..0cf1caaf 100644
--- a/packages/hoppscotch-common/src/components/http/PreRequestScript.vue
+++ b/packages/hoppscotch-common/src/components/http/PreRequestScript.vue
@@ -27,6 +27,13 @@
:icon="IconWrapText"
@click.prevent="toggleNestedSetting('WRAP_LINES', 'httpPreRequest')"
/>
+
@@ -58,6 +65,13 @@
+ (preRequestScript = updatedScript)"
+ />
@@ -65,7 +79,8 @@
import IconHelpCircle from "~icons/lucide/help-circle"
import IconWrapText from "~icons/lucide/wrap-text"
import IconTrash2 from "~icons/lucide/trash-2"
-import { reactive, ref } from "vue"
+import IconSparkles from "~icons/lucide/sparkles"
+import { reactive, ref, computed } from "vue"
import snippets from "@helpers/preRequestScriptSnippets"
import { useCodemirror } from "@composables/codemirror"
import linter from "~/helpers/editor/linting/preRequest"
@@ -74,6 +89,13 @@ import { useI18n } from "@composables/i18n"
import { useVModel } from "@vueuse/core"
import { useNestedSetting } from "~/composables/settings"
import { toggleNestedSetting } from "~/newstore/settings"
+import { useAIExperiments } from "~/composables/ai-experiments"
+import { useService } from "dioc/vue"
+import { RESTTabService } from "~/services/tab/rest"
+import { platform } from "~/platform"
+import { useReadonlyStream } from "~/composables/stream"
+import AiexperimentsModifyPreRequestModal from "@components/aiexperiments/ModifyPreRequestModal.vue"
+import { invokeAction } from "~/helpers/actions"
const t = useI18n()
@@ -112,6 +134,29 @@ const useSnippet = (script: string) => {
const clearContent = () => {
preRequestScript.value = ""
}
+const tabService = useService(RESTTabService)
+
+const currentRequest = computed(() =>
+ tabService.currentActiveTab.value?.document.type === "request"
+ ? tabService.currentActiveTab.value?.document.request
+ : null
+)
+
+const { shouldEnableAIFeatures } = useAIExperiments()
+const isModifyPreRequestModalOpen = ref(false)
+
+const currentUser = useReadonlyStream(
+ platform.auth.getCurrentUserStream(),
+ platform.auth.getCurrentUser()
+)
+
+const showModifyPreRequestModal = () => {
+ if (!currentUser.value) {
+ invokeAction("modals.login.toggle")
+ return
+ }
+ isModifyPreRequestModalOpen.value = true
+}