Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Command so that CopilotChat reads from current in-focus buffer when answering questions #67

Merged
merged 3 commits into from Feb 23, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Expand Up @@ -262,6 +262,12 @@ For further reference, you can view @jellydn's [configuration](https://github.co

### Toggle Vertical Split with `:CopilotChatVsplitToggle`

### Chat with Copilot with all contents of InFocus buffer

1. Run the command `:CopilotChatBuffer` and type your prompt. For example, `What does this code do?`
2. Press `Enter` to send your question to Github Copilot.
3. Copilot will pull the content of the infocus buffer and chat with you.

[![Toggle](https://i.gyazo.com/db5af9e5d88cd2fd09f58968914fa521.gif)](https://gyazo.com/db5af9e5d88cd2fd09f58968914fa521)

## Tips
Expand Down
16 changes: 10 additions & 6 deletions rplugin/python3/CopilotChat/copilot.py
Expand Up @@ -79,7 +79,8 @@ def poll_auth(self, device_code: str) -> bool:
def authenticate(self):
if self.github_token is None:
raise Exception("No token found")
self.vscode_sessionid = str(uuid.uuid4()) + str(round(time.time() * 1000))
self.vscode_sessionid = str(
uuid.uuid4()) + str(round(time.time() * 1000))
url = "https://api.github.com/copilot_internal/v2/token"
headers = {
"authorization": f"token {self.github_token}",
Expand All @@ -105,7 +106,7 @@ def ask(
if not self.token:
self.authenticate()
# If expired, reauthenticate
if self.token.get("expires_at") <= round(time.time()):
if self.token.get("expires_at", 0) <= round(time.time()):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed comparing NoneType with int

>>> None <= 2120
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '<=' not supported between instances of 'NoneType' and 'int'

self.authenticate()

if not system_prompt:
Expand Down Expand Up @@ -147,7 +148,8 @@ def ask(

raise Exception(
error_messages.get(
response.status_code, f"Unknown error: {response.status_code}"
response.status_code, f"Unknown error: {
response.status_code}"
)
)
for line in response.iter_lines():
Expand Down Expand Up @@ -183,8 +185,9 @@ def _get_embeddings(self, inputs: list[typings.FileExtract]):
if i + 18 > len(inputs):
data = utilities.generate_embedding_request(inputs[i:])
else:
data = utilities.generate_embedding_request(inputs[i : i + 18])
response = self.session.post(url, headers=self._headers(), json=data).json()
data = utilities.generate_embedding_request(inputs[i: i + 18])
response = self.session.post(
url, headers=self._headers(), json=data).json()
if "data" not in response:
raise Exception(f"Error fetching embeddings: {response}")
for embedding in response["data"]:
Expand Down Expand Up @@ -217,7 +220,8 @@ def main():
copilot = Copilot(token)
if copilot.github_token is None:
req = copilot.request_auth()
print("Please visit", req["verification_uri"], "and enter", req["user_code"])
print("Please visit", req["verification_uri"],
"and enter", req["user_code"])
while not copilot.poll_auth(req["device_code"]):
time.sleep(req["interval"])
print("Successfully authenticated")
Expand Down
22 changes: 18 additions & 4 deletions rplugin/python3/CopilotChat/copilot_plugin.py
Expand Up @@ -10,7 +10,8 @@
@pynvim.plugin
class CopilotPlugin(object):
def __init__(self, nvim: pynvim.Nvim):
self.nvim: MyNvim = MyNvim(nvim, PLUGIN_MAPPING_CMD, PLUGIN_AUTOCMD_CMD)
self.nvim: MyNvim = MyNvim(
nvim, PLUGIN_MAPPING_CMD, PLUGIN_AUTOCMD_CMD)
self.vsplit_chat_handler = None
self.inplace_chat_handler = None

Expand All @@ -24,6 +25,18 @@ def copilot_chat_toggle_cmd(self):
if self.vsplit_chat_handler:
self.vsplit_chat_handler.toggle_vsplit()

@pynvim.command("CopilotChatBuffer", nargs="1")
def copilot_agent_buffer_cmd(self, args: list[str]):
self.init_vsplit_chat_handler()
current_buffer = self.nvim.current.buffer
lines = current_buffer[:]
# Get code from the current infocus buffer
code = "\n".join(lines)
if self.vsplit_chat_handler:
file_type = self.nvim.current.buffer.options["filetype"]
self.vsplit_chat_handler.vsplit()
self.vsplit_chat_handler.chat(args[0], file_type, code)

@pynvim.command("CopilotChat", nargs="1")
def copilot_agent_cmd(self, args: list[str]):
self.init_vsplit_chat_handler()
Expand All @@ -45,7 +58,7 @@ def copilot_agent_visual_cmd(self, args: list[str], range: list[int]):
self.init_vsplit_chat_handler()
if self.vsplit_chat_handler:
file_type = self.nvim.current.buffer.options["filetype"]
code_lines = self.nvim.current.buffer[range[0] - 1 : range[1]]
code_lines = self.nvim.current.buffer[range[0] - 1: range[1]]
code = "\n".join(code_lines)
self.vsplit_chat_handler.vsplit()
self.vsplit_chat_handler.chat(args[0], file_type, code)
Expand All @@ -70,7 +83,8 @@ def inplace_cmd(self, args: list[str], range: list[int]):
self.init_inplace_chat_handler()
if self.inplace_chat_handler:
file_type = self.nvim.current.buffer.options["filetype"]
code_lines = self.nvim.current.buffer[range[0] - 1 : range[1]]
code_lines = self.nvim.current.buffer[range[0] - 1: range[1]]
code = "\n".join(code_lines)
user_buffer = self.nvim.current.buffer
self.inplace_chat_handler.mount(code, file_type, range, user_buffer)
self.inplace_chat_handler.mount(
code, file_type, range, user_buffer)