fix: correct export/import of OpenAI Compatible codebase indexing set… (#5383)

This commit is contained in:
Murilo Pires 2025-07-07 12:53:33 -03:00 committed by GitHub
parent 36b3cdc833
commit 6ec017ca65
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 1065 additions and 30 deletions

View file

@ -24,12 +24,16 @@ export const codebaseIndexConfigSchema = z.object({
codebaseIndexEmbedderProvider: z.enum(["openai", "ollama", "openai-compatible", "gemini"]).optional(),
codebaseIndexEmbedderBaseUrl: z.string().optional(),
codebaseIndexEmbedderModelId: z.string().optional(),
codebaseIndexEmbedderModelDimension: z.number().optional(),
codebaseIndexSearchMinScore: z.number().min(0).max(1).optional(),
codebaseIndexSearchMaxResults: z
.number()
.min(CODEBASE_INDEX_DEFAULTS.MIN_SEARCH_RESULTS)
.max(CODEBASE_INDEX_DEFAULTS.MAX_SEARCH_RESULTS)
.optional(),
// OpenAI Compatible specific fields
codebaseIndexOpenAiCompatibleBaseUrl: z.string().optional(),
codebaseIndexOpenAiCompatibleModelDimension: z.number().optional(),
})
export type CodebaseIndexConfig = z.infer<typeof codebaseIndexConfigSchema>

File diff suppressed because it is too large Load diff

View file

@ -68,6 +68,9 @@ export async function importSettingsFromPath(
(globalSettings.customModes ?? []).map((mode) => customModesManager.updateCustomMode(mode.slug, mode)),
)
// OpenAI Compatible settings are now correctly stored in codebaseIndexConfig
// They will be imported automatically with the config - no special handling needed
await providerSettingsManager.import(providerProfiles)
await contextProxy.setValues(globalSettings)
@ -161,10 +164,16 @@ export const exportSettings = async ({ providerSettingsManager, contextProxy }:
return
}
// OpenAI Compatible settings are now correctly stored in codebaseIndexConfig
// No workaround needed - they will be exported automatically with the config
const dirname = path.dirname(uri.fsPath)
await fs.mkdir(dirname, { recursive: true })
await safeWriteJson(uri.fsPath, { providerProfiles, globalSettings })
} catch (e) {}
} catch (e) {
console.error("Failed to export settings:", e)
// Don't re-throw - the UI will handle showing error messages
}
}
/**

View file

@ -96,10 +96,10 @@ describe("CodeIndexConfigManager", () => {
codebaseIndexEmbedderProvider: "openai-compatible",
codebaseIndexEmbedderBaseUrl: "",
codebaseIndexEmbedderModelId: "text-embedding-3-large",
codebaseIndexOpenAiCompatibleBaseUrl: "https://api.example.com/v1",
}
mockContextProxy.getGlobalState.mockImplementation((key: string) => {
if (key === "codebaseIndexConfig") return mockGlobalState
if (key === "codebaseIndexOpenAiCompatibleBaseUrl") return "https://api.example.com/v1"
return undefined
})
@ -134,11 +134,11 @@ describe("CodeIndexConfigManager", () => {
codebaseIndexEmbedderProvider: "openai-compatible",
codebaseIndexEmbedderBaseUrl: "",
codebaseIndexEmbedderModelId: "custom-model",
codebaseIndexOpenAiCompatibleBaseUrl: "https://api.example.com/v1",
codebaseIndexOpenAiCompatibleModelDimension: 1024,
}
mockContextProxy.getGlobalState.mockImplementation((key: string) => {
if (key === "codebaseIndexConfig") return mockGlobalState
if (key === "codebaseIndexOpenAiCompatibleBaseUrl") return "https://api.example.com/v1"
if (key === "codebaseIndexOpenAiCompatibleModelDimension") return 1024
return undefined
})
setupSecretMocks({
@ -173,11 +173,11 @@ describe("CodeIndexConfigManager", () => {
codebaseIndexEmbedderProvider: "openai-compatible",
codebaseIndexEmbedderBaseUrl: "",
codebaseIndexEmbedderModelId: "custom-model",
codebaseIndexOpenAiCompatibleBaseUrl: "https://api.example.com/v1",
// modelDimension is not set
}
mockContextProxy.getGlobalState.mockImplementation((key: string) => {
if (key === "codebaseIndexConfig") return mockGlobalState
if (key === "codebaseIndexOpenAiCompatibleBaseUrl") return "https://api.example.com/v1"
if (key === "codebaseIndexOpenAiCompatibleModelDimension") return undefined
return undefined
})
setupSecretMocks({
@ -197,6 +197,7 @@ describe("CodeIndexConfigManager", () => {
openAiCompatibleOptions: {
baseUrl: "https://api.example.com/v1",
apiKey: "test-openai-compatible-key",
// modelDimension is undefined when not set
},
qdrantUrl: "http://qdrant.local",
qdrantApiKey: "test-qdrant-key",
@ -211,11 +212,11 @@ describe("CodeIndexConfigManager", () => {
codebaseIndexEmbedderProvider: "openai-compatible",
codebaseIndexEmbedderBaseUrl: "",
codebaseIndexEmbedderModelId: "custom-model",
codebaseIndexOpenAiCompatibleBaseUrl: "https://api.example.com/v1",
codebaseIndexOpenAiCompatibleModelDimension: "invalid-dimension", // Invalid type
}
mockContextProxy.getGlobalState.mockImplementation((key: string) => {
if (key === "codebaseIndexConfig") return mockGlobalState
if (key === "codebaseIndexOpenAiCompatibleBaseUrl") return "https://api.example.com/v1"
if (key === "codebaseIndexOpenAiCompatibleModelDimension") return "invalid-dimension"
return undefined
})
setupSecretMocks({
@ -461,9 +462,9 @@ describe("CodeIndexConfigManager", () => {
codebaseIndexQdrantUrl: "http://qdrant.local",
codebaseIndexEmbedderProvider: "openai-compatible",
codebaseIndexEmbedderModelId: "text-embedding-3-small",
codebaseIndexOpenAiCompatibleBaseUrl: "https://old-api.example.com/v1",
}
}
if (key === "codebaseIndexOpenAiCompatibleBaseUrl") return "https://old-api.example.com/v1"
return undefined
})
setupSecretMocks({
@ -481,9 +482,9 @@ describe("CodeIndexConfigManager", () => {
codebaseIndexQdrantUrl: "http://qdrant.local",
codebaseIndexEmbedderProvider: "openai-compatible",
codebaseIndexEmbedderModelId: "text-embedding-3-small",
codebaseIndexOpenAiCompatibleBaseUrl: "https://new-api.example.com/v1",
}
}
if (key === "codebaseIndexOpenAiCompatibleBaseUrl") return "https://new-api.example.com/v1"
return undefined
})
@ -500,9 +501,9 @@ describe("CodeIndexConfigManager", () => {
codebaseIndexQdrantUrl: "http://qdrant.local",
codebaseIndexEmbedderProvider: "openai-compatible",
codebaseIndexEmbedderModelId: "text-embedding-3-small",
codebaseIndexOpenAiCompatibleBaseUrl: "https://api.example.com/v1",
}
}
if (key === "codebaseIndexOpenAiCompatibleBaseUrl") return "https://api.example.com/v1"
return undefined
})
setupSecretMocks({
@ -531,10 +532,10 @@ describe("CodeIndexConfigManager", () => {
codebaseIndexQdrantUrl: "http://qdrant.local",
codebaseIndexEmbedderProvider: "openai-compatible",
codebaseIndexEmbedderModelId: "custom-model",
codebaseIndexOpenAiCompatibleBaseUrl: "https://api.example.com/v1",
codebaseIndexOpenAiCompatibleModelDimension: 1024,
}
}
if (key === "codebaseIndexOpenAiCompatibleBaseUrl") return "https://api.example.com/v1"
if (key === "codebaseIndexOpenAiCompatibleModelDimension") return 1024
return undefined
})
setupSecretMocks({
@ -552,10 +553,10 @@ describe("CodeIndexConfigManager", () => {
codebaseIndexQdrantUrl: "http://qdrant.local",
codebaseIndexEmbedderProvider: "openai-compatible",
codebaseIndexEmbedderModelId: "custom-model",
codebaseIndexOpenAiCompatibleBaseUrl: "https://api.example.com/v1",
codebaseIndexOpenAiCompatibleModelDimension: 2048,
}
}
if (key === "codebaseIndexOpenAiCompatibleBaseUrl") return "https://api.example.com/v1"
if (key === "codebaseIndexOpenAiCompatibleModelDimension") return 2048
return undefined
})
@ -614,10 +615,10 @@ describe("CodeIndexConfigManager", () => {
codebaseIndexQdrantUrl: "http://qdrant.local",
codebaseIndexEmbedderProvider: "openai-compatible",
codebaseIndexEmbedderModelId: "custom-model",
codebaseIndexOpenAiCompatibleBaseUrl: "https://api.example.com/v1",
// modelDimension not set initially
}
}
if (key === "codebaseIndexOpenAiCompatibleBaseUrl") return "https://api.example.com/v1"
if (key === "codebaseIndexOpenAiCompatibleModelDimension") return undefined
return undefined
})
setupSecretMocks({
@ -635,10 +636,10 @@ describe("CodeIndexConfigManager", () => {
codebaseIndexQdrantUrl: "http://qdrant.local",
codebaseIndexEmbedderProvider: "openai-compatible",
codebaseIndexEmbedderModelId: "custom-model",
codebaseIndexOpenAiCompatibleBaseUrl: "https://api.example.com/v1",
codebaseIndexOpenAiCompatibleModelDimension: 1024,
}
}
if (key === "codebaseIndexOpenAiCompatibleBaseUrl") return "https://api.example.com/v1"
if (key === "codebaseIndexOpenAiCompatibleModelDimension") return 1024
return undefined
})
@ -655,10 +656,10 @@ describe("CodeIndexConfigManager", () => {
codebaseIndexQdrantUrl: "http://qdrant.local",
codebaseIndexEmbedderProvider: "openai-compatible",
codebaseIndexEmbedderModelId: "custom-model",
codebaseIndexOpenAiCompatibleBaseUrl: "https://api.example.com/v1",
codebaseIndexOpenAiCompatibleModelDimension: 1024,
}
}
if (key === "codebaseIndexOpenAiCompatibleBaseUrl") return "https://api.example.com/v1"
if (key === "codebaseIndexOpenAiCompatibleModelDimension") return 1024
return undefined
})
setupSecretMocks({
@ -676,10 +677,10 @@ describe("CodeIndexConfigManager", () => {
codebaseIndexQdrantUrl: "http://qdrant.local",
codebaseIndexEmbedderProvider: "openai-compatible",
codebaseIndexEmbedderModelId: "custom-model",
codebaseIndexOpenAiCompatibleBaseUrl: "https://api.example.com/v1",
// modelDimension removed
}
}
if (key === "codebaseIndexOpenAiCompatibleBaseUrl") return "https://api.example.com/v1"
if (key === "codebaseIndexOpenAiCompatibleModelDimension") return undefined
return undefined
})
@ -1082,9 +1083,9 @@ describe("CodeIndexConfigManager", () => {
codebaseIndexEnabled: true,
codebaseIndexQdrantUrl: "http://qdrant.local",
codebaseIndexEmbedderProvider: "openai-compatible",
codebaseIndexOpenAiCompatibleBaseUrl: "https://api.example.com/v1",
}
}
if (key === "codebaseIndexOpenAiCompatibleBaseUrl") return "https://api.example.com/v1"
return undefined
})
setupSecretMocks({

View file

@ -62,11 +62,12 @@ export class CodeIndexConfigManager {
const openAiKey = this.contextProxy?.getSecret("codeIndexOpenAiKey") ?? ""
const qdrantApiKey = this.contextProxy?.getSecret("codeIndexQdrantApiKey") ?? ""
const openAiCompatibleBaseUrl = this.contextProxy?.getGlobalState("codebaseIndexOpenAiCompatibleBaseUrl") ?? ""
// Fix: Read OpenAI Compatible settings from the correct location within codebaseIndexConfig
const openAiCompatibleBaseUrl = codebaseIndexConfig.codebaseIndexOpenAiCompatibleBaseUrl ?? ""
const openAiCompatibleApiKey = this.contextProxy?.getSecret("codebaseIndexOpenAiCompatibleApiKey") ?? ""
const openAiCompatibleModelDimension = this.contextProxy?.getGlobalState(
"codebaseIndexOpenAiCompatibleModelDimension",
) as number | undefined
const openAiCompatibleModelDimension = codebaseIndexConfig.codebaseIndexOpenAiCompatibleModelDimension as
| number
| undefined
const geminiApiKey = this.contextProxy?.getSecret("codebaseIndexGeminiApiKey") ?? ""
// Update instance variables with configuration

View file

@ -121,9 +121,10 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
codebaseIndexConfig.codebaseIndexSearchMinScore ?? CODEBASE_INDEX_DEFAULTS.DEFAULT_SEARCH_MIN_SCORE,
codeIndexOpenAiKey: "",
codeIndexQdrantApiKey: "",
codebaseIndexOpenAiCompatibleBaseUrl: "",
codebaseIndexOpenAiCompatibleBaseUrl: codebaseIndexConfig.codebaseIndexOpenAiCompatibleBaseUrl || "",
codebaseIndexOpenAiCompatibleApiKey: "",
codebaseIndexOpenAiCompatibleModelDimension: undefined,
codebaseIndexOpenAiCompatibleModelDimension:
codebaseIndexConfig.codebaseIndexOpenAiCompatibleModelDimension || undefined,
codebaseIndexGeminiApiKey: "",
}
setInitialSettings(settings)