feat: add general subagent model override (#24610)

Adds a deployment-wide admin override for general delegated subagents.

## What changed
- store the general override in `site_configs` and expose it through the
shared `agent-model-override/{context}` API
- apply the general override when spawning delegated general subagents,
while preserving the existing Explore override behavior
- reuse a shared Agents settings form for the general and Explore
override sections

## Validation
- `make gen`
- `go test ./coderd -run 'TestChatModelOverrides'`
- `go test ./coderd/x/chatd -run
'TestSpawnAgent_(GeneralUsesConfiguredModelOverride|GeneralOverrideLogsAndFallsBackWhenCredentialsUnavailable|GeneralOverrideLogsAndFallsBackWhenProviderDisabled)'`
- `pnpm -C site lint:types`
- `pnpm -C site test:storybook --
AgentSettingsAgentsPageView.stories.tsx`
- `make lint`
- `make pre-commit`

> Mux is acting on Mike's behalf.
This commit is contained in:
Michael Suchacz
2026-04-24 12:37:20 +02:00
committed by GitHub
parent 4505278a9f
commit 3d90546aae
23 changed files with 1780 additions and 677 deletions
+13 -11
View File
@@ -3257,20 +3257,22 @@ class ExperimentalApiMethods {
);
};
getChatExploreModelOverride =
async (): Promise<TypesGen.ChatExploreModelOverrideResponse> => {
const response =
await this.axios.get<TypesGen.ChatExploreModelOverrideResponse>(
"/api/experimental/chats/config/explore-model-override",
);
return response.data;
};
getChatAgentModelOverride = async (
context: TypesGen.ChatAgentModelOverrideContext,
): Promise<TypesGen.ChatAgentModelOverrideResponse> => {
const response =
await this.axios.get<TypesGen.ChatAgentModelOverrideResponse>(
`/api/experimental/chats/config/agent-model-override/${encodeURIComponent(context)}`,
);
return response.data;
};
updateChatExploreModelOverride = async (
req: TypesGen.UpdateChatExploreModelOverrideRequest,
updateChatAgentModelOverride = async (
context: TypesGen.ChatAgentModelOverrideContext,
req: TypesGen.UpdateChatAgentModelOverrideRequest,
): Promise<void> => {
await this.axios.put(
"/api/experimental/chats/config/explore-model-override",
`/api/experimental/chats/config/agent-model-override/${encodeURIComponent(context)}`,
req,
);
};
-17
View File
@@ -1127,23 +1127,6 @@ export const updateChatPlanModeInstructions = (queryClient: QueryClient) => ({
},
});
const chatExploreModelOverrideKey = ["chat-explore-model-override"] as const;
export const chatExploreModelOverride = () => ({
queryKey: chatExploreModelOverrideKey,
queryFn: () => API.experimental.getChatExploreModelOverride(),
});
export const updateChatExploreModelOverride = (queryClient: QueryClient) => ({
mutationFn: (req: TypesGen.UpdateChatExploreModelOverrideRequest) =>
API.experimental.updateChatExploreModelOverride(req),
onSuccess: async () => {
await queryClient.invalidateQueries({
queryKey: chatExploreModelOverrideKey,
});
},
});
const chatDesktopEnabledKey = ["chat-desktop-enabled"] as const;
export const chatDesktopEnabled = () => ({
+28 -23
View File
@@ -1272,6 +1272,25 @@ export interface Chat {
readonly children: readonly Chat[];
}
// From codersdk/chats.go
export type ChatAgentModelOverrideContext = "explore" | "general";
export const ChatAgentModelOverrideContexts: ChatAgentModelOverrideContext[] = [
"explore",
"general",
];
// From codersdk/chats.go
/**
* ChatAgentModelOverrideResponse is the response body for the chat agent
* model override configuration endpoint.
*/
export interface ChatAgentModelOverrideResponse {
readonly context: ChatAgentModelOverrideContext;
readonly model_config_id: string;
readonly is_malformed: boolean;
}
// From codersdk/chats.go
export type ChatBusyBehavior = "interrupt" | "queue";
@@ -1590,20 +1609,6 @@ export interface ChatDiffStatus {
readonly stale_at?: string;
}
// From codersdk/chats.go
/**
* ChatExploreModelOverrideResponse is the response body for the Explore
* subagent model override configuration endpoint.
*/
export interface ChatExploreModelOverrideResponse {
readonly model_config_id?: string;
/**
* HasMalformedOverride reports whether the saved override is malformed and
* is currently being treated as unset.
*/
readonly has_malformed_override: boolean;
}
// From codersdk/chats.go
/**
* ChatFileMetadata contains lightweight metadata about a file
@@ -7657,6 +7662,15 @@ export interface UpdateAppearanceConfig {
readonly announcement_banners: readonly BannerConfig[];
}
// From codersdk/chats.go
/**
* UpdateChatAgentModelOverrideRequest is the request body for updating the
* chat agent model override configuration endpoint.
*/
export interface UpdateChatAgentModelOverrideRequest {
readonly model_config_id: string;
}
// From codersdk/chats.go
/**
* UpdateChatDebugLoggingAllowUsersRequest is the admin request to
@@ -7674,15 +7688,6 @@ export interface UpdateChatDesktopEnabledRequest {
readonly enable_desktop: boolean;
}
// From codersdk/chats.go
/**
* UpdateChatExploreModelOverrideRequest is the request body for updating the
* Explore subagent model override configuration endpoint.
*/
export interface UpdateChatExploreModelOverrideRequest {
readonly model_config_id?: string;
}
// From codersdk/chats.go
/**
* UpdateChatModelConfigRequest updates a chat model config.