diff --git a/ui/desktop/src/components/onboarding/InstitutionalSetupCard.test.tsx b/ui/desktop/src/components/onboarding/InstitutionalSetupCard.test.tsx
index 847a9befc..75fe49435 100644
--- a/ui/desktop/src/components/onboarding/InstitutionalSetupCard.test.tsx
+++ b/ui/desktop/src/components/onboarding/InstitutionalSetupCard.test.tsx
@@ -20,11 +20,27 @@ const PUBLIC_AZURE_KEYS = [
'AZURE_OPENAI_API_VERSION',
];
-async function connectVersaAzure() {
- render();
+/** Types a key, optionally edits Advanced, and waits for the connect to finish. */
+async function connectVersaAzure(advanced: { endpoint?: string; apiVersion?: string } = {}) {
+ const onSuccess = vi.fn();
+ render();
fireEvent.change(screen.getByLabelText(/API Key/i), { target: { value: 'a-key' } });
+ if (advanced.endpoint !== undefined || advanced.apiVersion !== undefined) {
+ fireEvent.click(screen.getByRole('button', { name: /Advanced/i }));
+ }
+ if (advanced.endpoint !== undefined) {
+ fireEvent.change(screen.getByDisplayValue('https://unified-api.ucsf.edu/general'), {
+ target: { value: advanced.endpoint },
+ });
+ }
+ if (advanced.apiVersion !== undefined) {
+ fireEvent.change(screen.getByDisplayValue('2025-01-01-preview'), {
+ target: { value: advanced.apiVersion },
+ });
+ }
fireEvent.click(screen.getByRole('button', { name: /Connect to Versa Azure OpenAI/i }));
- await waitFor(() => expect(mockCheckProvider).toHaveBeenCalled());
+ // Past `checkProvider`, so every write the connect makes has been recorded.
+ await waitFor(() => expect(onSuccess).toHaveBeenCalledWith('versa_azure'));
}
async function connectVersaBedrock() {
@@ -38,6 +54,8 @@ async function connectVersaBedrock() {
await waitFor(() => expect(onSuccess).toHaveBeenCalledWith('versa_bedrock'));
}
+const writtenKeys = () => mockUpsert.mock.calls.map((c) => c[0] as string);
+
describe('InstitutionalSetupCard', () => {
beforeEach(() => {
vi.clearAllMocks();
@@ -52,19 +70,52 @@ describe('InstitutionalSetupCard', () => {
// `check_provider_configured` report a Public provider the user never set
// up as Configured, one row away in the same grid.
await connectVersaAzure();
- const written = mockUpsert.mock.calls.map((c) => c[0] as string);
for (const key of PUBLIC_AZURE_KEYS) {
- expect(written).not.toContain(key);
+ expect(writtenKeys()).not.toContain(key);
}
});
- it('writes the key and the Versa-namespaced overrides', async () => {
+ it('never writes a deployment: the model a chat picks chooses it', async () => {
+ // `versa_azure` posts each model to its own deployment. A configured
+ // `VERSA_AZURE_DEPLOYMENT_NAME` that names a catalog deployment is ignored,
+ // and any other value pins EVERY model to that one deployment while the
+ // chat still shows the model it picked. Writing the shipped default was
+ // the first case on every connect; the box that let a user write anything
+ // else was the second.
await connectVersaAzure();
- const written = mockUpsert.mock.calls.map((c) => c[0] as string);
- expect(written).toContain('VERSA_AZURE_API_KEY');
- expect(written).toContain('VERSA_AZURE_ENDPOINT');
- expect(written).toContain('VERSA_AZURE_DEPLOYMENT_NAME');
- expect(written).toContain('VERSA_AZURE_API_VERSION');
+ expect(writtenKeys()).not.toContain('VERSA_AZURE_DEPLOYMENT_NAME');
+ });
+
+ it('writes the key, the endpoint and the API version, then selects the provider', async () => {
+ await connectVersaAzure();
+ expect(mockUpsert.mock.calls).toEqual([
+ ['VERSA_AZURE_API_KEY', 'a-key', true],
+ ['VERSA_AZURE_ENDPOINT', 'https://unified-api.ucsf.edu/general', false],
+ ['VERSA_AZURE_API_VERSION', '2025-01-01-preview', false],
+ ['BIOROUTER_PROVIDER', 'versa_azure', false],
+ ]);
+ });
+
+ it('writes the endpoint and API version typed into Advanced', async () => {
+ await connectVersaAzure({
+ endpoint: ' https://gateway.example.edu/general ',
+ apiVersion: '2024-10-21',
+ });
+ expect(mockUpsert).toHaveBeenCalledWith(
+ 'VERSA_AZURE_ENDPOINT',
+ 'https://gateway.example.edu/general',
+ false
+ );
+ expect(mockUpsert).toHaveBeenCalledWith('VERSA_AZURE_API_VERSION', '2024-10-21', false);
+ });
+
+ it('offers the endpoint and API version in Advanced, and no deployment', () => {
+ render();
+ fireEvent.click(screen.getByRole('button', { name: /Advanced/i }));
+ expect(screen.getByText('VERSA_AZURE_ENDPOINT')).toBeInTheDocument();
+ expect(screen.getByText('VERSA_AZURE_API_VERSION')).toBeInTheDocument();
+ // Neither a field nor a mention in the collapsed label.
+ expect(screen.queryAllByText(/deployment/i)).toHaveLength(0);
});
it('never writes a key in the public AWS namespace when connecting UCSF Versa Bedrock', async () => {
diff --git a/ui/desktop/src/components/onboarding/InstitutionalSetupCard.tsx b/ui/desktop/src/components/onboarding/InstitutionalSetupCard.tsx
index a297f40be..98863acb2 100644
--- a/ui/desktop/src/components/onboarding/InstitutionalSetupCard.tsx
+++ b/ui/desktop/src/components/onboarding/InstitutionalSetupCard.tsx
@@ -24,9 +24,16 @@ const VERSA_BEDROCK_DEFAULTS = {
VERSA_BEDROCK_REGION: 'us-west-2',
};
+// ⚠ No deployment, deliberately. `versa_azure` posts each model to its own
+// deployment (`VERSA_AZURE_DEPLOYMENTS` in versa_azure.rs), so the model a chat
+// selects chooses it. A `VERSA_AZURE_DEPLOYMENT_NAME` that names a catalog
+// deployment is ignored, and any other value pins EVERY model to that one
+// deployment while the chat still shows the model it selected. This card used
+// to write the shipped default on every connect (ignored) and offer a box for
+// any other value (that trap, in a first-run form). An operator who needs a
+// deployment the catalog does not list yet sets the key in config instead.
const VERSA_AZURE_DEFAULTS = {
VERSA_AZURE_ENDPOINT: 'https://unified-api.ucsf.edu/general',
- VERSA_AZURE_DEPLOYMENT_NAME: 'gpt-5.5-2026-04-24',
VERSA_AZURE_API_VERSION: '2025-01-01-preview',
};
@@ -69,9 +76,6 @@ export default function InstitutionalSetupCard({
);
const [bedrockRegion, setBedrockRegion] = useState(VERSA_BEDROCK_DEFAULTS.VERSA_BEDROCK_REGION);
const [azureEndpoint, setAzureEndpoint] = useState(VERSA_AZURE_DEFAULTS.VERSA_AZURE_ENDPOINT);
- const [azureDeployment, setAzureDeployment] = useState(
- VERSA_AZURE_DEFAULTS.VERSA_AZURE_DEPLOYMENT_NAME
- );
const [azureApiVersion, setAzureApiVersion] = useState(
VERSA_AZURE_DEFAULTS.VERSA_AZURE_API_VERSION
);
@@ -103,7 +107,6 @@ export default function InstitutionalSetupCard({
} else {
await upsert('VERSA_AZURE_API_KEY', azureApiKey.trim(), true);
await upsert('VERSA_AZURE_ENDPOINT', azureEndpoint.trim(), false);
- await upsert('VERSA_AZURE_DEPLOYMENT_NAME', azureDeployment.trim(), false);
await upsert('VERSA_AZURE_API_VERSION', azureApiVersion.trim(), false);
await checkProvider({ body: { provider: 'versa_azure' }, throwOnError: true });
await upsert('BIOROUTER_PROVIDER', 'versa_azure', false);
@@ -219,8 +222,7 @@ export default function InstitutionalSetupCard({
{advancedOpen ? '▾' : '▸'}
- Advanced (
- {flavor === 'azure' ? 'endpoint, deployment, API version' : 'endpoint, region'})
+ Advanced ({flavor === 'azure' ? 'endpoint, API version' : 'endpoint, region'})
@@ -238,18 +240,6 @@ export default function InstitutionalSetupCard({
disabled={isLoading}
/>
-