feat(app): provider system overhaul with model selector, diagnostics, and UX polish
- Add CombinedModelSelector with two-level drill-down (providers → models), favorites section, search, and single-provider auto-drill mode - Add provider snapshot system (ProviderSnapshotManager) for cached provider/model state - Add provider diagnostics with resolved binary paths and versions across all providers - Add StatusBadge shared component for consistent status visual language - Add ProviderDiagnosticSheet for detailed provider health inspection - Add desktop auto-focus on input after any status bar interaction (model, mode, thinking, features) using focusWithRetries - Fix Combobox flicker on height change by switching to bottom-based CSS positioning once initial floating-ui position resolves - Add dynamic dropdown height: Level 1 fits content, Level 2 calculates from model count - Remove "Other providers" section from model selector (only show available providers)
This commit is contained in:
@@ -54,6 +54,8 @@ import type {
|
||||
AgentPermissionRequest,
|
||||
AgentPermissionResponse,
|
||||
AgentPersistenceHandle,
|
||||
ProviderSnapshotEntry,
|
||||
ProviderStatus,
|
||||
AgentRuntimeInfo,
|
||||
AgentTimelineItem,
|
||||
ToolCallDetail,
|
||||
@@ -69,6 +71,13 @@ const AgentModeSchema: z.ZodType<AgentMode> = z.object({
|
||||
description: z.string().optional(),
|
||||
});
|
||||
|
||||
const ProviderStatusSchema: z.ZodType<ProviderStatus> = z.enum([
|
||||
"ready",
|
||||
"loading",
|
||||
"error",
|
||||
"unavailable",
|
||||
]);
|
||||
|
||||
const AgentSelectOptionSchema = z.object({
|
||||
id: z.string(),
|
||||
label: z.string(),
|
||||
@@ -114,6 +123,15 @@ const AgentModelDefinitionSchema: z.ZodType<AgentModelDefinition> = z.object({
|
||||
defaultThinkingOptionId: z.string().optional(),
|
||||
});
|
||||
|
||||
const ProviderSnapshotEntrySchema: z.ZodType<ProviderSnapshotEntry> = z.object({
|
||||
provider: AgentProviderSchema,
|
||||
status: ProviderStatusSchema,
|
||||
error: z.string().optional(),
|
||||
models: z.array(AgentModelDefinitionSchema).optional(),
|
||||
modes: z.array(AgentModeSchema).optional(),
|
||||
fetchedAt: z.string().optional(),
|
||||
});
|
||||
|
||||
const AgentCapabilityFlagsSchema: z.ZodType<AgentCapabilityFlags> = z.object({
|
||||
supportsStreaming: z.boolean(),
|
||||
supportsSessionPersistence: z.boolean(),
|
||||
@@ -772,6 +790,24 @@ export const ListAvailableProvidersRequestMessageSchema = z.object({
|
||||
requestId: z.string(),
|
||||
});
|
||||
|
||||
export const GetProvidersSnapshotRequestMessageSchema = z.object({
|
||||
type: z.literal("get_providers_snapshot_request"),
|
||||
cwd: z.string().optional(),
|
||||
requestId: z.string(),
|
||||
});
|
||||
|
||||
export const RefreshProvidersSnapshotRequestMessageSchema = z.object({
|
||||
type: z.literal("refresh_providers_snapshot_request"),
|
||||
cwd: z.string().optional(),
|
||||
requestId: z.string(),
|
||||
});
|
||||
|
||||
export const ProviderDiagnosticRequestMessageSchema = z.object({
|
||||
type: z.literal("provider_diagnostic_request"),
|
||||
provider: AgentProviderSchema,
|
||||
requestId: z.string(),
|
||||
});
|
||||
|
||||
export const ResumeAgentRequestMessageSchema = z.object({
|
||||
type: z.literal("resume_agent_request"),
|
||||
handle: AgentPersistenceHandleSchema,
|
||||
@@ -1275,6 +1311,9 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
||||
ListProviderModesRequestMessageSchema,
|
||||
ListProviderFeaturesRequestMessageSchema,
|
||||
ListAvailableProvidersRequestMessageSchema,
|
||||
GetProvidersSnapshotRequestMessageSchema,
|
||||
RefreshProvidersSnapshotRequestMessageSchema,
|
||||
ProviderDiagnosticRequestMessageSchema,
|
||||
ResumeAgentRequestMessageSchema,
|
||||
RefreshAgentRequestMessageSchema,
|
||||
CancelAgentRequestMessageSchema,
|
||||
@@ -1500,6 +1539,12 @@ export const ServerInfoStatusPayloadSchema = z
|
||||
hostname: ServerInfoHostnameSchema.optional(),
|
||||
version: ServerInfoVersionSchema.optional(),
|
||||
capabilities: ServerCapabilitiesFromUnknownSchema,
|
||||
// COMPAT(providersSnapshot): added in v0.1.48, remove gating when all clients use snapshot
|
||||
features: z
|
||||
.object({
|
||||
providersSnapshot: z.boolean().optional(),
|
||||
})
|
||||
.optional(),
|
||||
})
|
||||
.passthrough()
|
||||
.transform((payload) => ({
|
||||
@@ -2235,6 +2280,45 @@ export const ListAvailableProvidersResponseSchema = z.object({
|
||||
}),
|
||||
});
|
||||
|
||||
// COMPAT(providersSnapshot): added in v0.1.48, remove gating when all clients use snapshot
|
||||
export const GetProvidersSnapshotResponseMessageSchema = z.object({
|
||||
type: z.literal("get_providers_snapshot_response"),
|
||||
payload: z.object({
|
||||
entries: z.array(ProviderSnapshotEntrySchema),
|
||||
generatedAt: z.string(),
|
||||
requestId: z.string(),
|
||||
}),
|
||||
});
|
||||
|
||||
// COMPAT(providersSnapshot): added in v0.1.48, remove gating when all clients use snapshot
|
||||
export const ProvidersSnapshotUpdateMessageSchema = z.object({
|
||||
type: z.literal("providers_snapshot_update"),
|
||||
payload: z.object({
|
||||
cwd: z.string().optional(),
|
||||
entries: z.array(ProviderSnapshotEntrySchema),
|
||||
generatedAt: z.string(),
|
||||
}),
|
||||
});
|
||||
|
||||
// COMPAT(providersSnapshot): added in v0.1.48, remove gating when all clients use snapshot
|
||||
export const RefreshProvidersSnapshotResponseMessageSchema = z.object({
|
||||
type: z.literal("refresh_providers_snapshot_response"),
|
||||
payload: z.object({
|
||||
requestId: z.string(),
|
||||
acknowledged: z.boolean(),
|
||||
}),
|
||||
});
|
||||
|
||||
// COMPAT(providersSnapshot): added in v0.1.48, remove gating when all clients use snapshot
|
||||
export const ProviderDiagnosticResponseMessageSchema = z.object({
|
||||
type: z.literal("provider_diagnostic_response"),
|
||||
payload: z.object({
|
||||
provider: AgentProviderSchema,
|
||||
diagnostic: z.string(),
|
||||
requestId: z.string(),
|
||||
}),
|
||||
});
|
||||
|
||||
const AgentSlashCommandSchema = z.object({
|
||||
name: z.string(),
|
||||
description: z.string(),
|
||||
@@ -2428,6 +2512,10 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
||||
ListProviderModesResponseMessageSchema,
|
||||
ListProviderFeaturesResponseMessageSchema,
|
||||
ListAvailableProvidersResponseSchema,
|
||||
GetProvidersSnapshotResponseMessageSchema,
|
||||
ProvidersSnapshotUpdateMessageSchema,
|
||||
RefreshProvidersSnapshotResponseMessageSchema,
|
||||
ProviderDiagnosticResponseMessageSchema,
|
||||
ListCommandsResponseSchema,
|
||||
ListTerminalsResponseSchema,
|
||||
TerminalsChangedSchema,
|
||||
@@ -2507,6 +2595,16 @@ export type ListProviderFeaturesResponseMessage = z.infer<
|
||||
typeof ListProviderFeaturesResponseMessageSchema
|
||||
>;
|
||||
export type ListAvailableProvidersResponse = z.infer<typeof ListAvailableProvidersResponseSchema>;
|
||||
export type GetProvidersSnapshotResponseMessage = z.infer<
|
||||
typeof GetProvidersSnapshotResponseMessageSchema
|
||||
>;
|
||||
export type ProvidersSnapshotUpdateMessage = z.infer<typeof ProvidersSnapshotUpdateMessageSchema>;
|
||||
export type RefreshProvidersSnapshotResponseMessage = z.infer<
|
||||
typeof RefreshProvidersSnapshotResponseMessageSchema
|
||||
>;
|
||||
export type ProviderDiagnosticResponseMessage = z.infer<
|
||||
typeof ProviderDiagnosticResponseMessageSchema
|
||||
>;
|
||||
export type ChatCreateResponse = z.infer<typeof ChatCreateResponseSchema>;
|
||||
export type ChatListResponse = z.infer<typeof ChatListResponseSchema>;
|
||||
export type ChatInspectResponse = z.infer<typeof ChatInspectResponseSchema>;
|
||||
@@ -2554,6 +2652,15 @@ export type ListProviderFeaturesRequestMessage = z.infer<
|
||||
export type ListAvailableProvidersRequestMessage = z.infer<
|
||||
typeof ListAvailableProvidersRequestMessageSchema
|
||||
>;
|
||||
export type GetProvidersSnapshotRequestMessage = z.infer<
|
||||
typeof GetProvidersSnapshotRequestMessageSchema
|
||||
>;
|
||||
export type RefreshProvidersSnapshotRequestMessage = z.infer<
|
||||
typeof RefreshProvidersSnapshotRequestMessageSchema
|
||||
>;
|
||||
export type ProviderDiagnosticRequestMessage = z.infer<
|
||||
typeof ProviderDiagnosticRequestMessageSchema
|
||||
>;
|
||||
export type ChatCreateRequest = z.infer<typeof ChatCreateRequestSchema>;
|
||||
export type ChatListRequest = z.infer<typeof ChatListRequestSchema>;
|
||||
export type ChatInspectRequest = z.infer<typeof ChatInspectRequestSchema>;
|
||||
|
||||
Reference in New Issue
Block a user