修复arm的问题

This commit is contained in:
wisdgod
2025-01-29 14:47:59 +08:00
parent 6c982483d5
commit fb0de13712
8 changed files with 114 additions and 56 deletions

View File

@@ -25,33 +25,26 @@ jobs:
run: | run: |
RUSTFLAGS="-C link-arg=-s -C target-cpu=x86-64-v3" \ RUSTFLAGS="-C link-arg=-s -C target-cpu=x86-64-v3" \
cargo build --release --target x86_64-apple-darwin cargo build --release --target x86_64-apple-darwin
mv target/x86_64-apple-darwin/release/cursor-api cursor-api-x86_64-apple-darwin
- name: Build arm64 binary - name: Build arm64 binary
run: | run: |
RUSTFLAGS="-C link-arg=-s -C target-cpu=apple-m1" \ RUSTFLAGS="-C link-arg=-s -C target-cpu=apple-m1" \
cargo build --release --target aarch64-apple-darwin cargo build --release --target aarch64-apple-darwin
mv target/aarch64-apple-darwin/release/cursor-api cursor-api-aarch64-apple-darwin
- name: Create universal binary - name: Create universal binary
run: | run: |
lipo -create \ lipo -create \
target/x86_64-apple-darwin/release/cursor-api \ cursor-api-x86_64-apple-darwin \
target/aarch64-apple-darwin/release/cursor-api \ cursor-api-aarch64-apple-darwin \
-output target/cursor-api-universal -output cursor-api-universal-apple-darwin
- name: Upload x86_64 artifact - name: Upload artifacts
uses: actions/upload-artifact@v4.6.0 uses: actions/upload-artifact@v4.6.0
with: with:
name: cursor-api-x86_64-apple-darwin name: cursor-api-darwin
path: target/x86_64-apple-darwin/release/cursor-api path: |
cursor-api-x86_64-apple-darwin
- name: Upload arm64 artifact cursor-api-aarch64-apple-darwin
uses: actions/upload-artifact@v4.6.0 cursor-api-universal-apple-darwin
with:
name: cursor-api-aarch64-apple-darwin
path: target/aarch64-apple-darwin/release/cursor-api
- name: Upload universal artifact
uses: actions/upload-artifact@v4.6.0
with:
name: cursor-api-universal-apple-darwin
path: target/cursor-api-universal

1
.gitignore vendored
View File

