mirror of
https://github.com/wisdgod/cursor-api.git
synced 2025-10-16 11:40:38 +08:00
修复arm的问题
This commit is contained in:
29
.github/workflows/build-darwin.yml
vendored
29
.github/workflows/build-darwin.yml
vendored
@@ -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
1
.gitignore
vendored
@@ -23,3 +23,4 @@ node_modules
|
|||||||
/build*
|
/build*
|
||||||
/*.bin
|
/*.bin
|
||||||
/result.txt
|
/result.txt
|
||||||
|
tools/tokenizer/
|
||||||
|
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -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",
|
||||||
|
@@ -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"
|
||||||
|
45
Dockerfile
45
Dockerfile
@@ -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"]
|
@@ -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()),
|
||||||
|
@@ -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
|
||||||
|
@@ -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 = '';
|
||||||
|
Reference in New Issue
Block a user