Skip to content

Commit 9034268

Browse files
authored
fix: user doesn't open webview but trigger completion (#127)
Enhances user authentication by adding logic to manage authentication callbacks without opening the webview when a valid token is present.
1 parent a970f9f commit 9034268

File tree

8 files changed

+195
-101
lines changed

8 files changed

+195
-101
lines changed

src/activate/handleUri.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,35 @@ import * as vscode from "vscode"
22

33
import { ClineProvider } from "../core/webview/ClineProvider"
44

5+
const handleAuthWithoutVisibleProvider = async (provider: ClineProvider | undefined, params: URLSearchParams) => {
6+
if (!provider) {
7+
return
8+
}
9+
10+
const code = params.get("code")
11+
const state = params.get("state")
12+
const token = params.get("token")
13+
14+
if ((code && state) || token) {
15+
await provider?.handleZgsmAuthCallback(code, state, token, false)
16+
}
17+
}
18+
519
export const handleUri = async (uri: vscode.Uri) => {
620
const path = uri.path
721
const query = new URLSearchParams(uri.query.replace(/\+/g, "%2B"))
822
const visibleProvider = ClineProvider.getVisibleInstance()
23+
24+
// not open webview to re-login
925
if (!visibleProvider) {
26+
if (path === "/callback") {
27+
const cacheProvider = ClineProvider.getCacheInstances()
28+
handleAuthWithoutVisibleProvider(cacheProvider, query)
29+
}
30+
1031
return
1132
}
33+
1234
switch (path) {
1335
case "/glama": {
1436
const code = query.get("code")

src/core/config/ContextProxy.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
} from "../../schemas"
1818
import { logger } from "../../utils/logging"
1919
import { telemetryService } from "../../services/telemetry/TelemetryService"
20+
import { ClineProvider } from "../webview/ClineProvider"
2021

2122
type GlobalStateKey = keyof GlobalState
2223
type SecretStateKey = keyof SecretState
@@ -256,4 +257,14 @@ export class ContextProxy {
256257

257258
await this.initialize()
258259
}
260+
261+
// get state from originContext.globalState
262+
public async getOriginGlobalState(key: string) {
263+
return await this?.originalContext?.globalState.get(key)
264+
}
265+
266+
// get state from originContext.secrets
267+
public async getOriginSecrets(key: string) {
268+
return await this?.originalContext?.secrets.get(key)
269+
}
259270
}

src/core/webview/ClineProvider.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ import { WebviewMessage } from "../../shared/WebviewMessage"
5858
import { afterZgsmPostLogin, getZgsmAccessToken } from "../../zgsmAuth/zgsmAuthHandler"
5959
import { defaultZgsmAuthConfig } from "../../zgsmAuth/config"
6060
import { CompletionStatusBar } from "../../../zgsm/src/codeCompletion/completionStatusBar"
61+
import { CompletionClient } from "../../../zgsm/src/codeCompletion/completionClient"
6162

6263
/**
6364
* https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/default/weather-webview/src/providers/WeatherViewProvider.ts
@@ -1015,11 +1016,11 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
10151016

10161017
// Zgsm
10171018

1018-
async handleZgsmAuthCallback(code: string | null, state: string | null, token: string | null) {
1019+
async handleZgsmAuthCallback(code: string | null, state: string | null, token: string | null, needVisible = true) {
10191020
let { apiConfiguration, currentApiConfigName } = await this.getState()
10201021
const visibleProvider = await ClineProvider.getInstance()
10211022

1022-
if (!visibleProvider) {
1023+
if (!visibleProvider && needVisible) {
10231024
return
10241025
}
10251026

@@ -1522,6 +1523,11 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
15221523
return getWorkspacePath()
15231524
}
15241525

1526+
// has view
1527+
get hasView() {
1528+
return !!this.view
1529+
}
1530+
15251531
// dev
15261532

15271533
async resetState() {

zgsm/src/codeCompletion/completionClient.ts

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,15 @@ import { Logger } from "../common/log-util"
1313
import { workspace } from "vscode"
1414
import { AxiosError } from "axios"
1515
import { createAuthenticatedHeaders } from "../common/api"
16-
import { configCompletion, settings, OPENAI_CLIENT_NOT_INITIALIZED } from "../common/constant"
16+
import {
17+
configCompletion,
18+
settings,
19+
OPENAI_CLIENT_NOT_INITIALIZED,
20+
NOT_PROVIDERED,
21+
ZGSM_API_KEY,
22+
ZGSM_BASE_URL,
23+
ZGSM_COMPLETION_URL,
24+
} from "../common/constant"
1725
import { CompletionPoint } from "./completionPoint"
1826
import { CompletionScores } from "./completionScore"
1927
import { CompletionTrace } from "./completionTrace"
@@ -32,6 +40,28 @@ export class CompletionClient {
3240
private reqs: Map<string, any> = new Map<string, any>()
3341
private betaMode?: any
3442

43+
private async getApiConfig(hasView: boolean, apiConfiguration: any) {
44+
if (hasView) {
45+
return {
46+
baseUrl: apiConfiguration.zgsmBaseUrl || defaultZgsmAuthConfig.baseUrl,
47+
completionUrl: apiConfiguration.zgsmCompletionUrl || defaultZgsmAuthConfig.completionUrl,
48+
apiKey: apiConfiguration.zgsmApiKey || NOT_PROVIDERED,
49+
}
50+
}
51+
52+
const context = CompletionClient.providerRef.deref()?.contextProxy
53+
54+
const contextApiKey = await context?.getOriginSecrets(ZGSM_API_KEY)
55+
const contextBaseUrl = await context?.getGlobalState(ZGSM_BASE_URL)
56+
const contextCompletionUrl = await context?.getGlobalState(ZGSM_COMPLETION_URL)
57+
58+
return {
59+
baseUrl: contextBaseUrl || defaultZgsmAuthConfig.baseUrl,
60+
completionUrl: contextCompletionUrl || defaultZgsmAuthConfig.completionUrl,
61+
apiKey: contextApiKey || NOT_PROVIDERED,
62+
}
63+
}
64+
3565
public static async setProvider(provider: ClineProvider) {
3666
CompletionClient.providerRef = new WeakRef(provider)
3767

@@ -119,14 +149,24 @@ export class CompletionClient {
119149
const provider = CompletionClient.providerRef.deref()
120150

121151
const { apiConfiguration } = await provider!.getState()
122-
if (!apiConfiguration?.zgsmApiKey) {
152+
153+
const hasView = !!provider?.hasView
154+
155+
if (!apiConfiguration?.zgsmApiKey && hasView) {
123156
Logger.error("Failed to get login information. Please log in again to use the completion service")
124157
return false
125158
}
126-
const completionUrl = `${apiConfiguration.zgsmBaseUrl || defaultZgsmAuthConfig.baseUrl}${apiConfiguration.zgsmCompletionUrl || defaultZgsmAuthConfig.completionUrl}`
159+
160+
const config = await this.getApiConfig(hasView, apiConfiguration)
161+
const fullUrl = `${config.baseUrl}${config.completionUrl}`
162+
163+
if (config.apiKey === NOT_PROVIDERED) {
164+
return false
165+
}
166+
127167
this.openai = new OpenAI({
128-
baseURL: completionUrl,
129-
apiKey: apiConfiguration.zgsmApiKey || "not-provided",
168+
baseURL: fullUrl,
169+
apiKey: config.apiKey,
130170
})
131171
if (!this.openai) {
132172
// Logger.error("Completion: Configuration error: configuration:", configuration, "openai: ", this.openai);
@@ -136,7 +176,7 @@ export class CompletionClient {
136176
this.stopWords = workspace.getConfiguration(configCompletion).get("inlineCompletion") ? ["\n", "\r"] : []
137177
this.betaMode = workspace.getConfiguration(configCompletion).get("betaMode")
138178
Logger.info(
139-
`Completion: Create OpenAIApi client, URL: ${completionUrl}, betaMode: ${this.betaMode}, stopWords: ${this.stopWords}`,
179+
`Completion: Create OpenAIApi client, URL: ${fullUrl}, betaMode: ${this.betaMode}, stopWords: ${this.stopWords}`,
140180
)
141181
return true
142182
}
@@ -209,8 +249,12 @@ export class CompletionClient {
209249
Logger.log(`Completion [${cp.id}]: Sending API request`)
210250
const headers = createAuthenticatedHeaders()
211251
const repo = workspace?.name?.split(" ")[0] ?? ""
212-
this.openai.baseURL = `${apiConfiguration.zgsmBaseUrl || defaultZgsmAuthConfig.baseUrl}${apiConfiguration.zgsmCompletionUrl || defaultZgsmAuthConfig.completionUrl}`
213-
this.openai.apiKey = apiConfiguration.zgsmApiKey || "not-provided"
252+
253+
const config = await this.getApiConfig(!!provider?.hasView, apiConfiguration)
254+
255+
this.openai.baseURL = `${config.baseUrl}${config.completionUrl}`
256+
this.openai.apiKey = config.apiKey
257+
214258
return this.openai.completions.create(
215259
{
216260
// no use

zgsm/src/codeCompletion/completionCommands.ts

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,53 +6,53 @@
66
* The above copyright notice and this permission notice shall be included in all
77
* copies or substantial portions of the Software.
88
*/
9-
import * as vscode from "vscode";
10-
import { Logger } from "../common/log-util";
11-
import { setupLangSwitchs } from "../common/services";
9+
import * as vscode from "vscode"
10+
import { Logger } from "../common/log-util"
11+
import { handleStatusBarClick } from "../common/services"
1212

13-
export type Command = { command: string, callback: (...args: any[]) => any, thisArg?: any; };
13+
export type Command = { command: string; callback: (...args: any[]) => any; thisArg?: any }
1414

1515
/**
1616
* Add a command to the completion status bar item.
1717
*/
1818
export const statusBarCommand: Command = {
19-
command: "zgsm-statusBar.showInformationMessage",
20-
callback: () => setupLangSwitchs()
21-
};
19+
command: "zgsm-statusBar.showInformationMessage",
20+
callback: () => handleStatusBarClick(),
21+
}
2222

