fix(ai): improve API retry handling
This commit is contained in:
1 parent
a4352d6560
commit
52d5c99a92
29 files changed
+3962
-1097
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -1776,6 +1776,12 @@ export default {
|
||||
contextWindow: "Context Window",
|
||||
contextWindowAuto: "Auto (detect from model name)",
|
||||
contextWindowHint: "Tokens. Leave empty to auto-detect. Set manually for local/custom models.",
|
||||
maxRetries: "Max Retries",
|
||||
maxRetriesHint: "Retry on rate limits, timeouts, and temporary network errors. 0 = never, max 10.",
|
||||
maxRetriesGlobal: "Max Retries",
|
||||
maxRetriesGlobalDescription: "Number of automatic retries on transient API errors (rate limits, timeouts, network blips). Applies to all API-backed AI providers. CLI providers (claude-code, codex, pi) are unaffected.",
|
||||
maxRetriesRange: "{min}–{max}, default {default}",
|
||||
maxRetriesSaved: "Max retries saved",
|
||||
codexCliPath: "Codex CLI Path",
|
||||
codexCliPathHint: "Leave empty to use codex from PATH. Sign in separately with codex login.",
|
||||
codexCliPathEnvError: "Codex CLI Path should contain only the executable path. Add environment variables below.",
|
||||
|
||||
@@ -1815,6 +1815,10 @@ export default withEnglishFallback({
|
||||
contextWindow: "Ventana de contexto",
|
||||
contextWindowAuto: "Auto (detectar desde el nombre del modelo)",
|
||||
contextWindowHint: "Tokens. Déjalo vacío para detección automática. Configúralo manualmente para modelos locales/personalizados.",
|
||||
maxRetriesGlobal: "Reintentos máximos",
|
||||
maxRetriesGlobalDescription: "Número de reintentos automáticos en errores transitorios de API (límite de tasa, timeout, fallos de red). Se aplica a todos los proveedores de IA por API. Los proveedores CLI (claude-code, codex, pi) no se ven afectados.",
|
||||
maxRetriesRange: "{min}–{max}, predeterminado {default}",
|
||||
maxRetriesSaved: "Reintentos máximos guardados",
|
||||
codexCliPath: "Ruta de Codex CLI",
|
||||
codexCliPathHint: "Déjalo vacío para usar codex desde PATH. Inicia sesión por separado con codex login.",
|
||||
actions: {
|
||||
@@ -1846,6 +1850,8 @@ export default withEnglishFallback({
|
||||
editResend: "Reenviar",
|
||||
editCancel: "Cancelar",
|
||||
cannotDeleteActiveConfig: "No se puede eliminar la configuración activa actual. Cambie a otra configuración primero.",
|
||||
maxRetries: "Número máximo de reintentos",
|
||||
maxRetriesHint: "Reintentar automáticamente en caso de limitación de tasa, tiempo de espera o error de red temporal. 0 = no reintentar, máximo 10.",
|
||||
},
|
||||
contextMenu: {
|
||||
openConnection: "Abrir conexión",
|
||||
|
||||
@@ -1755,6 +1755,10 @@ export default withEnglishFallback({
|
||||
contextWindow: "Finestra di Contesto",
|
||||
contextWindowAuto: "Auto (rileva dal nome del modello)",
|
||||
contextWindowHint: "Token. Lascia vuoto per il rilevamento automatico. Imposta manualmente per modelli locali/personalizzati.",
|
||||
maxRetriesGlobal: "Tentativi massimi",
|
||||
maxRetriesGlobalDescription: "Numero di tentativi automatici su errori API transitori (limite di velocità, timeout, problemi di rete). Si applica a tutti i provider IA via API. I provider CLI (claude-code, codex, pi) non sono interessati.",
|
||||
maxRetriesRange: "{min}–{max}, predefinito {default}",
|
||||
maxRetriesSaved: "Tentativi massimi salvati",
|
||||
codexCliPath: "Percorso Codex CLI",
|
||||
codexCliPathHint: "Lascia vuoto per usare codex dal PATH. Esegui login separatamente con codex login.",
|
||||
codexCliPathEnvError: "Codex CLI Path deve contenere solo il percorso dell'eseguibile. Aggiungi le variabili d'ambiente sotto.",
|
||||
@@ -1844,6 +1848,8 @@ export default withEnglishFallback({
|
||||
editResend: "Invia di nuovo",
|
||||
editCancel: "Annulla",
|
||||
cannotDeleteActiveConfig: "Non è possibile eliminare la configurazione attualmente attiva. Passa a un'altra configurazione prima.",
|
||||
maxRetries: "Numero massimo di tentativi",
|
||||
maxRetriesHint: "Riprova automaticamente in caso di limitazione, timeout o errore di rete temporaneo. 0 = nessun tentativo, massimo 10.",
|
||||
},
|
||||
contextMenu: {
|
||||
openConnection: "Apri Connessione",
|
||||
|
||||
@@ -1649,6 +1649,10 @@ export default withEnglishFallback({
|
||||
contextWindow: "コンテキストウィンドウ",
|
||||
contextWindowAuto: "自動(モデル名から検出)",
|
||||
contextWindowHint: "トークン数。空欄で自動検出。ローカル/カスタムモデルは手動設定してください。",
|
||||
maxRetriesGlobal: "最大再試行回数",
|
||||
maxRetriesGlobalDescription: "一時的なAPIエラー(レート制限、タイムアウト、ネットワーク障害)発生時の自動再試行回数。すべてのAPI対応AIプロバイダーに適用されます。CLIプロバイダー(claude-code、codex、pi)は影響を受けません。",
|
||||
maxRetriesRange: "{min}–{max}、デフォルト {default}",
|
||||
maxRetriesSaved: "最大再試行回数を保存しました",
|
||||
codexCliPath: "Codex CLI パス",
|
||||
codexCliPathHint: "空欄の場合はPATHからcodexを使用します。codex loginで別途サインインしてください。",
|
||||
reasoningLevel: "推論レベル",
|
||||
@@ -1845,6 +1849,8 @@ export default withEnglishFallback({
|
||||
editResend: "再送信",
|
||||
editCancel: "キャンセル",
|
||||
cannotDeleteActiveConfig: "現在アクティブな設定は削除できません。先に他の設定に切り替えてください。",
|
||||
maxRetries: "最大リトライ回数",
|
||||
maxRetriesHint: "レート制限、タイムアウト、または一時的なネットワークエラーが発生した場合に自動的にリトライします。0 = リトライなし、最大10。",
|
||||
},
|
||||
contextMenu: {
|
||||
openConnection: "接続を開く",
|
||||
|
||||
@@ -1813,6 +1813,10 @@ export default withEnglishFallback({
|
||||
contextWindow: "Janela de Contexto",
|
||||
contextWindowAuto: "Automático (detectar pelo nome do modelo)",
|
||||
contextWindowHint: "Tokens. Deixe vazio para detecção automática. Defina manualmente para modelos locais/personalizados.",
|
||||
maxRetriesGlobal: "Máximo de Tentativas",
|
||||
maxRetriesGlobalDescription: "Número de tentativas automáticas em erros transitórios de API (limite de taxa, timeout, falhas de rede). Aplica-se a todos os provedores de IA via API. Provedores CLI (claude-code, codex, pi) não são afetados.",
|
||||
maxRetriesRange: "{min}–{max}, padrão {default}",
|
||||
maxRetriesSaved: "Máximo de tentativas salvo",
|
||||
enableThinking: "Raciocínio",
|
||||
enableThinkingOn: "Ativado",
|
||||
enableThinkingOff: "Desativado",
|
||||
@@ -1846,6 +1850,8 @@ export default withEnglishFallback({
|
||||
editResend: "Reenviar",
|
||||
editCancel: "Cancelar",
|
||||
cannotDeleteActiveConfig: "Não é possível excluir a configuração ativa atual. Mude para outra configuração primeiro.",
|
||||
maxRetries: "Número máximo de tentativas",
|
||||
maxRetriesHint: "Tente novamente automaticamente ao encontrar limitação de taxa, tempo limite ou erro de rede temporário. 0 = não tentar novamente, máximo 10.",
|
||||
},
|
||||
contextMenu: {
|
||||
openConnection: "Abrir Conexão",
|
||||
|
||||
@@ -1777,6 +1777,12 @@ export default withEnglishFallback({
|
||||
contextWindow: "上下文窗口",
|
||||
contextWindowAuto: "自动(根据模型名称推断)",
|
||||
contextWindowHint: "单位:token。留空自动推断,本地/自定义模型建议手动设置。",
|
||||
maxRetries: "最大重试次数",
|
||||
maxRetriesHint: "遇到限流、超时或临时网络错误时自动重试。0 = 不重试,最大 10。",
|
||||
maxRetriesGlobal: "最大重试次数",
|
||||
maxRetriesGlobalDescription: "遇到临时 API 错误(限流、超时、网络波动)时的自动重试次数。适用于所有 API 模式 AI 供应商。CLI 供应商(claude-code、codex、pi)不受影响。",
|
||||
maxRetriesRange: "{min}–{max},默认 {default}",
|
||||
maxRetriesSaved: "最大重试次数已保存",
|
||||
codexCliPath: "Codex CLI 路径",
|
||||
codexCliPathHint: "留空则使用 PATH 中的 codex。请先在终端执行 codex login 登录。",
|
||||
codexCliPathEnvError: "Codex CLI 路径只能填写可执行文件路径。请在下方添加环境变量。",
|
||||
|
||||
@@ -1756,6 +1756,12 @@ export default withEnglishFallback({
|
||||
contextWindow: "Context Window",
|
||||
contextWindowAuto: "自動(從模型名稱偵測)",
|
||||
contextWindowHint: "Token 數。留空以自動偵測。本機/自訂模型請手動設定。",
|
||||
maxRetries: "最大重試次數",
|
||||
maxRetriesHint: "遇到限流、超時或暫時性網路錯誤時自動重試。0 = 不重試,最大 10。",
|
||||
maxRetriesGlobal: "最大重試次數",
|
||||
maxRetriesGlobalDescription: "遇到暫時性 API 錯誤(限流、超時、網路波動)時的自動重試次數。適用於所有 API 模式 AI 供應商。CLI 供應商(claude-code、codex、pi)不受影響。",
|
||||
maxRetriesRange: "{min}–{max},預設 {default}",
|
||||
maxRetriesSaved: "最大重試次數已儲存",
|
||||
codexCliPath: "Codex CLI 路徑",
|
||||
codexCliPathHint: "留空以使用 PATH 中的 codex。請另外以 codex login 登入。",
|
||||
codexMcpRequiredTitle: "需要 DBX MCP Server",
|
||||
|
||||
@@ -272,6 +272,8 @@ export const loadMcpGlobalPolicy = forward("loadMcpGlobalPolicy");
|
||||
export const saveMcpGlobalPolicy = forward("saveMcpGlobalPolicy");
|
||||
export const loadMaxAgentTurns = forward("loadMaxAgentTurns");
|
||||
export const saveMaxAgentTurns = forward("saveMaxAgentTurns");
|
||||
export const loadMaxRetries = forward("loadMaxRetries");
|
||||
export const saveMaxRetries = forward("saveMaxRetries");
|
||||
export const completeAppClose = forward("completeAppClose");
|
||||
export const requestAppClose = forward("requestAppClose");
|
||||
export const setDriverStoreDir = forward("setDriverStoreDir");
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -393,7 +393,14 @@ export interface CustomTheme {
|
||||
ddlColors: CustomThemeDdlColors;
|
||||
}
|
||||
|
||||
export const DEFAULT_CUSTOM_THEMES: CustomTheme[] = [{ id: "default", name: "Custom", colors: { ...DEFAULT_CUSTOM_THEME_COLORS }, ddlColors: { ...DEFAULT_CUSTOM_THEME_DDL_COLORS } }];
|
||||
export const DEFAULT_CUSTOM_THEMES: CustomTheme[] = [
|
||||
{
|
||||
id: "default",
|
||||
name: "Custom",
|
||||
colors: { ...DEFAULT_CUSTOM_THEME_COLORS },
|
||||
ddlColors: { ...DEFAULT_CUSTOM_THEME_DDL_COLORS },
|
||||
},
|
||||
];
|
||||
|
||||
export type SidebarObjectInfoMode = "comment-inline" | "comment-aligned" | "comment-right" | "size" | "hidden";
|
||||
|
||||
@@ -538,7 +545,11 @@ export function enforceRightSidebarPanelExclusivity(current: RightSidebarPanelSt
|
||||
return transitionRightSidebarPanels(current, panelToKeep, true, true);
|
||||
}
|
||||
|
||||
export const EDITOR_THEMES: { value: EditorTheme; label: string; dark: boolean }[] = [
|
||||
export const EDITOR_THEMES: {
|
||||
value: EditorTheme;
|
||||
label: string;
|
||||
dark: boolean;
|
||||
}[] = [
|
||||
{ value: "app", label: "Follow app theme", dark: false },
|
||||
{ value: "one-dark", label: "One Dark", dark: true },
|
||||
{ value: "vscode-dark", label: "VS Dark+", dark: true },
|
||||
@@ -790,7 +801,13 @@ function normalizeSqlSnippets(value: unknown, existing?: SqlSnippet[]): SqlSnipp
|
||||
if (seenPrefixes.has(item.prefix)) continue;
|
||||
seenPrefixes.add(item.prefix);
|
||||
// Older settings do not have this field; only an explicit false disables a snippet.
|
||||
valid.push({ id: item.id, label: item.label, prefix: item.prefix, body: item.body, enabled: item.enabled !== false });
|
||||
valid.push({
|
||||
id: item.id,
|
||||
label: item.label,
|
||||
prefix: item.prefix,
|
||||
body: item.body,
|
||||
enabled: item.enabled !== false,
|
||||
});
|
||||
}
|
||||
if (valid.length === 0) return existing ?? DEFAULT_SQL_SNIPPETS;
|
||||
return valid;
|
||||
@@ -845,7 +862,10 @@ export function normalizeEditorSettings(settings: Partial<EditorSettings>, exist
|
||||
return {
|
||||
...renamed,
|
||||
colors: { ...DEFAULT_CUSTOM_THEME_COLORS, ...renamed.colors },
|
||||
ddlColors: { ...DEFAULT_CUSTOM_THEME_DDL_COLORS, ...(renamed as any).ddlColors },
|
||||
ddlColors: {
|
||||
...DEFAULT_CUSTOM_THEME_DDL_COLORS,
|
||||
...(renamed as any).ddlColors,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -854,7 +874,10 @@ export function normalizeEditorSettings(settings: Partial<EditorSettings>, exist
|
||||
{
|
||||
id: "migrated",
|
||||
name: "Migrated",
|
||||
colors: { ...DEFAULT_CUSTOM_THEME_COLORS, ...settings.customThemeColors },
|
||||
colors: {
|
||||
...DEFAULT_CUSTOM_THEME_COLORS,
|
||||
...settings.customThemeColors,
|
||||
},
|
||||
ddlColors: { ...DEFAULT_CUSTOM_THEME_DDL_COLORS },
|
||||
},
|
||||
]
|
||||
@@ -915,17 +938,43 @@ export function normalizeEditorSettings(settings: Partial<EditorSettings>, exist
|
||||
sidebarObjectDisplay: settings.sidebarObjectDisplay === "simple" || settings.sidebarObjectDisplay === "grouped" ? settings.sidebarObjectDisplay : DEFAULT_EDITOR_SETTINGS.sidebarObjectDisplay,
|
||||
sidebarTableSearchEnabled: typeof settings.sidebarTableSearchEnabled === "boolean" ? settings.sidebarTableSearchEnabled : DEFAULT_EDITOR_SETTINGS.sidebarTableSearchEnabled,
|
||||
autoSelectActiveSidebarNode: settings.autoSelectActiveSidebarNode ?? DEFAULT_EDITOR_SETTINGS.autoSelectActiveSidebarNode,
|
||||
openTabsRestoreMode: normalizeOpenTabsRestoreMode((settings as Partial<EditorSettings>).openTabsRestoreMode, (settings as Partial<EditorSettings> & { restoreOpenTabsOnLaunch?: boolean }).restoreOpenTabsOnLaunch),
|
||||
disconnectTabHandlingMode: normalizeDisconnectTabHandlingMode((settings as Partial<EditorSettings>).disconnectTabHandlingMode, (settings as Partial<EditorSettings> & { closeQueryTabsOnDisconnect?: boolean }).closeQueryTabsOnDisconnect),
|
||||
openTabsRestoreMode: normalizeOpenTabsRestoreMode(
|
||||
(settings as Partial<EditorSettings>).openTabsRestoreMode,
|
||||
(
|
||||
settings as Partial<EditorSettings> & {
|
||||
restoreOpenTabsOnLaunch?: boolean;
|
||||
}
|
||||
).restoreOpenTabsOnLaunch,
|
||||
),
|
||||
disconnectTabHandlingMode: normalizeDisconnectTabHandlingMode(
|
||||
(settings as Partial<EditorSettings>).disconnectTabHandlingMode,
|
||||
(
|
||||
settings as Partial<EditorSettings> & {
|
||||
closeQueryTabsOnDisconnect?: boolean;
|
||||
}
|
||||
).closeQueryTabsOnDisconnect,
|
||||
),
|
||||
reuseDataTab: settings.reuseDataTab ?? DEFAULT_EDITOR_SETTINGS.reuseDataTab,
|
||||
prefillNewQueryWithSelect: typeof settings.prefillNewQueryWithSelect === "boolean" ? settings.prefillNewQueryWithSelect : DEFAULT_EDITOR_SETTINGS.prefillNewQueryWithSelect,
|
||||
updateNotificationsEnabled: settings.updateNotificationsEnabled ?? DEFAULT_EDITOR_SETTINGS.updateNotificationsEnabled,
|
||||
sidebarHiddenTablePrefixes: normalizeSidebarHiddenTablePrefixes(settings.sidebarHiddenTablePrefixes),
|
||||
sidebarObjectInfoMode: normalizeSidebarObjectInfoMode(
|
||||
settings.sidebarObjectInfoMode,
|
||||
(settings as Partial<EditorSettings> & { sidebarTableCommentLayout?: string }).sidebarTableCommentLayout,
|
||||
(settings as Partial<EditorSettings> & { sidebarHideTableComments?: boolean }).sidebarHideTableComments,
|
||||
(settings as Partial<EditorSettings> & { sidebarShowDatabaseSizes?: boolean }).sidebarShowDatabaseSizes,
|
||||
(
|
||||
settings as Partial<EditorSettings> & {
|
||||
sidebarTableCommentLayout?: string;
|
||||
}
|
||||
).sidebarTableCommentLayout,
|
||||
(
|
||||
settings as Partial<EditorSettings> & {
|
||||
sidebarHideTableComments?: boolean;
|
||||
}
|
||||
).sidebarHideTableComments,
|
||||
(
|
||||
settings as Partial<EditorSettings> & {
|
||||
sidebarShowDatabaseSizes?: boolean;
|
||||
}
|
||||
).sidebarShowDatabaseSizes,
|
||||
),
|
||||
sidebarAllowHorizontalScroll: settings.sidebarAllowHorizontalScroll ?? DEFAULT_EDITOR_SETTINGS.sidebarAllowHorizontalScroll,
|
||||
columnFormatters: normalizeColumnFormatters(settings.columnFormatters),
|
||||
@@ -996,7 +1045,9 @@ export const useSettingsStore = defineStore("settings", () => {
|
||||
const isAiConfigLoaded = ref(false);
|
||||
const aiConfigs = ref<AiConfigItem[]>([]);
|
||||
const desktopSettings = ref<DesktopSettings>({ ...DEFAULT_DESKTOP_SETTINGS });
|
||||
const mcpGlobalPolicy = ref<McpGlobalPolicy>({ ...DEFAULT_MCP_GLOBAL_POLICY });
|
||||
const mcpGlobalPolicy = ref<McpGlobalPolicy>({
|
||||
...DEFAULT_MCP_GLOBAL_POLICY,
|
||||
});
|
||||
const isDesktopSettingsLoaded = ref(false);
|
||||
const isMcpGlobalPolicyLoaded = ref(false);
|
||||
const isEditorSettingsLoaded = ref(false);
|
||||
@@ -1119,7 +1170,10 @@ export const useSettingsStore = defineStore("settings", () => {
|
||||
const savedActive = savedSelection?.active;
|
||||
const savedConfig = savedActive ? aiConfigs.value.find((config) => config.id === savedActive.configId) : undefined;
|
||||
if (savedConfig && savedActive?.modelId.trim()) {
|
||||
activeModel.value = { configId: savedConfig.id, modelId: savedActive.modelId.trim() };
|
||||
activeModel.value = {
|
||||
configId: savedConfig.id,
|
||||
modelId: savedActive.modelId.trim(),
|
||||
};
|
||||
} else {
|
||||
const fallback = aiConfigs.value.find((config) => config.isDefault) || aiConfigs.value[0];
|
||||
activeModel.value = fallback?.model.trim() ? { configId: fallback.id, modelId: fallback.model.trim() } : null;
|
||||
@@ -1175,7 +1229,10 @@ export const useSettingsStore = defineStore("settings", () => {
|
||||
await api.saveAiConfigItem(normalized);
|
||||
aiConfigs.value.push(normalized);
|
||||
if (aiConfigs.value.length === 1 && normalized.model.trim()) {
|
||||
activeModel.value = { configId: normalized.id, modelId: normalized.model };
|
||||
activeModel.value = {
|
||||
configId: normalized.id,
|
||||
modelId: normalized.model,
|
||||
};
|
||||
persistAiChatSelection();
|
||||
}
|
||||
}
|
||||
@@ -1214,7 +1271,10 @@ export const useSettingsStore = defineStore("settings", () => {
|
||||
}
|
||||
|
||||
function updateActiveModel(model: { configId: string; modelId: string }) {
|
||||
activeModel.value = { configId: model.configId, modelId: model.modelId.trim() };
|
||||
activeModel.value = {
|
||||
configId: model.configId,
|
||||
modelId: model.modelId.trim(),
|
||||
};
|
||||
persistAiChatSelection();
|
||||
}
|
||||
|
||||
@@ -1412,7 +1472,9 @@ export const useSettingsStore = defineStore("settings", () => {
|
||||
}
|
||||
|
||||
function deleteCustomColumnFormatter(id: string) {
|
||||
const customColumnFormatters = { ...editorSettings.value.customColumnFormatters };
|
||||
const customColumnFormatters = {
|
||||
...editorSettings.value.customColumnFormatters,
|
||||
};
|
||||
delete customColumnFormatters[id];
|
||||
const columnFormatters = Object.fromEntries(
|
||||
Object.entries(editorSettings.value.columnFormatters).filter(([, formatter]) => {
|
||||
|
||||
Reference in new issue
Block a user