dustinblackman / oatmeal

Terminal UI to chat with large language models (LLM) using different model backends, and integrations with your favourite editors!
https://dustinblackman.com/posts/oatmeal/
MIT License
477 stars 23 forks source link

Feature/GitHub copilot #49

Open aislasq opened 6 months ago

aislasq commented 6 months ago

This is a first draft to add github copilot to Oatmeal. It is working fine, but it is very hacky to adjust the Github Copilot login flow. I am out of my means here and would appreciate some help.

  1. A new GithubAuth struct was created to handle Github Authentication:
    • It checks the default ~/.config/github-copilot/hosts.json for an oauth token. If it does not exists it proceeds to ask the user to approve the device, requests the oauth token, and saves the result to the hosts.json file.
    • With the oauth token, it then requests a github copilot token (it is different), and saves that to the GithubAuth struct.
    • The GithubAuth flow is called on each request, this is not good because it is regenerating the github copilot token each time.
    • The request login Message shown by Author::Oatmeal does not call done: true, so the pending result will be appended to the message bubble.
    • It is mocking a vscode editor with the headers.
  2. The it_gets_completion is failing due to the GithubAuth flow inside the get_completion function.
  3. There are no extra parameters (URL, Token) to set, the url does not change and the token comes from the ~/.config/github-copilot/hosts.json file
dustinblackman commented 5 months ago

@aislasq Hey there! Sorry for the late reply, weekends are my time for looking at open source.

This is exciting! I haven't played with Copilot since beta, I'd be really happy to play with again in Oatmeal.

A new GithubAuth struct was created to handle Github Authentication:

So your biggest issue here is the fact you want to do the initial authentication from inside Oatmeal. What if you didn't? I'm imagining on first run if ~/.config/github-copilot/hosts.json does not exist, Oatmeal can provide an error message stating authethencation does not exist and to run command gh extension install github/gh-copilot && gh auth login. This way if authentication ever changes on Github's side, no additional work is required in Oatmeal.

Fix GithubAuth flow called on each completion request. Should only be called once and use the token from then on, until expires_at

Is this a short lived token, 15 minutes? Or is it a long lived token managed by the Github CLI?

aislasq commented 5 months ago

Refactored the code as you suggested. It is more straightforward. I do believe we could handle the login from within Oatmeal, but maybe later. The token's lifetime is 30 min, which is just long enough for a question/session. I have it set up to save it in the struct, but I cannot mutate it; a hacky thing I could do is to save it in the messages context with { role: "token", content: ":" }. Let me know what you think

dustinblackman commented 5 months ago

could do is to save it in the messages context with { role: "token", content: ":" }.

Let's do that! I can refactor the model to allow mutations in the future. :) Thank you very much!

aislasq commented 5 months ago

I added the serialized session token to the content and added expiration management, along with the 3 new tests.

It looks like the hosts.json file where the oauth token is for third party extensions so gh auth login nor VSCode login work. It does work for Android Studio, the neovim copilot and copilot chat plugins, and the implementation we are leaving pending for Oatmeal.

Although I suspect some users will already have this token from other clients, I think we should give a clearer message that the device login is not yet implemented in Oatmeal. What do you think that should be?

dustinblackman commented 5 months ago

Although I suspect some users will already have this token from other clients, I think we should give a clearer message that the device login is not yet implemented in Oatmeal. What do you think that should be?

Odd, so there's no token file provided anywhere for the gh command line such as the copilot extension? I don't have an active subscription at the moment to test myself (that's a job for next week!)

Although I suspect some users will already have this token from other clients, I think we should give a clearer message that the device login is not yet implemented in Oatmeal. What do you think that should be?

I agree! We for sure want to specify you must login in another form, but it's best to provide how. I'm finding it difficult to see answers when quickly searching online. Do all the other existing implementation do it themselves? I'm almost wondering if it's worth adding a CLI command to create the token initially as you've already done the bulk of the work for authorization, with the goal of taking the easiest/fastest solution. I wouldn't want you spending hours trying to recreate something that already exists externally.

aislasq commented 5 months ago

Odd, so there's no token file provided anywhere for the gh command line such as the copilot extension?

At least on my tests there is not. I've been looking in my computer and cannot find where is the configuration saved for gh or vscode. I also tested with copilot.lua (my daily client) and they have the auth implementation (in lua) as a command as you suggested. I've seen other examples of the authentication flow in typescript and python, though I don't have the repos on hand.

I'll try to add the auth as a command with the authentication flow I have. I'll try to use /githubcopilot-auth inside oatmeal, or oatmeal --auth githubcopilot. It depends if I can recreate the Backend as it depends on the oauth token.

dustinblackman commented 5 months ago

I was thinking a command line call. Taking it out of the UI would probably be easiest as it gives you a bit more control to do what you need.

aislasq commented 5 months ago

I added the new command oatmeal auth --service <service-name>, it works well right now for githubcopilot.

I want to check with you on a couple of things:

dustinblackman commented 4 months ago

I'm so sorry for the super late reply. I've been really out of the loop this month.

Service works for me! And the path will all depends if it's cross platform or not. May be worth adding it if the path on Windows for example is unknown.

aislasq commented 3 months ago

So I ended up adding a couple of things.