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:
boos
2026-05-16 00:46:28 +08:00
parent d2c16c3919
commit 0106dd3f5d
46 changed files with 168 additions and 170 deletions
+2 -2
View File
@@ -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() {
+3 -3
View File
@@ -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;
}
+2 -2
View File
@@ -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');
}
+4 -4
View File
@@ -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',
+3 -3
View File
@@ -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>>>;
+2 -2
View File
@@ -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,
+1 -1
View File
@@ -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:`;
+1 -1
View File
@@ -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',