forked from boos/BoosAPI
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
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user