Remove Glama provider integration and related references

- Deleted GlamaHandler export from providers index.
- Removed Glama callback handling from ClineProvider.
- Updated tests to exclude Glama API key and model checks.
- Removed Glama-related configurations from ProfileValidator and validation functions.
- Eliminated Glama components and settings from the UI.
- Cleaned up localization files by removing Glama-specific entries.
- Updated API utility functions to exclude Glama authentication.
This commit is contained in:
hannesrudolph 2025-06-02 16:59:04 -06:00
parent af2e9ed725
commit d5c92801ca
49 changed files with 17 additions and 745 deletions

View file

@ -170,7 +170,6 @@ export function NewRun() {
apiProvider,
apiModelId,
openRouterModelId,
glamaModelId,
requestyModelId,
unboundModelId,
ollamaModelId,
@ -192,9 +191,6 @@ export function NewRun() {
case "openrouter":
setValue("model", openRouterModelId ?? "")
break
case "glama":
setValue("model", glamaModelId ?? "")
break
case "requesty":
setValue("model", requestyModelId ?? "")
break

View file

@ -8,7 +8,6 @@ import { Equals, Keys, AssertEqual } from "./utils.js"
export const providerNames = [
"anthropic",
"glama",
"openrouter",
"bedrock",
"vertex",
@ -353,11 +352,6 @@ const anthropicSchema = z.object({
anthropicUseAuthToken: z.boolean().optional(),
})
const glamaSchema = z.object({
glamaModelId: z.string().optional(),
glamaApiKey: z.string().optional(),
})
const openRouterSchema = z.object({
openRouterApiKey: z.string().optional(),
openRouterModelId: z.string().optional(),
@ -488,11 +482,6 @@ export const providerSettingsSchemaDiscriminated = z
apiProvider: z.literal("anthropic"),
}),
),
glamaSchema.merge(
z.object({
apiProvider: z.literal("glama"),
}),
),
openRouterSchema.merge(
z.object({
apiProvider: z.literal("openrouter"),
@ -595,7 +584,6 @@ export const providerSettingsSchemaDiscriminated = z
export const providerSettingsSchema = z.object({
apiProvider: providerNamesSchema.optional(),
...anthropicSchema.shape,
...glamaSchema.shape,
...openRouterSchema.shape,
...bedrockSchema.shape,
...vertexSchema.shape,
@ -629,9 +617,6 @@ const providerSettingsRecord: ProviderSettingsRecord = {
apiKey: undefined,
anthropicBaseUrl: undefined,
anthropicUseAuthToken: undefined,
// Glama
glamaModelId: undefined,
glamaApiKey: undefined,
// OpenRouter
openRouterApiKey: undefined,
openRouterModelId: undefined,
@ -896,7 +881,6 @@ export const ROO_CODE_SETTINGS_KEYS = [...GLOBAL_SETTINGS_KEYS, ...PROVIDER_SETT
export type SecretState = Pick<
ProviderSettings,
| "apiKey"
| "glamaApiKey"
| "openRouterApiKey"
| "awsAccessKey"
| "awsSecretKey"
@ -915,7 +899,6 @@ type SecretStateRecord = Record<Keys<SecretState>, undefined>
const secretStateRecord: SecretStateRecord = {
apiKey: undefined,
glamaApiKey: undefined,
openRouterApiKey: undefined,
awsAccessKey: undefined,
awsSecretKey: undefined,

View file

@ -48,7 +48,7 @@ export const globalSettingsSchema = z.object({
allowedMaxRequests: z.number().nullish(),
autoCondenseContext: z.boolean().optional(),
autoCondenseContextPercent: z.number().optional(),
maxConcurrentFileReads: z.number().optional(),
maxConcurrentFileReads: z.number().optional(),
browserToolEnabled: z.boolean().optional(),
browserViewportSize: z.string().optional(),
@ -205,7 +205,6 @@ export type RooCodeSettings = GlobalSettings & ProviderSettings
export type SecretState = Pick<
ProviderSettings,
| "apiKey"
| "glamaApiKey"
| "openRouterApiKey"
| "awsAccessKey"
| "awsSecretKey"
@ -227,7 +226,6 @@ export type SecretState = Pick<
export const SECRET_STATE_KEYS = keysOf<SecretState>()([
"apiKey",
"glamaApiKey",
"openRouterApiKey",
"awsAccessKey",
"awsSecretKey",

View file

@ -10,7 +10,6 @@ import { codebaseIndexProviderSchema } from "./codebase-index.js"
export const providerNames = [
"anthropic",
"glama",
"openrouter",
"bedrock",
"vertex",
@ -77,11 +76,6 @@ const anthropicSchema = apiModelIdProviderModelSchema.extend({
anthropicUseAuthToken: z.boolean().optional(),
})
const glamaSchema = baseProviderSettingsSchema.extend({
glamaModelId: z.string().optional(),
glamaApiKey: z.string().optional(),
})
const openRouterSchema = baseProviderSettingsSchema.extend({
openRouterApiKey: z.string().optional(),
openRouterModelId: z.string().optional(),
@ -208,7 +202,6 @@ const defaultSchema = z.object({
export const providerSettingsSchemaDiscriminated = z.discriminatedUnion("apiProvider", [
anthropicSchema.merge(z.object({ apiProvider: z.literal("anthropic") })),
glamaSchema.merge(z.object({ apiProvider: z.literal("glama") })),
openRouterSchema.merge(z.object({ apiProvider: z.literal("openrouter") })),
bedrockSchema.merge(z.object({ apiProvider: z.literal("bedrock") })),
vertexSchema.merge(z.object({ apiProvider: z.literal("vertex") })),
@ -234,7 +227,6 @@ export const providerSettingsSchemaDiscriminated = z.discriminatedUnion("apiProv
export const providerSettingsSchema = z.object({
apiProvider: providerNamesSchema.optional(),
...anthropicSchema.shape,
...glamaSchema.shape,
...openRouterSchema.shape,
...bedrockSchema.shape,
...vertexSchema.shape,
@ -266,9 +258,6 @@ export const PROVIDER_SETTINGS_KEYS = keysOf<ProviderSettings>()([
"apiKey",
"anthropicBaseUrl",
"anthropicUseAuthToken",
// Glama
"glamaModelId",
"glamaApiKey",
// OpenRouter
"openRouterApiKey",
"openRouterModelId",

View file

@ -1,20 +0,0 @@
import type { ModelInfo } from "../model.js"
// https://glama.ai/models
export const glamaDefaultModelId = "anthropic/claude-3-7-sonnet"
export const glamaDefaultModelInfo: ModelInfo = {
maxTokens: 8192,
contextWindow: 200_000,
supportsImages: true,
supportsComputerUse: true,
supportsPromptCache: true,
inputPrice: 3.0,
outputPrice: 15.0,
cacheWritesPrice: 3.75,
cacheReadsPrice: 0.3,
description:
"Claude 3.7 Sonnet is an advanced large language model with improved reasoning, coding, and problem-solving capabilities. It introduces a hybrid reasoning approach, allowing users to choose between rapid responses and extended, step-by-step processing for complex tasks. The model demonstrates notable improvements in coding, particularly in front-end development and full-stack updates, and excels in agentic workflows, where it can autonomously navigate multi-step processes. Claude 3.7 Sonnet maintains performance parity with its predecessor in standard mode while offering an extended reasoning mode for enhanced accuracy in math, coding, and instruction-following tasks. Read more at the [blog post here](https://www.anthropic.com/news/claude-3-7-sonnet)",
}
export const GLAMA_DEFAULT_TEMPERATURE = 0

View file

@ -3,7 +3,6 @@ export * from "./bedrock.js"
export * from "./chutes.js"
export * from "./deepseek.js"
export * from "./gemini.js"
export * from "./glama.js"
export * from "./groq.js"
export * from "./lite-llm.js"
export * from "./lm-studio.js"

View file

@ -14,13 +14,6 @@ export const handleUri = async (uri: vscode.Uri) => {
}
switch (path) {
case "/glama": {
const code = query.get("code")
if (code) {
await visibleProvider.handleGlamaCallback(code)
}
break
}
case "/openrouter": {
const code = query.get("code")
if (code) {

View file

@ -5,7 +5,6 @@ import type { ProviderSettings, ModelInfo } from "@roo-code/types"
import { ApiStream } from "./transform/stream"
import {
GlamaHandler,
AnthropicHandler,
AwsBedrockHandler,
OpenRouterHandler,
@ -64,8 +63,6 @@ export function buildApiHandler(configuration: ProviderSettings): ApiHandler {
switch (apiProvider) {
case "anthropic":
return new AnthropicHandler(options)
case "glama":
return new GlamaHandler(options)
case "openrouter":
return new OpenRouterHandler(options)
case "bedrock":

View file

@ -1,233 +0,0 @@
// npx jest src/api/providers/__tests__/glama.test.ts
import { Anthropic } from "@anthropic-ai/sdk"
import { GlamaHandler } from "../glama"
import { ApiHandlerOptions } from "../../../shared/api"
// Mock dependencies
jest.mock("../fetchers/modelCache", () => ({
getModels: jest.fn().mockImplementation(() => {
return Promise.resolve({
"anthropic/claude-3-7-sonnet": {
maxTokens: 8192,
contextWindow: 200000,
supportsImages: true,
supportsPromptCache: true,
inputPrice: 3,
outputPrice: 15,
cacheWritesPrice: 3.75,
cacheReadsPrice: 0.3,
description: "Claude 3.7 Sonnet",
thinking: false,
supportsComputerUse: true,
},
"openai/gpt-4o": {
maxTokens: 4096,
contextWindow: 128000,
supportsImages: true,
supportsPromptCache: false,
inputPrice: 5,
outputPrice: 15,
description: "GPT-4o",
},
})
}),
}))
// Mock OpenAI client
const mockCreate = jest.fn()
const mockWithResponse = jest.fn()
jest.mock("openai", () => {
return {
__esModule: true,
default: jest.fn().mockImplementation(() => ({
chat: {
completions: {
create: (...args: any[]) => {
const stream = {
[Symbol.asyncIterator]: async function* () {
yield {
choices: [{ delta: { content: "Test response" }, index: 0 }],
usage: null,
}
yield {
choices: [{ delta: {}, index: 0 }],
usage: { prompt_tokens: 10, completion_tokens: 5, total_tokens: 15 },
}
},
}
const result = mockCreate(...args)
if (args[0].stream) {
mockWithResponse.mockReturnValue(
Promise.resolve({
data: stream,
response: {
headers: {
get: (name: string) =>
name === "x-completion-request-id" ? "test-request-id" : null,
},
},
}),
)
result.withResponse = mockWithResponse
}
return result
},
},
},
})),
}
})
describe("GlamaHandler", () => {
let handler: GlamaHandler
let mockOptions: ApiHandlerOptions
beforeEach(() => {
mockOptions = {
glamaApiKey: "test-api-key",
glamaModelId: "anthropic/claude-3-7-sonnet",
}
handler = new GlamaHandler(mockOptions)
mockCreate.mockClear()
mockWithResponse.mockClear()
// Default mock implementation for non-streaming responses
mockCreate.mockResolvedValue({
id: "test-completion",
choices: [
{
message: { role: "assistant", content: "Test response" },
finish_reason: "stop",
index: 0,
},
],
usage: {
prompt_tokens: 10,
completion_tokens: 5,
total_tokens: 15,
},
})
})
describe("constructor", () => {
it("should initialize with provided options", () => {
expect(handler).toBeInstanceOf(GlamaHandler)
expect(handler.getModel().id).toBe(mockOptions.glamaModelId)
})
})
describe("createMessage", () => {
const systemPrompt = "You are a helpful assistant."
const messages: Anthropic.Messages.MessageParam[] = [
{
role: "user",
content: "Hello!",
},
]
it("should handle streaming responses", async () => {
const stream = handler.createMessage(systemPrompt, messages)
const chunks: any[] = []
for await (const chunk of stream) {
chunks.push(chunk)
}
expect(chunks.length).toBe(1)
expect(chunks[0]).toEqual({ type: "text", text: "Test response" })
})
it("should handle API errors", async () => {
mockCreate.mockImplementationOnce(() => {
throw new Error("API Error")
})
const stream = handler.createMessage(systemPrompt, messages)
const chunks = []
try {
for await (const chunk of stream) {
chunks.push(chunk)
}
fail("Expected error to be thrown")
} catch (error) {
expect(error).toBeInstanceOf(Error)
expect(error.message).toBe("API Error")
}
})
})
describe("completePrompt", () => {
it("should complete prompt successfully", async () => {
const result = await handler.completePrompt("Test prompt")
expect(result).toBe("Test response")
expect(mockCreate).toHaveBeenCalledWith(
expect.objectContaining({
model: mockOptions.glamaModelId,
messages: [{ role: "user", content: "Test prompt" }],
temperature: 0,
max_tokens: 8192,
}),
)
})
it("should handle API errors", async () => {
mockCreate.mockRejectedValueOnce(new Error("API Error"))
await expect(handler.completePrompt("Test prompt")).rejects.toThrow("Glama completion error: API Error")
})
it("should handle empty response", async () => {
mockCreate.mockResolvedValueOnce({
choices: [{ message: { content: "" } }],
})
const result = await handler.completePrompt("Test prompt")
expect(result).toBe("")
})
it("should not set max_tokens for non-Anthropic models", async () => {
// Reset mock to clear any previous calls
mockCreate.mockClear()
const nonAnthropicOptions = {
glamaApiKey: "test-key",
glamaModelId: "openai/gpt-4o",
}
const nonAnthropicHandler = new GlamaHandler(nonAnthropicOptions)
await nonAnthropicHandler.completePrompt("Test prompt")
expect(mockCreate).toHaveBeenCalledWith(
expect.objectContaining({
model: "openai/gpt-4o",
messages: [{ role: "user", content: "Test prompt" }],
temperature: 0,
}),
)
expect(mockCreate.mock.calls[0][0]).not.toHaveProperty("max_tokens")
})
})
describe("fetchModel", () => {
it("should return model info", async () => {
const modelInfo = await handler.fetchModel()
expect(modelInfo.id).toBe(mockOptions.glamaModelId)
expect(modelInfo.info).toBeDefined()
expect(modelInfo.info.maxTokens).toBe(8192)
expect(modelInfo.info.contextWindow).toBe(200_000)
})
it("should return default model when invalid model provided", async () => {
const handlerWithInvalidModel = new GlamaHandler({ ...mockOptions, glamaModelId: "invalid/model" })
const modelInfo = await handlerWithInvalidModel.fetchModel()
expect(modelInfo.id).toBe("anthropic/claude-3-7-sonnet")
expect(modelInfo.info).toBeDefined()
})
})
})

View file

@ -2,7 +2,6 @@ import { getModels } from "../modelCache"
import { getLiteLLMModels } from "../litellm"
import { getOpenRouterModels } from "../openrouter"
import { getRequestyModels } from "../requesty"
import { getGlamaModels } from "../glama"
import { getUnboundModels } from "../unbound"
// Mock NodeCache to avoid cache interference
@ -25,13 +24,11 @@ jest.mock("fs/promises", () => ({
jest.mock("../litellm")
jest.mock("../openrouter")
jest.mock("../requesty")
jest.mock("../glama")
jest.mock("../unbound")
const mockGetLiteLLMModels = getLiteLLMModels as jest.MockedFunction<typeof getLiteLLMModels>
const mockGetOpenRouterModels = getOpenRouterModels as jest.MockedFunction<typeof getOpenRouterModels>
const mockGetRequestyModels = getRequestyModels as jest.MockedFunction<typeof getRequestyModels>
const mockGetGlamaModels = getGlamaModels as jest.MockedFunction<typeof getGlamaModels>
const mockGetUnboundModels = getUnboundModels as jest.MockedFunction<typeof getUnboundModels>
const DUMMY_REQUESTY_KEY = "requesty-key-for-testing"
@ -97,23 +94,6 @@ describe("getModels with new GetModelsOptions", () => {
expect(result).toEqual(mockModels)
})
it("calls getGlamaModels for glama provider", async () => {
const mockModels = {
"glama/model": {
maxTokens: 4096,
contextWindow: 8192,
supportsPromptCache: false,
description: "Glama model",
},
}
mockGetGlamaModels.mockResolvedValue(mockModels)
const result = await getModels({ provider: "glama" })
expect(mockGetGlamaModels).toHaveBeenCalled()
expect(result).toEqual(mockModels)
})
it("calls getUnboundModels with optional API key", async () => {
const mockModels = {
"unbound/model": {

View file

@ -1,43 +0,0 @@
import axios from "axios"
import type { ModelInfo } from "@roo-code/types"
import { parseApiPrice } from "../../../shared/cost"
export async function getGlamaModels(): Promise<Record<string, ModelInfo>> {
const models: Record<string, ModelInfo> = {}
try {
const response = await axios.get("https://glama.ai/api/gateway/v1/models")
const rawModels = response.data
for (const rawModel of rawModels) {
const modelInfo: ModelInfo = {
maxTokens: rawModel.maxTokensOutput,
contextWindow: rawModel.maxTokensInput,
supportsImages: rawModel.capabilities?.includes("input:image"),
supportsComputerUse: rawModel.capabilities?.includes("computer_use"),
supportsPromptCache: rawModel.capabilities?.includes("caching"),
inputPrice: parseApiPrice(rawModel.pricePerToken?.input),
outputPrice: parseApiPrice(rawModel.pricePerToken?.output),
description: undefined,
cacheWritesPrice: parseApiPrice(rawModel.pricePerToken?.cacheWrite),
cacheReadsPrice: parseApiPrice(rawModel.pricePerToken?.cacheRead),
}
switch (rawModel.id) {
case rawModel.id.startsWith("anthropic/"):
modelInfo.maxTokens = 8192
break
default:
break
}
models[rawModel.id] = modelInfo
}
} catch (error) {
console.error(`Error fetching Glama models: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`)
}
return models
}

View file

@ -10,7 +10,6 @@ import { fileExistsAtPath } from "../../../utils/fs"
import { getOpenRouterModels } from "./openrouter"
import { getRequestyModels } from "./requesty"
import { getGlamaModels } from "./glama"
import { getUnboundModels } from "./unbound"
import { getLiteLLMModels } from "./litellm"
import { GetModelsOptions } from "../../../shared/api"
@ -57,9 +56,6 @@ export const getModels = async (options: GetModelsOptions): Promise<ModelRecord>
// Requesty models endpoint requires an API key for per-user custom policies
models = await getRequestyModels(options.apiKey)
break
case "glama":
models = await getGlamaModels()
break
case "unbound":
// Unbound models endpoint requires an API key to fetch application specific models
models = await getUnboundModels(options.apiKey)

View file

@ -1,146 +0,0 @@
import { Anthropic } from "@anthropic-ai/sdk"
import axios from "axios"
import OpenAI from "openai"
import { glamaDefaultModelId, glamaDefaultModelInfo, GLAMA_DEFAULT_TEMPERATURE } from "@roo-code/types"
import { Package } from "../../shared/package"
import { ApiHandlerOptions } from "../../shared/api"
import { ApiStream } from "../transform/stream"
import { convertToOpenAiMessages } from "../transform/openai-format"
import { addCacheBreakpoints } from "../transform/caching/anthropic"
import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"
import { RouterProvider } from "./router-provider"
const DEFAULT_HEADERS = {
"X-Glama-Metadata": JSON.stringify({
labels: [{ key: "app", value: `vscode.${Package.publisher}.${Package.name}` }],
}),
}
export class GlamaHandler extends RouterProvider implements SingleCompletionHandler {
constructor(options: ApiHandlerOptions) {
super({
options,
name: "glama",
baseURL: "https://glama.ai/api/gateway/openai/v1",
apiKey: options.glamaApiKey,
modelId: options.glamaModelId,
defaultModelId: glamaDefaultModelId,
defaultModelInfo: glamaDefaultModelInfo,
})
}
override async *createMessage(
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
metadata?: ApiHandlerCreateMessageMetadata,
): ApiStream {
const { id: modelId, info } = await this.fetchModel()
const openAiMessages: OpenAI.Chat.ChatCompletionMessageParam[] = [
{ role: "system", content: systemPrompt },
...convertToOpenAiMessages(messages),
]
if (modelId.startsWith("anthropic/claude-3")) {
addCacheBreakpoints(systemPrompt, openAiMessages)
}
// Required by Anthropic; other providers default to max tokens allowed.
let maxTokens: number | undefined
if (modelId.startsWith("anthropic/")) {
maxTokens = info.maxTokens ?? undefined
}
const requestOptions: OpenAI.Chat.ChatCompletionCreateParams = {
model: modelId,
max_tokens: maxTokens,
messages: openAiMessages,
stream: true,
}
if (this.supportsTemperature(modelId)) {
requestOptions.temperature = this.options.modelTemperature ?? GLAMA_DEFAULT_TEMPERATURE
}
const { data: completion, response } = await this.client.chat.completions
.create(requestOptions, { headers: DEFAULT_HEADERS })
.withResponse()
const completionRequestId = response.headers.get("x-completion-request-id")
for await (const chunk of completion) {
const delta = chunk.choices[0]?.delta
if (delta?.content) {
yield { type: "text", text: delta.content }
}
}
try {
let attempt = 0
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
while (attempt++ < 10) {
// In case of an interrupted request, we need to wait for the upstream API to finish processing the request
// before we can fetch information about the token usage and cost.
const response = await axios.get(
`https://glama.ai/api/gateway/v1/completion-requests/${completionRequestId}`,
{ headers: { Authorization: `Bearer ${this.options.glamaApiKey}` } },
)
const completionRequest = response.data
if (completionRequest.tokenUsage && completionRequest.totalCostUsd) {
yield {
type: "usage",
cacheWriteTokens: completionRequest.tokenUsage.cacheCreationInputTokens,
cacheReadTokens: completionRequest.tokenUsage.cacheReadInputTokens,
inputTokens: completionRequest.tokenUsage.promptTokens,
outputTokens: completionRequest.tokenUsage.completionTokens,
totalCost: parseFloat(completionRequest.totalCostUsd),
}
break
}
await delay(200)
}
} catch (error) {
console.error("Error fetching Glama completion details", error)
}
}
async completePrompt(prompt: string): Promise<string> {
const { id: modelId, info } = await this.fetchModel()
try {
const requestOptions: OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming = {
model: modelId,
messages: [{ role: "user", content: prompt }],
}
if (this.supportsTemperature(modelId)) {
requestOptions.temperature = this.options.modelTemperature ?? GLAMA_DEFAULT_TEMPERATURE
}
if (modelId.startsWith("anthropic/")) {
requestOptions.max_tokens = info.maxTokens
}
const response = await this.client.chat.completions.create(requestOptions)
return response.choices[0]?.message.content || ""
} catch (error) {
if (error instanceof Error) {
throw new Error(`Glama completion error: ${error.message}`)
}
throw error
}
}
}

View file

@ -5,7 +5,6 @@ export { ChutesHandler } from "./chutes"
export { DeepSeekHandler } from "./deepseek"
export { FakeAIHandler } from "./fake-ai"
export { GeminiHandler } from "./gemini"
export { GlamaHandler } from "./glama"
export { GroqHandler } from "./groq"
export { HumanRelayHandler } from "./human-relay"
export { LiteLLMHandler } from "./lite-llm"

View file

@ -25,7 +25,6 @@ import {
type CloudUserInfo,
requestyDefaultModelId,
openRouterDefaultModelId,
glamaDefaultModelId,
ORGANIZATION_ALLOW_ALL,
} from "@roo-code/types"
import { TelemetryService } from "@roo-code/telemetry"
@ -1053,36 +1052,6 @@ export class ClineProvider
await this.upsertProviderProfile(currentApiConfigName, newConfiguration)
}
// Glama
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) {
this.log(
`Error exchanging code for API key: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
)
throw error
}
const { apiConfiguration, currentApiConfigName } = await this.getState()
const newConfiguration: ProviderSettings = {
...apiConfiguration,
apiProvider: "glama",
glamaApiKey: apiKey,
glamaModelId: apiConfiguration?.glamaModelId || glamaDefaultModelId,
}
await this.upsertProviderProfile(currentApiConfigName, newConfiguration)
}
// Requesty
async handleRequestyCallback(code: string) {

View file

@ -2241,7 +2241,6 @@ describe("ClineProvider - Router Models", () => {
apiConfiguration: {
openRouterApiKey: "openrouter-key",
requestyApiKey: "requesty-key",
glamaApiKey: "glama-key",
unboundApiKey: "unbound-key",
litellmApiKey: "litellm-key",
litellmBaseUrl: "http://localhost:4000",
@ -2261,7 +2260,6 @@ describe("ClineProvider - Router Models", () => {
// Verify getModels was called for each provider with correct options
expect(getModels).toHaveBeenCalledWith({ provider: "openrouter" })
expect(getModels).toHaveBeenCalledWith({ provider: "requesty", apiKey: "requesty-key" })
expect(getModels).toHaveBeenCalledWith({ provider: "glama" })
expect(getModels).toHaveBeenCalledWith({ provider: "unbound", apiKey: "unbound-key" })
expect(getModels).toHaveBeenCalledWith({
provider: "litellm",
@ -2275,7 +2273,6 @@ describe("ClineProvider - Router Models", () => {
routerModels: {
openrouter: mockModels,
requesty: mockModels,
glama: mockModels,
unbound: mockModels,
litellm: mockModels,
},
@ -2290,7 +2287,6 @@ describe("ClineProvider - Router Models", () => {
apiConfiguration: {
openRouterApiKey: "openrouter-key",
requestyApiKey: "requesty-key",
glamaApiKey: "glama-key",
unboundApiKey: "unbound-key",
litellmApiKey: "litellm-key",
litellmBaseUrl: "http://localhost:4000",
@ -2304,7 +2300,6 @@ describe("ClineProvider - Router Models", () => {
getModels
.mockResolvedValueOnce(mockModels) // openrouter success
.mockRejectedValueOnce(new Error("Requesty API error")) // requesty fail
.mockResolvedValueOnce(mockModels) // glama success
.mockRejectedValueOnce(new Error("Unbound API error")) // unbound fail
.mockRejectedValueOnce(new Error("LiteLLM connection failed")) // litellm fail
@ -2316,7 +2311,6 @@ describe("ClineProvider - Router Models", () => {
routerModels: {
openrouter: mockModels,
requesty: {},
glama: mockModels,
unbound: {},
litellm: {},
},
@ -2354,7 +2348,6 @@ describe("ClineProvider - Router Models", () => {
apiConfiguration: {
openRouterApiKey: "openrouter-key",
requestyApiKey: "requesty-key",
glamaApiKey: "glama-key",
unboundApiKey: "unbound-key",
// No litellm config
},
@ -2388,7 +2381,6 @@ describe("ClineProvider - Router Models", () => {
apiConfiguration: {
openRouterApiKey: "openrouter-key",
requestyApiKey: "requesty-key",
glamaApiKey: "glama-key",
unboundApiKey: "unbound-key",
// No litellm config
},
@ -2413,7 +2405,6 @@ describe("ClineProvider - Router Models", () => {
routerModels: {
openrouter: mockModels,
requesty: mockModels,
glama: mockModels,
unbound: mockModels,
litellm: {},
},

View file

@ -20,7 +20,6 @@ describe("webviewMessageHandler - requestRouterModels", () => {
apiConfiguration: {
openRouterApiKey: "openrouter-key",
requestyApiKey: "requesty-key",
glamaApiKey: "glama-key",
unboundApiKey: "unbound-key",
litellmApiKey: "litellm-key",
litellmBaseUrl: "http://localhost:4000",
@ -53,7 +52,6 @@ describe("webviewMessageHandler - requestRouterModels", () => {
// Verify getModels was called for each provider
expect(mockGetModels).toHaveBeenCalledWith({ provider: "openrouter" })
expect(mockGetModels).toHaveBeenCalledWith({ provider: "requesty", apiKey: "requesty-key" })
expect(mockGetModels).toHaveBeenCalledWith({ provider: "glama" })
expect(mockGetModels).toHaveBeenCalledWith({ provider: "unbound", apiKey: "unbound-key" })
expect(mockGetModels).toHaveBeenCalledWith({
provider: "litellm",
@ -67,7 +65,6 @@ describe("webviewMessageHandler - requestRouterModels", () => {
routerModels: {
openrouter: mockModels,
requesty: mockModels,
glama: mockModels,
unbound: mockModels,
litellm: mockModels,
},
@ -79,7 +76,6 @@ describe("webviewMessageHandler - requestRouterModels", () => {
apiConfiguration: {
openRouterApiKey: "openrouter-key",
requestyApiKey: "requesty-key",
glamaApiKey: "glama-key",
unboundApiKey: "unbound-key",
// Missing litellm config
},
@ -117,7 +113,6 @@ describe("webviewMessageHandler - requestRouterModels", () => {
apiConfiguration: {
openRouterApiKey: "openrouter-key",
requestyApiKey: "requesty-key",
glamaApiKey: "glama-key",
unboundApiKey: "unbound-key",
// Missing litellm config
},
@ -152,7 +147,6 @@ describe("webviewMessageHandler - requestRouterModels", () => {
routerModels: {
openrouter: mockModels,
requesty: mockModels,
glama: mockModels,
unbound: mockModels,
litellm: {},
},
@ -173,7 +167,6 @@ describe("webviewMessageHandler - requestRouterModels", () => {
mockGetModels
.mockResolvedValueOnce(mockModels) // openrouter
.mockRejectedValueOnce(new Error("Requesty API error")) // requesty
.mockResolvedValueOnce(mockModels) // glama
.mockRejectedValueOnce(new Error("Unbound API error")) // unbound
.mockRejectedValueOnce(new Error("LiteLLM connection failed")) // litellm
@ -187,7 +180,6 @@ describe("webviewMessageHandler - requestRouterModels", () => {
routerModels: {
openrouter: mockModels,
requesty: {},
glama: mockModels,
unbound: {},
litellm: {},
},
@ -221,9 +213,8 @@ describe("webviewMessageHandler - requestRouterModels", () => {
mockGetModels
.mockRejectedValueOnce(new Error("Structured error message")) // Error object
.mockRejectedValueOnce("String error message") // String error
.mockRejectedValueOnce({ message: "Object with message" }) // Object error
.mockResolvedValueOnce({}) // Success
.mockResolvedValueOnce({}) // Success
.mockRejectedValueOnce(new Error("Unbound API error")) // unbound
.mockRejectedValueOnce(new Error("LiteLLM connection failed")) // litellm
await webviewMessageHandler(mockClineProvider, {
type: "requestRouterModels",
@ -247,8 +238,15 @@ describe("webviewMessageHandler - requestRouterModels", () => {
expect(mockClineProvider.postMessageToWebview).toHaveBeenCalledWith({
type: "singleRouterModelFetchResponse",
success: false,
error: "[object Object]",
values: { provider: "glama" },
error: "Unbound API error",
values: { provider: "unbound" },
})
expect(mockClineProvider.postMessageToWebview).toHaveBeenCalledWith({
type: "singleRouterModelFetchResponse",
success: false,
error: "LiteLLM connection failed",
values: { provider: "litellm" },
})
})

View file

@ -300,7 +300,6 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
const routerModels: Partial<Record<RouterName, ModelRecord>> = {
openrouter: {},
requesty: {},
glama: {},
unbound: {},
litellm: {},
}
@ -320,7 +319,6 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
const modelFetchPromises: Array<{ key: RouterName; options: GetModelsOptions }> = [
{ key: "openrouter", options: { provider: "openrouter" } },
{ key: "requesty", options: { provider: "requesty", apiKey: apiConfiguration.requestyApiKey } },
{ key: "glama", options: { provider: "glama" } },
{ key: "unbound", options: { provider: "unbound", apiKey: apiConfiguration.unboundApiKey } },
]

View file

@ -78,8 +78,6 @@ export class ProfileValidator {
return profile.vsCodeLmModelSelector?.id
case "openrouter":
return profile.openRouterModelId
case "glama":
return profile.glamaModelId
case "ollama":
return profile.ollamaModelId
case "requesty":

View file

@ -286,21 +286,6 @@ describe("ProfileValidator", () => {
expect(ProfileValidator.isProfileAllowed(profile, allowList)).toBe(true)
})
it("should extract glamaModelId for glama provider", () => {
const allowList: OrganizationAllowList = {
allowAll: false,
providers: {
glama: { allowAll: false, models: ["glama-model"] },
},
}
const profile: ProviderSettings = {
apiProvider: "glama",
glamaModelId: "glama-model",
}
expect(ProfileValidator.isProfileAllowed(profile, allowList)).toBe(true)
})
it("should extract requestyModelId for requesty provider", () => {
const allowList: OrganizationAllowList = {
allowAll: false,

View file

@ -24,7 +24,6 @@ describe("checkExistKey", () => {
it("should return true when multiple keys are defined", () => {
const config: ProviderSettings = {
apiKey: "test-key",
glamaApiKey: "glama-key",
openRouterApiKey: "openrouter-key",
}
expect(checkExistKey(config)).toBe(true)
@ -43,7 +42,6 @@ describe("checkExistKey", () => {
it("should return false when all key fields are undefined", () => {
const config: ProviderSettings = {
apiKey: undefined,
glamaApiKey: undefined,
openRouterApiKey: undefined,
awsRegion: undefined,
vertexProjectId: undefined,

View file

@ -6,7 +6,7 @@ export type ApiHandlerOptions = Omit<ProviderSettings, "apiProvider">
// RouterName
const routerNames = ["openrouter", "requesty", "glama", "unbound", "litellm"] as const
const routerNames = ["openrouter", "requesty", "unbound", "litellm"] as const
export type RouterName = (typeof routerNames)[number]
@ -78,7 +78,6 @@ export const getModelMaxOutputTokens = ({
export type GetModelsOptions =
| { provider: "openrouter" }
| { provider: "glama" }
| { provider: "requesty"; apiKey?: string }
| { provider: "unbound"; apiKey?: string }
| { provider: "litellm"; apiKey: string; baseUrl: string }

View file

@ -8,7 +8,6 @@ import {
type ProviderSettings,
openRouterDefaultModelId,
requestyDefaultModelId,
glamaDefaultModelId,
unboundDefaultModelId,
litellmDefaultModelId,
} from "@roo-code/types"
@ -28,7 +27,6 @@ import {
Chutes,
DeepSeek,
Gemini,
Glama,
Groq,
LMStudio,
LiteLLM,
@ -199,7 +197,7 @@ const ApiOptions = ({
(value: ProviderName) => {
// It would be much easier to have a single attribute that stores
// the modelId, but we have a separate attribute for each of
// OpenRouter, Glama, Unbound, and Requesty.
// OpenRouter, Unbound, and Requesty.
// If you switch to one of these providers and the corresponding
// modelId is not set then you immediately end up in an error state.
// To address that we set the modelId to the default value for th
@ -210,11 +208,6 @@ const ApiOptions = ({
setApiConfigurationField("openRouterModelId", openRouterDefaultModelId)
}
break
case "glama":
if (!apiConfiguration.glamaModelId) {
setApiConfigurationField("glamaModelId", glamaDefaultModelId)
}
break
case "unbound":
if (!apiConfiguration.unboundModelId) {
setApiConfigurationField("unboundModelId", unboundDefaultModelId)
@ -237,7 +230,6 @@ const ApiOptions = ({
[
setApiConfigurationField,
apiConfiguration.openRouterModelId,
apiConfiguration.glamaModelId,
apiConfiguration.unboundModelId,
apiConfiguration.requestyModelId,
apiConfiguration.litellmModelId,
@ -316,16 +308,6 @@ const ApiOptions = ({
/>
)}
{selectedProvider === "glama" && (
<Glama
apiConfiguration={apiConfiguration}
setApiConfigurationField={setApiConfigurationField}
routerModels={routerModels}
uriScheme={uriScheme}
organizationAllowList={organizationAllowList}
/>
)}
{selectedProvider === "unbound" && (
<Unbound
apiConfiguration={apiConfiguration}

View file

@ -26,7 +26,7 @@ import { ModelInfoView } from "./ModelInfoView"
type ModelIdKey = keyof Pick<
ProviderSettings,
"glamaModelId" | "openRouterModelId" | "unboundModelId" | "requestyModelId" | "openAiModelId" | "litellmModelId"
"openRouterModelId" | "unboundModelId" | "requestyModelId" | "openAiModelId" | "litellmModelId"
>
interface ModelPickerProps {

View file

@ -45,7 +45,7 @@ describe("ModelPicker", () => {
const defaultProps = {
apiConfiguration: {},
defaultModelId: "model1",
modelIdKey: "glamaModelId" as const,
modelIdKey: "openRouterModelId" as const,
serviceName: "Test Service",
serviceUrl: "https://test.service",
recommendedModel: "recommended-model",

View file

@ -35,7 +35,6 @@ export const PROVIDERS = [
{ value: "openai", label: "OpenAI Compatible" },
{ value: "vertex", label: "GCP Vertex AI" },
{ value: "bedrock", label: "Amazon Bedrock" },
{ value: "glama", label: "Glama" },
{ value: "vscode-lm", label: "VS Code LM API" },
{ value: "mistral", label: "Mistral" },
{ value: "lmstudio", label: "LM Studio" },

View file

@ -1,73 +0,0 @@
import { useCallback } from "react"
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
import { type ProviderSettings, type OrganizationAllowList, glamaDefaultModelId } from "@roo-code/types"
import type { RouterModels } from "@roo/api"
import { useAppTranslation } from "@src/i18n/TranslationContext"
import { getGlamaAuthUrl } from "@src/oauth/urls"
import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"
import { inputEventTransform } from "../transforms"
import { ModelPicker } from "../ModelPicker"
type GlamaProps = {
apiConfiguration: ProviderSettings
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
routerModels?: RouterModels
uriScheme?: string
organizationAllowList: OrganizationAllowList
}
export const Glama = ({
apiConfiguration,
setApiConfigurationField,
routerModels,
uriScheme,
organizationAllowList,
}: GlamaProps) => {
const { t } = useAppTranslation()
const handleInputChange = useCallback(
<K extends keyof ProviderSettings, E>(
field: K,
transform: (event: E) => ProviderSettings[K] = inputEventTransform,
) =>
(event: E | Event) => {
setApiConfigurationField(field, transform(event as E))
},
[setApiConfigurationField],
)
return (
<>
<VSCodeTextField
value={apiConfiguration?.glamaApiKey || ""}
type="password"
onInput={handleInputChange("glamaApiKey")}
placeholder={t("settings:placeholders.apiKey")}
className="w-full">
<label className="block font-medium mb-1">{t("settings:providers.glamaApiKey")}</label>
</VSCodeTextField>
<div className="text-sm text-vscode-descriptionForeground -mt-2">
{t("settings:providers.apiKeyStorageNotice")}
</div>
{!apiConfiguration?.glamaApiKey && (
<VSCodeButtonLink href={getGlamaAuthUrl(uriScheme)} style={{ width: "100%" }} appearance="primary">
{t("settings:providers.getGlamaApiKey")}
</VSCodeButtonLink>
)}
<ModelPicker
apiConfiguration={apiConfiguration}
setApiConfigurationField={setApiConfigurationField}
defaultModelId={glamaDefaultModelId}
models={routerModels?.glama ?? {}}
modelIdKey="glamaModelId"
serviceName="Glama"
serviceUrl="https://glama.ai/models"
organizationAllowList={organizationAllowList}
/>
</>
)
}

View file

@ -3,7 +3,6 @@ export { Bedrock } from "./Bedrock"
export { Chutes } from "./Chutes"
export { DeepSeek } from "./DeepSeek"
export { Gemini } from "./Gemini"
export { Glama } from "./Glama"
export { Groq } from "./Groq"
export { LMStudio } from "./LMStudio"
export { Mistral } from "./Mistral"

View file

@ -56,7 +56,6 @@ describe("useSelectedModel", () => {
"test-model": baseModelInfo,
},
requesty: {},
glama: {},
unbound: {},
litellm: {},
},
@ -108,7 +107,6 @@ describe("useSelectedModel", () => {
data: {
openrouter: {},
requesty: {},
glama: {},
unbound: {},
litellm: {},
},
@ -162,7 +160,6 @@ describe("useSelectedModel", () => {
"test-model": baseModelInfo,
},
requesty: {},
glama: {},
unbound: {},
litellm: {},
},
@ -217,7 +214,6 @@ describe("useSelectedModel", () => {
data: {
openrouter: { "test-model": baseModelInfo },
requesty: {},
glama: {},
unbound: {},
litellm: {},
},
@ -261,7 +257,6 @@ describe("useSelectedModel", () => {
},
},
requesty: {},
glama: {},
unbound: {},
litellm: {},
},
@ -321,7 +316,7 @@ describe("useSelectedModel", () => {
it("should return loading state when open router model providers are loading", () => {
mockUseRouterModels.mockReturnValue({
data: { openrouter: {}, requesty: {}, glama: {}, unbound: {}, litellm: {} },
data: { openrouter: {}, requesty: {}, unbound: {}, litellm: {} },
isLoading: false,
isError: false,
} as any)

View file

@ -27,7 +27,6 @@ import {
vscodeLlmDefaultModelId,
openRouterDefaultModelId,
requestyDefaultModelId,
glamaDefaultModelId,
unboundDefaultModelId,
litellmDefaultModelId,
} from "@roo-code/types"
@ -102,11 +101,6 @@ function getSelectedModel({
? { id, info }
: { id: requestyDefaultModelId, info: routerModels.requesty[requestyDefaultModelId] }
}
case "glama": {
const id = apiConfiguration.glamaModelId ?? glamaDefaultModelId
const info = routerModels.glama[id]
return info ? { id, info } : { id: glamaDefaultModelId, info: routerModels.glama[glamaDefaultModelId] }
}
case "unbound": {
const id = apiConfiguration.unboundModelId ?? unboundDefaultModelId
const info = routerModels.unbound[id]

View file

@ -139,8 +139,6 @@
"openRouterApiKey": "Clau API d'OpenRouter",
"getOpenRouterApiKey": "Obtenir clau API d'OpenRouter",
"apiKeyStorageNotice": "Les claus API s'emmagatzemen de forma segura a l'Emmagatzematge Secret de VSCode",
"glamaApiKey": "Clau API de Glama",
"getGlamaApiKey": "Obtenir clau API de Glama",
"useCustomBaseUrl": "Utilitzar URL base personalitzada",
"useReasoning": "Activar raonament",
"useHostHeader": "Utilitzar capçalera Host personalitzada",

View file

@ -139,8 +139,6 @@
"openRouterApiKey": "OpenRouter API-Schlüssel",
"getOpenRouterApiKey": "OpenRouter API-Schlüssel erhalten",
"apiKeyStorageNotice": "API-Schlüssel werden sicher im VSCode Secret Storage gespeichert",
"glamaApiKey": "Glama API-Schlüssel",
"getGlamaApiKey": "Glama API-Schlüssel erhalten",
"useCustomBaseUrl": "Benutzerdefinierte Basis-URL verwenden",
"useReasoning": "Reasoning aktivieren",
"useHostHeader": "Benutzerdefinierten Host-Header verwenden",

View file

@ -139,8 +139,6 @@
"openRouterApiKey": "OpenRouter API Key",
"getOpenRouterApiKey": "Get OpenRouter API Key",
"apiKeyStorageNotice": "API keys are stored securely in VSCode's Secret Storage",
"glamaApiKey": "Glama API Key",
"getGlamaApiKey": "Get Glama API Key",
"useCustomBaseUrl": "Use custom base URL",
"useReasoning": "Enable reasoning",
"useHostHeader": "Use custom Host header",

View file

@ -139,8 +139,6 @@
"openRouterApiKey": "Clave API de OpenRouter",
"getOpenRouterApiKey": "Obtener clave API de OpenRouter",
"apiKeyStorageNotice": "Las claves API se almacenan de forma segura en el Almacenamiento Secreto de VSCode",
"glamaApiKey": "Clave API de Glama",
"getGlamaApiKey": "Obtener clave API de Glama",
"useCustomBaseUrl": "Usar URL base personalizada",
"useReasoning": "Habilitar razonamiento",
"useHostHeader": "Usar encabezado Host personalizado",

View file

@ -139,8 +139,6 @@
"openRouterApiKey": "Clé API OpenRouter",
"getOpenRouterApiKey": "Obtenir la clé API OpenRouter",
"apiKeyStorageNotice": "Les clés API sont stockées en toute sécurité dans le stockage sécurisé de VSCode",
"glamaApiKey": "Clé API Glama",
"getGlamaApiKey": "Obtenir la clé API Glama",
"useCustomBaseUrl": "Utiliser une URL de base personnalisée",
"useReasoning": "Activer le raisonnement",
"useHostHeader": "Utiliser un en-tête Host personnalisé",

View file

@ -139,8 +139,6 @@
"openRouterApiKey": "OpenRouter API कुंजी",
"getOpenRouterApiKey": "OpenRouter API कुंजी प्राप्त करें",
"apiKeyStorageNotice": "API कुंजियाँ VSCode के सुरक्षित स्टोरेज में सुरक्षित रूप से संग्रहीत हैं",
"glamaApiKey": "Glama API कुंजी",
"getGlamaApiKey": "Glama API कुंजी प्राप्त करें",
"useCustomBaseUrl": "कस्टम बेस URL का उपयोग करें",
"useReasoning": "तर्क सक्षम करें",
"useHostHeader": "कस्टम होस्ट हेडर का उपयोग करें",

View file

@ -139,8 +139,6 @@
"openRouterApiKey": "Chiave API OpenRouter",
"getOpenRouterApiKey": "Ottieni chiave API OpenRouter",
"apiKeyStorageNotice": "Le chiavi API sono memorizzate in modo sicuro nell'Archivio Segreto di VSCode",
"glamaApiKey": "Chiave API Glama",
"getGlamaApiKey": "Ottieni chiave API Glama",
"useCustomBaseUrl": "Usa URL base personalizzato",
"useReasoning": "Abilita ragionamento",
"useHostHeader": "Usa intestazione Host personalizzata",

View file

@ -139,8 +139,6 @@
"openRouterApiKey": "OpenRouter APIキー",
"getOpenRouterApiKey": "OpenRouter APIキーを取得",
"apiKeyStorageNotice": "APIキーはVSCodeのシークレットストレージに安全に保存されます",
"glamaApiKey": "Glama APIキー",
"getGlamaApiKey": "Glama APIキーを取得",
"useCustomBaseUrl": "カスタムベースURLを使用",
"useReasoning": "推論を有効化",
"useHostHeader": "カスタムHostヘッダーを使用",

View file

@ -139,8 +139,6 @@
"openRouterApiKey": "OpenRouter API 키",
"getOpenRouterApiKey": "OpenRouter API 키 받기",
"apiKeyStorageNotice": "API 키는 VSCode의 보안 저장소에 안전하게 저장됩니다",
"glamaApiKey": "Glama API 키",
"getGlamaApiKey": "Glama API 키 받기",
"useCustomBaseUrl": "사용자 정의 기본 URL 사용",
"useReasoning": "추론 활성화",
"useHostHeader": "사용자 정의 Host 헤더 사용",

View file

@ -139,8 +139,6 @@
"openRouterApiKey": "OpenRouter API-sleutel",
"getOpenRouterApiKey": "OpenRouter API-sleutel ophalen",
"apiKeyStorageNotice": "API-sleutels worden veilig opgeslagen in de geheime opslag van VSCode",
"glamaApiKey": "Glama API-sleutel",
"getGlamaApiKey": "Glama API-sleutel ophalen",
"useCustomBaseUrl": "Aangepaste basis-URL gebruiken",
"useReasoning": "Redenering inschakelen",
"useHostHeader": "Aangepaste Host-header gebruiken",

View file

@ -139,8 +139,6 @@
"openRouterApiKey": "Klucz API OpenRouter",
"getOpenRouterApiKey": "Uzyskaj klucz API OpenRouter",
"apiKeyStorageNotice": "Klucze API są bezpiecznie przechowywane w Tajnym Magazynie VSCode",
"glamaApiKey": "Klucz API Glama",
"getGlamaApiKey": "Uzyskaj klucz API Glama",
"useCustomBaseUrl": "Użyj niestandardowego URL bazowego",
"useReasoning": "Włącz rozumowanie",
"useHostHeader": "Użyj niestandardowego nagłówka Host",

View file

@ -139,8 +139,6 @@
"openRouterApiKey": "Chave de API OpenRouter",
"getOpenRouterApiKey": "Obter chave de API OpenRouter",
"apiKeyStorageNotice": "As chaves de API são armazenadas com segurança no Armazenamento Secreto do VSCode",
"glamaApiKey": "Chave de API Glama",
"getGlamaApiKey": "Obter chave de API Glama",
"useCustomBaseUrl": "Usar URL base personalizado",
"useReasoning": "Habilitar raciocínio",
"useHostHeader": "Usar cabeçalho Host personalizado",

View file

@ -139,8 +139,6 @@
"openRouterApiKey": "OpenRouter API-ключ",
"getOpenRouterApiKey": "Получить OpenRouter API-ключ",
"apiKeyStorageNotice": "API-ключи хранятся безопасно в Secret Storage VSCode",
"glamaApiKey": "Glama API-ключ",
"getGlamaApiKey": "Получить Glama API-ключ",
"useCustomBaseUrl": "Использовать пользовательский базовый URL",
"useReasoning": "Включить рассуждения",
"useHostHeader": "Использовать пользовательский Host-заголовок",

View file

@ -139,8 +139,6 @@
"openRouterApiKey": "OpenRouter API Anahtarı",
"getOpenRouterApiKey": "OpenRouter API Anahtarı Al",
"apiKeyStorageNotice": "API anahtarları VSCode'un Gizli Depolamasında güvenli bir şekilde saklanır",
"glamaApiKey": "Glama API Anahtarı",
"getGlamaApiKey": "Glama API Anahtarı Al",
"useCustomBaseUrl": "Özel temel URL kullan",
"useReasoning": "Akıl yürütmeyi etkinleştir",
"useHostHeader": "Özel Host başlığı kullan",

View file

@ -139,8 +139,6 @@
"openRouterApiKey": "Khóa API OpenRouter",
"getOpenRouterApiKey": "Lấy khóa API OpenRouter",
"apiKeyStorageNotice": "Khóa API được lưu trữ an toàn trong Bộ lưu trữ bí mật của VSCode",
"glamaApiKey": "Khóa API Glama",
"getGlamaApiKey": "Lấy khóa API Glama",
"useCustomBaseUrl": "Sử dụng URL cơ sở tùy chỉnh",
"useReasoning": "Bật lý luận",
"useHostHeader": "Sử dụng tiêu đề Host tùy chỉnh",

View file

@ -139,8 +139,6 @@
"openRouterApiKey": "OpenRouter API 密钥",
"getOpenRouterApiKey": "获取 OpenRouter API 密钥",
"apiKeyStorageNotice": "API 密钥安全存储在 VSCode 的密钥存储中",
"glamaApiKey": "Glama API 密钥",
"getGlamaApiKey": "获取 Glama API 密钥",
"useCustomBaseUrl": "使用自定义基础 URL",
"useReasoning": "启用推理",
"useHostHeader": "使用自定义 Host 标头",

View file

@ -139,8 +139,6 @@
"openRouterApiKey": "OpenRouter API 金鑰",
"getOpenRouterApiKey": "取得 OpenRouter API 金鑰",
"apiKeyStorageNotice": "API 金鑰安全儲存於 VSCode 金鑰儲存中",
"glamaApiKey": "Glama API 金鑰",
"getGlamaApiKey": "取得 Glama API 金鑰",
"useCustomBaseUrl": "使用自訂基礎 URL",
"useReasoning": "啟用推理",
"useHostHeader": "使用自訂 Host 標頭",

View file

@ -4,10 +4,6 @@ export function getCallbackUrl(provider: string, uriScheme?: string) {
return encodeURIComponent(`${uriScheme || "vscode"}://${Package.publisher}.${Package.name}/${provider}`)
}
export function getGlamaAuthUrl(uriScheme?: string) {
return `https://glama.ai/oauth/authorize?callback_url=${getCallbackUrl("glama", uriScheme)}`
}
export function getOpenRouterAuthUrl(uriScheme?: string) {
return `https://openrouter.ai/auth?callback_url=${getCallbackUrl("openrouter", uriScheme)}`
}

View file

@ -32,11 +32,6 @@ function validateModelsAndKeysProvided(apiConfiguration: ProviderSettings): stri
return i18next.t("settings:validation.apiKey")
}
break
case "glama":
if (!apiConfiguration.glamaApiKey) {
return i18next.t("settings:validation.apiKey")
}
break
case "unbound":
if (!apiConfiguration.unboundApiKey) {
return i18next.t("settings:validation.apiKey")
@ -138,8 +133,6 @@ function getModelIdForProvider(apiConfiguration: ProviderSettings, provider: str
switch (provider) {
case "openrouter":
return apiConfiguration.openRouterModelId
case "glama":
return apiConfiguration.glamaModelId
case "unbound":
return apiConfiguration.unboundModelId
case "requesty":
@ -207,9 +200,6 @@ export function validateModelId(apiConfiguration: ProviderSettings, routerModels
case "openrouter":
modelId = apiConfiguration.openRouterModelId
break
case "glama":
modelId = apiConfiguration.glamaModelId
break
case "unbound":
modelId = apiConfiguration.unboundModelId
break