mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-06-16 21:03:58 +08:00
Compare commits
2 Commits
@@ -3,6 +3,7 @@ import { Modal } from '@/components/ui/Modal';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { LoadingSpinner } from '@/components/ui/LoadingSpinner';
|
||||
import { Input } from '@/components/ui/Input';
|
||||
import { ToggleSwitch } from '@/components/ui/ToggleSwitch';
|
||||
import type {
|
||||
PrefixProxyEditorField,
|
||||
PrefixProxyEditorFieldValue,
|
||||
@@ -141,6 +142,18 @@ export function AuthFilesPrefixProxyEditorModal(props: AuthFilesPrefixProxyEdito
|
||||
disabled={disableControls || editor.saving || !editor.json}
|
||||
onChange={(e) => onChange('priority', e.target.value)}
|
||||
/>
|
||||
{editor.providerKey === 'codex' && (
|
||||
<div className="form-group">
|
||||
<label>{t('ai_providers.codex_websockets_label')}</label>
|
||||
<ToggleSwitch
|
||||
checked={editor.websockets}
|
||||
onChange={(value) => onChange('websockets', value)}
|
||||
disabled={disableControls || editor.saving || !editor.json}
|
||||
ariaLabel={t('ai_providers.codex_websockets_label')}
|
||||
/>
|
||||
<div className="hint">{t('ai_providers.codex_websockets_hint')}</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="form-group">
|
||||
<label>{t('auth_files.headers_label')}</label>
|
||||
<textarea
|
||||
|
||||
@@ -222,7 +222,7 @@ export const parseDisableCoolingValue = (value: unknown): boolean | undefined =>
|
||||
};
|
||||
|
||||
export const readCodexAuthFileWebsockets = (value: Record<string, unknown>): boolean =>
|
||||
parseDisableCoolingValue(value.websockets) ?? false;
|
||||
parseDisableCoolingValue(value.websockets ?? value.websocket) ?? false;
|
||||
|
||||
export const applyCodexAuthFileWebsockets = (
|
||||
value: Record<string, unknown>,
|
||||
|
||||
@@ -3,7 +3,12 @@ import { useTranslation } from 'react-i18next';
|
||||
import { authFilesApi, type AuthFileFieldsPatch } from '@/services/api';
|
||||
import type { AuthFileItem } from '@/types';
|
||||
import { useNotificationStore } from '@/stores';
|
||||
import { parsePriorityValue } from '@/features/authFiles/constants';
|
||||
import {
|
||||
applyCodexAuthFileWebsockets,
|
||||
normalizeProviderKey,
|
||||
parsePriorityValue,
|
||||
readCodexAuthFileWebsockets,
|
||||
} from '@/features/authFiles/constants';
|
||||
|
||||
type AuthFileHeaders = Record<string, string>;
|
||||
type AuthFileHeadersErrorKey =
|
||||
@@ -14,9 +19,15 @@ type AuthFileContentErrorKey =
|
||||
| 'auth_files.prefix_proxy_invalid_json'
|
||||
| 'auth_files.prefix_proxy_html_challenge';
|
||||
|
||||
export type PrefixProxyEditorField = 'prefix' | 'proxyUrl' | 'priority' | 'note' | 'headersText';
|
||||
export type PrefixProxyEditorField =
|
||||
| 'prefix'
|
||||
| 'proxyUrl'
|
||||
| 'priority'
|
||||
| 'websockets'
|
||||
| 'note'
|
||||
| 'headersText';
|
||||
|
||||
export type PrefixProxyEditorFieldValue = string;
|
||||
export type PrefixProxyEditorFieldValue = string | boolean;
|
||||
|
||||
export type PrefixProxyEditorState = {
|
||||
fileName: string;
|
||||
@@ -28,9 +39,12 @@ export type PrefixProxyEditorState = {
|
||||
rawText: string;
|
||||
invalidContentPreview: string;
|
||||
json: Record<string, unknown> | null;
|
||||
providerKey: string;
|
||||
prefix: string;
|
||||
proxyUrl: string;
|
||||
priority: string;
|
||||
websockets: boolean;
|
||||
websocketsTouched: boolean;
|
||||
note: string;
|
||||
noteTouched: boolean;
|
||||
headersText: string;
|
||||
@@ -242,6 +256,14 @@ const buildAuthFileFieldsPatch = (
|
||||
}
|
||||
}
|
||||
|
||||
if (editor.providerKey === 'codex' && editor.websocketsTouched) {
|
||||
const originalWebsockets = readCodexAuthFileWebsockets(original);
|
||||
const nextWebsockets = Boolean(editor.websockets);
|
||||
if (nextWebsockets !== originalWebsockets) {
|
||||
patch.websockets = nextWebsockets;
|
||||
}
|
||||
}
|
||||
|
||||
if (editor.headersTouched) {
|
||||
const { value: parsedHeaders, errorKey } = parseHeadersText(editor.headersText);
|
||||
if (errorKey) {
|
||||
@@ -265,7 +287,7 @@ const buildPrefixProxyUpdatedText = (
|
||||
): string => {
|
||||
if (!editor?.json) return editor?.rawText ?? '';
|
||||
const patch = buildAuthFileFieldsPatch(editor, resolveHeadersError);
|
||||
const next: Record<string, unknown> = { ...editor.json };
|
||||
let next: Record<string, unknown> = { ...editor.json };
|
||||
if (patch.prefix !== undefined) {
|
||||
if (patch.prefix) {
|
||||
next.prefix = patch.prefix;
|
||||
@@ -299,6 +321,10 @@ const buildPrefixProxyUpdatedText = (
|
||||
|
||||
applyHeadersPatch(next, patch.headers);
|
||||
|
||||
if (patch.websockets !== undefined) {
|
||||
next = applyCodexAuthFileWebsockets(next, patch.websockets);
|
||||
}
|
||||
|
||||
return JSON.stringify(next);
|
||||
};
|
||||
|
||||
@@ -332,6 +358,7 @@ export function useAuthFilesPrefixProxyEditor(
|
||||
|
||||
const openPrefixProxyEditor = async (file: AuthFileItem) => {
|
||||
const name = file.name;
|
||||
const fileProviderKey = normalizeProviderKey(String(file.type ?? file.provider ?? ''));
|
||||
|
||||
if (disableControls) return;
|
||||
if (prefixProxyEditor?.fileName === name) {
|
||||
@@ -349,9 +376,12 @@ export function useAuthFilesPrefixProxyEditor(
|
||||
rawText: '',
|
||||
invalidContentPreview: '',
|
||||
json: null,
|
||||
providerKey: fileProviderKey,
|
||||
prefix: '',
|
||||
proxyUrl: '',
|
||||
priority: '',
|
||||
websockets: false,
|
||||
websocketsTouched: false,
|
||||
note: '',
|
||||
noteTouched: false,
|
||||
headersText: '',
|
||||
@@ -390,9 +420,13 @@ export function useAuthFilesPrefixProxyEditor(
|
||||
|
||||
const json = { ...(parsed as Record<string, unknown>) };
|
||||
const originalText = JSON.stringify(json);
|
||||
const providerKey = normalizeProviderKey(
|
||||
String(json.type ?? json.provider ?? file.type ?? file.provider ?? '')
|
||||
);
|
||||
const prefix = typeof json.prefix === 'string' ? json.prefix : '';
|
||||
const proxyUrl = typeof json.proxy_url === 'string' ? json.proxy_url : '';
|
||||
const priority = parsePriorityValue(json.priority);
|
||||
const websockets = providerKey === 'codex' ? readCodexAuthFileWebsockets(json) : false;
|
||||
const note = typeof json.note === 'string' ? json.note : '';
|
||||
const headers = json.headers;
|
||||
let headersText = '';
|
||||
@@ -412,9 +446,12 @@ export function useAuthFilesPrefixProxyEditor(
|
||||
rawText: originalText,
|
||||
invalidContentPreview: '',
|
||||
json,
|
||||
providerKey,
|
||||
prefix,
|
||||
proxyUrl,
|
||||
priority: priority !== undefined ? String(priority) : '',
|
||||
websockets,
|
||||
websocketsTouched: false,
|
||||
note,
|
||||
noteTouched: false,
|
||||
headersText,
|
||||
@@ -442,6 +479,9 @@ export function useAuthFilesPrefixProxyEditor(
|
||||
if (field === 'prefix') return { ...prev, prefix: String(value) };
|
||||
if (field === 'proxyUrl') return { ...prev, proxyUrl: String(value) };
|
||||
if (field === 'priority') return { ...prev, priority: String(value) };
|
||||
if (field === 'websockets') {
|
||||
return { ...prev, websockets: Boolean(value), websocketsTouched: true };
|
||||
}
|
||||
if (field === 'note') return { ...prev, note: String(value), noteTouched: true };
|
||||
if (field === 'headersText') {
|
||||
const headersText = String(value);
|
||||
|
||||
@@ -15,6 +15,7 @@ export type AuthFileFieldsPatch = {
|
||||
proxy_url?: string;
|
||||
headers?: Record<string, string>;
|
||||
priority?: number;
|
||||
websockets?: boolean;
|
||||
note?: string;
|
||||
};
|
||||
type AuthFileBatchFailure = { name: string; error: string };
|
||||
|
||||
Reference in New Issue
Block a user