From 3e304f53d4fa43b393fd6541b4c407d0bd264562 Mon Sep 17 00:00:00 2001 From: wisdgod Date: Sat, 18 Jan 2025 04:19:55 +0800 Subject: [PATCH] v0.1.3-rc.3.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 限制 `TOKEN_DELIMITER` 为 ASCII 避免问题 --- .github/workflows/build.yml | 6 ++-- .github/workflows/docker.yml | 19 ++++++++---- Cargo.lock | 2 +- Cargo.toml | 2 +- Dockerfile | 4 +-- src/app/lazy.rs | 16 ++++++++-- src/common/utils.rs | 4 +-- static/api.html | 25 ++-------------- static/logs.html | 58 +++--------------------------------- static/shared.js | 19 +----------- 10 files changed, 43 insertions(+), 112 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d2868d7..e5b9d10 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,9 +2,9 @@ name: Build on: workflow_dispatch: - push: - tags: - - 'v*' + # push: + # tags: + # - 'v*' jobs: build: diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 3684641..49a1ba6 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -49,7 +49,7 @@ jobs: tags: | type=raw,value=latest,enable=${{ github.event_name == 'workflow_dispatch' && inputs.update_latest }} type=raw,value=${{ steps.cargo_version.outputs.version }},enable=${{ github.event_name == 'workflow_dispatch' }} - type=ref,event=tag,enable=${{ github.event_name == 'push' }} + type=raw,value=${{ github.ref_name }},enable=${{ github.event_name == 'push' }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3.8.0 @@ -70,17 +70,24 @@ jobs: labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max - outputs: type=local,dest=./dist,enable=${{ github.event_name == 'workflow_dispatch' && inputs.upload_artifacts }} + outputs: type=local,dest=./dist,enable=${{ (github.event_name == 'workflow_dispatch' && inputs.upload_artifacts) || github.event_name == 'push'}} - name: Prepare artifacts if: github.event_name == 'workflow_dispatch' && inputs.upload_artifacts run: | - mkdir -p artifacts/amd64 artifacts/arm64 - cp dist/linux_amd64/app/cursor-api artifacts/amd64/ - cp dist/linux_arm64/app/cursor-api artifacts/arm64/ + mkdir -p artifacts + cp dist/linux_amd64/app/cursor-api artifacts/cursor-api-x86_64-${{ steps.cargo_version.outputs.version }} + cp dist/linux_arm64/app/cursor-api artifacts/cursor-api-aarch64-${{ steps.cargo_version.outputs.version }} + + - name: Prepare artifacts + if: github.event_name == 'push' + run: | + mkdir -p artifacts + cp dist/linux_amd64/app/cursor-api artifacts/cursor-api-x86_64-${{ github.event_name }} + cp dist/linux_arm64/app/cursor-api artifacts/cursor-api-aarch64-${{ github.event_name }} - name: Upload artifacts - if: github.event_name == 'workflow_dispatch' && inputs.upload_artifacts + if: (github.event_name == 'workflow_dispatch' && inputs.upload_artifacts) || github.event_name == 'push' uses: actions/upload-artifact@v4.6.0 with: name: cursor-api-binaries diff --git a/Cargo.lock b/Cargo.lock index 11740a7..2e9f779 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -327,7 +327,7 @@ dependencies = [ [[package]] name = "cursor-api" -version = "0.1.3-rc.3.2" +version = "0.1.3-rc.3.3" dependencies = [ "axum", "base64", diff --git a/Cargo.toml b/Cargo.toml index 518df74..b9577e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cursor-api" -version = "0.1.3-rc.3.2" +version = "0.1.3-rc.3.3" edition = "2021" authors = ["wisdgod "] description = "OpenAI format compatibility layer for the Cursor API" diff --git a/Dockerfile b/Dockerfile index 75a927c..012409b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # AMD64 构建阶段 -FROM --platform=linux/amd64 rust:1.83.0-slim-bookworm as builder-amd64 +FROM --platform=linux/amd64 rust:1.84.0-slim-bookworm as builder-amd64 WORKDIR /app RUN apt-get update && \ apt-get install -y --no-install-recommends \ @@ -11,7 +11,7 @@ RUN cargo build --release && \ cp target/release/cursor-api /app/cursor-api # ARM64 构建阶段 -FROM --platform=linux/arm64 rust:1.83.0-slim-bookworm as builder-arm64 +FROM --platform=linux/arm64 rust:1.84.0-slim-bookworm as builder-arm64 WORKDIR /app RUN apt-get update && \ apt-get install -y --no-install-recommends \ diff --git a/src/app/lazy.rs b/src/app/lazy.rs index 66c1756..c3cb7bf 100644 --- a/src/app/lazy.rs +++ b/src/app/lazy.rs @@ -3,7 +3,7 @@ use crate::{ CURSOR_API2_HOST, CURSOR_HOST, DEFAULT_TOKEN_FILE_NAME, DEFAULT_TOKEN_LIST_FILE_NAME, EMPTY_STRING, }, - common::utils::{parse_char_from_env, parse_string_from_env}, + common::utils::{parse_ascii_char_from_env, parse_string_from_env}, }; use std::sync::LazyLock; @@ -55,8 +55,18 @@ def_pub_static!(SHARED_AUTH_TOKEN, env: "SHARED_AUTH_TOKEN", default: EMPTY_STRI pub static USE_SHARE: LazyLock = LazyLock::new(|| !SHARED_AUTH_TOKEN.is_empty()); -pub static TOKEN_DELIMITER: LazyLock = - LazyLock::new(|| parse_char_from_env("TOKEN_DELIMITER", ',')); +pub static TOKEN_DELIMITER: LazyLock = LazyLock::new(|| { + let delimiter = parse_ascii_char_from_env("TOKEN_DELIMITER", ','); + if delimiter.is_ascii_alphabetic() + || delimiter.is_ascii_digit() + || delimiter == '+' + || delimiter == '/' + { + ',' + } else { + delimiter + } +}); pub static TOKEN_DELIMITER_LEN: LazyLock = LazyLock::new(|| TOKEN_DELIMITER.len_utf8()); diff --git a/src/common/utils.rs b/src/common/utils.rs index d14b4cc..bbe20c8 100644 --- a/src/common/utils.rs +++ b/src/common/utils.rs @@ -24,12 +24,12 @@ pub fn parse_string_from_env(key: &str, default: &str) -> String { std::env::var(key).unwrap_or_else(|_| default.to_string()) } -pub fn parse_char_from_env(key: &str, default: char) -> char { +pub fn parse_ascii_char_from_env(key: &str, default: char) -> char { std::env::var(key) .ok() .and_then(|v| { let chars: Vec = v.chars().collect(); - if chars.len() == 1 { + if chars.len() == 1 && chars[0].is_ascii() { Some(chars[0]) } else { None diff --git a/static/api.html b/static/api.html index 69cd63c..5228d64 100644 --- a/static/api.html +++ b/static/api.html @@ -307,24 +307,13 @@ // 添加用户基本信息 if (tokenInfo.user || calibInfo) { const user = tokenInfo.user || {}; - userDetails.innerHTML += ` -

