ci: auto build & obfuscate [2026-04-23 00:35:57] (Jenkins #17)

This commit is contained in:
Jenkins CI
2026-04-23 00:35:57 +08:00
parent 8d590073f4
commit 544937bb91
23 changed files with 160 additions and 84 deletions

View File

@@ -179,9 +179,12 @@ class Amily2Updater {
if (this.compareVersions(this.latestVersion, this.currentVersion) > 0) {
$updateIndicator.show();
$updateButton.attr('title', `发现新版本 ${this.latestVersion}!点击查看详情`);
const safeVersion = /^[\w.+\-]{1,40}$/.test(String(this.latestVersion ?? '')) ? this.latestVersion : '未知';
$updateButtonNew
.show()
.html(`<i class="fas fa-gift"></i> 新版 ${this.latestVersion}`)
.empty()
.append($('<i>').addClass('fas fa-gift'))
.append(document.createTextNode(` 新版 ${safeVersion}`))
.off('click')
.on('click', () => this.showUpdateConfirmDialog());
} else {

View File

@@ -330,10 +330,12 @@ async function fetchGoogleDirectModels(apiUrl, apiKey) {
const GOOGLE_API_BASE_URL = 'https://generativelanguage.googleapis.com';
const fetchGoogleModels = async (version) => {
const url = `${GOOGLE_API_BASE_URL}/${version}/models?key=${apiKey}`;
const url = `${GOOGLE_API_BASE_URL}/${version}/models`;
console.log(`[Amily2号-使节团] 正在从 Google API (${version}) 获取模型列表: ${url}`);
const response = await fetch(url);
const response = await fetch(url, {
headers: { 'x-goog-api-key': apiKey },
});
if (!response.ok) {
console.warn(`获取 Google API (${version}) 模型列表失败: ${response.status}`);
return [];
@@ -745,12 +747,13 @@ async function callGoogleDirect(messages, options) {
const GOOGLE_API_BASE_URL = 'https://generativelanguage.googleapis.com';
const apiVersion = options.model.includes('gemini-1.5') ? 'v1beta' : 'v1';
const finalApiUrl = `${GOOGLE_API_BASE_URL}/${apiVersion}/models/${options.model}:generateContent?key=${options.apiKey}`;
const finalApiUrl = `${GOOGLE_API_BASE_URL}/${apiVersion}/models/${options.model}:generateContent`;
console.log(`[Amily2号-Google直连] API地址: ${finalApiUrl}`);
const headers = {
"Content-Type": "application/json"
const headers = {
"Content-Type": "application/json",
"x-goog-api-key": options.apiKey,
};
const requestBody = JSON.stringify(convertToGoogleRequest({

View File

@@ -485,7 +485,8 @@ Example:
.replace(/<\/thinking>/gi, '');
const toolNames = Object.keys(tools);
const toolRegex = new RegExp(`<(${toolNames.join('|')})(?:\\s+[^>]*)?>[\\s\\S]*?<\\/\\1>`, 'gi');
const escapedToolNames = toolNames.map(n => String(n).replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
const toolRegex = new RegExp(`<(${escapedToolNames.join('|')})(?:\\s+[^>]*)?>[\\s\\S]*?<\\/\\1>`, 'gi');
cleanContent = cleanContent.replace(toolRegex, '').trim();
if (cleanContent) {

View File

@@ -112,9 +112,11 @@ export async function fetchEmbeddingModels(overrideSettings = null) {
if (!apiKey) throw new Error("Google直连模式需要API Key。");
const fetchGoogleModels = async (version) => {
const url = `${GOOGLE_API_BASE_URL}/${version}/models?key=${apiKey}`;
const url = `${GOOGLE_API_BASE_URL}/${version}/models`;
console.log(`[翰林院] 正在从 Google API (${version}) 获取模型列表: ${url}`);
const response = await fetch(url);
const response = await fetch(url, {
headers: { 'x-goog-api-key': apiKey },
});
if (!response.ok) {
console.warn(`获取 Google API (${version}) 模型列表失败: ${response.status}`);
return [];
@@ -345,8 +347,8 @@ export async function getEmbeddings(texts, signal = null) {
console.log('[翰林院-API] 使用Google直连模式获取向量。');
if (!apiKey) throw new Error('Google直连模式需要API Key。');
// 使用适配器构建URL和请求体
const googleUrl = `${buildGoogleEmbeddingApiUrl(GOOGLE_API_BASE_URL, embeddingModel)}?key=${apiKey}`;
// 使用适配器构建URL和请求体Key 通过 x-goog-api-key 头传递避免 URL 泄露
const googleUrl = buildGoogleEmbeddingApiUrl(GOOGLE_API_BASE_URL, embeddingModel);
const googleBody = buildGoogleEmbeddingRequest(batch, embeddingModel);
console.log(`[翰林院-API] 发送到 Google API 的请求 URL: ${googleUrl}`);
@@ -356,6 +358,7 @@ export async function getEmbeddings(texts, signal = null) {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-goog-api-key': apiKey,
},
body: JSON.stringify(googleBody),
signal: signal,

View File

@@ -80,12 +80,23 @@ function containsPinyinMatch(text, query) {
function highlightSearchMatch(text, query) {
const safeText = String(text ?? '')
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
if (!query || !query.trim()) {
return text;
return safeText;
}
const regex = new RegExp(`(${query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
return text.replace(regex, '<mark class="search-highlight">$1</mark>');
const safeQuery = String(query)
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
const regex = new RegExp(`(${safeQuery.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
return safeText.replace(regex, '<mark class="search-highlight">$1</mark>');
}
function debounce(func, wait) {

View File

@@ -137,7 +137,12 @@ export function progressTracker(operationId, maxAttempts) {
container.style.backgroundColor = 'rgba(80,0,0,0.9)';
progress.style.display = 'none';
info.style.whiteSpace = 'pre-wrap';
info.innerHTML = `<span style="color:#ff9494">错误详情:</span>\n${errorMsg}`;
info.innerHTML = '';
const label = document.createElement('span');
label.style.color = '#ff9494';
label.textContent = '错误详情:';
info.appendChild(label);
info.appendChild(document.createTextNode('\n' + String(errorMsg ?? '')));
}
};
}