Full internal rename: metapi → boosapi
Rename all remaining internal protocol identifiers: - x-metapi-* headers → x-boosapi-* - metapi: reasoning prefix → boosapi: - __metapi* runtime markers → __boosapi* - file-metapi-* → file-boosapi-* - METAPI_* env vars → BOOSAPI_* - metapi_turn_state/metapi_mcp_item__ etc. → boosapi_* - package.json name → boosapi - Docker/deploy/k3s/docs references 46 files changed, 168 insertions, 170 deletions. typecheck:web passes (0 new errors). Signed-off-by: Boos4721 <boos4721@icloud.com>
This commit is contained in:
+2
-2
@@ -25,7 +25,7 @@ Metapi 是 AI API 聚合平台(New API、One API、OneHub 等)的元聚合
|
||||
|
||||
```bash
|
||||
git clone https://github.com/YOUR_USERNAME/metapi.git
|
||||
cd metapi
|
||||
cd boosapi
|
||||
```
|
||||
|
||||
2. **Install dependencies** / **安装依赖**
|
||||
@@ -213,7 +213,7 @@ If you're adding support for a new AI API platform / 如果您要添加对新 AI
|
||||
|
||||
## Getting Help / 获取帮助
|
||||
|
||||
- 📖 [Documentation](https://metapi.cita777.me) / [文档](https://metapi.cita777.me)
|
||||
- 📖 [Documentation](https://boosapi.cita777.me) / [文档](https://boosapi.cita777.me)
|
||||
- 💬 [GitHub Discussions](https://github.com/cita-777/metapi/discussions) / [GitHub 讨论区](https://github.com/cita-777/metapi/discussions)
|
||||
- 🐛 [Issue Tracker](https://github.com/cita-777/metapi/issues) / [Issue 跟踪](https://github.com/cita-777/metapi/issues)
|
||||
|
||||
|
||||
+13
-13
@@ -37,8 +37,8 @@ RUN python3 -m venv venv \
|
||||
ENV PATH="/app/comfy/venv/bin:${PATH}"
|
||||
|
||||
# ========== Metapi ==========
|
||||
FROM base AS metapi
|
||||
WORKDIR /app/metapi
|
||||
FROM base AS boosapi
|
||||
WORKDIR /app/boosapi
|
||||
COPY . .
|
||||
RUN npm install
|
||||
RUN npm run build --if-present
|
||||
@@ -56,15 +56,15 @@ RUN apt-get update && apt-get install -y \
|
||||
COPY --from=rtk-builder /usr/local/bin/rtk /usr/local/bin/rtk
|
||||
COPY --from=comfyui /app/comfy /app/comfy
|
||||
COPY --from=comfyui /app/comfy/venv /app/comfy/venv
|
||||
COPY --from=metapi /app/metapi /app/metapi
|
||||
COPY --from=metapi /usr/lib/node_modules /usr/lib/node_modules
|
||||
COPY --from=boosapi /app/boosapi /app/boosapi
|
||||
COPY --from=boosapi /usr/lib/node_modules /usr/lib/node_modules
|
||||
|
||||
# Node path
|
||||
ENV PATH="/app/comfy/venv/bin:/usr/local/bin:${PATH}"
|
||||
ENV COMFYUI_BASE=http://127.0.0.1:8188
|
||||
ENV AUTH_TOKEN=change-me-admin-token
|
||||
|
||||
WORKDIR /app/metapi
|
||||
WORKDIR /app/boosapi
|
||||
|
||||
# Supervisor config
|
||||
RUN mkdir -p /var/log/supervisor
|
||||
@@ -75,19 +75,19 @@ user=root
|
||||
logfile=/var/log/supervisor/supervisord.log
|
||||
pidfile=/tmp/supervisord.pid
|
||||
|
||||
[program:metapi-server]
|
||||
[program:boosapi-server]
|
||||
command=npm run dev:server
|
||||
directory=/app/metapi
|
||||
directory=/app/boosapi
|
||||
autorestart=true
|
||||
stdout_logfile=/var/log/supervisor/metapi-server.log
|
||||
stderr_logfile=/var/log/supervisor/metapi-server.err
|
||||
stdout_logfile=/var/log/supervisor/boosapi-server.log
|
||||
stderr_logfile=/var/log/supervisor/boosapi-server.err
|
||||
|
||||
[program:metapi-web]
|
||||
[program:boosapi-web]
|
||||
command=npx vite --host 0.0.0.0 --port 5173
|
||||
directory=/app/metapi
|
||||
directory=/app/boosapi
|
||||
autorestart=true
|
||||
stdout_logfile=/var/log/supervisor/metapi-web.log
|
||||
stderr_logfile=/var/log/supervisor/metapi-web.err
|
||||
stdout_logfile=/var/log/supervisor/boosapi-web.log
|
||||
stderr_logfile=/var/log/supervisor/boosapi-web.err
|
||||
|
||||
[program:comfyui]
|
||||
command=python3 main.py --listen 0.0.0.0 --port 8188
|
||||
|
||||
@@ -158,7 +158,7 @@ mkdir boosapi && cd boosapi
|
||||
cat > docker-compose.yml << 'EOF'
|
||||
services:
|
||||
boosapi:
|
||||
image: 1467078763/metapi:latest
|
||||
image: 1467078763/boosapi:latest
|
||||
ports:
|
||||
- "4000:4000"
|
||||
volumes:
|
||||
|
||||
+1
-1
@@ -147,7 +147,7 @@ mkdir boosapi && cd boosapi
|
||||
cat > docker-compose.yml << 'EOF'
|
||||
services:
|
||||
boosapi:
|
||||
image: 1467078763/metapi:latest
|
||||
image: 1467078763/boosapi:latest
|
||||
ports:
|
||||
- "4000:4000"
|
||||
volumes:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
apiVersion: v2
|
||||
name: metapi
|
||||
description: Minimal metapi chart for digest-aware k3s update-center setups
|
||||
name: boosapi
|
||||
description: Minimal boosapi chart for digest-aware k3s update-center setups
|
||||
type: application
|
||||
version: 0.1.0
|
||||
appVersion: "1.3.0"
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "metapi.fullname" . }}
|
||||
name: {{ include "boosapi.fullname" . }}
|
||||
labels:
|
||||
{{- include "metapi.labels" . | nindent 4 }}
|
||||
{{- include "boosapi.labels" . | nindent 4 }}
|
||||
spec:
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
revisionHistoryLimit: 2
|
||||
@@ -17,25 +17,25 @@ spec:
|
||||
maxUnavailable: {{ .Values.deployment.strategy.maxUnavailable }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: {{ include "metapi.name" . }}
|
||||
app.kubernetes.io/name: {{ include "boosapi.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: {{ include "metapi.name" . }}
|
||||
app.kubernetes.io/name: {{ include "boosapi.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
annotations:
|
||||
metapi/image-tag: {{ .Values.image.tag | quote }}
|
||||
metapi/image-digest: {{ .Values.image.digest | quote }}
|
||||
boosapi/image-tag: {{ .Values.image.tag | quote }}
|
||||
boosapi/image-digest: {{ .Values.image.digest | quote }}
|
||||
checksum/env-secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum | quote }}
|
||||
spec:
|
||||
containers:
|
||||
- name: metapi
|
||||
- name: boosapi
|
||||
image: "{{ .Values.image.repository }}{{ if .Values.image.digest }}@{{ .Values.image.digest }}{{ else }}:{{ .Values.image.tag }}{{ end }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: {{ include "metapi.envSecretName" . }}
|
||||
name: {{ include "boosapi.envSecretName" . }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 4000
|
||||
@@ -50,10 +50,10 @@ spec:
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 20
|
||||
volumeMounts:
|
||||
- name: metapi-data
|
||||
- name: boosapi-data
|
||||
mountPath: /app/data
|
||||
volumes:
|
||||
- name: metapi-data
|
||||
- name: boosapi-data
|
||||
hostPath:
|
||||
path: {{ .Values.persistence.hostPath }}
|
||||
type: DirectoryOrCreate
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ include "metapi.envSecretName" . }}
|
||||
name: {{ include "boosapi.envSecretName" . }}
|
||||
labels:
|
||||
{{- include "metapi.labels" . | nindent 4 }}
|
||||
{{- include "boosapi.labels" . | nindent 4 }}
|
||||
type: Opaque
|
||||
stringData:
|
||||
AUTH_TOKEN: {{ required "env.authToken is required" .Values.env.authToken | quote }}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "metapi.fullname" . }}
|
||||
name: {{ include "boosapi.fullname" . }}
|
||||
labels:
|
||||
{{- include "metapi.labels" . | nindent 4 }}
|
||||
{{- include "boosapi.labels" . | nindent 4 }}
|
||||
spec:
|
||||
type: {{ .Values.service.type }}
|
||||
selector:
|
||||
app.kubernetes.io/name: {{ include "metapi.name" . }}
|
||||
app.kubernetes.io/name: {{ include "boosapi.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
ports:
|
||||
- name: http
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
replicaCount: 1
|
||||
|
||||
image:
|
||||
repository: 1467078763/metapi
|
||||
repository: 1467078763/boosapi
|
||||
tag: latest
|
||||
digest: ""
|
||||
pullPolicy: Always
|
||||
@@ -17,7 +17,7 @@ deployment:
|
||||
maxUnavailable: 0
|
||||
|
||||
persistence:
|
||||
hostPath: /opt/1panel/docker/compose/metapihub/data
|
||||
hostPath: /opt/1panel/docker/compose/boosapihub/data
|
||||
|
||||
env:
|
||||
authToken: ""
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: metapi-deploy-helper
|
||||
name: boosapi-deploy-helper
|
||||
namespace: ai
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: metapi-deploy-helper-admin
|
||||
name: boosapi-deploy-helper-admin
|
||||
namespace: ai
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: metapi-deploy-helper
|
||||
name: boosapi-deploy-helper
|
||||
namespace: ai
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
@@ -21,7 +21,7 @@ roleRef:
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: metapi-deploy-helper-auth
|
||||
name: boosapi-deploy-helper-auth
|
||||
namespace: ai
|
||||
type: Opaque
|
||||
stringData:
|
||||
@@ -30,22 +30,22 @@ stringData:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: metapi-deploy-helper
|
||||
name: boosapi-deploy-helper
|
||||
namespace: ai
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: metapi-deploy-helper
|
||||
app.kubernetes.io/name: boosapi-deploy-helper
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: metapi-deploy-helper
|
||||
app.kubernetes.io/name: boosapi-deploy-helper
|
||||
spec:
|
||||
serviceAccountName: metapi-deploy-helper
|
||||
serviceAccountName: boosapi-deploy-helper
|
||||
containers:
|
||||
- name: helper
|
||||
image: 1467078763/metapi:latest
|
||||
image: 1467078763/boosapi:latest
|
||||
imagePullPolicy: Always
|
||||
command: ["/bin/sh", "-lc"]
|
||||
args:
|
||||
@@ -85,7 +85,7 @@ spec:
|
||||
- name: DEPLOY_HELPER_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: metapi-deploy-helper-auth
|
||||
name: boosapi-deploy-helper-auth
|
||||
key: DEPLOY_HELPER_TOKEN
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
@@ -100,23 +100,23 @@ spec:
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 20
|
||||
volumeMounts:
|
||||
- name: metapi-chart
|
||||
mountPath: /opt/metapi-k3s/chart
|
||||
- name: boosapi-chart
|
||||
mountPath: /opt/boosapi-k3s/chart
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: metapi-chart
|
||||
- name: boosapi-chart
|
||||
hostPath:
|
||||
path: /opt/metapi-k3s/chart
|
||||
path: /opt/boosapi-k3s/chart
|
||||
type: Directory
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: metapi-deploy-helper
|
||||
name: boosapi-deploy-helper
|
||||
namespace: ai
|
||||
spec:
|
||||
selector:
|
||||
app.kubernetes.io/name: metapi-deploy-helper
|
||||
app.kubernetes.io/name: boosapi-deploy-helper
|
||||
ports:
|
||||
- name: http
|
||||
port: 9850
|
||||
|
||||
+12
-12
@@ -1,4 +1,4 @@
|
||||
FROM node:22-bookworm-slim AS metapi-builder
|
||||
FROM node:22-bookworm-slim AS boosapi-builder
|
||||
|
||||
WORKDIR /app
|
||||
RUN echo 'Acquire::http::Proxy "false";' > /etc/apt/apt.conf.d/99no-proxy && apt-get update && apt-get install -y --no-install-recommends python3 make g++ && rm -rf /var/lib/apt/lists/*
|
||||
@@ -54,16 +54,16 @@ RUN git clone https://github.com/comfyanonymous/ComfyUI.git . \
|
||||
&& rm -rf ~/.cache/pip
|
||||
ENV PATH="/app/comfy/venv/bin:${PATH}"
|
||||
|
||||
# Copy metapi (built)
|
||||
WORKDIR /app/metapi
|
||||
COPY --from=metapi-builder /app/dist ./dist
|
||||
COPY --from=metapi-builder /app/node_modules ./node_modules
|
||||
COPY --from=metapi-builder /app/package.json ./
|
||||
COPY --from=metapi-builder /app/drizzle ./drizzle
|
||||
# Copy boosapi (built)
|
||||
WORKDIR /app/boosapi
|
||||
COPY --from=boosapi-builder /app/dist ./dist
|
||||
COPY --from=boosapi-builder /app/node_modules ./node_modules
|
||||
COPY --from=boosapi-builder /app/package.json ./
|
||||
COPY --from=boosapi-builder /app/drizzle ./drizzle
|
||||
RUN mkdir -p data
|
||||
|
||||
# Copy BoosAPI custom nodes for ComfyUI (call local BoosAPI API)
|
||||
COPY --from=metapi-builder /app/boosapi_comfy_nodes.py /app/comfy/custom_nodes/boosapi_comfy_nodes.py
|
||||
COPY --from=boosapi-builder /app/boosapi_comfy_nodes.py /app/comfy/custom_nodes/boosapi_comfy_nodes.py
|
||||
|
||||
# Supervisor config
|
||||
RUN mkdir -p /var/log/supervisor
|
||||
@@ -74,12 +74,12 @@ user=root
|
||||
logfile=/var/log/supervisor/supervisord.log
|
||||
pidfile=/tmp/supervisord.pid
|
||||
|
||||
[program:metapi]
|
||||
[program:boosapi]
|
||||
command=sh -c "node dist/server/db/migrate.js && node dist/server/index.js"
|
||||
directory=/app/metapi
|
||||
directory=/app/boosapi
|
||||
autorestart=true
|
||||
stdout_logfile=/var/log/supervisor/metapi.log
|
||||
stderr_logfile=/var/log/supervisor/metapi.err
|
||||
stdout_logfile=/var/log/supervisor/boosapi.log
|
||||
stderr_logfile=/var/log/supervisor/boosapi.err
|
||||
|
||||
[program:comfyui]
|
||||
command=python3 main.py --listen 0.0.0.0 --port 8188 --cpu
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# This file is automatically picked up by Docker Compose during local development.
|
||||
# It overrides the image reference in docker-compose.yml with a local build.
|
||||
services:
|
||||
metapi:
|
||||
boosapi:
|
||||
image: ~
|
||||
build:
|
||||
context: ..
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
metapi:
|
||||
image: 1467078763/metapi:latest
|
||||
boosapi:
|
||||
image: 1467078763/boosapi:latest
|
||||
ports:
|
||||
- "127.0.0.1:4000:4000"
|
||||
volumes:
|
||||
|
||||
@@ -72,7 +72,7 @@ export default withMermaid(
|
||||
{ text: 'OAuth 管理', link: '/oauth' },
|
||||
{ text: 'FAQ', link: '/faq' },
|
||||
{ text: '文档维护', link: '/README' },
|
||||
{ text: '项目主页', link: 'https://github.com/cita-777/metapi' },
|
||||
{ text: '项目主页', link: 'https://github.com/cita-777/boosapi' },
|
||||
],
|
||||
sidebar: [
|
||||
{
|
||||
@@ -106,7 +106,7 @@ export default withMermaid(
|
||||
},
|
||||
],
|
||||
socialLinks: [
|
||||
{ icon: 'github', link: 'https://github.com/cita-777/metapi' },
|
||||
{ icon: 'github', link: 'https://github.com/cita-777/boosapi' },
|
||||
],
|
||||
outline: {
|
||||
level: [2, 3],
|
||||
|
||||
@@ -105,10 +105,10 @@ Metapi 暴露标准 OpenAI / Claude 兼容接口,下游客户端通常只需
|
||||
|
||||
```toml
|
||||
model = "gpt-5"
|
||||
model_provider = "metapi"
|
||||
model_provider = "boosapi"
|
||||
|
||||
[model_providers.metapi]
|
||||
name = "metapi"
|
||||
[model_providers.boosapi]
|
||||
name = "boosapi"
|
||||
base_url = "https://your-domain.com/v1"
|
||||
```
|
||||
|
||||
|
||||
+2
-2
@@ -161,7 +161,7 @@ Render 免费实例在 15 分钟无流量后会自动休眠。使用 UptimeRobot
|
||||
### 标准步骤
|
||||
|
||||
```bash
|
||||
mkdir metapi && cd metapi
|
||||
mkdir boosapi && cd boosapi
|
||||
|
||||
# 创建 docker-compose.yml(参见快速上手)
|
||||
# 设置环境变量
|
||||
@@ -193,7 +193,7 @@ docker compose --env-file .env up -d
|
||||
## Docker 命令部署
|
||||
|
||||
```bash
|
||||
docker run -d --name metapi \
|
||||
docker run -d --name boosapi \
|
||||
-p 4000:4000 \
|
||||
-e AUTH_TOKEN=your-admin-token \
|
||||
-e PROXY_TOKEN=your-proxy-sk-token \
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
### 1. 创建项目目录
|
||||
|
||||
```bash
|
||||
mkdir metapi && cd metapi
|
||||
mkdir boosapi && cd boosapi
|
||||
```
|
||||
|
||||
### 2. 创建 `docker-compose.yml`
|
||||
@@ -34,7 +34,7 @@ mkdir metapi && cd metapi
|
||||
```yaml
|
||||
services:
|
||||
metapi:
|
||||
image: 1467078763/metapi:latest
|
||||
image: 1467078763/boosapi:latest
|
||||
ports:
|
||||
- "4000:4000"
|
||||
volumes:
|
||||
@@ -111,7 +111,7 @@ Linux 安装包选择建议:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/cita-777/metapi.git
|
||||
cd metapi
|
||||
cd boosapi
|
||||
npm install
|
||||
npm run db:migrate
|
||||
npm run dev
|
||||
|
||||
+21
-21
@@ -37,7 +37,7 @@ K3s 更新中心的日常入口位于:
|
||||
| Deploy Helper URL | UI:设置 → 更新中心 | 例如集群内 Service 地址 |
|
||||
| Namespace / Release Name / Chart Ref / Image Repository | UI:设置 → 更新中心 | 都是页面里直接填的部署配置 |
|
||||
| GitHub Releases / Docker Hub / 默认部署来源 | UI:设置 → 更新中心 | 属于页面里的版本来源策略 |
|
||||
| 主 Metapi 到 helper 的认证 token | 主 Metapi 环境变量 | `DEPLOY_HELPER_TOKEN` 或 `UPDATE_CENTER_HELPER_TOKEN` |
|
||||
| 主 BoosAPI 到 helper 的认证 token | 主 BoosAPI 环境变量 | `DEPLOY_HELPER_TOKEN` 或 `UPDATE_CENTER_HELPER_TOKEN` |
|
||||
| helper 自己监听在哪个地址和端口 | helper 环境变量 / manifest | `DEPLOY_HELPER_HOST` / `DEPLOY_HELPER_PORT` |
|
||||
| helper 自己的 Bearer Token | helper 环境变量 / manifest | `DEPLOY_HELPER_TOKEN`,且必须与主服务一致 |
|
||||
| chart 是否真的支持 digest 部署 | chart 文件本身 | 这不是 UI,也不是普通 env,要看 chart 模板 |
|
||||
@@ -151,7 +151,7 @@ docker compose up -d
|
||||
- `image.tag`
|
||||
- `image.digest`
|
||||
- 目标 Deployment 带有 `app.kubernetes.io/instance=<releaseName>` 标签
|
||||
- 主 Metapi 服务可以访问:
|
||||
- 主 BoosAPI 服务可以访问:
|
||||
- GitHub API
|
||||
- Docker Hub API
|
||||
- Deploy Helper 的集群内地址
|
||||
@@ -160,7 +160,7 @@ docker compose up -d
|
||||
|
||||
## helper 是什么
|
||||
|
||||
Deploy Helper 是一个跑在集群里的小服务。它不负责对外提供 Metapi 功能,只负责接受主 Metapi 发来的部署请求,然后在集群里执行:
|
||||
Deploy Helper 是一个跑在集群里的小服务。它不负责对外提供 Metapi 功能,只负责接受主 BoosAPI 发来的部署请求,然后在集群里执行:
|
||||
|
||||
- `helm history`
|
||||
- `helm get values`
|
||||
@@ -202,7 +202,7 @@ Deploy Helper 是一个跑在集群里的小服务。它不负责对外提供 Me
|
||||
|
||||
仓库里带了一个最小示例清单:
|
||||
|
||||
- `deploy/k3s/metapi-deploy-helper.yaml`
|
||||
- `deploy/k3s/boosapi-deploy-helper.yaml`
|
||||
- `deploy/k3s/chart`
|
||||
|
||||
使用前至少要改这些值:
|
||||
@@ -213,8 +213,8 @@ Deploy Helper 是一个跑在集群里的小服务。它不负责对外提供 Me
|
||||
|
||||
如果你准备直接按仓库示例接入,推荐把它们放到这两个路径:
|
||||
|
||||
- `/opt/metapi-k3s/metapi-deploy-helper.yaml`
|
||||
- `/opt/metapi-k3s/chart`
|
||||
- `/opt/boosapi-k3s/boosapi-deploy-helper.yaml`
|
||||
- `/opt/boosapi-k3s/chart`
|
||||
|
||||
这里有一个很容易漏掉、但会直接决定更新中心是否真的可靠的约束:
|
||||
|
||||
@@ -223,16 +223,16 @@ Deploy Helper 是一个跑在集群里的小服务。它不负责对外提供 Me
|
||||
|
||||
这两个值必须指向同一份 chart。
|
||||
|
||||
如果你在设置页把 `Chart Ref` 填成 `/opt/metapi-k3s/chart`,但 helper Pod 里根本没有把那份 chart 挂进去,那么更新中心即使能看到版本,也无法稳定把 digest 部署到真正运行中的 Pod。
|
||||
如果你在设置页把 `Chart Ref` 填成 `/opt/boosapi-k3s/chart`,但 helper Pod 里根本没有把那份 chart 挂进去,那么更新中心即使能看到版本,也无法稳定把 digest 部署到真正运行中的 Pod。
|
||||
|
||||
最小部署命令示例:
|
||||
|
||||
```bash
|
||||
kubectl create namespace ai
|
||||
mkdir -p /opt/metapi-k3s/chart
|
||||
cp -R deploy/k3s/chart/. /opt/metapi-k3s/chart/
|
||||
cp deploy/k3s/metapi-deploy-helper.yaml /opt/metapi-k3s/metapi-deploy-helper.yaml
|
||||
kubectl apply -f /opt/metapi-k3s/metapi-deploy-helper.yaml
|
||||
mkdir -p /opt/boosapi-k3s/chart
|
||||
cp -R deploy/k3s/chart/. /opt/boosapi-k3s/chart/
|
||||
cp deploy/k3s/boosapi-deploy-helper.yaml /opt/boosapi-k3s/boosapi-deploy-helper.yaml
|
||||
kubectl apply -f /opt/boosapi-k3s/boosapi-deploy-helper.yaml
|
||||
```
|
||||
|
||||
### 1.1 首次接入前一定要做的自检
|
||||
@@ -255,8 +255,8 @@ kubectl apply -f /opt/metapi-k3s/metapi-deploy-helper.yaml
|
||||
你可以在接入前先跑一次自检:
|
||||
|
||||
```bash
|
||||
helm template metapi /opt/metapi-k3s/chart \
|
||||
--set image.repository=1467078763/metapi \
|
||||
helm template boosapi /opt/boosapi-k3s/chart \
|
||||
--set image.repository=1467078763/boosapi \
|
||||
--set image.tag=latest \
|
||||
--set-string image.digest=sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef \
|
||||
| grep -n 'image:'
|
||||
@@ -264,17 +264,17 @@ helm template metapi /opt/metapi-k3s/chart \
|
||||
|
||||
你期望看到的是:
|
||||
|
||||
- `image: "1467078763/metapi@sha256:..."`
|
||||
- `image: "1467078763/boosapi@sha256:..."`
|
||||
|
||||
如果输出仍然是:
|
||||
|
||||
- `image: "1467078763/metapi:latest"`
|
||||
- `image: "1467078763/boosapi:latest"`
|
||||
|
||||
那说明这份 chart 还是 tag 语义,先不要继续配置更新中心。
|
||||
|
||||
### 2. 让主 Metapi 和 helper 用同一个 token
|
||||
### 2. 让主 BoosAPI 和 helper 用同一个 token
|
||||
|
||||
主 Metapi 端支持这两个环境变量,设置一个即可:
|
||||
主 BoosAPI 端支持这两个环境变量,设置一个即可:
|
||||
|
||||
- `DEPLOY_HELPER_TOKEN`
|
||||
- `UPDATE_CENTER_HELPER_TOKEN`
|
||||
@@ -295,11 +295,11 @@ helper 端使用:
|
||||
|
||||
| 字段 | 怎么理解 | 典型示例 |
|
||||
|------|--------|----------|
|
||||
| `Deploy Helper URL` | 主 Metapi 访问 helper 的地址 | `http://metapi-deploy-helper.ai.svc.cluster.local:9850` |
|
||||
| `Deploy Helper URL` | 主 BoosAPI 访问 helper 的地址 | `http://boosapi-deploy-helper.ai.svc.cluster.local:9850` |
|
||||
| `Namespace` | 目标 release 所在命名空间 | `ai` |
|
||||
| `Release Name` | Helm release 名 | `metapi` |
|
||||
| `Chart Ref` | helper Pod 能访问到的 chart 引用 | `/opt/metapi-k3s/chart` |
|
||||
| `Image Repository` | 升级时写入 chart 的镜像仓库 | `1467078763/metapi` |
|
||||
| `Chart Ref` | helper Pod 能访问到的 chart 引用 | `/opt/boosapi-k3s/chart` |
|
||||
| `Image Repository` | 升级时写入 chart 的镜像仓库 | `1467078763/boosapi` |
|
||||
| `默认部署来源` | 默认从 GitHub 还是 Docker Hub 取版本 | `GitHub Releases` |
|
||||
|
||||
另外还有 3 个开关:
|
||||
@@ -395,7 +395,7 @@ About 页里的“更新提醒”更像一个轻量入口:
|
||||
如果你是第一次接入,最稳妥的方式就是直接从仓库自带的:
|
||||
|
||||
- `deploy/k3s/chart`
|
||||
- `deploy/k3s/metapi-deploy-helper.yaml`
|
||||
- `deploy/k3s/boosapi-deploy-helper.yaml`
|
||||
|
||||
开始,不要自己先抄一份简化版再改。
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
appId: me.cita777.metapi.desktop
|
||||
appId: me.cita777.boosapi.desktop
|
||||
productName: Metapi
|
||||
artifactName: ${name}-${version}-${os}-${arch}.${ext}
|
||||
directories:
|
||||
@@ -31,7 +31,7 @@ linux:
|
||||
publish:
|
||||
provider: github
|
||||
owner: cita-777
|
||||
repo: metapi
|
||||
repo: boosapi
|
||||
releaseType: release
|
||||
publishAutoUpdate: true
|
||||
nsis:
|
||||
|
||||
Generated
+2
-2
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "metapi",
|
||||
"name": "boosapi",
|
||||
"version": "1.3.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "metapi",
|
||||
"name": "boosapi",
|
||||
"version": "1.3.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "metapi",
|
||||
"name": "boosapi",
|
||||
"version": "1.3.0",
|
||||
"description": "Meta-layer management and unified proxy for AI API aggregation platforms",
|
||||
"main": "dist/desktop/main.js",
|
||||
|
||||
@@ -17,25 +17,23 @@
|
||||
| 后端通知 | `notifyService.ts` 通知前缀 `[metapi]` → `[BoosAPI]` |
|
||||
| 桌面元数据 | Electron/Docker 描述信息 |
|
||||
|
||||
### 保留不变的
|
||||
### 已全部改完的(此表仅作历史记录)
|
||||
|
||||
| 项 | 原因 |
|
||||
| 项 | 说明 |
|
||||
|---|------|
|
||||
| `x-metapi-*` HTTP 头 | 有线协议,向后兼容 |
|
||||
| `metapi:` 推理签名前缀 | 内部协议标识 |
|
||||
| `__metapiTruncated` 等运行时属性 | 内部运行时标记 |
|
||||
| `METAPI_*` 环境变量 | 外部契约,改了就断 |
|
||||
| localStorage key | 改了丢用户数据 |
|
||||
| DB schema 列名 | 影响持久化数据 |
|
||||
| `package.json` name | npm 包名 |
|
||||
| `x-metapi-*` HTTP 头 | 已改 `x-boosapi-*`,注意有外部依赖的需同步更新 |
|
||||
| `metapi:` 推理签名前缀 | 已改 `boosapi:` |
|
||||
| `__metapiTruncated` 等运行时属性 | 已改 `__boosapi*` |
|
||||
| `METAPI_*` 环境变量 | 已改 `BOOSAPI_*`,部署配置需要同步 |
|
||||
| `package.json` name | 已改 `boosapi` |
|
||||
|
||||
### 验证
|
||||
|
||||
```bash
|
||||
# 确认没有遗漏的用户可见"Metapi"
|
||||
grep -rn 'Metapi\|metapi' src/ --include='*.ts' --include='*.tsx' --include='*.html' \
|
||||
# 确认没有遗漏的 metapi
|
||||
grep -rn 'mM]etapi' src/ --include='*.ts' --include='*.tsx' --include='*.html' \
|
||||
| grep -v '.test.' | grep -v node_modules | grep -iv 'boosapi'
|
||||
# 剩余应只有 x-metapi、metapi:、__metapi 等内部标识
|
||||
# 应无输出
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
services:
|
||||
- type: web
|
||||
name: metapi
|
||||
name: boosapi
|
||||
runtime: docker
|
||||
repo: https://github.com/cita-777/metapi
|
||||
repo: https://github.com/cita-777/boosapi
|
||||
dockerfilePath: ./docker/Dockerfile
|
||||
dockerContext: .
|
||||
plan: free
|
||||
|
||||
@@ -37,7 +37,7 @@ async function ensureBetterSqliteCompatible() {
|
||||
}
|
||||
|
||||
const rebuild = buildBetterSqliteRebuildCommand();
|
||||
console.log('[metapi] Detected better-sqlite3 ABI mismatch. Rebuilding for the current Node.js runtime...');
|
||||
console.log('[boosapi] Detected better-sqlite3 ABI mismatch. Rebuilding for the current Node.js runtime...');
|
||||
await run(rebuild.command, rebuild.args);
|
||||
|
||||
try {
|
||||
|
||||
@@ -3,10 +3,10 @@ import { readFileSync, writeFileSync } from 'node:fs';
|
||||
import { resolve } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const REPO = 'cita-777/metapi';
|
||||
const REPO = 'cita-777/boosapi';
|
||||
const README_FILES = ['README.md', 'README_EN.md'] as const;
|
||||
const START_MARKER = '<!-- metapi-contributors:start -->';
|
||||
const END_MARKER = '<!-- metapi-contributors:end -->';
|
||||
const START_MARKER = '<!-- boosapi-contributors:start -->';
|
||||
const END_MARKER = '<!-- boosapi-contributors:end -->';
|
||||
const PER_LINE = 10;
|
||||
const EXCLUDED_LOGINS = new Set(['dependabot[bot]']);
|
||||
|
||||
|
||||
+2
-2
@@ -61,13 +61,13 @@ function getWindowIconPath() {
|
||||
}
|
||||
|
||||
function resolveFrontendUrl() {
|
||||
const devUrl = (process.env.METAPI_DESKTOP_DEV_SERVER_URL || '').trim();
|
||||
const devUrl = (process.env.BOOSAPI_DESKTOP_DEV_SERVER_URL || '').trim();
|
||||
if (devUrl) return devUrl;
|
||||
return serverUrl;
|
||||
}
|
||||
|
||||
function resolveExternalServerUrl() {
|
||||
return (process.env.METAPI_DESKTOP_EXTERNAL_SERVER_URL || '').trim();
|
||||
return (process.env.BOOSAPI_DESKTOP_EXTERNAL_SERVER_URL || '').trim();
|
||||
}
|
||||
|
||||
function showMainWindow() {
|
||||
|
||||
@@ -39,8 +39,8 @@ export function buildDesktopServerEnv(input: DesktopServerEnvInput): NodeJS.Proc
|
||||
HOST: host,
|
||||
PORT: String(input.port),
|
||||
DATA_DIR: input.userDataDir,
|
||||
METAPI_DESKTOP: '1',
|
||||
METAPI_LOG_DIR: input.logsDir,
|
||||
BOOSAPI_DESKTOP: '1',
|
||||
BOOSAPI_LOG_DIR: input.logsDir,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ export function createDesktopHealthUrl(port: number): string {
|
||||
}
|
||||
|
||||
export function resolveDesktopServerPort(env?: NodeJS.ProcessEnv): number {
|
||||
const forcedPort = Number.parseInt(env?.METAPI_DESKTOP_SERVER_PORT || '', 10);
|
||||
const forcedPort = Number.parseInt(env?.BOOSAPI_DESKTOP_SERVER_PORT || '', 10);
|
||||
if (Number.isFinite(forcedPort) && forcedPort > 0) return forcedPort;
|
||||
return DEFAULT_DESKTOP_SERVER_PORT;
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ import { tokenRouter } from '../services/tokenRouter.js';
|
||||
|
||||
type SelectedChannel = Awaited<ReturnType<typeof tokenRouter.selectChannel>>;
|
||||
|
||||
export const TESTER_FORCED_CHANNEL_HEADER = 'x-metapi-tester-forced-channel-id';
|
||||
export const TESTER_REQUEST_HEADER = 'x-metapi-tester-request';
|
||||
export const TESTER_FORCED_CHANNEL_HEADER = 'x-boosapi-tester-forced-channel-id';
|
||||
export const TESTER_REQUEST_HEADER = 'x-boosapi-tester-request';
|
||||
|
||||
function headerValueEquals(
|
||||
headers: Record<string, unknown> | undefined,
|
||||
|
||||
@@ -54,7 +54,7 @@ function normalizeLowerCaseHeaderMap(
|
||||
}
|
||||
|
||||
export function uuidFromSeed(seed: string): string {
|
||||
const derived = pbkdf2Sync(seed, 'metapi-runtime-header-seed', 10_000, 16, 'sha256');
|
||||
const derived = pbkdf2Sync(seed, 'boosapi-runtime-header-seed', 10_000, 16, 'sha256');
|
||||
const bytes = new Uint8Array(derived);
|
||||
bytes[6] = (bytes[6]! & 0x0f) | 0x50;
|
||||
bytes[8] = (bytes[8]! & 0x3f) | 0x80;
|
||||
@@ -159,7 +159,7 @@ export function buildCodexRuntimeHeaders(input: {
|
||||
getInputHeader(input.baseHeaders, 'session_id')
|
||||
|| getInputHeader(input.baseHeaders, 'session-id')
|
||||
|| explicitSessionId
|
||||
|| (continuityKey ? uuidFromSeed(`metapi:codex:${continuityKey}`) : null)
|
||||
|| (continuityKey ? uuidFromSeed(`boosapi:codex:${continuityKey}`) : null)
|
||||
|| randomUUID()
|
||||
);
|
||||
const conversationId = (
|
||||
|
||||
@@ -124,7 +124,7 @@ function getCodexSessionHeaderValue(headers: Record<string, string>): string {
|
||||
}
|
||||
function isResponsesWebsocketTransportRequest(headers: Record<string, unknown>): boolean {
|
||||
return Object.entries(headers)
|
||||
.some(([rawKey, rawValue]) => rawKey.trim().toLowerCase() === 'x-metapi-responses-websocket-transport'
|
||||
.some(([rawKey, rawValue]) => rawKey.trim().toLowerCase() === 'x-boosapi-responses-websocket-transport'
|
||||
&& String(rawValue).trim() === '1');
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { FastifyInstance } from 'fastify';
|
||||
import { fetch } from 'undici';
|
||||
|
||||
const METAPI_BASE = `http://127.0.0.1:${process.env.PORT || 3000}`;
|
||||
const BOOSAPI_BASE = `http://127.0.0.1:${process.env.PORT || 3000}`;
|
||||
|
||||
interface AgentRequest {
|
||||
script: string;
|
||||
@@ -72,7 +72,7 @@ const SCENE_PROMPT_GEN = `根据场景描述生成图像生成提示词,用于
|
||||
只返回 JSON。`;
|
||||
|
||||
async function callLLM(prompt: string, system: string): Promise<string> {
|
||||
const resp = await fetch(`${METAPI_BASE}/v1/chat/completions`, {
|
||||
const resp = await fetch(`${BOOSAPI_BASE}/v1/chat/completions`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
@@ -92,7 +92,7 @@ async function callLLM(prompt: string, system: string): Promise<string> {
|
||||
}
|
||||
|
||||
async function callImageGen(prompt: string): Promise<string> {
|
||||
const resp = await fetch(`${METAPI_BASE}/v1/images/generations`, {
|
||||
const resp = await fetch(`${BOOSAPI_BASE}/v1/images/generations`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
@@ -110,7 +110,7 @@ async function callImageGen(prompt: string): Promise<string> {
|
||||
}
|
||||
|
||||
async function callTTS(text: string, voice = 'alloy'): Promise<Buffer | null> {
|
||||
const resp = await fetch(`${METAPI_BASE}/v1/audio/speech`, {
|
||||
const resp = await fetch(`${BOOSAPI_BASE}/v1/audio/speech`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { FastifyInstance, FastifyRequest } from 'fastify';
|
||||
|
||||
type MultipartAwareFastify = FastifyInstance & {
|
||||
__metapiMultipartParserRegistered?: boolean;
|
||||
__boosapiMultipartParserRegistered?: boolean;
|
||||
};
|
||||
|
||||
function getContentType(request: FastifyRequest): string {
|
||||
@@ -12,13 +12,13 @@ function getContentType(request: FastifyRequest): string {
|
||||
|
||||
export function ensureMultipartBufferParser(app: FastifyInstance): void {
|
||||
const target = app as MultipartAwareFastify;
|
||||
if (target.__metapiMultipartParserRegistered) return;
|
||||
if (target.__boosapiMultipartParserRegistered) return;
|
||||
|
||||
app.addContentTypeParser(/^multipart\/form-data(?:;.*)?$/i, { parseAs: 'buffer' }, (_request, body, done) => {
|
||||
done(null, body);
|
||||
});
|
||||
|
||||
target.__metapiMultipartParserRegistered = true;
|
||||
target.__boosapiMultipartParserRegistered = true;
|
||||
}
|
||||
|
||||
export function isMultipartRequest(request: FastifyRequest): boolean {
|
||||
|
||||
@@ -22,8 +22,8 @@ import { applyOpenAiServiceTierPolicy } from '../../proxy-core/serviceTierPolicy
|
||||
|
||||
const installedApps = new WeakSet<FastifyInstance>();
|
||||
const WS_TURN_STATE_HEADER = 'x-codex-turn-state';
|
||||
const RESPONSES_WEBSOCKET_MODE_HEADER = 'x-metapi-responses-websocket-mode';
|
||||
const RESPONSES_WEBSOCKET_TRANSPORT_HEADER = 'x-metapi-responses-websocket-transport';
|
||||
const RESPONSES_WEBSOCKET_MODE_HEADER = 'x-boosapi-responses-websocket-mode';
|
||||
const RESPONSES_WEBSOCKET_TRANSPORT_HEADER = 'x-boosapi-responses-websocket-transport';
|
||||
const codexWebsocketRuntime = createCodexWebsocketRuntime();
|
||||
|
||||
type SelectedChannel = NonNullable<Awaited<ReturnType<typeof tokenRouter.selectChannel>>>;
|
||||
|
||||
@@ -27,7 +27,7 @@ let lastPruneAtMs = 0;
|
||||
const PRUNE_INTERVAL_MS = 5 * 60 * 1000;
|
||||
|
||||
type TruncatedDebugPreview = {
|
||||
__metapiTruncated: true;
|
||||
__boosapiTruncated: true;
|
||||
preview: string;
|
||||
originalBytes: number;
|
||||
storedBytes: number;
|
||||
@@ -36,7 +36,7 @@ type TruncatedDebugPreview = {
|
||||
function buildTruncatedDebugPreview(text: string, maxBytes: number, originalBytes: number): string {
|
||||
const truncated = Buffer.from(text, 'utf8').subarray(0, Math.max(0, maxBytes)).toString('utf8');
|
||||
const payload: TruncatedDebugPreview = {
|
||||
__metapiTruncated: true,
|
||||
__boosapiTruncated: true,
|
||||
preview: truncated,
|
||||
originalBytes,
|
||||
storedBytes: maxBytes,
|
||||
|
||||
@@ -4,7 +4,7 @@ import { db, schema } from '../db/index.js';
|
||||
import type { ProxyResourceOwner } from '../middleware/auth.js';
|
||||
import { formatUtcSqlDateTime } from './localTimeService.js';
|
||||
|
||||
export const LOCAL_PROXY_FILE_ID_PREFIX = 'file-metapi-';
|
||||
export const LOCAL_PROXY_FILE_ID_PREFIX = 'file-boosapi-';
|
||||
|
||||
export type ProxyFileRecord = {
|
||||
publicId: string;
|
||||
|
||||
@@ -85,19 +85,19 @@ const GENERIC_PASSTHROUGH_ALLOWED_HEADERS = new Set([
|
||||
'x-codex-turn-metadata',
|
||||
'x-codex-turn-state',
|
||||
]);
|
||||
const METAPI_INTERNAL_HEADER_BLOCKLIST = new Set([
|
||||
'x-metapi-tester-request',
|
||||
'x-metapi-tester-forced-channel-id',
|
||||
'x-metapi-responses-websocket-mode',
|
||||
'x-metapi-responses-websocket-transport',
|
||||
const BOOSAPI_INTERNAL_HEADER_BLOCKLIST = new Set([
|
||||
'x-boosapi-tester-request',
|
||||
'x-boosapi-tester-forced-channel-id',
|
||||
'x-boosapi-responses-websocket-mode',
|
||||
'x-boosapi-responses-websocket-transport',
|
||||
]);
|
||||
|
||||
const ANTIGRAVITY_RUNTIME_USER_AGENT = 'antigravity/1.19.6 darwin/arm64';
|
||||
|
||||
function shouldSkipPassthroughHeader(key: string): boolean {
|
||||
if (HOP_BY_HOP_HEADERS.has(key) || BLOCKED_PASSTHROUGH_HEADERS.has(key)) return true;
|
||||
if (METAPI_INTERNAL_HEADER_BLOCKLIST.has(key)) return true;
|
||||
if (key.startsWith('x-metapi-')) return true;
|
||||
if (BOOSAPI_INTERNAL_HEADER_BLOCKLIST.has(key)) return true;
|
||||
if (key.startsWith('x-boosapi-')) return true;
|
||||
if (!GENERIC_PASSTHROUGH_ALLOWED_HEADERS.has(key)) return true;
|
||||
return false;
|
||||
}
|
||||
@@ -645,9 +645,9 @@ export function buildUpstreamEndpointRequest(input: {
|
||||
if (input.endpoint === 'responses') {
|
||||
const responsesWebsocketTransport = getInputHeader(
|
||||
input.downstreamHeaders,
|
||||
'x-metapi-responses-websocket-transport',
|
||||
'x-boosapi-responses-websocket-transport',
|
||||
) === '1';
|
||||
const websocketMode = Object.entries(input.downstreamHeaders || {}).find(([rawKey]) => rawKey.trim().toLowerCase() === 'x-metapi-responses-websocket-mode');
|
||||
const websocketMode = Object.entries(input.downstreamHeaders || {}).find(([rawKey]) => rawKey.trim().toLowerCase() === 'x-boosapi-responses-websocket-mode');
|
||||
const preserveWebsocketIncrementalMode = asTrimmedString(websocketMode?.[1]).toLowerCase() === 'incremental';
|
||||
const responsesHeaders = input.downstreamFormat === 'responses'
|
||||
? extractResponsesPassthroughHeaders(input.downstreamHeaders)
|
||||
|
||||
@@ -350,7 +350,7 @@ function resolveAnthropicThinkingSignature(item: Record<string, unknown>): strin
|
||||
if (decodedTaggedSignature !== null) {
|
||||
return decodedTaggedSignature;
|
||||
}
|
||||
if (item.reasoning_signature !== undefined || rawSignature.startsWith('metapi:')) {
|
||||
if (item.reasoning_signature !== undefined || rawSignature.startsWith('boosapi:')) {
|
||||
return null;
|
||||
}
|
||||
return rawSignature;
|
||||
|
||||
@@ -51,7 +51,7 @@ function cleanAnthropicReasoningSignature(value: unknown): string | null {
|
||||
if (!raw) return null;
|
||||
const decoded = decodeAnthropicReasoningSignature(raw);
|
||||
if (decoded) return decoded;
|
||||
if (raw.startsWith('metapi:')) return null;
|
||||
if (raw.startsWith('boosapi:')) return null;
|
||||
return raw;
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ function cleanAnthropicReasoningSignature(value: unknown): string | null {
|
||||
if (!raw) return null;
|
||||
const decoded = decodeAnthropicReasoningSignature(raw);
|
||||
if (decoded) return decoded;
|
||||
if (raw.startsWith('metapi:')) return null;
|
||||
if (raw.startsWith('boosapi:')) return null;
|
||||
return raw;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { CanonicalContinuation } from './types.js';
|
||||
|
||||
export const OPENAI_CONTINUATION_TURN_STATE_METADATA_KEY = 'metapi_turn_state';
|
||||
export const OPENAI_CONTINUATION_TURN_STATE_METADATA_KEY = 'boosapi_turn_state';
|
||||
|
||||
function asTrimmedString(value: unknown): string {
|
||||
return typeof value === 'string' ? value.trim() : '';
|
||||
|
||||
@@ -19,10 +19,10 @@ function cloneJsonValue<T>(value: T): T {
|
||||
}
|
||||
|
||||
const RESPONSES_MCP_COMPAT_MARKER = 'responses_mcp_item';
|
||||
const RESPONSES_MCP_COMPAT_PREFIX = 'metapi_mcp_item__';
|
||||
const RESPONSES_MCP_COMPAT_PREFIX = 'boosapi_mcp_item__';
|
||||
|
||||
type ResponsesMcpCompatEnvelope = {
|
||||
metapi_compat: typeof RESPONSES_MCP_COMPAT_MARKER;
|
||||
boosapi_compat: typeof RESPONSES_MCP_COMPAT_MARKER;
|
||||
itemType: string;
|
||||
item: Record<string, unknown>;
|
||||
};
|
||||
@@ -38,7 +38,7 @@ function createResponsesMcpCompatEnvelope(
|
||||
if (!itemType.startsWith('mcp_')) return null;
|
||||
|
||||
return {
|
||||
metapi_compat: RESPONSES_MCP_COMPAT_MARKER,
|
||||
boosapi_compat: RESPONSES_MCP_COMPAT_MARKER,
|
||||
itemType,
|
||||
item: cloneJsonValue(item),
|
||||
};
|
||||
@@ -81,14 +81,14 @@ function parseCompatEnvelope(rawArguments: unknown): ResponsesMcpCompatEnvelope
|
||||
try {
|
||||
const parsed = JSON.parse(trimmed) as unknown;
|
||||
if (!isRecord(parsed)) return null;
|
||||
if (asTrimmedString(parsed.metapi_compat) !== RESPONSES_MCP_COMPAT_MARKER) return null;
|
||||
if (asTrimmedString(parsed.boosapi_compat) !== RESPONSES_MCP_COMPAT_MARKER) return null;
|
||||
|
||||
const itemType = asTrimmedString(parsed.itemType).toLowerCase();
|
||||
if (!itemType.startsWith('mcp_')) return null;
|
||||
if (!isRecord(parsed.item)) return null;
|
||||
|
||||
return {
|
||||
metapi_compat: RESPONSES_MCP_COMPAT_MARKER,
|
||||
boosapi_compat: RESPONSES_MCP_COMPAT_MARKER,
|
||||
itemType,
|
||||
item: cloneJsonValue(parsed.item),
|
||||
};
|
||||
|
||||
@@ -361,7 +361,7 @@ export function buildNormalizedFinalToOpenAiResponsesPayload(input: {
|
||||
? normalized.reasoningSignature.trim()
|
||||
: '';
|
||||
const encryptedReasoning = decodeOpenAiEncryptedReasoning(rawReasoningSignature)
|
||||
?? (rawReasoningSignature && !rawReasoningSignature.startsWith('metapi:') ? rawReasoningSignature : null);
|
||||
?? (rawReasoningSignature && !rawReasoningSignature.startsWith('boosapi:') ? rawReasoningSignature : null);
|
||||
const annotations = extractAnnotationsFromUpstream(upstreamPayload);
|
||||
|
||||
const output: Array<Record<string, unknown>> = syntheticOutput.map((item) => cloneJson(item));
|
||||
|
||||
@@ -2251,7 +2251,7 @@ export function serializeFinalResponse(
|
||||
const rawReasoningSignature = typeof normalized.reasoningSignature === 'string'
|
||||
? normalized.reasoningSignature.trim()
|
||||
: '';
|
||||
const taggedReasoningSignature = rawReasoningSignature.startsWith('metapi:');
|
||||
const taggedReasoningSignature = rawReasoningSignature.startsWith('boosapi:');
|
||||
const claudeReasoningSignature = decodeAnthropicReasoningSignature(rawReasoningSignature)
|
||||
?? (rawReasoningSignature && !taggedReasoningSignature ? rawReasoningSignature : null);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const PROVIDER_PREFIX = 'metapi';
|
||||
const PROVIDER_PREFIX = 'boosapi';
|
||||
|
||||
export const ANTHROPIC_REASONING_SIGNATURE_PREFIX = `${PROVIDER_PREFIX}:anthropic-signature:`;
|
||||
export const GEMINI_THOUGHT_SIGNATURE_PREFIX = `${PROVIDER_PREFIX}:gemini-thought-signature:`;
|
||||
|
||||
@@ -259,7 +259,7 @@ export const zhToEnSupplemental: Record<string, string> = {
|
||||
'拉取分组失败': 'Failed to pull group',
|
||||
'拉取分组失败,已回退 default': 'Failed to pull the group and has fallen back to default',
|
||||
'冷却中': 'Cooling down',
|
||||
'例如 BoosAPI': 'For example metapi',
|
||||
'例如 BoosAPI': 'For example BoosAPI',
|
||||
'例如: admin@example.com': 'For example: admin@example.com',
|
||||
'例如: smtp.qq.com': 'For example: smtp.qq.com',
|
||||
'例如: target@example.com': 'For example: target@example.com',
|
||||
|
||||
@@ -4,8 +4,8 @@ metadata:
|
||||
name: Metapi
|
||||
spec:
|
||||
description: Meta-layer management and unified proxy for AI API aggregation platforms.
|
||||
icon: https://raw.githubusercontent.com/cita-777/metapi/main/docs/logos/logo-icon-512.png
|
||||
coverImage: https://raw.githubusercontent.com/cita-777/metapi/main/docs/logos/logo-banner.png
|
||||
icon: https://raw.githubusercontent.com/cita-777/boosapi/main/docs/logos/logo-icon-512.png
|
||||
coverImage: https://raw.githubusercontent.com/cita-777/boosapi/main/docs/logos/logo-banner.png
|
||||
tags:
|
||||
- AI
|
||||
- Tool
|
||||
@@ -41,12 +41,12 @@ spec:
|
||||
name: Service Port
|
||||
description: Internal HTTP port (default 4000).
|
||||
services:
|
||||
- name: metapi
|
||||
icon: https://raw.githubusercontent.com/cita-777/metapi/main/docs/logos/logo-icon-512.png
|
||||
- name: boosapi
|
||||
icon: https://raw.githubusercontent.com/cita-777/boosapi/main/docs/logos/logo-icon-512.png
|
||||
template: PREBUILT
|
||||
spec:
|
||||
source:
|
||||
image: 1467078763/metapi:latest
|
||||
image: 1467078763/boosapi:latest
|
||||
ports:
|
||||
- id: web
|
||||
port: 4000
|
||||
|
||||
Reference in New Issue
Block a user