feat(ui): overhaul default channel editor with full param override visual editor
- Port classic ParamOverrideEditorModal to default as standalone dialog (~3200 lines) with two-panel layout, drag-to-reorder, 23 operation modes, template library, visual/JSON dual mode, conditions management, and legacy format support - Redesign channel drawer layout with clear visual hierarchy (CardHeading vs SubHeading) and bordered sub-modules for Field Passthrough and Upstream Model Detection - Replace header override JsonEditor with plain textarea matching classic behavior - Add searchable channel type combobox with scroll fix - Add 100+ i18n keys across all 6 locales (en, zh, fr, ja, ru, vi)
This commit is contained in:
+3248
File diff suppressed because it is too large
Load Diff
+1159
-817
File diff suppressed because it is too large
Load Diff
+25
-10
@@ -60,15 +60,30 @@ export const CHANNEL_TYPES = {
|
||||
57: 'Codex',
|
||||
} as const
|
||||
|
||||
export const CHANNEL_TYPE_OPTIONS = Object.entries(CHANNEL_TYPES)
|
||||
.filter(([value]) => {
|
||||
const num = Number(value)
|
||||
return num !== 0 // Exclude Unknown
|
||||
})
|
||||
.map(([value, label]) => ({
|
||||
value: Number(value),
|
||||
label,
|
||||
}))
|
||||
const CHANNEL_TYPE_DISPLAY_ORDER: number[] = [
|
||||
1, 14, 33, 24, 43, 3, 41, 48, 42, 34, 20, 4, 40, 27, 25, 17, 26, 15, 46, 23,
|
||||
18, 45, 31, 35, 49, 19, 47, 37, 38, 39, 11, 8, 57, 22, 21, 44, 2, 5, 36, 50,
|
||||
51, 52, 53, 54, 55, 56,
|
||||
]
|
||||
|
||||
export const CHANNEL_TYPE_OPTIONS: { value: number; label: string }[] = (() => {
|
||||
const ordered: { value: number; label: string }[] = []
|
||||
const seen = new Set<number>()
|
||||
for (const id of CHANNEL_TYPE_DISPLAY_ORDER) {
|
||||
const label = CHANNEL_TYPES[id as keyof typeof CHANNEL_TYPES]
|
||||
if (label) {
|
||||
ordered.push({ value: id, label })
|
||||
seen.add(id)
|
||||
}
|
||||
}
|
||||
for (const [key, label] of Object.entries(CHANNEL_TYPES)) {
|
||||
const id = Number(key)
|
||||
if (id !== 0 && !seen.has(id)) {
|
||||
ordered.push({ value: id, label })
|
||||
}
|
||||
}
|
||||
return ordered
|
||||
})()
|
||||
|
||||
// ============================================================================
|
||||
// Channel Status (label values are i18n keys; use t(config.label) in components)
|
||||
@@ -347,7 +362,7 @@ export const FIELD_DESCRIPTIONS = {
|
||||
// ============================================================================
|
||||
|
||||
export const MODEL_FETCHABLE_TYPES = new Set([
|
||||
1, 4, 14, 17, 20, 23, 24, 25, 26, 31, 34, 35, 40, 42, 43, 47, 48,
|
||||
1, 4, 14, 17, 20, 23, 24, 25, 26, 27, 31, 34, 35, 40, 42, 43, 47, 48,
|
||||
])
|
||||
|
||||
export const TYPE_TO_KEY_PROMPT: Record<number, string> = {
|
||||
|
||||
@@ -59,6 +59,7 @@ export const channelFormSchema = z.object({
|
||||
// Upstream model update settings (stored in settings JSON)
|
||||
upstream_model_update_check_enabled: z.boolean().optional(),
|
||||
upstream_model_update_auto_sync_enabled: z.boolean().optional(),
|
||||
upstream_model_update_ignored_models: z.string().optional(),
|
||||
})
|
||||
|
||||
export type ChannelFormValues = z.infer<typeof channelFormSchema>
|
||||
@@ -113,6 +114,9 @@ export const CHANNEL_FORM_DEFAULT_VALUES: ChannelFormValues = {
|
||||
allow_inference_geo: false,
|
||||
allow_speed: false,
|
||||
claude_beta_query: false,
|
||||
upstream_model_update_check_enabled: false,
|
||||
upstream_model_update_auto_sync_enabled: false,
|
||||
upstream_model_update_ignored_models: '',
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
@@ -166,6 +170,7 @@ export function transformChannelToFormDefaults(
|
||||
let claudeBetaQuery = false
|
||||
let upstreamModelUpdateCheckEnabled = false
|
||||
let upstreamModelUpdateAutoSyncEnabled = false
|
||||
let upstreamModelUpdateIgnoredModels = ''
|
||||
|
||||
if (channel.settings) {
|
||||
try {
|
||||
@@ -185,6 +190,11 @@ export function transformChannelToFormDefaults(
|
||||
parsed.upstream_model_update_check_enabled === true
|
||||
upstreamModelUpdateAutoSyncEnabled =
|
||||
parsed.upstream_model_update_auto_sync_enabled === true
|
||||
upstreamModelUpdateIgnoredModels = Array.isArray(
|
||||
parsed.upstream_model_update_ignored_models
|
||||
)
|
||||
? parsed.upstream_model_update_ignored_models.join(',')
|
||||
: ''
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Failed to parse channel settings:', error)
|
||||
@@ -233,6 +243,7 @@ export function transformChannelToFormDefaults(
|
||||
allow_safety_identifier: allowSafetyIdentifier,
|
||||
upstream_model_update_check_enabled: upstreamModelUpdateCheckEnabled,
|
||||
upstream_model_update_auto_sync_enabled: upstreamModelUpdateAutoSyncEnabled,
|
||||
upstream_model_update_ignored_models: upstreamModelUpdateIgnoredModels,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,7 +347,25 @@ function buildSettingsJSON(formData: ChannelFormValues): string {
|
||||
settingsObj.upstream_model_update_check_enabled =
|
||||
formData.upstream_model_update_check_enabled === true
|
||||
settingsObj.upstream_model_update_auto_sync_enabled =
|
||||
settingsObj.upstream_model_update_check_enabled === true &&
|
||||
formData.upstream_model_update_auto_sync_enabled === true
|
||||
settingsObj.upstream_model_update_ignored_models = Array.from(
|
||||
new Set(
|
||||
String(formData.upstream_model_update_ignored_models || '')
|
||||
.split(',')
|
||||
.map((model) => model.trim())
|
||||
.filter(Boolean)
|
||||
)
|
||||
)
|
||||
if (
|
||||
!Array.isArray(settingsObj.upstream_model_update_last_detected_models) ||
|
||||
settingsObj.upstream_model_update_check_enabled !== true
|
||||
) {
|
||||
settingsObj.upstream_model_update_last_detected_models = []
|
||||
}
|
||||
if (typeof settingsObj.upstream_model_update_last_check_time !== 'number') {
|
||||
settingsObj.upstream_model_update_last_check_time = 0
|
||||
}
|
||||
}
|
||||
|
||||
return JSON.stringify(settingsObj)
|
||||
|
||||
+9
@@ -78,6 +78,15 @@ export interface ChannelOtherSettings {
|
||||
allow_service_tier?: boolean
|
||||
disable_store?: boolean
|
||||
allow_safety_identifier?: boolean
|
||||
allow_include_obfuscation?: boolean
|
||||
allow_inference_geo?: boolean
|
||||
allow_speed?: boolean
|
||||
claude_beta_query?: boolean
|
||||
upstream_model_update_check_enabled?: boolean
|
||||
upstream_model_update_auto_sync_enabled?: boolean
|
||||
upstream_model_update_ignored_models?: string[]
|
||||
upstream_model_update_last_check_time?: number
|
||||
upstream_model_update_last_detected_models?: string[]
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user