mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-10 08:07:03 +00:00
feat: add windmill context to autocomplete (#5548)
* add windmill context to autocomplete * fix formatting * remove console log * do not mention tool call for autocomplete * apply logic to php --------- Co-authored-by: HugoCasa <hugo@casademont.ch>
This commit is contained in:
@@ -635,7 +635,10 @@
|
||||
if (completorDisposable) {
|
||||
completorDisposable.dispose()
|
||||
}
|
||||
autocompletor = new Autocompletor(editor, lang)
|
||||
if (!scriptLang) {
|
||||
throw new Error('No script lang')
|
||||
}
|
||||
autocompletor = new Autocompletor(editor, lang, scriptLang)
|
||||
|
||||
// last user events (currently disabled):
|
||||
// let lastTs = Date.now()
|
||||
@@ -690,6 +693,7 @@
|
||||
$codeCompletionSessionEnabled &&
|
||||
initialized &&
|
||||
editor &&
|
||||
scriptLang &&
|
||||
addSuperCompletor(editor)
|
||||
|
||||
$: $copilotInfo.enabled && initialized && editor && addChatHandler(editor)
|
||||
|
||||
@@ -3,6 +3,7 @@ import { type editor as meditor } from 'monaco-editor'
|
||||
import { autocompleteRequest } from './request'
|
||||
import { sleep } from '$lib/utils'
|
||||
import { displayVisualChanges, getLines, setGlobalCSS, type VisualChange } from '../shared'
|
||||
import type { ScriptLang } from '$lib/gen'
|
||||
|
||||
function lineChangesToVisualChanges(changes: Change[], startLineNumber: number) {
|
||||
let originalLineNumber = startLineNumber
|
||||
@@ -153,7 +154,7 @@ const MAX_PATCHES = 4
|
||||
export class Autocompletor {
|
||||
editor: meditor.IStandaloneCodeEditor
|
||||
language: string
|
||||
|
||||
scriptLang: ScriptLang | 'bunnative'
|
||||
viewZoneIds: string[] = []
|
||||
decorationsCollection: meditor.IEditorDecorationsCollection | undefined = undefined
|
||||
visualChanges: VisualChange[] = []
|
||||
@@ -188,9 +189,14 @@ export class Autocompletor {
|
||||
| undefined = undefined
|
||||
tabWidget: meditor.IContentWidget | undefined = undefined
|
||||
|
||||
constructor(editor: meditor.IStandaloneCodeEditor, language: string) {
|
||||
constructor(
|
||||
editor: meditor.IStandaloneCodeEditor,
|
||||
language: string,
|
||||
scriptLang: ScriptLang | 'bunnative'
|
||||
) {
|
||||
this.editor = editor
|
||||
this.language = language
|
||||
this.scriptLang = scriptLang
|
||||
this.lastCodeValue = editor.getModel()?.getValue() || ''
|
||||
}
|
||||
|
||||
@@ -445,6 +451,7 @@ export class Autocompletor {
|
||||
modifiableSuffix,
|
||||
suffix,
|
||||
language: this.language,
|
||||
scriptLang: this.scriptLang,
|
||||
events: this.patches
|
||||
},
|
||||
this.abortController
|
||||
|
||||
@@ -2,6 +2,8 @@ import { codeCompletionLoading, copilotInfo } from '$lib/stores'
|
||||
import { get } from 'svelte/store'
|
||||
|
||||
import { getNonStreamingCompletion } from '../lib'
|
||||
import { getLangContext } from '../chat/core'
|
||||
import { type ScriptLang } from '$lib/gen/types.gen'
|
||||
|
||||
const AUTOCOMPLETE_SYSTEM_PROMPT = `You're a code assistant. Your task is to help the user write code by suggesting the next edit for the user.
|
||||
|
||||
@@ -31,6 +33,9 @@ Follow the following criteria.
|
||||
- Never remove line breaks inside the <EDITABLE_CODE> section.`
|
||||
|
||||
const AUTOCOMPLETE_USER_PROMPT = `
|
||||
WINDMILL LANGUAGE CONTEXT:
|
||||
{lang_context}
|
||||
|
||||
<CODE>
|
||||
{prefix}<EDITABLE_CODE>
|
||||
{modifiablePrefix}<CURSOR>{modifiableSuffix}
|
||||
@@ -59,13 +64,18 @@ export async function autocompleteRequest(
|
||||
modifiableSuffix: string
|
||||
suffix: string
|
||||
language: string
|
||||
scriptLang: ScriptLang | 'bunnative'
|
||||
events: string[]
|
||||
},
|
||||
abortController: AbortController
|
||||
) {
|
||||
codeCompletionLoading.set(true)
|
||||
const systemPrompt = AUTOCOMPLETE_SYSTEM_PROMPT
|
||||
const userPrompt = AUTOCOMPLETE_USER_PROMPT.replace('{prefix}', context.prefix)
|
||||
const userPrompt = AUTOCOMPLETE_USER_PROMPT.replace(
|
||||
'{lang_context}',
|
||||
getLangContext(context.scriptLang)
|
||||
)
|
||||
.replace('{prefix}', context.prefix)
|
||||
.replace('{modifiablePrefix}', context.modifiablePrefix)
|
||||
.replace('{modifiableSuffix}', context.modifiableSuffix)
|
||||
.replace('{suffix}', context.suffix)
|
||||
|
||||
@@ -58,12 +58,10 @@ async function getResourceTypes(prompt: string, workspace: string) {
|
||||
|
||||
const TS_RESOURCE_TYPE_SYSTEM = `On Windmill, credentials and configuration are stored in resources and passed as parameters to main.
|
||||
If you need credentials, you should add a parameter to \`main\` with the corresponding resource type inside the \`RT\` namespace: for instance \`RT.Stripe\`.
|
||||
You should only them if you need them to satisfy the user's instructions. Always use the RT namespace.
|
||||
To query the RT namespace, you can use the \`search_resource_types\` function.`
|
||||
You should only use them if you need them to satisfy the user's instructions. Always use the RT namespace.`
|
||||
|
||||
const PYTHON_RESOURCE_TYPE_SYSTEM = `On Windmill, credentials and configuration are stored in resources and passed as parameters to main.
|
||||
If you need credentials, you should add a parameter to \`main\` with the corresponding resource type.
|
||||
To query the available resource types, you can use the \`search_resource_types\` function.
|
||||
You need to **redefine** the type of the resources that are needed before the main function as TypedDict, but only include them if they are actually needed to achieve the function purpose.
|
||||
The resource type name has to be exactly as specified (has to be IN LOWERCASE).
|
||||
If an import conflicts with a resource type name, **you have to rename the imported object, not the type name**.
|
||||
@@ -71,7 +69,6 @@ Make sure to import TypedDict from typing **if you're using it**`
|
||||
|
||||
const PHP_RESOURCE_TYPE_SYSTEM = `On Windmill, credentials and configuration are stored in resources and passed as parameters to main.
|
||||
If you need credentials, you should add a parameter to \`main\` with the corresponding resource type
|
||||
The available resource types are provided by the user under the \`RESOURCE_TYPE_CONTEXT\` key.
|
||||
You need to **redefine** the type of the resources that are needed before the main function, but only include them if they are actually needed to achieve the function purpose.
|
||||
Before defining each type, check if the class already exists using class_exists.
|
||||
The resource type name has to be exactly as specified.`
|
||||
@@ -95,34 +92,44 @@ export const SUPPORTED_CHAT_SCRIPT_LANGUAGES = [
|
||||
'powershell'
|
||||
]
|
||||
|
||||
function getLangContext(lang: ScriptLang | 'bunnative') {
|
||||
export function getLangContext(
|
||||
lang: ScriptLang | 'bunnative',
|
||||
{ allowResourcesFetch = false }: { allowResourcesFetch?: boolean } = {}
|
||||
) {
|
||||
const tsContext =
|
||||
TS_RESOURCE_TYPE_SYSTEM +
|
||||
(allowResourcesFetch
|
||||
? `\nTo query the RT namespace, you can use the \`search_resource_types\` function.`
|
||||
: '')
|
||||
switch (lang) {
|
||||
case 'bunnative':
|
||||
case 'nativets':
|
||||
return (
|
||||
'The user is coding in TypeScript. On Windmill, it is expected that the script exports a single **async** function called `main`. You should use fetch (available globally, no need to import) and are not allowed to import any libraries.\n' +
|
||||
TS_RESOURCE_TYPE_SYSTEM
|
||||
tsContext
|
||||
)
|
||||
case 'bun':
|
||||
return (
|
||||
'The user is coding in TypeScript (bun runtime). On Windmill, it is expected that the script exports a single **async** function called `main`. Do not call the main function. Libraries are installed automatically, do not show how to install them.\n' +
|
||||
TS_RESOURCE_TYPE_SYSTEM
|
||||
tsContext
|
||||
)
|
||||
case 'deno':
|
||||
return (
|
||||
'The user is coding in TypeScript (deno runtime). On Windmill, it is expected that the script exports a single **async** function called `main`. Do not call the main function. Libraries are installed automatically, do not show how to install them.\n' +
|
||||
TS_RESOURCE_TYPE_SYSTEM +
|
||||
tsContext +
|
||||
'\nYou can import deno libraries or you can import npm libraries like that: `import ... from "npm:{package}";`.'
|
||||
)
|
||||
case 'python3':
|
||||
return (
|
||||
'The user is coding in Python. On Windmill, it is expected the script contains at least one function called `main`. Do not call the main function. Libraries are installed automatically, do not show how to install them.' +
|
||||
PYTHON_RESOURCE_TYPE_SYSTEM
|
||||
PYTHON_RESOURCE_TYPE_SYSTEM +
|
||||
`${allowResourcesFetch ? `\nTo query the available resource types, you can use the \`search_resource_types\` function.` : ''}`
|
||||
)
|
||||
case 'php':
|
||||
return (
|
||||
'The user is coding in PHP. On Windmill, it is expected the script contains at least one function called `main`. The script must start with <?php.' +
|
||||
PHP_RESOURCE_TYPE_SYSTEM +
|
||||
`${allowResourcesFetch ? `\nTo query the available resource types, you can use the \`search_resource_types\` function.` : ''}` +
|
||||
`\nIf you need to import libraries, you need to specify them as comments in the following manner before the main function:
|
||||
\`\`\`
|
||||
// require:
|
||||
@@ -366,7 +373,7 @@ export async function prepareUserMessage(
|
||||
|
||||
let userMessage = CHAT_USER_PROMPT.replace('{instructions}', instructions).replace(
|
||||
'{lang_context}',
|
||||
getLangContext(language)
|
||||
getLangContext(language, { allowResourcesFetch: true })
|
||||
)
|
||||
if (hasCode) {
|
||||
userMessage += codeContext
|
||||
|
||||
Reference in New Issue
Block a user