Skip to content

Commit

Permalink
rough edges, but roundtrip works
Browse files Browse the repository at this point in the history
  • Loading branch information
PankajBhojwani committed Jul 4, 2024
1 parent 8bf23bc commit 65c2587
Show file tree
Hide file tree
Showing 13 changed files with 137 additions and 5 deletions.
11 changes: 9 additions & 2 deletions src/cascadia/TerminalApp/AppActionHandlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1496,9 +1496,16 @@ namespace winrt::TerminalApp::implementation
{
if (const auto& uriArgs{ args.ActionArgs().try_as<HandleUriArgs>() })
{
if (!uriArgs.Uri().empty())
const auto uriString{ uriArgs.Uri() };
if (!uriString.empty())
{
args.Handled(true);
Windows::Foundation::Uri uri{ uriString };
// we only accept "github-auth" host names for now
if (uri.Host() == L"github-auth")
{
_CompleteGithubAuth(uri);
args.Handled(true);
}
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/cascadia/TerminalApp/AppCommandlineArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,6 @@ void AppCommandlineArgs::_buildHandleUriParser()
// that `this` will still be safe - this function just lets us know this
// command was parsed.
subcommand->callback([&, this]() {
wil::WaitForDebuggerPresent(false);
// Build the action from the values we've parsed on the commandline.
const auto cmdlineArgs = _currentCommandline->Args();
winrt::hstring uri;
Expand Down Expand Up @@ -994,7 +993,8 @@ void AppCommandlineArgs::ValidateStartupCommands()
// If we parsed no commands, or the first command we've parsed is not a new
// tab action, prepend a new-tab command to the front of the list.
if (_startupActions.empty() ||
_startupActions.front().Action() != ShortcutAction::NewTab)
(_startupActions.front().Action() != ShortcutAction::NewTab &&
_startupActions.front().Action() != ShortcutAction::HandleUri))
{
// Build the NewTab action from the values we've parsed on the commandline.
NewTerminalArgs newTerminalArgs{};
Expand Down
85 changes: 85 additions & 0 deletions src/cascadia/TerminalApp/TerminalPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
#include <TerminalCore/ControlKeyStates.hpp>
#include <til/latch.h>

#include <winrt/Windows.Web.Http.h>
#include <winrt/Windows.Web.Http.Headers.h>
#include <winrt/Windows.Web.Http.Filters.h>

#include <winrt/Windows.Data.Json.h>

#include "../../types/inc/utils.hpp"
#include "App.h"
#include "ColorHelper.h"
Expand Down Expand Up @@ -45,6 +51,9 @@ using namespace ::TerminalApp;
using namespace ::Microsoft::Console;
using namespace ::Microsoft::Terminal::Core;
using namespace std::chrono_literals;
namespace WWH = ::winrt::Windows::Web::Http;
namespace WSS = ::winrt::Windows::Storage::Streams;
namespace WDJ = ::winrt::Windows::Data::Json;

#define HOOKUP_ACTION(action) _actionDispatch->action({ this, &TerminalPage::_Handle##action });

Expand Down Expand Up @@ -4029,9 +4038,85 @@ namespace winrt::TerminalApp::implementation
}
});

sui.GithubAuthRequested([weakThis{ get_weak() }](auto&& /*s*/, auto&& /*e*/) {
if (auto page{ weakThis.get() })
{
page->_InitiateGithubAuth();
}
});

return *settingsContent;
}

void TerminalPage::_InitiateGithubAuth()
{
// todo: we probably want a "state" parameter for protection against forgery attacks
ShellExecute(nullptr, L"open", L"https://github.com/login/oauth/authorize?client_id=Iv1.b0870d058e4473a1", nullptr, nullptr, SW_SHOWNORMAL);
}

winrt::fire_and_forget TerminalPage::_CompleteGithubAuth(const Windows::Foundation::Uri uri)
{
winrt::Windows::Web::Http::HttpClient httpClient{};
httpClient.DefaultRequestHeaders().Accept().TryParseAdd(L"application/json");

WWH::HttpRequestMessage request{ WWH::HttpMethod::Post(), Windows::Foundation::Uri{ L"https://github.com/login/oauth/access_token" } };
request.Headers().Accept().TryParseAdd(L"application/json");

WDJ::JsonObject jsonContent;
jsonContent.SetNamedValue(L"client_id", WDJ::JsonValue::CreateStringValue(L"Iv1.b0870d058e4473a1"));
jsonContent.SetNamedValue(L"client_secret", WDJ::JsonValue::CreateStringValue(L"notShowingSecretForCommitForObviousReasons"));
jsonContent.SetNamedValue(L"code", WDJ::JsonValue::CreateStringValue(uri.QueryParsed().GetFirstValueByName(L"code")));
const auto stringContent = jsonContent.ToString();
WWH::HttpStringContent requestContent{
stringContent,
WSS::UnicodeEncoding::Utf8,
L"application/json"
};

request.Content(requestContent);

co_await winrt::resume_background();

try
{
const auto response = httpClient.SendRequestAsync(request).get();
// Parse out the suggestion from the response
const auto string{ response.Content().ReadAsStringAsync().get() };
const auto jsonResult{ WDJ::JsonObject::Parse(string) };
const auto authToken{ jsonResult.GetNamedString(L"access_token") };
const auto refreshToken{ jsonResult.GetNamedString(L"refresh_token") };
if (!authToken.empty() && !refreshToken.empty())
{
_settings.GlobalSettings().AIInfo().GithubCopilotAuthToken(authToken);
_settings.GlobalSettings().AIInfo().GithubCopilotRefreshToken(refreshToken);

// todo: this _settingsTab check only works if new instance behavior is set to attach to this window,
// fix this to work with any new instance behavior
if (_settingsTab)
{
if (auto terminalTab{ _GetTerminalTabImpl(_settingsTab) })
{
// refresh the settings UI now that we have the auth tokens stored
co_await winrt::resume_foreground(Dispatcher());
terminalTab->UpdateSettings(_settings);

// also reload the extension palette with the new settings
if (_extensionPalette)
{
_extensionPalette = nullptr;
_loadQueryExtension();
}
}
}
}
}
catch (...)
{
}

co_return;
}

// Method Description:
// - Creates a settings UI tab and focuses it. If there's already a settings UI tab open,
// just focus the existing one.
Expand Down
3 changes: 3 additions & 0 deletions src/cascadia/TerminalApp/TerminalPage.h
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,9 @@ namespace winrt::TerminalApp::implementation

fire_and_forget _LaunchSettings(const Microsoft::Terminal::Settings::Model::SettingsTarget target);

void _InitiateGithubAuth();
winrt::fire_and_forget _CompleteGithubAuth(const Windows::Foundation::Uri uri);

void _TabDragStarted(const IInspectable& sender, const IInspectable& eventArgs);
void _TabDragCompleted(const IInspectable& sender, const IInspectable& eventArgs);

Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalSettingsEditor/AISettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,5 +123,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation

void AISettings::ClearGithubCopilotTokens_Click(const IInspectable& /*sender*/, const RoutedEventArgs& /*e*/)
{
_ViewModel.GithubCopilotAuthToken(L"");
_ViewModel.GithubCopilotRefreshToken(L"");
}
}
7 changes: 7 additions & 0 deletions src/cascadia/TerminalSettingsEditor/AISettings.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,13 @@
</muxc:InfoBadge.IconSource>
</muxc:InfoBadge>
</StackPanel>
<Button Grid.Row="1"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Click="{x:Bind ViewModel.InitiateGithubAuth_Click}"
Style="{StaticResource AccentButtonStyle}">
<TextBlock x:Uid="AISettings_InitiateGithubAuthFlow" />
</Button>
</Grid>
</StackPanel>
</local:SettingContainer>
Expand Down
7 changes: 7 additions & 0 deletions src/cascadia/TerminalSettingsEditor/AISettingsViewModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <LibraryResources.h>
#include <WtExeUtils.h>
#include <shellapi.h>