2323
/**
2424
* Set the enabled status of the completion extension.
2525
*/
2626
function setExtensionStatus(enabled: boolean) {
27-
const config = vscode.workspace.getConfiguration();
28-
const target = vscode.ConfigurationTarget.Global;
29-
Logger.info("Set the status of 'zgsm-completion.enabled' to", enabled);
30-
config.update('zgsm-completion.enabled', enabled, target, false).then(console.error);
27+
const config = vscode.workspace.getConfiguration()
28+
const target = vscode.ConfigurationTarget.Global
29+
Logger.info("Set the status of 'zgsm-completion.enabled' to", enabled)
30+
config.update("zgsm-completion.enabled", enabled, target, false).then(console.error)
3131
}
3232

3333
/**
3434
* Command to enable completion.
3535
*/
3636
export const turnOnCompletion: Command = {
37-
command: "zgsm-completion.enable",
38-
callback: () => setExtensionStatus(true)
39-
};
37+
command: "zgsm-completion.enable",
38+
callback: () => setExtensionStatus(true),
39+
}
4040

4141
/**
4242
* Command to disable completion.
4343
*/
4444
export const turnOffCompletion: Command = {
45-
command: "zgsm-completion.disable",
46-
callback: () => setExtensionStatus(false)
47-
};
45+
command: "zgsm-completion.disable",
46+
callback: () => setExtensionStatus(false),
47+
}
4848

