Merge pull request from Budibase/js-ai-gen-context

Send context information to the JS generation endpoint.
This commit is contained in:
Sam Rose 2025-03-13 17:08:02 +00:00 committed by GitHub
commit 90a5c00913
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 50 additions and 11 deletions
packages
bbui/src/Form/Core
builder/src/components
types/src/api/web

View File

@ -19,7 +19,7 @@
const dispatch = createEventDispatcher()
let focus = false
let isFocused = false
let textarea: HTMLTextAreaElement
let scrollable = false
@ -27,8 +27,16 @@
$: minHeightString = getStyleString("min-height", minHeight)
$: dispatch("scrollable", scrollable)
export function focus() {
textarea.focus()
}
export function contents() {
return textarea.value
}
const onBlur = () => {
focus = false
isFocused = false
updateValue()
}
@ -65,7 +73,7 @@
style={`${heightString}${minHeightString}`}
class="spectrum-Textfield spectrum-Textfield--multiline"
class:is-disabled={disabled}
class:is-focused={focus}
class:is-focused={isFocused}
>
<!-- prettier-ignore -->
<textarea
@ -77,7 +85,7 @@
{readonly}
{id}
on:input={onChange}
on:focus={() => (focus = true)}
on:focus={() => (isFocused = true)}
on:blur={onBlur}
on:blur
on:keypress

View File

@ -1059,6 +1059,7 @@
inputData[key] = e.detail
}}
completions={stepCompletions}
{bindings}
mode={codeMode}
autocompleteEnabled={codeMode !== EditorModes.JS}
bind:getCaretPosition

View File

@ -152,6 +152,7 @@
<div class="field-wrap json-field">
<CodeEditor
value={readableValue}
{bindings}
on:blur={e => {
onChange({
row: {

View File

@ -59,7 +59,11 @@
import { javascript } from "@codemirror/lang-javascript"
import { EditorModes } from "./"
import { themeStore } from "@/stores/portal"
import { FeatureFlag, type EditorMode } from "@budibase/types"
import {
type EnrichedBinding,
FeatureFlag,
type EditorMode,
} from "@budibase/types"
import { tooltips } from "@codemirror/view"
import type { BindingCompletion, CodeValidator } from "@/types"
import { validateHbsTemplate } from "./validator/hbs"
@ -80,6 +84,7 @@
export let readonly = false
export let readonlyLineNumbers = false
export let dropdown = DropdownPosition.Relative
export let bindings: EnrichedBinding[] = []
const dispatch = createEventDispatcher()
@ -100,7 +105,8 @@
let promptInput: TextArea
$: aiGenEnabled =
featureFlag.isEnabled(FeatureFlag.AI_JS_GENERATION) &&
mode.name === "javascript"
mode.name === "javascript" &&
!readonly
$: {
if (autofocus && isEditorInitialised) {
@ -165,15 +171,24 @@
popoverWidth = 30
let code = ""
try {
const resp = await API.generateJs({ prompt })
const resp = await API.generateJs({ prompt, bindings })
code = resp.code
if (code === "") {
throw new Error(
"we didn't understand your prompt, please phrase your request in another way"
)
}
} catch (e) {
console.error(e)
notifications.error("Unable to generate code, please try again later.")
if (e instanceof Error) {
notifications.error(`Unable to generate code: ${e.message}`)
} else {
notifications.error("Unable to generate code, please try again later.")
}
code = previousContents
popoverWidth = 300
promptLoading = false
popover.hide()
resetPopover()
return
}
value = code
@ -189,6 +204,8 @@
suggestedCode = null
previousContents = null
resetPopover()
dispatch("change", editor.state.doc.toString())
dispatch("blur", editor.state.doc.toString())
}
const rejectSuggestion = () => {
@ -513,13 +530,18 @@
bind:this={popover}
minWidth={popoverWidth}
anchor={popoverAnchor}
on:close={() => {
if (suggestedCode) {
acceptSuggestion()
}
}}
align="left-outside"
>
{#if promptLoading}
<div class="prompt-spinner">
<Spinner size="20" color="white" />
</div>
{:else if suggestedCode}
{:else if suggestedCode !== null}
<Button on:click={acceptSuggestion}>Accept</Button>
<Button on:click={rejectSuggestion}>Reject</Button>
{:else}

View File

@ -359,6 +359,7 @@
bind:getCaretPosition
bind:insertAtPos
{completions}
{bindings}
{validations}
autofocus={autofocusEditor}
placeholder={placeholder ||
@ -372,6 +373,7 @@
value={jsValue ? decodeJSBinding(jsValue) : ""}
on:change={onChangeJSValue}
{completions}
{bindings}
{validations}
mode={EditorModes.JS}
bind:getCaretPosition

View File

@ -147,6 +147,7 @@
on:change={onChangeJSValue}
on:blur
completions={jsCompletions}
{bindings}
mode={EditorModes.JS}
bind:getCaretPosition
bind:insertAtPos

View File

@ -1,6 +1,10 @@
import { EnrichedBinding } from "../../ui"
export interface GenerateJsRequest {
prompt: string
bindings?: EnrichedBinding[]
}
export interface GenerateJsResponse {
code: string
}