feat!: implement AI Bridge heading to /deployment/observability (#20791)

> [!CAUTION]
> In whichever release this lands, we've removed the ability to provide
keys via a YAML file (specifically on `openai_key`, `anthropic_key`,
`bedrock_access_key` and finally `bedrock_access_key_secret`). This will
need to be described in the release notes as to not break peoples AI
Bridge integrations upgrading from older versions.

This pull-request ensures that we can see the overview of the settings
of the `AI Bridge` feature within the `/deployment/observability` route.
This set of options only render when the `aibridge` feature flag is
enabled.

### Preview


![preview-ai-bridge-observability](https://github.com/user-attachments/assets/262d2456-94b4-49b2-9b4e-b14583e70ede)
This commit is contained in:
Jake Howell
2025-12-02 08:23:46 +11:00
committed by GitHub
parent afbe9ea154
commit ab4366f5c6
7 changed files with 64 additions and 22 deletions
-13
View File
@@ -720,25 +720,12 @@ aibridge:
# The base URL of the OpenAI API.
# (default: https://api.openai.com/v1/, type: string)
openai_base_url: https://api.openai.com/v1/
# The key to authenticate against the OpenAI API.
# (default: <unset>, type: string)
openai_key: ""
# The base URL of the Anthropic API.
# (default: https://api.anthropic.com/, type: string)
anthropic_base_url: https://api.anthropic.com/
# The key to authenticate against the Anthropic API.
# (default: <unset>, type: string)
anthropic_key: ""
# The AWS Bedrock API region.
# (default: <unset>, type: string)
bedrock_region: ""
# The access key to authenticate against the AWS Bedrock API.
# (default: <unset>, type: string)
bedrock_access_key: ""
# The access key secret to use with the access key to authenticate against the AWS
# Bedrock API.
# (default: <unset>, type: string)
bedrock_access_key_secret: ""
# The model to use when making requests to the AWS Bedrock API.
# (default: global.anthropic.claude-sonnet-4-5-20250929-v1:0, type: string)
bedrock_model: global.anthropic.claude-sonnet-4-5-20250929-v1:0
+4 -4
View File
@@ -3270,7 +3270,7 @@ Write out the current server config as YAML to stdout.`,
Value: &c.AI.BridgeConfig.OpenAI.Key,
Default: "",
Group: &deploymentGroupAIBridge,
YAML: "openai_key",
Annotations: serpent.Annotations{}.Mark(annotationSecretKey, "true"),
},
{
Name: "AI Bridge Anthropic Base URL",
@@ -3290,7 +3290,7 @@ Write out the current server config as YAML to stdout.`,
Value: &c.AI.BridgeConfig.Anthropic.Key,
Default: "",
Group: &deploymentGroupAIBridge,
YAML: "anthropic_key",
Annotations: serpent.Annotations{}.Mark(annotationSecretKey, "true"),
},
{
Name: "AI Bridge Bedrock Region",
@@ -3310,7 +3310,7 @@ Write out the current server config as YAML to stdout.`,
Value: &c.AI.BridgeConfig.Bedrock.AccessKey,
Default: "",
Group: &deploymentGroupAIBridge,
YAML: "bedrock_access_key",
Annotations: serpent.Annotations{}.Mark(annotationSecretKey, "true"),
},
{
Name: "AI Bridge Bedrock Access Key Secret",
@@ -3320,7 +3320,7 @@ Write out the current server config as YAML to stdout.`,
Value: &c.AI.BridgeConfig.Bedrock.AccessKeySecret,
Default: "",
Group: &deploymentGroupAIBridge,
YAML: "bedrock_access_key_secret",
Annotations: serpent.Annotations{}.Mark(annotationSecretKey, "true"),
},
{
Name: "AI Bridge Bedrock Model",
+14
View File
@@ -84,6 +84,20 @@ func TestDeploymentValues_HighlyConfigurable(t *testing.T) {
"Notifications: Email Auth: Password": {
yaml: true,
},
// We don't want these to be configurable via YAML because they are secrets.
// However, we do want to allow them to be shown in documentation.
"AI Bridge OpenAI Key": {
yaml: true,
},
"AI Bridge Anthropic Key": {
yaml: true,
},
"AI Bridge Bedrock Access Key": {
yaml: true,
},
"AI Bridge Bedrock Access Key Secret": {
yaml: true,
},
}
set := (&codersdk.DeploymentValues{}).Options()
-4
View File
@@ -1676,7 +1676,6 @@ The base URL of the OpenAI API.
|-------------|-----------------------------------------|
| Type | <code>string</code> |
| Environment | <code>$CODER_AIBRIDGE_OPENAI_KEY</code> |
| YAML | <code>aibridge.openai_key</code> |
The key to authenticate against the OpenAI API.
@@ -1697,7 +1696,6 @@ The base URL of the Anthropic API.
|-------------|--------------------------------------------|
| Type | <code>string</code> |
| Environment | <code>$CODER_AIBRIDGE_ANTHROPIC_KEY</code> |
| YAML | <code>aibridge.anthropic_key</code> |
The key to authenticate against the Anthropic API.
@@ -1717,7 +1715,6 @@ The AWS Bedrock API region.
|-------------|-------------------------------------------------|
| Type | <code>string</code> |
| Environment | <code>$CODER_AIBRIDGE_BEDROCK_ACCESS_KEY</code> |
| YAML | <code>aibridge.bedrock_access_key</code> |
The access key to authenticate against the AWS Bedrock API.
@@ -1727,7 +1724,6 @@ The access key to authenticate against the AWS Bedrock API.
|-------------|--------------------------------------------------------|
| Type | <code>string</code> |
| Environment | <code>$CODER_AIBRIDGE_BEDROCK_ACCESS_KEY_SECRET</code> |
| YAML | <code>aibridge.bedrock_access_key_secret</code> |
The access key secret to use with the access key to authenticate against the AWS Bedrock API.
@@ -17,6 +17,7 @@ const ObservabilitySettingsPage: FC = () => {
<ObservabilitySettingsPageView
options={deploymentConfig.options}
featureAuditLogEnabled={entitlements.features.audit_log.enabled}
featureAIBridgeEnabled={entitlements.features.aibridge.enabled}
isPremium={hasPremiumLicense}
/>
</>
@@ -54,3 +54,18 @@ type Story = StoryObj<typeof ObservabilitySettingsPageView>;
export const Page: Story = {};
export const Premium: Story = { args: { isPremium: true } };
export const AI_Bridge: Story = {
args: {
featureAIBridgeEnabled: true,
options: [
{
name: "AI Bridge Enabled",
value: true,
group: { name: "AI Bridge" },
flag: "aibridge-enabled",
hidden: false,
},
],
},
};
@@ -25,12 +25,18 @@ import OptionsTable from "../OptionsTable";
type ObservabilitySettingsPageViewProps = {
options: SerpentOption[];
featureAuditLogEnabled: boolean;
featureAIBridgeEnabled: boolean;
isPremium: boolean;
};
export const ObservabilitySettingsPageView: FC<
ObservabilitySettingsPageViewProps
> = ({ options, featureAuditLogEnabled, isPremium }) => {
> = ({
options,
featureAuditLogEnabled,
isPremium,
featureAIBridgeEnabled,
}) => {
return (
<Stack direction="column" spacing={6}>
<div>
@@ -94,6 +100,29 @@ export const ObservabilitySettingsPageView: FC<
)}
/>
</div>
{featureAIBridgeEnabled && (
<div>
<SettingsHeader
actions={
<SettingsHeaderDocsLink href={docs("/ai-coder/ai-bridge")} />
}
>
<SettingsHeaderTitle hierarchy="secondary" level="h2">
AI Bridge
</SettingsHeaderTitle>
<SettingsHeaderDescription>
Monitor and manage AI requests across your deployment.
</SettingsHeaderDescription>
</SettingsHeader>
<OptionsTable
options={options
.filter((o) => deploymentGroupHasParent(o.group, "AI Bridge"))
.filter((o) => !o.annotations?.secret === true)}
/>
</div>
)}
</Stack>
);
};