用户ID: ${calibInfo ? calibInfo.user_id : user.id}

-

邮箱: ${user.email || ''}

-

用户名: ${user.name || ''}

- ${user.updated_at ? `

更新时间: ${new Date(user.updated_at).toLocaleString()}

` : ''} - ${calibInfo ? `

令牌创建时间: ${new Date(calibInfo.create_at).toLocaleString()}

` : ''} - ${calibInfo && calibInfo.checksum_time ? `

校验和时间区间: ${new Date(calibInfo.checksum_time * 1e6).toLocaleString()} - ${new Date((calibInfo.checksum_time + 1) * 1e6 - 1).toLocaleString()}

` : ''} - `; + userDetails.innerHTML += `

用户ID: ${calibInfo ? calibInfo.user_id : user.id}

邮箱: ${user.email || ''}

用户名: ${user.name || ''}

${user.updated_at ? `

更新时间: ${new Date(user.updated_at).toLocaleString()}

` : ''}${calibInfo ? `

令牌创建时间: ${new Date(calibInfo.create_at).toLocaleString()}

` : ''}${calibInfo && calibInfo.checksum_time ? `

校验和时间区间: ${new Date(calibInfo.checksum_time * 1e6).toLocaleString()} - ${new Date((calibInfo.checksum_time + 1) * 1e6 - 1).toLocaleString()}

` : ''}`; } // 添加 Stripe 会员信息 if (tokenInfo.stripe) { const stripe = tokenInfo.stripe; - userDetails.innerHTML += ` -

