Merge pull request #360 from punkpeye/pkce

feat: Glama add pkce
This commit is contained in:
Matt Rubens
2025-01-15 14:11:04 -05:00
committed by GitHub
6 changed files with 53 additions and 11 deletions

View File

@@ -143,7 +143,7 @@ Once your merge is successful:
<table> <table>
<tbody> <tbody>
<td align="center"> <td align="center">
<a href="https://marketplace.visualstudio.com/items?itemName=saoudrizwan.claude-dev" target="_blank"><strong>Download on VS Marketplace</strong></a> <a href="https://marketplace.visualstudio.com/items?itemName=rooveterinaryinc.roo-cline" target="_blank"><strong>Download on VS Marketplace</strong></a>
</td> </td>
<td align="center"> <td align="center">
<a href="https://discord.gg/cline" target="_blank"><strong>Join the Discord</strong></a> <a href="https://discord.gg/cline" target="_blank"><strong>Join the Discord</strong></a>

View File

@@ -1273,6 +1273,33 @@ export class ClineProvider implements vscode.WebviewViewProvider {
return cacheDir return cacheDir
} }
async handleGlamaCallback(code: string) {
let apiKey: string
try {
const response = await axios.post("https://glama.ai/api/gateway/v1/auth/exchange-code", { code })
if (response.data && response.data.apiKey) {
apiKey = response.data.apiKey
} else {
throw new Error("Invalid response from Glama API")
}
} catch (error) {
console.error("Error exchanging code for API key:", error)
throw error
}
const glama: ApiProvider = "glama"
await this.updateGlobalState("apiProvider", glama)
await this.storeSecret("glamaApiKey", apiKey)
await this.postStateToWebview()
if (this.cline) {
this.cline.api = buildApiHandler({
apiProvider: glama,
glamaApiKey: apiKey,
})
}
// await this.postMessageToWebview({ type: "action", action: "settingsButtonClicked" }) // bad ux if user is on welcome
}
async readGlamaModels(): Promise<Record<string, ModelInfo> | undefined> { async readGlamaModels(): Promise<Record<string, ModelInfo> | undefined> {
const glamaModelsFilePath = path.join( const glamaModelsFilePath = path.join(
await this.ensureCacheDirectoryExists(), await this.ensureCacheDirectoryExists(),

View File

@@ -7,7 +7,7 @@ The Cline extension exposes an API that can be used by other extensions. To use
3. Get access to the API with the following code: 3. Get access to the API with the following code:
```ts ```ts
const clineExtension = vscode.extensions.getExtension<ClineAPI>("saoudrizwan.claude-dev") const clineExtension = vscode.extensions.getExtension<ClineAPI>("rooveterinaryinc.roo-cline")
if (!clineExtension?.isActive) { if (!clineExtension?.isActive) {
throw new Error("Cline extension is not activated") throw new Error("Cline extension is not activated")
@@ -44,11 +44,11 @@ The Cline extension exposes an API that can be used by other extensions. To use
} }
``` ```
**Note:** To ensure that the `saoudrizwan.claude-dev` extension is activated before your extension, add it to the `extensionDependencies` in your `package.json`: **Note:** To ensure that the `rooveterinaryinc.roo-cline` extension is activated before your extension, add it to the `extensionDependencies` in your `package.json`:
```json ```json
"extensionDependencies": [ "extensionDependencies": [
"saoudrizwan.claude-dev" "rooveterinaryinc.roo-cline"
] ]
``` ```

View File

@@ -139,6 +139,14 @@ export function activate(context: vscode.ExtensionContext) {
return return
} }
switch (path) { switch (path) {
case "/glama": {
const code = query.get("code")
if (code) {
await visibleProvider.handleGlamaCallback(code)
}
break
}
case "/openrouter": { case "/openrouter": {
const code = query.get("code") const code = query.get("code")
if (code) { if (code) {

View File

@@ -141,5 +141,5 @@ export function mergeJson(
} }
function getExtensionUri(): vscode.Uri { function getExtensionUri(): vscode.Uri {
return vscode.extensions.getExtension("saoudrizwan.claude-dev")!.extensionUri return vscode.extensions.getExtension("rooveterinaryinc.roo-cline")!.extensionUri
} }

View File

@@ -209,11 +209,12 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
<span style={{ fontWeight: 500 }}>Glama API Key</span> <span style={{ fontWeight: 500 }}>Glama API Key</span>
</VSCodeTextField> </VSCodeTextField>
{!apiConfiguration?.glamaApiKey && ( {!apiConfiguration?.glamaApiKey && (
<VSCodeLink <VSCodeButtonLink
href="https://glama.ai/settings/api-keys" href={getGlamaAuthUrl(uriScheme)}
style={{ display: "inline", fontSize: "inherit" }}> style={{ margin: "5px 0 0 0" }}
You can get an Glama API key by signing up here. appearance="secondary">
</VSCodeLink> Get Glama API Key
</VSCodeButtonLink>
)} )}
<p <p
style={{ style={{
@@ -739,8 +740,14 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
) )
} }
export function getGlamaAuthUrl(uriScheme?: string) {
const callbackUrl = `${uriScheme || "vscode"}://rooveterinaryinc.roo-cline/glama`
return `https://glama.ai/oauth/authorize?callback_url=${encodeURIComponent(callbackUrl)}`
}
export function getOpenRouterAuthUrl(uriScheme?: string) { export function getOpenRouterAuthUrl(uriScheme?: string) {
return `https://openrouter.ai/auth?callback_url=${uriScheme || "vscode"}://saoudrizwan.claude-dev/openrouter` return `https://openrouter.ai/auth?callback_url=${uriScheme || "vscode"}://rooveterinaryinc.roo-cline/openrouter`
} }
export const formatPrice = (price: number) => { export const formatPrice = (price: number) => {