Skip to content

Commit

Permalink
VS Code: require userInfo prop (#2470)
Browse files Browse the repository at this point in the history
- Fixes the issue caused by the fact that `userInfo` [was not
available](https://github.com/sourcegraph/cody/pull/2057/files#diff-3ef5ec11a5cb8846141e4fc4e08c5502837d912d07e00fadfbfa25187bdc0d84R20)
in the critical place required for a telemetry event creation. This PR
makes `userInfo` a required prop in the React component tree for all the
intermediate components to avoid such an issue in the future. It sets
the `userInfo` value to `{ isDotComUser: true, isCodyProUser: false }`
for the components reused in the web version. @chenkc805, let me know if
other default values make more sense.
- Closes #2468
  • Loading branch information
valerybugakov authored Jan 2, 2024
1 parent 66b40e1 commit 28a38c8
Show file tree
Hide file tree
Showing 13 changed files with 44 additions and 18 deletions.
2 changes: 2 additions & 0 deletions lib/shared/src/sourcegraph-api/environments.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// `TESTING_DOTCOM_URL` is not set in webviews. If `isDotCom` helper it called from the webview it will use
// the default ('https://sourcegraph.com') value.
export const DOTCOM_URL = new URL(process.env.TESTING_DOTCOM_URL || 'https://sourcegraph.com')
export const INTERNAL_S2_URL = new URL('https://sourcegraph.sourcegraph.com/')
export const LOCAL_APP_URL = new URL('http://localhost:3080')
Expand Down
2 changes: 1 addition & 1 deletion lib/ui/src/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ interface ChatProps extends ChatClassNames {
EnhancedContextSettings?: React.FunctionComponent<{ isOpen: boolean; setOpen: (open: boolean) => void }>
ChatModelDropdownMenu?: React.FunctionComponent<ChatModelDropdownMenuProps>
onCurrentChatModelChange?: (model: ChatModelProvider) => void
userInfo?: UserAccountInfo
userInfo: UserAccountInfo
postMessage?: ApiPostMessage
}

Expand Down
9 changes: 5 additions & 4 deletions lib/ui/src/chat/ErrorItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ import styles from './ErrorItem.module.css'
export const ErrorItem: React.FunctionComponent<{
error: Omit<ChatError, 'isChatErrorGuard'>
ChatButtonComponent?: React.FunctionComponent<ChatButtonProps>
userInfo?: UserAccountInfo
userInfo: UserAccountInfo
postMessage?: ApiPostMessage
}> = React.memo(function ErrorItemContent({ error, ChatButtonComponent, postMessage }) {
}> = React.memo(function ErrorItemContent({ error, ChatButtonComponent, userInfo, postMessage }) {
if (typeof error !== 'string' && error.name === RateLimitError.errorName && postMessage) {
return (
<RateLimitErrorItem
error={error as RateLimitError}
ChatButtonComponent={ChatButtonComponent}
userInfo={userInfo}
postMessage={postMessage}
/>
)
Expand Down Expand Up @@ -87,12 +88,12 @@ export const ContextWindowLimitErrorItem: React.FunctionComponent<{
export const RateLimitErrorItem: React.FunctionComponent<{
error: RateLimitError
ChatButtonComponent?: React.FunctionComponent<ChatButtonProps>
userInfo?: UserAccountInfo
userInfo: UserAccountInfo
postMessage: ApiPostMessage
}> = React.memo(function RateLimitErrorItemContent({ error, ChatButtonComponent, userInfo, postMessage }) {
// Only show Upgrades if both the error said an upgrade was available and we know the user
// has not since upgraded.
const isEnterpriseUser = userInfo?.isDotComUser !== true
const isEnterpriseUser = userInfo.isDotComUser !== true
const canUpgrade = error.upgradeIsAvailable && !userInfo?.isCodyProUser
const tier = isEnterpriseUser ? 'enterprise' : canUpgrade ? 'free' : 'pro'

Expand Down
3 changes: 2 additions & 1 deletion lib/ui/src/chat/Transcript.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export const Transcript: React.FunctionComponent<
chatModels?: ChatModelProvider[]
ChatModelDropdownMenu?: React.FunctionComponent<ChatModelDropdownMenuProps>
onCurrentChatModelChange?: (model: ChatModelProvider) => void
userInfo?: UserAccountInfo
userInfo: UserAccountInfo
postMessage?: ApiPostMessage
} & TranscriptItemClassNames
> = React.memo(function TranscriptContent({
Expand Down Expand Up @@ -224,6 +224,7 @@ export const Transcript: React.FunctionComponent<
chatInputClassName={chatInputClassName}
ChatButtonComponent={ChatButtonComponent}
postMessage={postMessage}
userInfo={userInfo}
/>
)}
{messageInProgress && messageInProgress.speaker === 'assistant' && (
Expand Down
2 changes: 1 addition & 1 deletion lib/ui/src/chat/TranscriptItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export const TranscriptItem: React.FunctionComponent<
abortMessageInProgressComponent?: React.FunctionComponent<{ onAbortMessageInProgress: () => void }>
onAbortMessageInProgress?: () => void
ChatButtonComponent?: React.FunctionComponent<ChatButtonProps>
userInfo?: UserAccountInfo
userInfo: UserAccountInfo
postMessage?: ApiPostMessage
} & TranscriptItemClassNames
> = React.memo(function TranscriptItemContent({
Expand Down
10 changes: 7 additions & 3 deletions vscode/src/chat/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ export const ACCOUNT_LIMITS_INFO_URL = new URL(
export interface AuthStatus {
username?: string
endpoint: string | null
isDotCom: boolean
isLoggedIn: boolean
showInvalidAccessTokenError: boolean
authenticated: boolean
Expand All @@ -170,6 +171,7 @@ export interface AuthStatus {

export const defaultAuthStatus = {
endpoint: '',
isDotCom: true,
isLoggedIn: false,
showInvalidAccessTokenError: false,
authenticated: false,
Expand All @@ -181,10 +183,11 @@ export const defaultAuthStatus = {
primaryEmail: '',
displayName: '',
avatarURL: '',
}
} satisfies AuthStatus

export const unauthenticatedStatus = {
endpoint: '',
isDotCom: true,
isLoggedIn: false,
showInvalidAccessTokenError: true,
authenticated: false,
Expand All @@ -196,9 +199,10 @@ export const unauthenticatedStatus = {
primaryEmail: '',
displayName: '',
avatarURL: '',
}
} satisfies AuthStatus

export const networkErrorAuthStatus = {
isDotCom: false,
showInvalidAccessTokenError: false,
authenticated: false,
isLoggedIn: false,
Expand All @@ -211,7 +215,7 @@ export const networkErrorAuthStatus = {
primaryEmail: '',
displayName: '',
avatarURL: '',
}
} satisfies Omit<AuthStatus, 'endpoint'>

/** The local environment of the editor. */
export interface LocalEnv {
Expand Down
2 changes: 2 additions & 0 deletions vscode/src/chat/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ describe('validateAuthStatus', () => {
authenticated: true,
siteHasCodyEnabled: true,
isLoggedIn: true,
isDotCom: false,
endpoint,
avatarURL,
primaryEmail,
Expand Down Expand Up @@ -147,6 +148,7 @@ describe('validateAuthStatus', () => {
avatarURL,
primaryEmail,
displayName,
isDotCom: false,
}
expect(
newAuthStatus(
Expand Down
1 change: 1 addition & 0 deletions vscode/src/chat/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export function newAuthStatus(
const isLoggedIn = authStatus.siteHasCodyEnabled && authStatus.authenticated
const isAllowed = authStatus.requiresVerifiedEmail ? authStatus.hasVerifiedEmail : true
authStatus.isLoggedIn = isLoggedIn && isAllowed
authStatus.isDotCom = isDotComOrApp
return authStatus
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const DUMMY_CONTEXT: vscode.InlineCompletionContext = {

const DUMMY_AUTH_STATUS: AuthStatus = {
endpoint: 'https://fastsourcegraph.com',
isDotCom: true,
isLoggedIn: true,
showInvalidAccessTokenError: false,
authenticated: true,
Expand Down
4 changes: 3 additions & 1 deletion vscode/test/e2e/chat.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { expect, Frame, FrameLocator, Locator, Page } from '@playwright/test'
import * as mockServer from '../fixtures/mock-server'

import { sidebarSignin } from './common'
import { test } from './helpers'
import { test as baseTest, DotcomUrlOverride } from './helpers'

const test = baseTest.extend<DotcomUrlOverride>({ dotcomUrl: mockServer.SERVER_URL })

test('shows upgrade rate limit message for free users', async ({ page, sidebar }) => {
await fetch(`${mockServer.SERVER_URL}/.test/completions/triggerRateLimit/free`, {
Expand Down
5 changes: 3 additions & 2 deletions vscode/webviews/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { trailingNonAlphaNumericRegex } from '@sourcegraph/cody-shared/src/chat/
import { ChatHistory, ChatMessage } from '@sourcegraph/cody-shared/src/chat/transcript/messages'
import { EnhancedContextContextT } from '@sourcegraph/cody-shared/src/codebase-context/context-status'
import { Configuration } from '@sourcegraph/cody-shared/src/configuration'
import { isDotCom } from '@sourcegraph/cody-shared/src/sourcegraph-api/environments'
import { UserAccountInfo } from '@sourcegraph/cody-ui/src/Chat'

import { AuthMethod, AuthStatus, LocalEnv } from '../src/chat/protocol'
Expand Down Expand Up @@ -91,7 +90,9 @@ export const App: React.FunctionComponent<{ vscodeAPI: VSCodeWrapper }> = ({ vsc
setAuthStatus(message.authStatus)
setUserAccountInfo({
isCodyProUser: !message.authStatus.userCanUpgrade,
isDotComUser: isDotCom(message.authStatus.endpoint || ''),
// Receive this value from the extension backend to make it work
// with E2E tests where change the DOTCOM_URL via the env variable TESTING_DOTCOM_URL.
isDotComUser: message.authStatus.isDotCom,
})
setView(message.authStatus.isLoggedIn ? 'chat' : 'login')
// Get chat models
Expand Down
5 changes: 5 additions & 0 deletions web/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Client, createClient, Transcript } from '@sourcegraph/cody-shared/src/c
import { ChatMessage } from '@sourcegraph/cody-shared/src/chat/transcript/messages'
import { ErrorLike, isErrorLike } from '@sourcegraph/cody-shared/src/common'
import type { Editor } from '@sourcegraph/cody-shared/src/editor'
import { isDotCom } from '@sourcegraph/cody-shared/src/sourcegraph-api/environments'
import { CodySvg } from '@sourcegraph/cody-ui/src/utils/icons'

import { Chat } from './Chat'
Expand Down Expand Up @@ -117,6 +118,10 @@ export const App: React.FunctionComponent = () => {
setInputHistory={setInputHistory}
isCodyEnabled={true}
onSubmit={onSubmit}
userInfo={{
isDotComUser: isDotCom(config.serverEndpoint),
isCodyProUser: false,
}}
/>
</>
)
Expand Down
16 changes: 11 additions & 5 deletions web/src/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,18 @@ import { SubmitSvg } from '@sourcegraph/cody-ui/src/utils/icons'

import styles from './Chat.module.css'

export const Chat: React.FunctionComponent<
Omit<
interface ChatProps
extends Omit<
React.ComponentPropsWithoutRef<typeof ChatUI>,
| 'textAreaComponent'
| 'submitButtonComponent'
| 'fileLinkComponent'
| 'symbolLinkComponent'
| 'messageBeingEdited'
| 'setMessageBeingEdited'
>
> = ({
> {}

export const Chat: React.FunctionComponent<ChatProps> = ({
messageInProgress,
transcript,
contextStatus,
Expand All @@ -29,6 +30,9 @@ export const Chat: React.FunctionComponent<
inputHistory,
setInputHistory,
onSubmit,
userInfo,
isCodyEnabled,
...rest
}) => (
<ChatUI
messageBeingEdited={false}
Expand All @@ -52,7 +56,9 @@ export const Chat: React.FunctionComponent<
transcriptActionClassName={styles.transcriptAction}
inputRowClassName={styles.inputRow}
chatInputClassName={styles.chatInput}
isCodyEnabled={true}
isCodyEnabled={isCodyEnabled}
userInfo={userInfo}
{...rest}
/>
)

Expand Down

0 comments on commit 28a38c8

Please sign in to comment.