using namespace winrt;
using namespace winrt::Windows::UI::Xaml;
Expand Down Expand Up @@ -97,4 +98,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
return _Settings.GlobalSettings().AIInfo().ActiveProvider() == Model::LLMProvider::GithubCopilot;
}

void AISettingsViewModel::InitiateGithubAuth_Click(const IInspectable& /*sender*/, const RoutedEventArgs& /*e*/)
{
_awaitingGithubAuth = true;
GithubAuthRequested.raise(nullptr, nullptr);
}
}
3 changes: 3 additions & 0 deletions src/cascadia/TerminalSettingsEditor/AISettingsViewModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
bool AzureOpenAIIsActive();
bool OpenAIIsActive();
bool GithubCopilotIsActive();
void InitiateGithubAuth_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
til::typed_event<Windows::Foundation::IInspectable, Windows::Foundation::IInspectable> GithubAuthRequested;

private:
Model::CascadiaSettings _Settings;
bool _awaitingGithubAuth{ false };
};
};

Expand Down
3 changes: 3 additions & 0 deletions src/cascadia/TerminalSettingsEditor/AISettingsViewModel.idl
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,8 @@ namespace Microsoft.Terminal.Settings.Editor
Boolean AreGithubCopilotTokensSet { get; };
void GithubCopilotAuthToken(String authToken);
void GithubCopilotRefreshToken(String refreshToken);

