-
Notifications
You must be signed in to change notification settings - Fork 4.6k
feat: new onboarding flow #7266
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
Merged
Merged
Changes from all commits
Commits
Show all changes
47 commits
Select commit
Hold shift + click to select a range
d0debc3
onboarding page to start
lifeizhou-ap 06dfcc9
added primary attribute on configKey in provider
lifeizhou-ap 75386e5
cherry pick primary configkey change
lifeizhou-ap 773d392
apply primary in cli config provider, also enables user to config all…
lifeizhou-ap c99cbc9
change SAGEMAKER_ENDPOINT_NAME as a required field
lifeizhou-ap f08a0b1
fmt
lifeizhou-ap 882a2b8
added some fallback
lifeizhou-ap 122221e
added props to show options in provider config component
lifeizhou-ap 6243dd0
onboarding page ui
lifeizhou-ap 992a64a
merge main
lifeizhou-ap a6e5e17
add instructions
lifeizhou-ap 831091b
set default model for selected provider
lifeizhou-ap 95c9361
crete feature toggle to switch between old/new onboarding
lifeizhou-ap 048059b
add option to add custom provider
lifeizhou-ap 743d49e
changed add custom provider response with provider name only
lifeizhou-ap 46fa106
enable nanogpt device login flow
lifeizhou-ap 535b6b5
added nanogpt provider
lifeizhou-ap 301d4f3
text change
lifeizhou-ap 2e85a79
change font size
lifeizhou-ap 6f03f6f
extract to constant
lifeizhou-ap 7488025
clean up special case for ollama and better error message
lifeizhou-ap 2ce5e27
added privacy and success page
lifeizhou-ap c504e2a
added tracking events
lifeizhou-ap affff89
updated the instructions
lifeizhou-ap d183cf0
error handling
lifeizhou-ap c1062da
feature toggle off by default
lifeizhou-ap 500f7d6
Merge branch 'main' into lifei/simplify_onboarding_flow
lifeizhou-ap bec2abf
added local model selection
lifeizhou-ap 898310f
fix test
lifeizhou-ap 3398621
revert testing code
lifeizhou-ap 07443dd
fix test compilation
lifeizhou-ap 0fef532
adddres copilot review comments
lifeizhou-ap 2bb1075
Merge branch 'main' into lifei/simplify_onboarding_flow
lifeizhou-ap c82bb85
resolve merge conflicts
lifeizhou-ap c708c26
text change
lifeizhou-ap ae924c0
error message and error handling
lifeizhou-ap a152100
track provider selected
lifeizhou-ap 4ec0e6f
used nano-gpt to get canonical model data
lifeizhou-ap 5c959b6
update text position
lifeizhou-ap 5454a49
fixed test
lifeizhou-ap 9696662
Merge branch 'main' into lifei/simplify_onboarding_flow
lifeizhou-ap 45f83d1
updated local model style
lifeizhou-ap da52745
tracking onboarding events
lifeizhou-ap 9cbe4d8
Merge branch 'main' into lifei/simplify_onboarding_flow
lifeizhou-ap 636d007
updated default model for nanogpt
lifeizhou-ap 51ef2dd
address review comments
lifeizhou-ap 36a51c9
Merge branch 'main' into lifei/simplify_onboarding_flow
lifeizhou-ap File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,128 @@ | ||
| use anyhow::{anyhow, Result}; | ||
| use reqwest::Client; | ||
| use serde::{Deserialize, Serialize}; | ||
| use std::time::Duration; | ||
| use tokio::time::{sleep, timeout}; | ||
|
|
||
| use crate::config::Config; | ||
|
|
||
| /// Default model for NanoGPT configuration | ||
| pub const NANOGPT_DEFAULT_MODEL: &str = "openai/gpt-4.1-nano"; | ||
|
|
||
| const NANOGPT_START_URL: &str = "https://nano-gpt.com/api/cli-login/start"; | ||
| const NANOGPT_POLL_URL: &str = "https://nano-gpt.com/api/cli-login/poll"; | ||
| const AUTH_TIMEOUT: Duration = Duration::from_secs(180); // 3 minutes | ||
| const POLL_INTERVAL: Duration = Duration::from_secs(2); | ||
|
|
||
| #[derive(Debug, Serialize)] | ||
| struct StartRequest { | ||
| client_name: String, | ||
| } | ||
|
|
||
| #[derive(Debug, Deserialize)] | ||
| struct StartResponse { | ||
| device_code: String, | ||
| verification_uri_complete: String, | ||
| } | ||
|
|
||
| #[derive(Debug, Serialize)] | ||
| struct PollRequest { | ||
| device_code: String, | ||
| } | ||
|
|
||
| #[derive(Debug, Deserialize)] | ||
| struct PollResponse { | ||
| key: String, | ||
| } | ||
|
|
||
| async fn poll_for_token(device_code: &str) -> Result<String> { | ||
| let client = Client::new(); | ||
|
|
||
| loop { | ||
| sleep(POLL_INTERVAL).await; | ||
|
|
||
| let body = PollRequest { | ||
| device_code: device_code.to_string(), | ||
| }; | ||
|
|
||
| let response = client.post(NANOGPT_POLL_URL).json(&body).send().await?; | ||
| // https://docs.nano-gpt.com/integrations/cli-login#response-codes | ||
| match response.status().as_u16() { | ||
| 200 => { | ||
| let poll_resp: PollResponse = response.json().await?; | ||
| return Ok(poll_resp.key); | ||
| } | ||
| 202 => { | ||
| continue; | ||
| } | ||
| 410 => { | ||
| return Err(anyhow!("Device code has expired - please try again")); | ||
| } | ||
| 409 => { | ||
| return Err(anyhow!("Device code has already been consumed")); | ||
| } | ||
| 404 => { | ||
| return Err(anyhow!("Invalid device code")); | ||
| } | ||
| 429 => { | ||
| return Err(anyhow!( | ||
| "Too many requests to NanoGPT. Please wait a moment and try again." | ||
| )); | ||
| } | ||
| other => { | ||
| let error_text = response.text().await.unwrap_or_default(); | ||
| return Err(anyhow!( | ||
| "Unexpected poll response: {} - {}", | ||
| other, | ||
| error_text | ||
| )); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| pub async fn complete_nanogpt_auth() -> Result<String> { | ||
| let client = Client::new(); | ||
| let body = StartRequest { | ||
| client_name: "goose".to_string(), | ||
| }; | ||
|
|
||
| let response = client.post(NANOGPT_START_URL).json(&body).send().await?; | ||
|
|
||
| if !response.status().is_success() { | ||
| let status = response.status(); | ||
| let error_text = response.text().await.unwrap_or_default(); | ||
| return Err(anyhow!( | ||
| "Failed to start NanoGPT device flow: {} - {}", | ||
| status, | ||
| error_text | ||
| )); | ||
| } | ||
|
|
||
| let start_resp: StartResponse = response.json().await?; | ||
|
|
||
| println!("Opening browser for NanoGPT authentication..."); | ||
|
|
||
| if let Err(e) = webbrowser::open(&start_resp.verification_uri_complete) { | ||
| eprintln!("Failed to open browser automatically: {}", e); | ||
| println!( | ||
| "Please open this URL manually: {}", | ||
| start_resp.verification_uri_complete | ||
| ); | ||
| } | ||
|
|
||
| println!("Waiting for NanoGPT authorization..."); | ||
|
|
||
| match timeout(AUTH_TIMEOUT, poll_for_token(&start_resp.device_code)).await { | ||
| Ok(Ok(api_key)) => Ok(api_key), | ||
| Ok(Err(e)) => Err(e), | ||
| Err(_) => Err(anyhow!("Authentication timed out - please try again")), | ||
| } | ||
| } | ||
|
|
||
| pub fn configure_nanogpt(config: &Config, api_key: String) -> Result<()> { | ||
| config.set_secret("NANOGPT_API_KEY", &api_key)?; | ||
| config.set_goose_provider("nano-gpt")?; | ||
| config.set_goose_model(NANOGPT_DEFAULT_MODEL)?; | ||
| Ok(()) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -168,6 +168,11 @@ impl ProviderDef for AnthropicProvider { | |
| ), | ||
| ], | ||
| ) | ||
| .with_setup_steps(vec![ | ||
| "Go to https://platform.claude.com/settings/keys", | ||
| "Click 'Create Key'", | ||
| "Copy the key and paste it above", | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| ]) | ||
| } | ||
|
|
||
| fn from_env( | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ideally we'd hold onto the event and then send it (or not) only if the user opts in -- think that's possible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, I think we could. I was thinking about this too originally although the code would be a bit complicated. However, we would like to get the metrics for the onboarding as much as we can as requested by UX.