feat: UI for test scripts generation (#4637)
AI experiments Co-authored-by: amk-dev <akash.k.mohan98@gmail.com>
This commit is contained in:
parent
f734bdea5c
commit
e16db0ca32
8 changed files with 549 additions and 3 deletions
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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']
|
||||
|
|
|
|||
|
|
@ -0,0 +1,159 @@
|
|||
<template>
|
||||
<HoppSmartModal styles="sm:max-w-3xl" full-width>
|
||||
<template #body>
|
||||
<div class="flex flex-col border-b border-divider transition relative">
|
||||
<div class="flex items-center pt-3 pb-3 sticky">
|
||||
<input
|
||||
id="command"
|
||||
v-model="userPrompt"
|
||||
v-focus
|
||||
type="text"
|
||||
autocomplete="off"
|
||||
name="command"
|
||||
:placeholder="`${t(
|
||||
'ai_experiments.generate_or_modify_prerequest_input_placeholder'
|
||||
)}`"
|
||||
class="flex flex-1 bg-transparent px-6 text-base text-secondaryDark"
|
||||
@keypress="
|
||||
async (e) => {
|
||||
if (e.key === 'Enter') {
|
||||
await modifyPreRequestScript()
|
||||
submittedFeedback = false
|
||||
}
|
||||
}
|
||||
"
|
||||
/>
|
||||
|
||||
<HoppButtonSecondary
|
||||
:icon="IconArrowRight"
|
||||
class="mr-6 rounded-md flex flex-col-reverse"
|
||||
:label="t('ai_experiments.generate')"
|
||||
outline
|
||||
filled
|
||||
:loading="isModifyPreRequestPending"
|
||||
:disabled="!userPrompt || isModifyPreRequestPending"
|
||||
@click="
|
||||
async () => {
|
||||
await modifyPreRequestScript()
|
||||
submittedFeedback = false
|
||||
}
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<AiexperimentsMergeView
|
||||
:content-left="{
|
||||
content: currentScript ?? '',
|
||||
langMime: 'application/javascript',
|
||||
}"
|
||||
:content-right="{
|
||||
content: generatedScriptContent,
|
||||
langMime: 'application/javascript',
|
||||
}"
|
||||
></AiexperimentsMergeView>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #footer>
|
||||
<div class="flex gap-1 px-6 py-3 justify-between items-center w-full">
|
||||
<div
|
||||
v-if="lastTraceID && !submittedFeedback"
|
||||
class="flex items-center gap-2"
|
||||
>
|
||||
<p>{{ t("ai_experiments.feedback_cta_text_long") }}</p>
|
||||
<template v-if="!isSubmitFeedbackPending">
|
||||
<HoppButtonSecondary
|
||||
:icon="IconThumbsUp"
|
||||
outline
|
||||
@click="
|
||||
async () => {
|
||||
if (lastTraceID) {
|
||||
await submitFeedback('positive', lastTraceID)
|
||||
submittedFeedback = true
|
||||
}
|
||||
}
|
||||
"
|
||||
/>
|
||||
<HoppButtonSecondary
|
||||
:icon="IconThumbsDown"
|
||||
outline
|
||||
@click="
|
||||
async () => {
|
||||
if (lastTraceID) {
|
||||
await submitFeedback('negative', lastTraceID)
|
||||
submittedFeedback = true
|
||||
}
|
||||
}
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
<HoppSmartSpinner v-else />
|
||||
</div>
|
||||
|
||||
<div v-if="submittedFeedback">
|
||||
<p>{{ t("ai_experiments.feedback_thank_you") }}</p>
|
||||
</div>
|
||||
|
||||
<div class="ml-auto space-x-2">
|
||||
<HoppButtonSecondary
|
||||
:label="t('action.cancel')"
|
||||
outline
|
||||
@click="emit('closeModal')"
|
||||
/>
|
||||
<HoppButtonSecondary
|
||||
:label="t('ai_experiments.accept_change')"
|
||||
outline
|
||||
filled
|
||||
:disabled="isModifyPreRequestPending || !generatedScriptContent"
|
||||
@click="
|
||||
() => {
|
||||
emit('updateScript', generatedScriptContent)
|
||||
emit('closeModal')
|
||||
}
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</HoppSmartModal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import IconArrowRight from "~icons/lucide/arrow-right"
|
||||
import IconThumbsUp from "~icons/lucide/thumbs-up"
|
||||
import IconThumbsDown from "~icons/lucide/thumbs-down"
|
||||
import { ref } from "vue"
|
||||
import { useI18n } from "~/composables/i18n"
|
||||
import {
|
||||
useModifyPreRequestScript,
|
||||
useSubmitFeedback,
|
||||
} from "~/composables/ai-experiments"
|
||||
import { HoppRESTRequest } from "@hoppscotch/data"
|
||||
|
||||
const props = defineProps<{
|
||||
currentScript: string
|
||||
requestInfo: HoppRESTRequest
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "closeModal"): void
|
||||
(e: "updateScript", script: string): void
|
||||
}>()
|
||||
|
||||
const t = useI18n()
|
||||
const generatedScriptContent = ref("")
|
||||
const userPrompt = ref("")
|
||||
const submittedFeedback = ref(false)
|
||||
|
||||
const { modifyPreRequestScript, isModifyPreRequestPending, lastTraceID } =
|
||||
useModifyPreRequestScript(
|
||||
props.currentScript,
|
||||
userPrompt,
|
||||
generatedScriptContent,
|
||||
props.requestInfo
|
||||
)
|
||||
|
||||
const { submitFeedback, isSubmitFeedbackPending } = useSubmitFeedback()
|
||||
</script>
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
<template>
|
||||
<HoppSmartModal styles="sm:max-w-3xl" full-width>
|
||||
<template #body>
|
||||
<div class="flex flex-col border-b border-divider transition relative">
|
||||
<div class="flex items-center pt-3 pb-3 sticky">
|
||||
<input
|
||||
id="command"
|
||||
v-model="userPrompt"
|
||||
v-focus
|
||||
type="text"
|
||||
autocomplete="off"
|
||||
name="command"
|
||||
:placeholder="`${t(
|
||||
'ai_experiments.generate_or_modify_test_script_input_placeholder'
|
||||
)}`"
|
||||
class="flex flex-1 bg-transparent px-6 text-base text-secondaryDark"
|
||||
@keypress="
|
||||
async (e) => {
|
||||
if (e.key === 'Enter') {
|
||||
await modifyTestScript()
|
||||
submittedFeedback = false
|
||||
}
|
||||
}
|
||||
"
|
||||
/>
|
||||
|
||||
<HoppButtonSecondary
|
||||
:icon="IconArrowRight"
|
||||
class="mr-6 rounded-md flex flex-col-reverse"
|
||||
:label="t('ai_experiments.generate')"
|
||||
outline
|
||||
filled
|
||||
:loading="isModifyTestScriptPending"
|
||||
:disabled="!userPrompt || isModifyTestScriptPending"
|
||||
@click="
|
||||
async () => {
|
||||
await modifyTestScript()
|
||||
submittedFeedback = false
|
||||
}
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<AiexperimentsMergeView
|
||||
:content-left="{
|
||||
content: currentScript ?? '',
|
||||
langMime: 'application/javascript',
|
||||
}"
|
||||
:content-right="{
|
||||
content: generatedScriptContent,
|
||||
langMime: 'application/javascript',
|
||||
}"
|
||||
></AiexperimentsMergeView>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #footer>
|
||||
<div class="flex gap-1 px-6 py-3 justify-between items-center w-full">
|
||||
<div
|
||||
v-if="lastTraceID && !submittedFeedback"
|
||||
class="flex items-center gap-2"
|
||||
>
|
||||
<p>{{ t("ai_experiments.feedback_cta_text_long") }}</p>
|
||||
<template v-if="!isSubmitFeedbackPending">
|
||||
<HoppButtonSecondary
|
||||
:icon="IconThumbsUp"
|
||||
outline
|
||||
@click="
|
||||
async () => {
|
||||
if (lastTraceID) {
|
||||
await submitFeedback('positive', lastTraceID)
|
||||
submittedFeedback = true
|
||||
}
|
||||
}
|
||||
"
|
||||
/>
|
||||
<HoppButtonSecondary
|
||||
:icon="IconThumbsDown"
|
||||
outline
|
||||
@click="
|
||||
async () => {
|
||||
if (lastTraceID) {
|
||||
await submitFeedback('negative', lastTraceID)
|
||||
submittedFeedback = true
|
||||
}
|
||||
}
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
<HoppSmartSpinner v-else />
|
||||
</div>
|
||||
|
||||
<div v-if="submittedFeedback">
|
||||
<p>{{ t("ai_experiments.feedback_thank_you") }}</p>
|
||||
</div>
|
||||
|
||||
<div class="ml-auto space-x-2">
|
||||
<HoppButtonSecondary
|
||||
:label="t('action.cancel')"
|
||||
outline
|
||||
@click="emit('closeModal')"
|
||||
/>
|
||||
<HoppButtonSecondary
|
||||
:label="t('ai_experiments.accept_change')"
|
||||
outline
|
||||
filled
|
||||
:disabled="isModifyTestScriptPending || !generatedScriptContent"
|
||||
@click="
|
||||
() => {
|
||||
emit('updateScript', generatedScriptContent)
|
||||
emit('closeModal')
|
||||
}
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</HoppSmartModal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import IconArrowRight from "~icons/lucide/arrow-right"
|
||||
import IconThumbsUp from "~icons/lucide/thumbs-up"
|
||||
import IconThumbsDown from "~icons/lucide/thumbs-down"
|
||||
import { ref } from "vue"
|
||||
import { useI18n } from "~/composables/i18n"
|
||||
import {
|
||||
useModifyTestScript,
|
||||
useSubmitFeedback,
|
||||
} from "~/composables/ai-experiments"
|
||||
import { HoppRESTRequest } from "@hoppscotch/data"
|
||||
|
||||
const props = defineProps<{
|
||||
currentScript: string
|
||||
requestInfo: HoppRESTRequest
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "closeModal"): void
|
||||
(e: "updateScript", script: string): void
|
||||
}>()
|
||||
|
||||
const t = useI18n()
|
||||
const generatedScriptContent = ref("")
|
||||
const userPrompt = ref("")
|
||||
const submittedFeedback = ref(false)
|
||||
|
||||
const { modifyTestScript, isModifyTestScriptPending, lastTraceID } =
|
||||
useModifyTestScript(
|
||||
props.currentScript,
|
||||
userPrompt,
|
||||
generatedScriptContent,
|
||||
props.requestInfo
|
||||
)
|
||||
|
||||
const { submitFeedback, isSubmitFeedbackPending } = useSubmitFeedback()
|
||||
</script>
|
||||
|
|
@ -27,6 +27,13 @@
|
|||
:icon="IconWrapText"
|
||||
@click.prevent="toggleNestedSetting('WRAP_LINES', 'httpPreRequest')"
|
||||
/>
|
||||
<HoppButtonSecondary
|
||||
v-if="shouldEnableAIFeatures && currentRequest"
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t('ai_experiments.modify_with_ai')"
|
||||
:icon="IconSparkles"
|
||||
@click="showModifyPreRequestModal"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-1 border-b border-dividerLight">
|
||||
|
|
@ -58,6 +65,13 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<AiexperimentsModifyPreRequestModal
|
||||
v-if="isModifyPreRequestModalOpen && currentRequest"
|
||||
:current-script="preRequestScript"
|
||||
:request-info="currentRequest"
|
||||
@close-modal="isModifyPreRequestModalOpen = false"
|
||||
@update-script="(updatedScript) => (preRequestScript = updatedScript)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -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
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -27,6 +27,13 @@
|
|||
:icon="IconWrapText"
|
||||
@click.prevent="toggleNestedSetting('WRAP_LINES', 'httpTest')"
|
||||
/>
|
||||
<HoppButtonSecondary
|
||||
v-if="shouldEnableAIFeatures && currentRequest"
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t('ai_experiments.modify_with_ai')"
|
||||
:icon="IconSparkles"
|
||||
@click="showModifyTestScriptModal"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-1 border-b border-dividerLight">
|
||||
|
|
@ -58,6 +65,13 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<AiexperimentsModifyTestScriptModal
|
||||
v-if="isModifyTestScriptModalOpen && currentRequest"
|
||||
:current-script="testScript"
|
||||
:request-info="currentRequest"
|
||||
@close-modal="isModifyTestScriptModalOpen = false"
|
||||
@update-script="(updatedScript) => (testScript = updatedScript)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -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 testSnippets from "~/helpers/testSnippets"
|
||||
import { useCodemirror } from "@composables/codemirror"
|
||||
import linter from "~/helpers/editor/linting/testScript"
|
||||
|
|
@ -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 AiexperimentsModifyTestScriptModal from "@components/aiexperiments/ModifyTestScriptModal.vue"
|
||||
import { invokeAction } from "~/helpers/actions"
|
||||
|
||||
const t = useI18n()
|
||||
|
||||
|
|
@ -108,6 +130,29 @@ const useSnippet = (script: string) => {
|
|||
const clearContent = () => {
|
||||
testScript.value = ""
|
||||
}
|
||||
const tabService = useService(RESTTabService)
|
||||
|
||||
const currentRequest = computed(() =>
|
||||
tabService.currentActiveTab.value?.document.type === "request"
|
||||
? tabService.currentActiveTab.value?.document.request
|
||||
: null
|
||||
)
|
||||
|
||||
const { shouldEnableAIFeatures } = useAIExperiments()
|
||||
const isModifyTestScriptModalOpen = ref(false)
|
||||
|
||||
const currentUser = useReadonlyStream(
|
||||
platform.auth.getCurrentUserStream(),
|
||||
platform.auth.getCurrentUser()
|
||||
)
|
||||
|
||||
const showModifyTestScriptModal = () => {
|
||||
if (!currentUser.value) {
|
||||
invokeAction("modals.login.toggle")
|
||||
return
|
||||
}
|
||||
isModifyTestScriptModalOpen.value = true
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -185,3 +185,124 @@ export const useSubmitFeedback = () => {
|
|||
isSubmitFeedbackPending,
|
||||
}
|
||||
}
|
||||
|
||||
export const useModifyPreRequestScript = (
|
||||
currentScript: string,
|
||||
userPromptRef: Ref<string>,
|
||||
generatedScriptRef: Ref<string>,
|
||||
requestInfo: HoppRESTRequest
|
||||
) => {
|
||||
const toast = useToast()
|
||||
const t = useI18n()
|
||||
const lastTraceID = ref<string | null>(null)
|
||||
const isModifyPreRequestPending = ref(false)
|
||||
|
||||
const modifyPreRequestScriptForPlatform =
|
||||
platform.experiments?.aiExperiments?.modifyPreRequestScript
|
||||
|
||||
const modifyPreRequestScript = async () => {
|
||||
isModifyPreRequestPending.value = true
|
||||
|
||||
if (!modifyPreRequestScriptForPlatform) {
|
||||
toast.error(t("ai_experiments.modify_prerequest_error"))
|
||||
isModifyPreRequestPending.value = false
|
||||
return
|
||||
}
|
||||
|
||||
const result = await modifyPreRequestScriptForPlatform(
|
||||
buildRequestInfoString(requestInfo, currentScript),
|
||||
userPromptRef.value
|
||||
)
|
||||
|
||||
if (result && E.isLeft(result)) {
|
||||
toast.error(t("ai_experiments.modify_prerequest_error"))
|
||||
isModifyPreRequestPending.value = false
|
||||
return
|
||||
}
|
||||
|
||||
generatedScriptRef.value = result.right.modified_script
|
||||
lastTraceID.value = result.right.trace_id
|
||||
|
||||
isModifyPreRequestPending.value = false
|
||||
return result.right
|
||||
}
|
||||
|
||||
return {
|
||||
modifyPreRequestScript,
|
||||
isModifyPreRequestPending,
|
||||
lastTraceID,
|
||||
}
|
||||
}
|
||||
|
||||
export const useModifyTestScript = (
|
||||
currentScript: string,
|
||||
userPromptRef: Ref<string>,
|
||||
generatedScriptRef: Ref<string>,
|
||||
requestInfo: HoppRESTRequest
|
||||
) => {
|
||||
const toast = useToast()
|
||||
const t = useI18n()
|
||||
const lastTraceID = ref<string | null>(null)
|
||||
const isModifyTestScriptPending = ref(false)
|
||||
|
||||
const modifyTestScriptForPlatform =
|
||||
platform.experiments?.aiExperiments?.modifyTestScript
|
||||
|
||||
const modifyTestScript = async () => {
|
||||
isModifyTestScriptPending.value = true
|
||||
|
||||
if (!modifyTestScriptForPlatform) {
|
||||
toast.error(t("ai_experiments.modify_test_script_error"))
|
||||
isModifyTestScriptPending.value = false
|
||||
return
|
||||
}
|
||||
|
||||
const result = await modifyTestScriptForPlatform(
|
||||
buildRequestInfoString(requestInfo, currentScript),
|
||||
userPromptRef.value
|
||||
)
|
||||
|
||||
if (result && E.isLeft(result)) {
|
||||
toast.error(t("ai_experiments.modify_test_script_error"))
|
||||
isModifyTestScriptPending.value = false
|
||||
return
|
||||
}
|
||||
|
||||
generatedScriptRef.value = result.right.modified_script
|
||||
lastTraceID.value = result.right.trace_id
|
||||
|
||||
isModifyTestScriptPending.value = false
|
||||
return result.right
|
||||
}
|
||||
|
||||
return {
|
||||
modifyTestScript,
|
||||
isModifyTestScriptPending,
|
||||
lastTraceID,
|
||||
}
|
||||
}
|
||||
|
||||
const buildRequestInfoString = (
|
||||
request: HoppRESTRequest,
|
||||
currentScript: string
|
||||
) => {
|
||||
return `
|
||||
METHOD:
|
||||
${request.method}
|
||||
|
||||
URL:
|
||||
${request.endpoint}
|
||||
|
||||
BODY:
|
||||
${JSON.stringify(request.body) ?? ""}
|
||||
|
||||
PARAMS:
|
||||
${JSON.stringify(request.params, null, 2)}
|
||||
|
||||
HEADERS:
|
||||
${JSON.stringify(request.headers, null, 2)}
|
||||
|
||||
EXISTING SCRIPT:
|
||||
${currentScript}
|
||||
`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,5 +28,17 @@ export type ExperimentsPlatformDef = {
|
|||
rating: -1 | 1,
|
||||
traceID: string
|
||||
) => Promise<E.Either<string, void>>
|
||||
modifyPreRequestScript?: (
|
||||
requestInfo: string,
|
||||
userPrompt: string
|
||||
) => Promise<
|
||||
E.Either<string, { modified_script: string; trace_id: string }>
|
||||
>
|
||||
modifyTestScript?: (
|
||||
requestInfo: string,
|
||||
userPrompt: string
|
||||
) => Promise<
|
||||
E.Either<string, { modified_script: string; trace_id: string }>
|
||||
>
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue