feat(ai): add skip TLS certificate verification for AI providers

This commit is contained in:
Resheba authored and GitHub committed 2026-09-05 14:03:58 +08:00
1 parent dca6d0e5f6
commit 54d7a2c05d
26 files changed
+111

No files matched your search

@@ -3524,6 +3524,7 @@ const aiEditApiStyle = ref<AiApiStyle>("completions");
const aiEditCustomHeaderRows = ref<AiHeaderRow[]>([]);
const aiEditProxyEnabled = ref(false);
const aiEditProxyUrl = ref("");
const aiEditSkipTlsVerify = ref(false);
const aiEditEnableThinking = ref(true);
const aiEditReasoningLevel = ref<AiReasoningLevel>("default");
const aiEditMaxOutputTokens = ref<number | undefined>(undefined);
@@ -3583,6 +3584,8 @@ const aiIsGrokCli = computed(() => aiEditProvider.value === "grok-cli");
const aiIsCodeBuddyCli = computed(() => aiEditProvider.value === "codebuddy-cli");
const aiIsQoderCli = computed(() => aiEditProvider.value === "qoder-cli");
const aiIsCliProvider = computed(() => CLI_AI_PROVIDERS.has(aiEditProvider.value));
const aiSupportsSkipTlsVerify = computed(() => aiEditProvider.value === "custom" || aiEditProvider.value === "openai-compatible" || aiEditProvider.value === "anthropic-compatible");
const aiCliProviderLabel = computed(() => selectedAiProviderPreset.value.label);
const aiCliCommandName = computed(() => {
if (aiIsClaudeCodeCli.value) return "claude";
@@ -3809,6 +3812,7 @@ function currentAiEditConfig() {
customHeaders: customHeadersFromRows(),
proxyEnabled: aiEditProxyEnabled.value,
proxyUrl: aiEditProxyUrl.value,
skipTlsVerify: aiSupportsSkipTlsVerify.value && aiEditSkipTlsVerify.value,
enableThinking: aiEditEnableThinking.value,
reasoningLevel: aiEditReasoningLevel.value,
maxOutputTokens: aiEditMaxOutputTokens.value || undefined,
@@ -3857,6 +3861,7 @@ function aiSelectProvider(presetId: string) {
aiEditLegacyModels.value = preset.group === "partner" ? [...(preset.models ?? [])] : [];
aiEditApiStyle.value = preset.apiStyle;
aiEditCustomHeaderRows.value = [];
aiEditSkipTlsVerify.value = false;
aiEditEnableThinking.value = true;
aiEditReasoningLevel.value = "default";
if (CLI_AI_PROVIDERS.has(provider)) void ensureCliMcpStatus();
@@ -3896,6 +3901,7 @@ function aiEnterEditMode(configId?: string) {
aiEditCustomHeaderRows.value = aiHeaderRowsFromConfig(config.customHeaders);
aiEditProxyEnabled.value = config.proxyEnabled ?? false;
aiEditProxyUrl.value = config.proxyUrl ?? "";
aiEditSkipTlsVerify.value = config.skipTlsVerify ?? false;
aiEditEnableThinking.value = config.enableThinking ?? true;
aiEditReasoningLevel.value = config.reasoningLevel ?? "default";
aiEditMaxOutputTokens.value = config.maxOutputTokens;
@@ -3930,6 +3936,7 @@ function aiEnterEditMode(configId?: string) {
aiEditCustomHeaderRows.value = [];
aiEditProxyEnabled.value = false;
aiEditProxyUrl.value = "";
aiEditSkipTlsVerify.value = false;
aiEditEnableThinking.value = true;
aiEditReasoningLevel.value = "default";
aiEditMaxOutputTokens.value = undefined;
@@ -7776,6 +7783,18 @@ LIMIT 100;</pre
<Label class="text-right text-xs">{{ t("ai.proxyUrl") }}</Label>
<Input v-model="aiEditProxyUrl" autocomplete="off" class="col-span-2" inputClass="h-8 text-xs" placeholder="socks5://127.0.0.1:7890" :disabled="!aiEditProxyEnabled" />
</div>
<!-- Skip TLS Verify -->
<div v-if="aiSupportsSkipTlsVerify" class="grid grid-cols-3 items-start gap-3">
<Label class="text-right text-xs">{{ t("ai.sslVerification") }}</Label>
<div class="col-span-2">
<label class="flex items-center gap-2 text-xs text-muted-foreground">
<input v-model="aiEditSkipTlsVerify" type="checkbox" class="h-4 w-4 shrink-0 accent-primary" />
{{ t("ai.skipTlsVerify") }}
</label>
<p class="mt-1 text-xs text-muted-foreground">{{ t("ai.skipTlsVerifyHint") }}</p>
</div>
</div>
</div>
</section>
@@ -53,6 +53,7 @@ function configSignature(config: AiConfigItem): string {
authMethod: config.authMethod,
apiStyle: config.apiStyle,
proxyEnabled: config.proxyEnabled ?? false,
skipTlsVerify: config.skipTlsVerify ?? false,
contextWindow: config.contextWindow ?? null,
codexCliPath: config.codexCliPath ?? null,
claudeCodeCliPath: config.claudeCodeCliPath ?? null,
+3
View File
@@ -2793,6 +2793,9 @@ export default {
proxy: "Proxy",
proxyEnable: "Send AI requests through proxy",
proxyUrl: "Proxy URL",
sslVerification: "SSL certificate",
skipTlsVerify: "Skip SSL certificate verification",
skipTlsVerifyHint: "Only skip for trusted endpoints with self-signed certificates. Skipping verification makes traffic vulnerable to interception.",
customHeaders: "Custom Headers",
customHeadersAdd: "Add header",
customHeadersHint: "Extra headers are sent with model discovery, connection tests, chat, and Agent requests. Header values may be sensitive.",
+3
View File
@@ -2864,6 +2864,9 @@ export default withEnglishFallback({
proxy: "Proxy",
proxyEnable: "Enviar solicitudes de IA mediante proxy",
proxyUrl: "URL del proxy",
sslVerification: "Certificado SSL",
skipTlsVerify: "Omitir la verificación del certificado SSL",
skipTlsVerifyHint: "Omite la verificación solo en endpoints de confianza con certificados autofirmados. Omitirla hace que el tráfico sea vulnerable a la interceptación.",
customHeaders: "Cabeceras personalizadas",
customHeadersAdd: "Añadir cabecera",
customHeadersHint: "Estas cabeceras se envían al descubrir modelos, probar la conexión, chatear y usar Agent. Sus valores pueden ser sensibles.",
+3
View File
@@ -2758,6 +2758,9 @@ export default withEnglishFallback({
proxy: "Proxy",
proxyEnable: "Invia richieste AI tramite proxy",
proxyUrl: "URL Proxy",
sslVerification: "Certificato SSL",
skipTlsVerify: "Salta la verifica del certificato SSL",
skipTlsVerifyHint: "Salta la verifica solo per endpoint attendibili con certificati autofirmati. Saltarla rende il traffico vulnerabile all'intercettazione.",
customHeaders: "Intestazioni personalizzate",
customHeadersAdd: "Aggiungi intestazione",
customHeadersHint: "Queste intestazioni vengono inviate durante la ricerca dei modelli, il test della connessione, la chat e le richieste Agent. I valori possono essere sensibili.",
+3
View File
@@ -2900,6 +2900,9 @@ export default withEnglishFallback({
proxy: "プロキシ",
proxyEnable: "プロキシ経由でAIリクエストを送信",
proxyUrl: "プロキシURL",
sslVerification: "SSL 証明書",
skipTlsVerify: "SSL 証明書の検証をスキップ",
skipTlsVerifyHint: "自己署名証明書を使用する信頼できるエンドポイントでのみスキップしてください。検証をスキップすると、トラフィックが傍受されやすくなります。",
customHeaders: "カスタムヘッダー",
customHeadersAdd: "ヘッダーを追加",
customHeadersHint: "モデル検出、接続テスト、チャット、Agent リクエストでこれらのヘッダーが送信されます。値には機密情報が含まれる場合があります。",
+3
View File
@@ -2609,6 +2609,9 @@ export default withEnglishFallback({
proxy: "프록시",
proxyEnable: "프록시를 통해 AI 요청 전송",
proxyUrl: "프록시 URL",
sslVerification: "SSL 인증서",
skipTlsVerify: "SSL 인증서 검증 건너뛰기",
skipTlsVerifyHint: "자체 서명 인증서를 사용하는 신뢰할 수 있는 엔드포인트에서만 건너뛰세요. 검증을 건너뛰면 트래픽이 가로채기에 취약해집니다.",
customHeaders: "사용자 지정 헤더",
customHeadersAdd: "헤더 추가",
customHeadersHint: "모델 검색, 연결 테스트, 채팅 및 Agent 요청에 이 헤더가 전송됩니다. 값에는 민감한 정보가 포함될 수 있습니다.",
+3
View File
@@ -2866,6 +2866,9 @@ export default withEnglishFallback({
proxy: "Proxy",
proxyEnable: "Enviar requisições de AI através do proxy",
proxyUrl: "URL do Proxy",
sslVerification: "Certificado SSL",
skipTlsVerify: "Ignorar verificação do certificado SSL",
skipTlsVerifyHint: "Ignore a verificação apenas em endpoints confiáveis com certificados autoassinados. Ignorá-la torna o tráfego vulnerável à interceptação.",
customHeaders: "Cabeçalhos personalizados",
customHeadersAdd: "Adicionar cabeçalho",
customHeadersHint: "Estes cabeçalhos são enviados na descoberta de modelos, teste de conexão, chat e solicitações do Agent. Os valores podem ser sensíveis.",
+3
View File
@@ -2716,6 +2716,9 @@ export default withEnglishFallback({
proxy: "代理",
proxyEnable: "AI 请求通过代理发送",
proxyUrl: "代理地址",
sslVerification: "SSL 证书",
skipTlsVerify: "跳过 SSL 证书校验",
skipTlsVerifyHint: "仅在目标端点使用自签名证书且可信时跳过。跳过校验会使流量面临中间人攻击风险。",
customHeaders: "自定义请求头",
customHeadersAdd: "添加请求头",
customHeadersHint: "模型发现、连接测试、对话和 Agent 请求都会携带这些请求头;值可能包含敏感信息。",
+3
View File
@@ -2757,6 +2757,9 @@ export default withEnglishFallback({
proxy: "代理伺服器",
proxyEnable: "經由代理伺服器發送 AI 請求",
proxyUrl: "代理伺服器地址",
sslVerification: "SSL 憑證",
skipTlsVerify: "略過 SSL 憑證驗證",
skipTlsVerifyHint: "僅在目標端點使用自簽憑證且可信時略過。略過驗證會使流量面臨中間人攻擊風險。",
customHeaders: "自訂請求標頭",
customHeadersAdd: "新增請求標頭",
customHeadersHint: "模型探索、連線測試、對話和 Agent 請求都會攜帶這些標頭;值可能包含敏感資訊。",
+1
View File
@@ -502,6 +502,7 @@ export function normalizeAiConfig(config: Partial<AiConfig> | null | undefined):
authMethod: config?.authMethod ?? defaultConfigs[provider].authMethod,
proxyEnabled: !!config?.proxyEnabled,
proxyUrl: config?.proxyUrl ?? "",
skipTlsVerify: !!config?.skipTlsVerify,
enableThinking: config?.enableThinking ?? true,
reasoningLevel: normalizeAiReasoningLevel(config?.reasoningLevel),
maxOutputTokens,
+2
View File
@@ -40,6 +40,8 @@ export interface AiConfig {
customHeaders?: Record<string, string>;
proxyEnabled?: boolean;
proxyUrl?: string;
/** Disable TLS certificate verification for the AI endpoint (self-signed/private CA only). */
skipTlsVerify?: boolean;
enableThinking?: boolean;
reasoningLevel?: AiReasoningLevel;
/** Optional per-configuration output budget sent as max_tokens/max_output_tokens. */