会员类型: ${stripe.membership_type}

- ${stripe.payment_id ? `

付款 ID: ${stripe.payment_id}

` : ''} -

试用剩余: ${stripe.days_remaining_on_trial} 天

- `; + userDetails.innerHTML += `

会员类型: ${stripe.membership_type}

${stripe.payment_id ? `

付款 ID: ${stripe.payment_id}

` : ''}

试用剩余: ${stripe.days_remaining_on_trial} 天

`; } // 添加使用情况进度条 @@ -342,15 +331,7 @@ const percentage = isUnlimited ? 100 : (data.requests / data.max_requests * 100).toFixed(1); const progressClass = isUnlimited ? 'unlimited' : getProgressBarClass(parseFloat(percentage)); - progressContainer.innerHTML += ` -
-

${modelName}: ${data.requests}/${isUnlimited ? '∞' : data.max_requests} 请求 - ${isUnlimited ? '' : `(${percentage}%)`}, ${data.tokens} tokens

-
-
-
-
- `; + progressContainer.innerHTML += `

${modelName}: ${data.requests}/${isUnlimited ? '∞' : data.max_requests} 请求 ${isUnlimited ? '' : `(${percentage}%)`}, ${data.tokens} tokens

`; } }); } diff --git a/static/logs.html b/static/logs.html index e3526fa..f8d528c 100644 --- a/static/logs.html +++ b/static/logs.html @@ -584,9 +584,7 @@ const progressDiv = document.createElement('div'); progressDiv.className = 'usage-progress-container'; const colorClass = getProgressBarClass(parseFloat(percentage)); - progressDiv.innerHTML = ` -
- `; + progressDiv.innerHTML = `
`; container.appendChild(progressDiv); } else { element.textContent = `${requests} requests, ${tokens} tokens`; @@ -629,54 +627,14 @@ ['Premium', premiumUsage] ]; - return rows.map(([label, value]) => ` -
- ${label}: - ${value} -
- `).join(''); + return rows.map(([label, value]) => `
${label}:${value}
`).join(''); } function updateTable(data) { const tbody = document.getElementById('logsBody'); updateStats(data); - tbody.innerHTML = data.logs.map(log => ` - - ${log.id} - ${new Date(log.timestamp).toLocaleString()} - ${log.model} - -
- -
- - - ${log.prompt ? - `
- -
` : - '-' - } - - - ${formatTiming(log.timing.total, log.timing.first)} - - ${log.stream ? '是' : '否'} - ${log.status} - ${log.error || '-'} - - `).join(''); + tbody.innerHTML = data.logs.map(log => `${log.id}${new Date(log.timestamp).toLocaleString()}${log.model}
${log.prompt ?`
` :'-'}${formatTiming(log.timing.total, log.timing.first)}${log.stream ? '是' : '否'}${log.status}${log.error || '-'}`).join(''); } function formatTiming(total, first) { @@ -700,15 +658,7 @@ 'assistant': '助手' }; - return ` -
最后一条消息 (${roleLabels[lastMessage.role] || lastMessage.role}):
-
${lastMessage.content - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/\n/g, '
') - }
- `; + return `
最后一条消息 (${roleLabels[lastMessage.role] || lastMessage.role}):
${lastMessage.content.replace(/&/g, '&').replace(//g, '>').replace(/\n/g, '
')}
`; } catch (e) { console.error('预览对话内容失败:', e); return '无法解析对话内容'; diff --git a/static/shared.js b/static/shared.js index 1628e1b..5cf6974 100644 --- a/static/shared.js +++ b/static/shared.js @@ -214,24 +214,7 @@ function formatPromptToTable(messages) { return escaped; } - return ` - - - - - - - - - ${messages.map(msg => ` - - - - - `).join('')} - -
角色内容
${roleLabels[msg.role] || msg.role}${escapeHtml(msg.content).replace(/\n/g, '
')}
- `; + return `${messages.map(msg => ``).join('')}
角色内容
${roleLabels[msg.role] || msg.role}${escapeHtml(msg.content).replace(/\n/g, '
')}
`; } /**