@@ -23,3 +23,4 @@ node_modules
/build* /build*
/*.bin /*.bin
/result.txt /result.txt
tools/tokenizer/

2
Cargo.lock generated
View File

@@ -361,7 +361,7 @@ dependencies = [
[[package]] [[package]]
name = "cursor-api" name = "cursor-api"
version = "0.1.3-rc.4.2" version = "0.1.3-rc.4.3"
dependencies = [ dependencies = [
"axum", "axum",
"base64", "base64",

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "cursor-api" name = "cursor-api"
version = "0.1.3-rc.4.2" version = "0.1.3-rc.4.3"
edition = "2021" edition = "2021"
authors = ["wisdgod <nav@wisdgod.com>"] authors = ["wisdgod <nav@wisdgod.com>"]
description = "OpenAI format compatibility layer for the Cursor API" description = "OpenAI format compatibility layer for the Cursor API"

View File

@@ -1,49 +1,36 @@
# AMD64 构建阶段 ARG TARGETARCH
FROM --platform=linux/amd64 rust:1.84.0-slim-bookworm as builder-amd64 FROM --platform=linux/${TARGETARCH} rust:1.84.0-slim-bookworm as builder
ARG TARGETARCH
WORKDIR /app WORKDIR /app
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y --no-install-recommends \ apt-get install -y --no-install-recommends \
build-essential protobuf-compiler pkg-config libssl-dev nodejs npm openssl \ build-essential protobuf-compiler pkg-config libssl-dev nodejs npm openssl \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
COPY . . COPY . .
ENV RUSTFLAGS="-C link-arg=-s -C target-cpu=x86-64-v3" RUN case "$TARGETARCH" in \
RUN cargo build --release && \ amd64) TARGET_CPU="x86-64-v3" ;; \
arm64) TARGET_CPU="neoverse-n1" ;; \
*) echo "Unsupported architecture: $TARGETARCH" && exit 1 ;; \
esac && \
RUSTFLAGS="-C link-arg=-s -C target-cpu=$TARGET_CPU" cargo build --release && \
cp target/release/cursor-api /app/cursor-api cp target/release/cursor-api /app/cursor-api
# ARM64 构建阶段 # 运行阶段
FROM --platform=linux/arm64 rust:1.84.0-slim-bookworm as builder-arm64 FROM --platform=linux/${TARGETARCH} debian:bookworm-slim
WORKDIR /app
RUN apt-get update && \
apt-get install -y --no-install-recommends \
build-essential protobuf-compiler pkg-config libssl-dev nodejs npm openssl \
&& rm -rf /var/lib/apt/lists/*
COPY . .
ENV RUSTFLAGS="-C link-arg=-s -C target-cpu=apple-m1"
RUN cargo build --release && \
cp target/release/cursor-api /app/cursor-api
# AMD64 运行阶段
FROM --platform=linux/amd64 debian:bookworm-slim as run-amd64
WORKDIR /app WORKDIR /app
ENV TZ=Asia/Shanghai ENV TZ=Asia/Shanghai
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y --no-install-recommends \ apt-get install -y --no-install-recommends \
ca-certificates tzdata openssl \ ca-certificates tzdata openssl \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
COPY --from=builder-amd64 /app/cursor-api .
# ARM64 运行阶段 COPY --from=builder /app/cursor-api .
FROM --platform=linux/arm64 debian:bookworm-slim as run-arm64
WORKDIR /app
ENV TZ=Asia/Shanghai
RUN apt-get update && \
apt-get install -y --no-install-recommends \
ca-certificates tzdata openssl \
&& rm -rf /var/lib/apt/lists/*
COPY --from=builder-arm64 /app/cursor-api .
# 通用配置
FROM run-${TARGETARCH}
ENV PORT=3000 ENV PORT=3000
EXPOSE ${PORT} EXPOSE ${PORT}
CMD ["./cursor-api"] CMD ["./cursor-api"]

View File

@@ -730,7 +730,7 @@ pub async fn handle_chat(
index: 0, index: 0,
message: Some(Message { message: Some(Message {
role: Role::Assistant, role: Role::Assistant,
content: MessageContent::Text(full_text), content: MessageContent::Text(full_text.trim_leading_newlines()),
}), }),
delta: None, delta: None,
finish_reason: Some(FINISH_REASON_STOP.to_string()), finish_reason: Some(FINISH_REASON_STOP.to_string()),

View File

@@ -55,11 +55,13 @@ pub trait TrimNewlines {
impl TrimNewlines for String { impl TrimNewlines for String {
#[inline(always)] #[inline(always)]
fn trim_leading_newlines(mut self) -> Self { fn trim_leading_newlines(mut self) -> Self {
if self.as_bytes().get(..2) == Some(b"\n\n".as_slice()) { let bytes = self.as_bytes();
if bytes.len() >= 2 && bytes[0] == b'\n' && bytes[1] == b'\n' {
unsafe { unsafe {
let vec = self.as_mut_vec(); let start_ptr = self.as_mut_ptr();
vec.copy_within(2.., 0); let new_len = self.len() - 2;
vec.truncate(vec.len() - 2); std::ptr::copy(start_ptr.add(2), start_ptr, new_len);
self.as_mut_vec().set_len(new_len);
} }
} }
self self

View File

@@ -91,7 +91,8 @@
/* 操作按钮样式 */ /* 操作按钮样式 */
.action-cell { .action-cell {
width: 100px; width: 160px;
/* 增加宽度以容纳两个按钮 */
text-align: center !important; text-align: center !important;
} }
@@ -99,6 +100,8 @@
padding: 2px 8px; padding: 2px 8px;
font-size: 12px; font-size: 12px;
white-space: nowrap; white-space: nowrap;
margin: 0 2px;
/* 添加按钮间距 */
} }
/* 提示框样式 */ /* 提示框样式 */
@@ -256,6 +259,21 @@
.model-item input[type="checkbox"] { .model-item input[type="checkbox"] {
margin-right: 8px; margin-right: 8px;
} }
/* 确认对话框的额外样式 */
#confirmModal {
max-width: 400px;
}
#confirmModal .modal-content {
margin: 20px 0;
text-align: center;
}
#confirmModal .modal-footer button {
min-width: 80px;
margin-left: 10px;
}
</style> </style>
</head> </head>
@@ -368,6 +386,21 @@
</div> </div>
</div> </div>
<!-- 添加确认对话框 -->
<div class="modal-backdrop" id="confirmModal-backdrop"></div>
<div class="modal" id="confirmModal">
<div class="modal-header">
<h3>确认删除</h3>
</div>
<div class="modal-content">
<p>确定要删除这个token吗</p>
</div>
<div class="modal-footer">
<button onclick="closeConfirmModal()" class="secondary">取消</button>
<button onclick="confirmDelete()" class="danger">删除</button>
</div>
</div>
<script> <script>
async function getTokenInfo() { async function getTokenInfo() {
const data = await makeAuthenticatedRequest('/tokens/get'); const data = await makeAuthenticatedRequest('/tokens/get');
@@ -380,7 +413,7 @@
const usage = profile.usage || {}; const usage = profile.usage || {};
const premium = usage.premium || {}; const premium = usage.premium || {};
return `<tr><td title="${t.token}">${t.token}</td><td title="${t.checksum}">${t.checksum}</td><td>${user.email || '-'}</td><td>${formatMembershipType(stripe.membership_type)}</td><td>${premium.requests || 0}/${premium.max_requests || '∞'}</td><td>${stripe.days_remaining_on_trial > 0 ? `${stripe.days_remaining_on_trial}` : '-'}</td><td class="action-cell"><button onclick="showKeyModal('${t.token}','${t.checksum}')" class="secondary">生成Key</button></td></tr>`; return `<tr><td title="${t.token}">${t.token}</td><td title="${t.checksum}">${t.checksum}</td><td>${user.email || '-'}</td><td>${formatMembershipType(stripe.membership_type)}</td><td>${premium.requests || 0}/${premium.max_requests || '∞'}</td><td>${stripe.days_remaining_on_trial > 0 ? `${stripe.days_remaining_on_trial}` : '-'}</td><td class="action-cell"><button onclick="showKeyModal('${t.token}','${t.checksum}')" class="secondary">生成Key</button><button onclick="deleteToken('${t.token}')" class="danger">删除</button></td></tr>`;
}).join(''); }).join('');
showGlobalMessage('配置获取成功'); showGlobalMessage('配置获取成功');
} }
@@ -477,6 +510,48 @@
} }
} }
// 添加删除单个token的函数
let tokenToDelete = null;
function showConfirmModal(token) {
tokenToDelete = token;
const modal = document.getElementById('confirmModal');
const backdrop = document.getElementById('confirmModal-backdrop');
modal.style.display = 'block';
backdrop.style.display = 'block';
}
function closeConfirmModal() {
const modal = document.getElementById('confirmModal');
const backdrop = document.getElementById('confirmModal-backdrop');
modal.style.display = 'none';
backdrop.style.display = 'none';
tokenToDelete = null;
}
async function confirmDelete() {
if (!tokenToDelete) return;
const data = await makeAuthenticatedRequest('/tokens/delete', {
body: JSON.stringify({
tokens: [tokenToDelete],
expectation: 'detailed'
})
});
if (data) {
showGlobalMessage('Token删除成功');
getTokenInfo();
}
closeConfirmModal();
}
// 修改deleteToken函数
function deleteToken(token) {
showConfirmModal(token);
}
// 动态key相关函数 // 动态key相关函数
let availableModels = []; let availableModels = [];
let currentToken = ''; let currentToken = '';