feat(auth-files): add note field for individual credentials

- Add note field to the credential field editor (PrefixProxyEditorModal)
- Store note as a string in the credential JSON file
- Display note on AuthFileCard with 2-line clamp for long text
- Note is saved when non-empty, removed from JSON when cleared
- Add i18n translations for zh-CN, en, and ru

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
RGBadmin
2026-03-14 11:22:54 +08:00
co-authored by Claude Opus 4.6
parent 8c2d0df32c
commit b2d89a8043
7 changed files with 57 additions and 1 deletions
@@ -112,6 +112,7 @@ export function AuthFileCard(props: AuthFileCardProps) {
Boolean(rawStatusMessage) && !HEALTHY_STATUS_MESSAGES.has(rawStatusMessage.toLowerCase());
const priorityValue = parsePriorityValue(file.priority ?? file['priority']);
const noteValue = typeof file.note === 'string' ? file.note.trim() : '';
return (
<div
@@ -161,6 +162,13 @@ export function AuthFileCard(props: AuthFileCardProps) {
)}
</div>
{noteValue && (
<div className={styles.noteText} title={noteValue}>
<span className={styles.noteLabel}>{t('auth_files.note_display')}: </span>
{noteValue}
</div>
)}
{rawStatusMessage && hasStatusWarning && (
<div className={styles.healthStatusMessage} title={rawStatusMessage}>
{rawStatusMessage}
@@ -114,6 +114,14 @@ export function AuthFilesPrefixProxyEditorModal(props: AuthFilesPrefixProxyEdito
disabled={disableControls || editor.saving || !editor.json}
onChange={(e) => onChange('disableCooling', e.target.value)}
/>
<Input
label={t('auth_files.note_label')}
value={editor.note}
placeholder={t('auth_files.note_placeholder')}
hint={t('auth_files.note_hint')}
disabled={disableControls || editor.saving || !editor.json}
onChange={(e) => onChange('note', e.target.value)}
/>
{editor.isCodexFile && (
<div className="form-group">
<label>{t('ai_providers.codex_websockets_label')}</label>
@@ -18,7 +18,8 @@ export type PrefixProxyEditorField =
| 'priority'
| 'excludedModelsText'
| 'disableCooling'
| 'websocket';
| 'websocket'
| 'note';
export type PrefixProxyEditorFieldValue = string | boolean;
@@ -37,6 +38,7 @@ export type PrefixProxyEditorState = {
excludedModelsText: string;
disableCooling: string;
websocket: boolean;
note: string;
};
export type UseAuthFilesPrefixProxyEditorOptions = {
@@ -93,6 +95,13 @@ const buildPrefixProxyUpdatedText = (editor: PrefixProxyEditorState | null): str
next.websocket = editor.websocket;
}
const noteValue = editor.note.trim();
if (noteValue) {
next.note = noteValue;
} else if ('note' in next) {
delete next.note;
}
return JSON.stringify(next);
};
@@ -146,6 +155,7 @@ export function useAuthFilesPrefixProxyEditor(
excludedModelsText: '',
disableCooling: '',
websocket: false,
note: '',
});
try {
@@ -195,6 +205,7 @@ export function useAuthFilesPrefixProxyEditor(
const excludedModels = normalizeExcludedModels(json.excluded_models);
const disableCoolingValue = parseDisableCoolingValue(json.disable_cooling);
const websocketValue = parseDisableCoolingValue(json.websocket);
const note = typeof json.note === 'string' ? json.note : '';
setPrefixProxyEditor((prev) => {
if (!prev || prev.fileName !== name) return prev;
@@ -211,6 +222,7 @@ export function useAuthFilesPrefixProxyEditor(
disableCooling:
disableCoolingValue === undefined ? '' : disableCoolingValue ? 'true' : 'false',
websocket: websocketValue ?? false,
note,
error: null,
};
});
@@ -235,6 +247,7 @@ export function useAuthFilesPrefixProxyEditor(
if (field === 'priority') return { ...prev, priority: String(value) };
if (field === 'excludedModelsText') return { ...prev, excludedModelsText: String(value) };
if (field === 'disableCooling') return { ...prev, disableCooling: String(value) };
if (field === 'note') return { ...prev, note: String(value) };
return { ...prev, websocket: Boolean(value) };
});
};