diff --git a/apps/remix-ide/src/app/plugins/solcoderAI.tsx b/apps/remix-ide/src/app/plugins/solcoderAI.tsx index 11b20c18c5..765ecfd8fe 100644 --- a/apps/remix-ide/src/app/plugins/solcoderAI.tsx +++ b/apps/remix-ide/src/app/plugins/solcoderAI.tsx @@ -15,7 +15,7 @@ const profile = { name: 'solcoder', displayName: 'solcoder', description: 'solcoder', - methods: ['code_generation', 'code_completion', "solidity_answer", "code_explaining"], + methods: ['code_generation', 'code_completion', "solidity_answer", "code_explaining", "code_insertion"], events: [], maintainedBy: 'Remix', } @@ -159,5 +159,42 @@ export class SolCoder extends Plugin { } } + async code_insertion(msg_pfx, msg_sfx): Promise { + this.emit("aiInfering") + let result + try { + result = await( + await fetch(this.completion_url, { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({"data":[ + msg_pfx, // Text before current cursor line + "code_insertion", + msg_sfx, // Text after current cursor line + 1024, + 0.5, + 0.92, + 50 + ] }), + }) + ).json() + + if ("error" in result){ + return result + } + return result.data + + } catch (e) { + this.call('terminal', 'log', { type: 'aitypewriterwarning', value: `Unable to get a response ${e.message}` }) + return + } finally { + this.emit("aiInferingDone") + } + } + + } diff --git a/libs/remix-ui/editor/src/lib/providers/inlineCompletionProvider.ts b/libs/remix-ui/editor/src/lib/providers/inlineCompletionProvider.ts index 7f1d77a23f..601a5513e3 100644 --- a/libs/remix-ui/editor/src/lib/providers/inlineCompletionProvider.ts +++ b/libs/remix-ui/editor/src/lib/providers/inlineCompletionProvider.ts @@ -25,6 +25,10 @@ export class RemixInLineCompletionProvider implements monacoTypes.languages.Inli if (context.selectedSuggestionInfo) { return; } + const getTextAtLine = (lineNumber) => { + const lineRange = model.getFullModelRange().setStartPosition(lineNumber, 1).setEndPosition(lineNumber + 1, 1); + return model.getValueInRange(lineRange); + } // get text before the position of the completion const word = model.getValueInRange({ startLineNumber: 1, @@ -33,6 +37,14 @@ export class RemixInLineCompletionProvider implements monacoTypes.languages.Inli endColumn: position.column, }); + // get text after the position of the completion + const word_after = model.getValueInRange({ + startLineNumber: position.lineNumber, + startColumn: position.column, + endLineNumber: model.getLineCount(), + endColumn: getTextAtLine(model.getLineCount()).length + 1, + }); + if (!word.endsWith(' ') && !word.endsWith('.') && !word.endsWith('(')) { @@ -90,8 +102,34 @@ export class RemixInLineCompletionProvider implements monacoTypes.languages.Inli return } + if (word.replace(/ +$/, '').endsWith('\n')){ + // Code insertion + try{ + const output = await this.props.plugin.call('solcoder', 'code_insertion', word, word_after) + _paq.push(['trackEvent', 'ai', 'solcoder', 'code_insertion']) + const generatedText = output[0] // no need to clean it. should already be + + const item: monacoTypes.languages.InlineCompletion = { + insertText: generatedText + }; + + this.completionEnabled = false + const handleCompletionTimer = new CompletionTimer(5000, () => { this.completionEnabled = true }); + handleCompletionTimer.start() + + return { + items: [item], + enableForwardStability: true + } + } + catch (err){ + return + } + } + let result try { + // Code completion const output = await this.props.plugin.call('solcoder', 'code_completion', word) _paq.push(['trackEvent', 'ai', 'solcoder', 'code_completion']) const generatedText = output[0]