From 52cf5fb613cc4ff4729153527a5b9d40557e3fc7 Mon Sep 17 00:00:00 2001 From: Zhiming Ma Date: Fri, 24 Nov 2023 14:56:31 +0800 Subject: [PATCH] feat(agent): support read clipboard as prompt (#885) * feat(agent): add support for reading clipboard text as prompt. * fix: add clipboard in context hash calculation. * fix: set default allowed clipboard chars to 2000. --- clients/intellij/package.json | 2 +- clients/tabby-agent/package.json | 2 +- clients/tabby-agent/src/AgentConfig.ts | 8 ++++++++ clients/tabby-agent/src/CompletionContext.ts | 16 +++++++++++----- clients/tabby-agent/src/TabbyAgent.ts | 10 ++++++++-- clients/vim/package.json | 2 +- clients/vscode/package.json | 4 ++-- clients/vscode/src/TabbyCompletionProvider.ts | 2 ++ 8 files changed, 34 insertions(+), 12 deletions(-) diff --git a/clients/intellij/package.json b/clients/intellij/package.json index 3598891b4957..62d579f8ec7c 100644 --- a/clients/intellij/package.json +++ b/clients/intellij/package.json @@ -10,6 +10,6 @@ "devDependencies": { "cpy-cli": "^4.2.0", "rimraf": "^5.0.1", - "tabby-agent": "1.1.1" + "tabby-agent": "1.2.0-dev" } } diff --git a/clients/tabby-agent/package.json b/clients/tabby-agent/package.json index c627c68ddd87..f62cd2ecbbbc 100644 --- a/clients/tabby-agent/package.json +++ b/clients/tabby-agent/package.json @@ -1,6 +1,6 @@ { "name": "tabby-agent", - "version": "1.1.1", + "version": "1.2.0-dev", "description": "Generic client agent for Tabby AI coding assistant IDE extensions.", "repository": "https://github.com/TabbyML/tabby", "main": "./dist/index.js", diff --git a/clients/tabby-agent/src/AgentConfig.ts b/clients/tabby-agent/src/AgentConfig.ts index 629db809466e..b24104a67ca1 100644 --- a/clients/tabby-agent/src/AgentConfig.ts +++ b/clients/tabby-agent/src/AgentConfig.ts @@ -13,6 +13,10 @@ export type AgentConfig = { experimentalStripAutoClosingCharacters: boolean; maxPrefixLines: number; maxSuffixLines: number; + clipboard: { + minChars: number; + maxChars: number; + }; }; debounce: { mode: "adaptive" | "fixed"; @@ -66,6 +70,10 @@ export const defaultAgentConfig: AgentConfig = { experimentalStripAutoClosingCharacters: false, maxPrefixLines: 20, maxSuffixLines: 20, + clipboard: { + minChars: 3, + maxChars: 2000, + }, }, debounce: { mode: "adaptive", diff --git a/clients/tabby-agent/src/CompletionContext.ts b/clients/tabby-agent/src/CompletionContext.ts index 7d34449248c0..954931b2d52f 100644 --- a/clients/tabby-agent/src/CompletionContext.ts +++ b/clients/tabby-agent/src/CompletionContext.ts @@ -1,4 +1,4 @@ -import { splitLines, autoClosingPairOpenings, autoClosingPairClosings } from "./utils"; +import { splitLines, autoClosingPairClosings } from "./utils"; import hashObject from "object-hash"; export type CompletionRequest = { @@ -6,6 +6,7 @@ export type CompletionRequest = { language: string; text: string; position: number; + clipboard?: string; manually?: boolean; }; @@ -43,6 +44,8 @@ export class CompletionContext { prefixLines: string[]; suffixLines: string[]; + clipboard: string; + // "default": the cursor is at the end of the line // "fill-in-line": the cursor is not at the end of the line, except auto closed characters // In this case, we assume the completion should be a single line, so multiple lines completion will be dropped. @@ -60,13 +63,16 @@ export class CompletionContext { this.prefixLines = splitLines(this.prefix); this.suffixLines = splitLines(this.suffix); + this.clipboard = request.clipboard?.trim() ?? ""; + const lineEnd = isAtLineEndExcludingAutoClosedChar(this.suffixLines[0] ?? ""); this.mode = lineEnd ? "default" : "fill-in-line"; this.hash = hashObject({ - filepath: request.filepath, - language: request.language, - text: request.text, - position: request.position, + filepath: this.filepath, + language: this.language, + text: this.text, + position: this.position, + clipboard: this.clipboard, }); } } diff --git a/clients/tabby-agent/src/TabbyAgent.ts b/clients/tabby-agent/src/TabbyAgent.ts index 607e54eb9024..4325dce1885e 100644 --- a/clients/tabby-agent/src/TabbyAgent.ts +++ b/clients/tabby-agent/src/TabbyAgent.ts @@ -275,7 +275,7 @@ export class TabbyAgent extends EventEmitter implements Agent { } } - private createSegments(context: CompletionContext): { prefix: string; suffix: string } { + private createSegments(context: CompletionContext): { prefix: string; suffix: string; clipboard?: string } { // max lines in prefix and suffix configurable const maxPrefixLines = this.config.completion.prompt.maxPrefixLines; const maxSuffixLines = this.config.completion.prompt.maxSuffixLines; @@ -287,7 +287,13 @@ export class TabbyAgent extends EventEmitter implements Agent { } else { suffix = suffixLines.slice(0, maxSuffixLines).join(""); } - return { prefix, suffix }; + + let clipboard = undefined; + const clipboardConfig = this.config.completion.prompt.clipboard; + if (context.clipboard.length >= clipboardConfig.minChars && context.clipboard.length <= clipboardConfig.maxChars) { + clipboard = context.clipboard; + } + return { prefix, suffix, clipboard }; } public async initialize(options: AgentInitOptions): Promise { diff --git a/clients/vim/package.json b/clients/vim/package.json index 2a44a11b0773..827e70eae945 100644 --- a/clients/vim/package.json +++ b/clients/vim/package.json @@ -10,6 +10,6 @@ "devDependencies": { "cpy-cli": "^4.2.0", "rimraf": "^5.0.1", - "tabby-agent": "1.1.1" + "tabby-agent": "1.2.0-dev" } } diff --git a/clients/vscode/package.json b/clients/vscode/package.json index 6a3ef8214ae3..920f0199d9b9 100644 --- a/clients/vscode/package.json +++ b/clients/vscode/package.json @@ -7,7 +7,7 @@ "repository": "https://github.com/TabbyML/tabby", "bugs": "https://github.com/TabbyML/tabby/issues", "license": "Apache-2.0", - "version": "1.1.3", + "version": "1.2.0-dev", "keywords": [ "ai", "autocomplete", @@ -226,6 +226,6 @@ }, "dependencies": { "@xstate/fsm": "^2.0.1", - "tabby-agent": "1.1.1" + "tabby-agent": "1.2.0-dev" } } diff --git a/clients/vscode/src/TabbyCompletionProvider.ts b/clients/vscode/src/TabbyCompletionProvider.ts index a9b08df2f25d..a6fd36ea6d2f 100644 --- a/clients/vscode/src/TabbyCompletionProvider.ts +++ b/clients/vscode/src/TabbyCompletionProvider.ts @@ -7,6 +7,7 @@ import { Position, Range, TextDocument, + env, workspace, } from "vscode"; import { EventEmitter } from "events"; @@ -66,6 +67,7 @@ export class TabbyCompletionProvider extends EventEmitter implements InlineCompl language: document.languageId, // https://code.visualstudio.com/docs/languages/identifiers text: document.getText(), position: document.offsetAt(position), + clipboard: await env.clipboard.readText(), manually: context.triggerKind === InlineCompletionTriggerKind.Invoke, };