4949
/**
5050
* Command for completion shortcut instructions.
5151
*/
5252
export const shortKeyCut: Command = {
53-
command: "zgsm-completion.shortKeyCut",
54-
callback: (context: vscode.ExtensionContext) => {
55-
context.workspaceState.update('shortCutKeys', true);
56-
vscode.commands.executeCommand('editor.action.inlineSuggest.trigger');
57-
}
58-
};
53+
command: "zgsm-completion.shortKeyCut",
54+
callback: (context: vscode.ExtensionContext) => {
55+
context.workspaceState.update("shortCutKeys", true)
56+
vscode.commands.executeCommand("editor.action.inlineSuggest.trigger")
57+
},
58+
}

zgsm/src/common/constant.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,3 +204,9 @@ export const ACCESS_TOKEN_KEY = `${AUTH_TYPE}.accessToken`
204204
// OpenAI Client
205205
export const OPENAI_CLIENT_NOT_INITIALIZED = "OpenAI client not initialized"
206206
export const OPENAI_REQUEST_ABORTED = "Request was aborted"
207+
208+
export const NOT_PROVIDERED = "not-provided"
209+
210+
export const ZGSM_API_KEY = "zgsmApiKey"
211+
export const ZGSM_BASE_URL = "zgsmBaseUrl"
212+
export const ZGSM_COMPLETION_URL = "zgsmCompletionUrl"

0 commit comments

Comments
 (0)