void InitiateGithubAuth_Click(IInspectable sender, Windows.UI.Xaml.RoutedEventArgs args);
event Windows.Foundation.TypedEventHandler<Object, Object> GithubAuthRequested;
}
}
10 changes: 9 additions & 1 deletion src/cascadia/TerminalSettingsEditor/MainPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,15 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
else if (clickedItemTag == AISettingsTag)
{
contentFrame().Navigate(xaml_typename<Editor::AISettings>(), winrt::make<AISettingsViewModel>(_settingsClone));
auto aiSettingsVM{ winrt::make<AISettingsViewModel>(_settingsClone) };
aiSettingsVM.GithubAuthRequested([weakThis{ get_weak() }](auto&& /*s*/, auto&& /*e*/) {
if (auto mainPage{ weakThis.get() })
{
// propagate the event to TerminalPage
mainPage->GithubAuthRequested.raise(nullptr, nullptr);
}
});
contentFrame().Navigate(xaml_typename<Editor::AISettings>(), aiSettingsVM);
const auto crumb = winrt::make<Breadcrumb>(box_value(clickedItemTag), RS_(L"Nav_AISettings/Content"), BreadcrumbSubPage::None);
_breadcrumbs.Append(crumb);
}
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalSettingsEditor/MainPage.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
Windows::Foundation::Collections::IObservableVector<IInspectable> Breadcrumbs() noexcept;

til::typed_event<Windows::Foundation::IInspectable, Model::SettingsTarget> OpenJson;
til::typed_event<Windows::Foundation::IInspectable, Windows::Foundation::IInspectable> GithubAuthRequested;

private:
Windows::Foundation::Collections::IObservableVector<IInspectable> _breadcrumbs;
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalSettingsEditor/MainPage.idl
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,7 @@ namespace Microsoft.Terminal.Settings.Editor
Windows.Foundation.Collections.IObservableVector<IInspectable> Breadcrumbs { get; };

Windows.UI.Xaml.Media.Brush BackgroundBrush { get; };

event Windows.Foundation.TypedEventHandler<Object, Object> GithubAuthRequested;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,10 @@
<value>Store</value>
<comment>Text on the button that allows the user to store their key and/or endpoint.</comment>
</data>
<data name="AISettings_InitiateGithubAuthFlow.Text" xml:space="preserve">
<value>Authenticate via Github</value>
<comment>Text on the button that allows the user to authenticate to Github.</comment>
</data>
<data name="AISettings_AzureOpenAIDescription.Text" xml:space="preserve">
<value>To use Azure OpenAI as a service provider, you need an Azure OpenAI service resource.</value>
<comment>Header of the description that informs the user about Azure OpenAI and the prerequisites for setting it up in Terminal.</comment>
Expand Down

