fix custom provider edit to preserve config scope

Derive the effective OpenCode config layer (custom > project > user) from
provider sources and send it on PUT /api/provider so project/custom edits
update that layer instead of creating a global user override. Resolve
OPENCODE_CONFIG at call time and add UI/web/VS Code coverage for scoped
upserts.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
This commit is contained in:
Cursor Agent
2026-08-03 08:22:30 +00:00
co-authored by Serhii Dziupin
parent b7c09ee137
commit 66c5f0cdd4
9 changed files with 271 additions and 14 deletions
@@ -5,6 +5,7 @@ import {
isConfigDefinedCustomProvider,
isCustomOpenAICompatibleProvider,
providerToCustomFormState,
resolveProviderConfigScope,
validateCustomProvider,
type CustomProviderConfig,
type CustomProviderFormState,
@@ -203,9 +204,22 @@ describe('request construction', () => {
expect(buildProviderUpsertRequest(plan)).toEqual({
providerID: 'custom-provider',
config: plan.config,
scope: 'user',
});
});
test('includes explicit project/custom scope on upsert requests', () => {
const validated = validateCustomProvider({
form: baseForm(),
t,
existingProviderIDs: new Set(),
});
const plan = validated.result!;
expect(buildProviderUpsertRequest(plan, { scope: 'project' }).scope).toBe('project');
expect(buildProviderUpsertRequest(plan, { scope: 'custom' }).scope).toBe('custom');
});
test('omits auth.set when using env credentials', () => {
const validated = validateCustomProvider({
form: baseForm({ apiKey: '{env:MY_KEY}' }),
@@ -309,4 +323,28 @@ describe('provider edit helpers', () => {
project: { exists: false },
})).toBe(true);
});
test('resolveProviderConfigScope follows custom > project > user precedence', () => {
expect(resolveProviderConfigScope(undefined)).toBe('user');
expect(resolveProviderConfigScope({
user: { exists: true },
project: { exists: false },
custom: { exists: false },
})).toBe('user');
expect(resolveProviderConfigScope({
user: { exists: true },
project: { exists: true },
custom: { exists: false },
})).toBe('project');
expect(resolveProviderConfigScope({
user: { exists: true },
project: { exists: true },
custom: { exists: true },
})).toBe('custom');
expect(resolveProviderConfigScope({
user: { exists: false },
project: { exists: false },
custom: { exists: true },
})).toBe('custom');
});
});