1 comment on commit 65c2587

@github-actions
Copy link

Choose a reason for hiding this comment

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

@check-spelling-bot Report

🔴 Please review

See the 📜action log or 📝 job summary for details.

Unrecognized words (3)

AIIs
AILLM
ietf

Previously acknowledged words that are now absent CRLFs Redir wcsicmp 🫥
To accept these unrecognized words as correct and remove the previously acknowledged and now absent words, you could run the following commands

... in a clone of the [email protected]:microsoft/terminal.git repository
on the dev/pabhoj/featurellm_capi branch (ℹ️ how do I use this?):

curl -s -S -L 'https://raw.githubusercontent.com/check-spelling/check-spelling/v0.0.22/apply.pl' |
perl - 'https://github.com/microsoft/terminal/actions/runs/9787173011/attempts/1'
Available 📚 dictionaries could cover words (expected and unrecognized) not in the 📘 dictionary

This includes both expected items (2213) from .github/actions/spelling/expect/04cdb9b77d6827c0202f51acd4205b017015bfff.txt
.github/actions/spelling/expect/alphabet.txt
.github/actions/spelling/expect/expect.txt
.github/actions/spelling/expect/web.txt and unrecognized words (3)

Dictionary Entries Covers Uniquely
cspell:cpp/src/lang-jargon.txt 11 1 1
cspell:swift/src/swift.txt 53 1 1
cspell:gaming-terms/dict/gaming-terms.txt 59 1 1
cspell:monkeyc/src/monkeyc_keywords.txt 123 1 1
cspell:cryptocurrencies/cryptocurrencies.txt 125 1 1

Consider adding them (in .github/workflows/spelling2.yml) for uses: check-spelling/[email protected] in its with:

      with:
        extra_dictionaries:
          cspell:cpp/src/lang-jargon.txt
          cspell:swift/src/swift.txt
          cspell:gaming-terms/dict/gaming-terms.txt
          cspell:monkeyc/src/monkeyc_keywords.txt
          cspell:cryptocurrencies/cryptocurrencies.txt

To stop checking additional dictionaries, add (in .github/workflows/spelling2.yml) for uses: check-spelling/[email protected] in its with:

check_extra_dictionaries: ''
Errors (3)

See the 📜action log or 📝 job summary for details.

❌ Errors Count
❌ check-file-path 3
❌ forbidden-pattern 8
❌ ignored-expect-variant 3

See ❌ Event descriptions for more information.

✏️ Contributor please read this

By default the command suggestion will generate a file named based on your commit. That's generally ok as long as you add the file to your commit. Someone can reorganize it later.

If the listed items are:

  • ... misspelled, then please correct them instead of using the command.
  • ... names, please add them to .github/actions/spelling/allow/names.txt.
  • ... APIs, you can add them to a file in .github/actions/spelling/allow/.
  • ... just things you're using, please add them to an appropriate file in .github/actions/spelling/expect/.
  • ... tokens you only need in one place and shouldn't generally be used, you can add an item in an appropriate file in .github/actions/spelling/patterns/.

See the README.md in each directory for more information.

🔬 You can test your commits without appending to a PR by creating a new branch with that extra change and pushing it to your fork. The check-spelling action will run in response to your push -- it doesn't require an open pull request. By using such a branch, you can limit the number of typos your peers see you make. 😉

If the flagged items are 🤯 false positives

If items relate to a ...

  • binary file (or some other file you wouldn't want to check at all).

    Please add a file path to the excludes.txt file matching the containing file.

    File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.

    ^ refers to the file's path from the root of the repository, so ^README\.md$ would exclude README.md (on whichever branch you're using).

  • well-formed pattern.

    If you can write a pattern that would match it,
    try adding it to the patterns.txt file.

    Patterns are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your lines.

    Note that patterns can't match multiline strings.

Please sign in to comment.